diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 4820366..6cb3080 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -56,7 +56,7 @@ syntax(); sub sp8870 { my $sourcefile = "tt_Premium_217g.zip"; - my $url = "http://www.technotrend.de/new/217g/$sourcefile"; + my $url = "http://www.softwarepatch.pl/9999ccd06a4813cb827dbb0005071c71/$sourcefile"; my $hash = "53970ec17a538945a6d8cb608a7b3899"; my $outfile = "dvb-fe-sp8870.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); @@ -110,21 +110,21 @@ sub tda10045 { } sub tda10046 { - my $sourcefile = "tt_budget_217g.zip"; - my $url = "http://www.technotrend.de/new/217g/$sourcefile"; - my $hash = "6a7e1e2f2644b162ff0502367553c72d"; - my $outfile = "dvb-fe-tda10046.fw"; - my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip"; + my $url = "http://technotrend-online.com/download/software/219/$sourcefile"; + my $hash = "6a7e1e2f2644b162ff0502367553c72d"; + my $outfile = "dvb-fe-tda10046.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); - checkstandard(); + checkstandard(); - wgetfile($sourcefile, $url); - unzip($sourcefile, $tmpdir); - extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp"); - verify("$tmpdir/fwtmp", $hash); - copy("$tmpdir/fwtmp", $outfile); + wgetfile($sourcefile, $url); + unzip($sourcefile, $tmpdir); + extract("$tmpdir/TT_PCI_2.19h_28_11_2006/software/OEM/PCI/App/ttlcdacc.dll", 0x65389, 24478, "$tmpdir/fwtmp"); + verify("$tmpdir/fwtmp", $hash); + copy("$tmpdir/fwtmp", $outfile); - $outfile; + $outfile; } sub tda10046lifeview { diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index af50f9b..026e4e5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -850,11 +850,6 @@ and is between 256 and 4096 characters. It is defined in the file lasi= [HW,SCSI] PARISC LASI driver for the 53c700 chip Format: addr:,irq: - legacy_serial.force [HW,IA-32,X86-64] - Probe for COM ports at legacy addresses even - if PNPBIOS or ACPI should describe them. This - is for working around firmware defects. - llsc*= [IA64] See function print_params() in arch/ia64/sn/kernel/llsc4.c. diff --git a/Makefile b/Makefile index de4f8f7..6f8adbb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 22 -EXTRAVERSION = +EXTRAVERSION = .9 NAME = Holy Dancing Manatees, Batman! # *DOCUMENTATION* diff --git a/arch/i386/Makefile b/arch/i386/Makefile index bd28f9f..541b3ae 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -51,8 +51,8 @@ cflags-y += -maccumulate-outgoing-args CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) # do binutils support CFI? -cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 06da59f..e9297cb 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -35,7 +35,6 @@ obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_DOUBLEFAULT) += doublefault.o -obj-$(CONFIG_SERIAL_8250) += legacy_serial.o obj-$(CONFIG_VM86) += vm86.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_HPET_TIMER) += hpet.o diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 10baa35..18c8b67 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -167,11 +167,13 @@ static void do_drv_read(struct drv_cmd *cmd) static void do_drv_write(struct drv_cmd *cmd) { - u32 h = 0; + u32 lo, hi; switch (cmd->type) { case SYSTEM_INTEL_MSR_CAPABLE: - wrmsr(cmd->addr.msr.reg, cmd->val, h); + rdmsr(cmd->addr.msr.reg, lo, hi); + lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE); + wrmsr(cmd->addr.msr.reg, lo, hi); break; case SYSTEM_IO_CAPABLE: acpi_os_write_port((acpi_io_address)cmd->addr.io.port, @@ -372,7 +374,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, struct cpufreq_freqs freqs; cpumask_t online_policy_cpus; struct drv_cmd cmd; - unsigned int msr; unsigned int next_state = 0; /* Index into freq_table */ unsigned int next_perf_state = 0; /* Index into perf table */ unsigned int i; @@ -417,11 +418,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, case SYSTEM_INTEL_MSR_CAPABLE: cmd.type = SYSTEM_INTEL_MSR_CAPABLE; cmd.addr.msr.reg = MSR_IA32_PERF_CTL; - msr = - (u32) perf->states[next_perf_state]. - control & INTEL_MSR_RANGE; - cmd.val = get_cur_val(online_policy_cpus); - cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr; + cmd.val = (u32) perf->states[next_perf_state].control; break; case SYSTEM_IO_CAPABLE: cmd.type = SYSTEM_IO_CAPABLE; diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c index 4d26d51..996f6f8 100644 --- a/arch/i386/kernel/cpu/perfctr-watchdog.c +++ b/arch/i386/kernel/cpu/perfctr-watchdog.c @@ -346,7 +346,9 @@ static int setup_p6_watchdog(unsigned nmi_hz) perfctr_msr = MSR_P6_PERFCTR0; evntsel_msr = MSR_P6_EVNTSEL0; - wrmsrl(perfctr_msr, 0UL); + /* KVM doesn't implement this MSR */ + if (wrmsr_safe(perfctr_msr, 0, 0) < 0) + return 0; evntsel = P6_EVNTSEL_INT | P6_EVNTSEL_OS diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c index 265c559..40978af 100644 --- a/arch/i386/kernel/doublefault.c +++ b/arch/i386/kernel/doublefault.c @@ -13,7 +13,7 @@ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) -#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000) +#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM) static void doublefault_fn(void) { @@ -23,23 +23,23 @@ static void doublefault_fn(void) store_gdt(&gdt_desc); gdt = gdt_desc.address; - printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); + printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); if (ptr_ok(gdt)) { gdt += GDT_ENTRY_TSS << 3; tss = *(u16 *)(gdt+2); tss += *(u8 *)(gdt+4) << 16; tss += *(u8 *)(gdt+7) << 24; - printk("double fault, tss at %08lx\n", tss); + printk(KERN_EMERG "double fault, tss at %08lx\n", tss); if (ptr_ok(tss)) { struct i386_hw_tss *t = (struct i386_hw_tss *)tss; - printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp); + printk(KERN_EMERG "eip = %08lx, esp = %08lx\n", t->eip, t->esp); - printk("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", + printk(KERN_EMERG "eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", t->eax, t->ebx, t->ecx, t->edx); - printk("esi = %08lx, edi = %08lx\n", + printk(KERN_EMERG "esi = %08lx, edi = %08lx\n", t->esi, t->edi); } } @@ -63,6 +63,7 @@ struct tss_struct doublefault_tss __cacheline_aligned = { .cs = __KERNEL_CS, .ss = __KERNEL_DS, .ds = __USER_DS, + .fs = __KERNEL_PERCPU, .__cr3 = __pa(swapper_pg_dir) } diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c index 17d7345..cbb4751 100644 --- a/arch/i386/kernel/hpet.c +++ b/arch/i386/kernel/hpet.c @@ -226,7 +226,8 @@ int __init hpet_enable(void) { unsigned long id; uint64_t hpet_freq; - u64 tmp; + u64 tmp, start, now; + cycle_t t1; if (!is_hpet_capable()) return 0; @@ -273,6 +274,27 @@ int __init hpet_enable(void) /* Start the counter */ hpet_start_counter(); + /* Verify whether hpet counter works */ + t1 = read_hpet(); + rdtscll(start); + + /* + * We don't know the TSC frequency yet, but waiting for + * 200000 TSC cycles is safe: + * 4 GHz == 50us + * 1 GHz == 200us + */ + do { + rep_nop(); + rdtscll(now); + } while ((now - start) < 200000UL); + + if (t1 == read_hpet()) { + printk(KERN_WARNING + "HPET counter not counting. HPET disabled\n"); + goto out_nohpet; + } + /* Initialize and register HPET clocksource * * hpet period is in femto seconds per cycle diff --git a/arch/i386/kernel/legacy_serial.c b/arch/i386/kernel/legacy_serial.c deleted file mode 100644 index 2151011..0000000 --- a/arch/i386/kernel/legacy_serial.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Legacy COM port devices for x86 platforms without PNPBIOS or ACPI. - * Data taken from include/asm-i386/serial.h. - * - * (c) Copyright 2007 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include - -/* Standard COM flags (except for COM4, because of the 8514 problem) */ -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) -#define COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) -#else -#define COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) -#define COM4_FLAGS UPF_BOOT_AUTOCONF -#endif - -#define PORT(_base,_irq,_flags) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = _flags, \ - } - -static struct plat_serial8250_port x86_com_data[] = { - PORT(0x3F8, 4, COM_FLAGS), - PORT(0x2F8, 3, COM_FLAGS), - PORT(0x3E8, 4, COM_FLAGS), - PORT(0x2E8, 3, COM4_FLAGS), - { }, -}; - -static struct platform_device x86_com_device = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = x86_com_data, - }, -}; - -static int force_legacy_probe; -module_param_named(force, force_legacy_probe, bool, 0); -MODULE_PARM_DESC(force, "Force legacy serial port probe"); - -static int __init serial8250_x86_com_init(void) -{ - if (pnp_platform_devices && !force_legacy_probe) - return -ENODEV; - - return platform_device_register(&x86_com_device); -} - -module_init(serial8250_x86_com_init); - -MODULE_AUTHOR("Bjorn Helgaas"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250/16x50 legacy probe module"); diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index ff4ee6f..6deb159 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -336,7 +336,9 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk) int in_gate_area(struct task_struct *task, unsigned long addr) { - return 0; + const struct vm_area_struct *vma = get_gate_vma(task); + + return vma && addr >= vma->vm_start && addr < vma->vm_end; } int in_gate_area_no_task(unsigned long addr) diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 1ecb3e4..27ba2fd 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -249,9 +249,10 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) pmd_k = pmd_offset(pud_k, address); if (!pmd_present(*pmd_k)) return NULL; - if (!pmd_present(*pmd)) + if (!pmd_present(*pmd)) { set_pmd(pmd, *pmd_k); - else + arch_flush_lazy_mmu_mode(); + } else BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); return pmd_k; } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6e2f035..87c474d 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -83,7 +83,7 @@ void flush_fp_to_thread(struct task_struct *tsk) */ BUG_ON(tsk != current); #endif - giveup_fpu(current); + giveup_fpu(tsk); } preempt_enable(); } @@ -143,7 +143,7 @@ void flush_altivec_to_thread(struct task_struct *tsk) #ifdef CONFIG_SMP BUG_ON(tsk != current); #endif - giveup_altivec(current); + giveup_altivec(tsk); } preempt_enable(); } @@ -182,7 +182,7 @@ void flush_spe_to_thread(struct task_struct *tsk) #ifdef CONFIG_SMP BUG_ON(tsk != current); #endif - giveup_spe(current); + giveup_spe(tsk); } preempt_enable(); } diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 3786dcc..b5c96af 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -24,7 +24,7 @@ /* Max address size we deal with */ #define OF_MAX_ADDR_CELLS 4 #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ - (ns) >= 0) + (ns) > 0) static struct of_bus *of_match_bus(struct device_node *np); static int __of_address_to_resource(struct device_node *dev, diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index f833dba..d5fd390 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -405,6 +405,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, if (len > mm->task_size) return -ENOMEM; + if (len & ((1ul << pshift) - 1)) + return -EINVAL; if (fixed && (addr & ((1ul << pshift) - 1))) return -EINVAL; if (fixed && addr > (mm->task_size - len)) diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 94843ed..fff09f5 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -111,7 +111,6 @@ static struct of_device_id mpc832x_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, - { .type = "mdio", }, {}, }; diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 3db68b7..44a7661 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -75,7 +75,6 @@ static struct of_device_id mpc832x_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, - { .type = "mdio", }, {}, }; diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index bceeff8..526ed09 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -118,7 +118,6 @@ static struct of_device_id mpc836x_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, - { .type = "mdio", }, {}, }; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index e3dddbf..54db416 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -147,7 +147,6 @@ static struct of_device_id mpc85xx_ids[] = { { .type = "soc", }, { .compatible = "soc", }, { .type = "qe", }, - { .type = "mdio", }, {}, }; diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 831f540..eac3838 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1749,8 +1749,8 @@ fpload: __ndelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 - call .umul - mov 0x1ad, %o1 ! 2**32 / (1 000 000 000 / HZ) + call .umul ! round multiplier up so large ns ok + mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) call .umul mov %i1, %o1 ! udelay_val ba delay_continue @@ -1760,11 +1760,17 @@ __ndelay: __udelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 - sethi %hi(0x10c6), %o1 + sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok call .umul - or %o1, %lo(0x10c6), %o1 ! 2**32 / 1 000 000 + or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 call .umul mov %i1, %o1 ! udelay_val + sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, + or %g0, %lo(0x028f4b62), %l0 + addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 + bcs,a 3f + add %o1, 0x01, %o1 +3: call .umul mov HZ, %o0 ! >>32 earlier for wider range diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S index a65eba4..1c37ea8 100644 --- a/arch/sparc/lib/memset.S +++ b/arch/sparc/lib/memset.S @@ -162,7 +162,7 @@ __bzero: 8: add %o0, 1, %o0 subcc %o1, 1, %o1 - bne,a 8b + bne 8b EX(stb %g3, [%o0 - 1], add %o1, 1) 0: retl diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 7725952..35feacb 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -458,7 +458,6 @@ tlb_fixup_done: or %g6, %lo(init_thread_union), %g6 ldx [%g6 + TI_TASK], %g4 mov %sp, %l6 - mov %o4, %l7 wr %g0, ASI_P, %asi mov 1, %g1 diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 81f4a5e..154f10e 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -422,10 +422,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->multifunction = 0; /* maybe a lie? */ if (host_controller) { - dev->vendor = 0x108e; - dev->device = 0x8000; - dev->subsystem_vendor = 0x0000; - dev->subsystem_device = 0x0000; + if (tlb_type != hypervisor) { + pci_read_config_word(dev, PCI_VENDOR_ID, + &dev->vendor); + pci_read_config_word(dev, PCI_DEVICE_ID, + &dev->device); + } else { + dev->vendor = PCI_VENDOR_ID_SUN; + dev->device = 0x80f0; + } dev->cfg_size = 256; dev->class = PCI_CLASS_BRIDGE_HOST << 8; sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), @@ -746,7 +751,7 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm, { struct device_node *child; const u32 *reg; - int reglen, devfn; + int reglen, devfn, prev_devfn; struct pci_dev *dev; if (ofpci_verbose) @@ -754,14 +759,25 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm, node->full_name, bus->number); child = NULL; + prev_devfn = -1; while ((child = of_get_next_child(node, child)) != NULL) { if (ofpci_verbose) printk(" * %s\n", child->full_name); reg = of_get_property(child, "reg", ®len); if (reg == NULL || reglen < 20) continue; + devfn = (reg[0] >> 8) & 0xff; + /* This is a workaround for some device trees + * which list PCI devices twice. On the V100 + * for example, device number 3 is listed twice. + * Once as "pm" and once again as "lomp". + */ + if (devfn == prev_devfn) + continue; + prev_devfn = devfn; + /* create a new pci_dev for this device */ dev = of_create_pci_dev(pbm, child, bus, devfn, 0); if (!dev) @@ -817,7 +833,7 @@ int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, { static u8 fake_pci_config[] = { 0x8e, 0x10, /* Vendor: 0x108e (Sun) */ - 0x00, 0x80, /* Device: 0x8000 (PBM) */ + 0xf0, 0x80, /* Device: 0x80f0 (Fire) */ 0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */ 0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */ 0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */ diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 4249214..2f61c4b 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -44,6 +44,67 @@ static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm, return (void *) (pbm->config_space | bus | devfn | reg); } +/* At least on Sabre, it is necessary to access all PCI host controller + * registers at their natural size, otherwise zeros are returned. + * Strange but true, and I see no language in the UltraSPARC-IIi + * programmer's manual that mentions this even indirectly. + */ +static int sun4u_read_pci_cfg_host(struct pci_pbm_info *pbm, + unsigned char bus, unsigned int devfn, + int where, int size, u32 *value) +{ + u32 tmp32, *addr; + u16 tmp16; + u8 tmp8; + + addr = sun4u_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + if (where < 8) { + unsigned long align = (unsigned long) addr; + + align &= ~1; + pci_config_read16((u16 *)align, &tmp16); + if (where & 1) + *value = tmp16 >> 8; + else + *value = tmp16 & 0xff; + } else { + pci_config_read8((u8 *)addr, &tmp8); + *value = (u32) tmp8; + } + break; + + case 2: + if (where < 8) { + pci_config_read16((u16 *)addr, &tmp16); + *value = (u32) tmp16; + } else { + pci_config_read8((u8 *)addr, &tmp8); + *value = (u32) tmp8; + pci_config_read8(((u8 *)addr) + 1, &tmp8); + *value |= ((u32) tmp8) << 8; + } + break; + + case 4: + tmp32 = 0xffffffff; + sun4u_read_pci_cfg_host(pbm, bus, devfn, + where, 2, &tmp32); + *value = tmp32; + + tmp32 = 0xffffffff; + sun4u_read_pci_cfg_host(pbm, bus, devfn, + where + 2, 2, &tmp32); + *value |= tmp32 << 16; + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, int where, int size, u32 *value) { @@ -53,10 +114,6 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, u16 tmp16; u8 tmp8; - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, - size, value); - switch (size) { case 1: *value = 0xff; @@ -69,6 +126,10 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, break; } + if (!bus_dev->number && !PCI_SLOT(devfn)) + return sun4u_read_pci_cfg_host(pbm, bus, devfn, where, + size, value); + addr = sun4u_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; @@ -101,6 +162,53 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, return PCIBIOS_SUCCESSFUL; } +static int sun4u_write_pci_cfg_host(struct pci_pbm_info *pbm, + unsigned char bus, unsigned int devfn, + int where, int size, u32 value) +{ + u32 *addr; + + addr = sun4u_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + if (where < 8) { + unsigned long align = (unsigned long) addr; + u16 tmp16; + + align &= ~1; + pci_config_read16((u16 *)align, &tmp16); + if (where & 1) { + tmp16 &= 0x00ff; + tmp16 |= value << 8; + } else { + tmp16 &= 0xff00; + tmp16 |= value; + } + pci_config_write16((u16 *)align, tmp16); + } else + pci_config_write8((u8 *)addr, value); + break; + case 2: + if (where < 8) { + pci_config_write16((u16 *)addr, value); + } else { + pci_config_write8((u8 *)addr, value & 0xff); + pci_config_write8(((u8 *)addr) + 1, value >> 8); + } + break; + case 4: + sun4u_write_pci_cfg_host(pbm, bus, devfn, + where, 2, value & 0xffff); + sun4u_write_pci_cfg_host(pbm, bus, devfn, + where + 2, 2, value >> 16); + break; + } + return PCIBIOS_SUCCESSFUL; +} + static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, int where, int size, u32 value) { @@ -108,9 +216,10 @@ static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned char bus = bus_dev->number; u32 *addr; - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, - size, value); + if (!bus_dev->number && !PCI_SLOT(devfn)) + return sun4u_write_pci_cfg_host(pbm, bus, devfn, where, + size, value); + addr = sun4u_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 00a9e32..a05b37f 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2134,12 +2134,20 @@ static void user_instruction_dump (unsigned int __user *pc) void show_stack(struct task_struct *tsk, unsigned long *_ksp) { unsigned long pc, fp, thread_base, ksp; - void *tp = task_stack_page(tsk); + struct thread_info *tp; struct reg_window *rw; int count = 0; ksp = (unsigned long) _ksp; - + if (!tsk) + tsk = current; + tp = task_thread_info(tsk); + if (ksp == 0UL) { + if (tsk == current) + asm("mov %%fp, %0" : "=r" (ksp)); + else + ksp = tp->ksp; + } if (tp == current_thread_info()) flushw_all(); @@ -2168,11 +2176,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) void dump_stack(void) { - unsigned long *ksp; - - __asm__ __volatile__("mov %%fp, %0" - : "=r" (ksp)); - show_stack(current, ksp); + show_stack(current, NULL); } EXPORT_SYMBOL(dump_stack); diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index b582024..e2cb991 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -112,15 +112,12 @@ static void __kprobes unhandled_fault(unsigned long address, static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) { - unsigned long *ksp; - printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", regs->tpc); printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]); print_symbol("RPC: <%s>\n", regs->u_regs[15]); printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr); - __asm__("mov %%sp, %0" : "=r" (ksp)); - show_stack(current, ksp); + dump_stack(); unhandled_fault(regs->tpc, current, regs); } diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 2e09f16..2c491a5 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -612,6 +612,8 @@ static int ubd_open_dev(struct ubd *ubd_dev) ubd_dev->fd = fd; if(ubd_dev->cow.file != NULL){ + blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long)); + err = -ENOMEM; ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); if(ubd_dev->cow.bitmap == NULL){ diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 3f33165..419b2d5 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -5,7 +5,8 @@ * so I *must* declare good prototypes for them and then EXPORT them. * The kernel code uses the macro defined by include/linux/string.h, * so I undef macros; the userspace code does not include that and I - * add an EXPORT for the glibc one.*/ + * add an EXPORT for the glibc one. + */ #undef strlen #undef strstr @@ -61,12 +62,18 @@ EXPORT_SYMBOL_PROTO(dup2); EXPORT_SYMBOL_PROTO(__xstat); EXPORT_SYMBOL_PROTO(__lxstat); EXPORT_SYMBOL_PROTO(__lxstat64); +EXPORT_SYMBOL_PROTO(__fxstat64); EXPORT_SYMBOL_PROTO(lseek); EXPORT_SYMBOL_PROTO(lseek64); EXPORT_SYMBOL_PROTO(chown); +EXPORT_SYMBOL_PROTO(fchown); EXPORT_SYMBOL_PROTO(truncate); +EXPORT_SYMBOL_PROTO(ftruncate64); EXPORT_SYMBOL_PROTO(utime); +EXPORT_SYMBOL_PROTO(utimes); +EXPORT_SYMBOL_PROTO(futimes); EXPORT_SYMBOL_PROTO(chmod); +EXPORT_SYMBOL_PROTO(fchmod); EXPORT_SYMBOL_PROTO(rename); EXPORT_SYMBOL_PROTO(__xmknod); @@ -102,14 +109,3 @@ EXPORT_SYMBOL(__stack_smash_handler); extern long __guard __attribute__((weak)); EXPORT_SYMBOL(__guard); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 29617ae..fdab077 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -57,8 +57,8 @@ cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) cflags-y += -maccumulate-outgoing-args # do binutils support CFI? -cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 47565c3..0bc623a 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -38,6 +38,18 @@ movq %rax,R8(%rsp) .endm + .macro LOAD_ARGS32 offset + movl \offset(%rsp),%r11d + movl \offset+8(%rsp),%r10d + movl \offset+16(%rsp),%r9d + movl \offset+24(%rsp),%r8d + movl \offset+40(%rsp),%ecx + movl \offset+48(%rsp),%edx + movl \offset+56(%rsp),%esi + movl \offset+64(%rsp),%edi + movl \offset+72(%rsp),%eax + .endm + .macro CFI_STARTPROC32 simple CFI_STARTPROC \simple CFI_UNDEFINED r8 @@ -152,7 +164,7 @@ sysenter_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST movl %ebp, %ebp /* no need to do an access_ok check here because rbp has been @@ -255,7 +267,7 @@ cstar_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST movl RSP-ARGOFFSET(%rsp), %r8d /* no need to do an access_ok check here because r8 has been @@ -333,7 +345,7 @@ ia32_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST jmp ia32_do_syscall END(ia32_syscall) diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index de1de8a..4d94c51 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary.o tce.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o -obj-$(CONFIG_SERIAL_8250) += legacy_serial.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o obj-$(CONFIG_X86_VSMP) += vsmp.o @@ -50,7 +49,6 @@ CFLAGS_vsyscall.o := $(PROFILING) -g0 therm_throt-y += ../../i386/kernel/cpu/mcheck/therm_throt.o bootflag-y += ../../i386/kernel/bootflag.o -legacy_serial-y += ../../i386/kernel/legacy_serial.o cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o topology-y += ../../i386/kernel/topology.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 1fab487..c63fc64 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -326,8 +326,7 @@ NEXT_PAGE(level2_kernel_pgt) /* 40MB kernel mapping. The kernel code cannot be bigger than that. When you change this change KERNEL_TEXT_SIZE in page.h too. */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ - PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, - KERNEL_TEXT_SIZE/PMD_SIZE) + PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, KERNEL_TEXT_SIZE/PMD_SIZE) /* Module mapping starts here */ .fill (PTRS_PER_PMD - (KERNEL_TEXT_SIZE/PMD_SIZE)),8,0 diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 9409117..8d89d8c 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -223,10 +223,6 @@ static int putreg(struct task_struct *child, { unsigned long tmp; - /* Some code in the 64bit emulation may not be 64bit clean. - Don't take any chances. */ - if (test_tsk_thread_flag(child, TIF_IA32)) - value &= 0xffffffff; switch (regno) { case offsetof(struct user_regs_struct,fs): if (value && (value & 3) != 3) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index baef5fc..a131d41 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -92,6 +92,8 @@ struct cfq_data { struct cfq_queue *active_queue; struct cfq_io_context *active_cic; + struct cfq_queue *async_cfqq[IOPRIO_BE_NR]; + struct timer_list idle_class_timer; sector_t last_position; @@ -1351,8 +1353,8 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc) } static struct cfq_queue * -cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk, - gfp_t gfp_mask) +cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, + struct task_struct *tsk, gfp_t gfp_mask) { struct cfq_queue *cfqq, *new_cfqq = NULL; struct cfq_io_context *cic; @@ -1405,12 +1407,35 @@ retry: if (new_cfqq) kmem_cache_free(cfq_pool, new_cfqq); - atomic_inc(&cfqq->ref); out: WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); return cfqq; } +static struct cfq_queue * +cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk, + gfp_t gfp_mask) +{ + const int ioprio = task_ioprio(tsk); + struct cfq_queue *cfqq = NULL; + + if (!is_sync) + cfqq = cfqd->async_cfqq[ioprio]; + if (!cfqq) + cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask); + + /* + * pin the queue now that it's allocated, scheduler exit will prune it + */ + if (!is_sync && !cfqd->async_cfqq[ioprio]) { + atomic_inc(&cfqq->ref); + cfqd->async_cfqq[ioprio] = cfqq; + } + + atomic_inc(&cfqq->ref); + return cfqq; +} + /* * We drop cfq io contexts lazily, so we may find a dead one. */ @@ -2019,6 +2044,7 @@ static void cfq_exit_queue(elevator_t *e) { struct cfq_data *cfqd = e->elevator_data; request_queue_t *q = cfqd->queue; + int i; cfq_shutdown_timer_wq(cfqd); @@ -2035,6 +2061,13 @@ static void cfq_exit_queue(elevator_t *e) __cfq_exit_single_io_context(cfqd, cic); } + /* + * Put the async queues + */ + for (i = 0; i < IOPRIO_BE_NR; i++) + if (cfqd->async_cfqq[i]) + cfq_put_queue(cfqd->async_cfqq[i]); + spin_unlock_irq(q->queue_lock); cfq_shutdown_timer_wq(cfqd); diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index c99b463..4369ff2 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1081,12 +1081,6 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) */ return; - if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { - printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", - __FUNCTION__, tag); - return; - } - list_del_init(&rq->queuelist); rq->cmd_flags &= ~REQ_QUEUED; rq->tag = -1; @@ -1096,6 +1090,13 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) __FUNCTION__, tag); bqt->tag_index[tag] = NULL; + + if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) { + printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", + __FUNCTION__, tag); + return; + } + bqt->busy--; } diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 8edf40c..cce9236 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -59,11 +59,13 @@ static inline void blkcipher_unmap_dst(struct blkcipher_walk *walk) scatterwalk_unmap(walk->dst.virt.addr, 1); } +/* Get a spot of the specified length that does not straddle a page. + * The caller needs to ensure that there is enough space for this operation. + */ static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len) { - if (offset_in_page(start + len) < len) - return (u8 *)((unsigned long)(start + len) & PAGE_MASK); - return start; + u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK); + return start > end_page ? start : end_page; } static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm, @@ -155,7 +157,8 @@ static inline int blkcipher_next_slow(struct blkcipher_desc *desc, if (walk->buffer) goto ok; - n = bsize * 2 + (alignmask & ~(crypto_tfm_ctx_alignment() - 1)); + n = bsize * 3 - (alignmask + 1) + + (alignmask & ~(crypto_tfm_ctx_alignment() - 1)); walk->buffer = kmalloc(n, GFP_ATOMIC); if (!walk->buffer) return blkcipher_walk_done(desc, walk, -ENOMEM); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4546bf8..9bc340b 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -716,6 +716,7 @@ static int dock_add(acpi_handle handle) if (ret) { printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret); kfree(dock_station); + dock_station = NULL; return ret; } ret = device_create_file(&dock_device.dev, &dev_attr_docked); @@ -723,6 +724,7 @@ static int dock_add(acpi_handle handle) printk("Error %d adding sysfs file\n", ret); platform_device_unregister(&dock_device); kfree(dock_station); + dock_station = NULL; return ret; } ret = device_create_file(&dock_device.dev, &dev_attr_undock); @@ -731,6 +733,7 @@ static int dock_add(acpi_handle handle) device_remove_file(&dock_device.dev, &dev_attr_docked); platform_device_unregister(&dock_device); kfree(dock_station); + dock_station = NULL; return ret; } ret = device_create_file(&dock_device.dev, &dev_attr_uid); @@ -738,6 +741,7 @@ static int dock_add(acpi_handle handle) printk("Error %d adding sysfs file\n", ret); platform_device_unregister(&dock_device); kfree(dock_station); + dock_station = NULL; return ret; } @@ -750,6 +754,7 @@ static int dock_add(acpi_handle handle) dd = alloc_dock_dependent_device(handle); if (!dd) { kfree(dock_station); + dock_station = NULL; ret = -ENOMEM; goto dock_add_err_unregister; } @@ -777,6 +782,7 @@ dock_add_err_unregister: device_remove_file(&dock_device.dev, &dev_attr_undock); platform_device_unregister(&dock_device); kfree(dock_station); + dock_station = NULL; return ret; } @@ -810,6 +816,7 @@ static int dock_remove(void) /* free dock station memory */ kfree(dock_station); + dock_station = NULL; return 0; } diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 902c287..361ebe6 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -586,6 +586,10 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); if (gpe_xrupt->previous) { gpe_xrupt->previous->next = gpe_xrupt->next; + } else { + /* No previous, update list head */ + + acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next; } if (gpe_xrupt->next) { diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 1285e91..002bb33 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -211,14 +211,17 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. * Performs validation on some important FADT fields. * + * NOTE: We create a local copy of the FADT regardless of the version. + * ******************************************************************************/ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) { /* - * Check if the FADT is larger than what we know about (ACPI 2.0 version). - * Truncate the table, but make some noise. + * Check if the FADT is larger than the largest table that we expect + * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue + * a warning. */ if (length > sizeof(struct acpi_table_fadt)) { ACPI_WARNING((AE_INFO, @@ -227,10 +230,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) sizeof(struct acpi_table_fadt))); } - /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ + /* Clear the entire local FADT */ ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); + /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ + ACPI_MEMCPY(&acpi_gbl_FADT, table, ACPI_MIN(length, sizeof(struct acpi_table_fadt))); @@ -251,7 +256,7 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) * RETURN: None * * DESCRIPTION: Converts all versions of the FADT to a common internal format. - * -> Expand all 32-bit addresses to 64-bit. + * Expand all 32-bit addresses to 64-bit. * * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), * and must contain a copy of the actual FADT. @@ -292,8 +297,23 @@ static void acpi_tb_convert_fadt(void) } /* - * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address - * structures as necessary. + * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which + * should be zero are indeed zero. This will workaround BIOSs that + * inadvertently place values in these fields. + * + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at + * offset 45, 55, 95, and the word located at offset 109, 110. + */ + if (acpi_gbl_FADT.header.revision < 3) { + acpi_gbl_FADT.preferred_profile = 0; + acpi_gbl_FADT.pstate_control = 0; + acpi_gbl_FADT.cst_control = 0; + acpi_gbl_FADT.boot_flags = 0; + } + + /* + * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X" + * generic address structures as necessary. */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { target = @@ -349,18 +369,6 @@ static void acpi_tb_convert_fadt(void) acpi_gbl_FADT.xpm1a_event_block.space_id; } - - /* - * For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero) - * are indeed zero. This will workaround BIOSs that inadvertently placed - * values in these fields. - */ - if (acpi_gbl_FADT.header.revision < 3) { - acpi_gbl_FADT.preferred_profile = 0; - acpi_gbl_FADT.pstate_control = 0; - acpi_gbl_FADT.cst_control = 0; - acpi_gbl_FADT.boot_flags = 0; - } } /****************************************************************************** diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 1da64b4..8cc9492 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -51,6 +51,65 @@ ACPI_MODULE_NAME("tbutils") static acpi_physical_address acpi_tb_get_root_table_entry(u8 * table_entry, acpi_native_uint table_entry_size); +/******************************************************************************* + * + * FUNCTION: acpi_tb_check_xsdt + * + * PARAMETERS: address - Pointer to the XSDT + * + * RETURN: status + * AE_OK - XSDT is okay + * AE_NO_MEMORY - can't map XSDT + * AE_INVALID_TABLE_LENGTH - invalid table length + * AE_NULL_ENTRY - XSDT has NULL entry + * + * DESCRIPTION: validate XSDT +******************************************************************************/ + +static acpi_status +acpi_tb_check_xsdt(acpi_physical_address address) +{ + struct acpi_table_header *table; + u32 length; + u64 xsdt_entry_address; + u8 *table_entry; + u32 table_count; + int i; + + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) + return AE_NO_MEMORY; + + length = table->length; + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + if (length < sizeof(struct acpi_table_header)) + return AE_INVALID_TABLE_LENGTH; + + table = acpi_os_map_memory(address, length); + if (!table) + return AE_NO_MEMORY; + + /* Calculate the number of tables described in XSDT */ + table_count = + (u32) ((table->length - + sizeof(struct acpi_table_header)) / sizeof(u64)); + table_entry = + ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); + for (i = 0; i < table_count; i++) { + ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry); + if (!xsdt_entry_address) { + /* XSDT has NULL entry */ + break; + } + table_entry += sizeof(u64); + } + acpi_os_unmap_memory(table, length); + + if (i < table_count) + return AE_NULL_ENTRY; + else + return AE_OK; +} /******************************************************************************* * @@ -341,6 +400,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) u32 table_count; struct acpi_table_header *table; acpi_physical_address address; + acpi_physical_address rsdt_address; u32 length; u8 *table_entry; acpi_status status; @@ -369,6 +429,8 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) */ address = (acpi_physical_address) rsdp->xsdt_physical_address; table_entry_size = sizeof(u64); + rsdt_address = (acpi_physical_address) + rsdp->rsdt_physical_address; } else { /* Root table is an RSDT (32-bit physical addresses) */ @@ -382,6 +444,15 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) */ acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); + if (table_entry_size == sizeof(u64)) { + if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) { + /* XSDT has NULL entry, RSDT is used */ + address = rsdt_address; + table_entry_size = sizeof(u32); + ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry," + "using RSDT")); + } + } /* Map the RSDT/XSDT table header to get the full table length */ table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ca5229d..3400b3e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -399,7 +399,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ - { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700 */ + { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700 IDE */ + { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700 AHCI */ + { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700 nraid5 */ + { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700 raid5 */ /* VIA */ { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 9c07b88..5a148bd 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -200,6 +200,8 @@ static const struct pci_device_id piix_pci_tbl[] = { /* ICH7/7-R (i945, i975) UDMA 100*/ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, + /* ICH8 Mobile PATA Controller */ + { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* NOTE: The following PCI ids must be kept in sync with the * list in drivers/pci/quirks.c. @@ -426,7 +428,7 @@ static const struct piix_map_db ich8_map_db = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ { RV, RV, RV, RV }, - { IDE, IDE, NA, NA }, /* 10b (IDE mode) */ + { P0, P2, IDE, IDE }, /* 10b (IDE mode) */ { RV, RV, RV, RV }, }, }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 981b397..9ad8caf 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3800,6 +3800,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, }, { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, }, { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, + { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, }, /* Devices with NCQ limits */ diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index fa1c22c..13c1486 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -211,6 +211,8 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->hob_lbal = ioread8(ioaddr->lbal_addr); tf->hob_lbam = ioread8(ioaddr->lbam_addr); tf->hob_lbah = ioread8(ioaddr->lbah_addr); + iowrite8(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; } } diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 8449146..eceea6c 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -285,6 +285,7 @@ static const struct pci_device_id atiixp[] = { { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), }, + { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), }, { }, }; diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 61502bc..63f6e2c 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -352,6 +352,8 @@ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf) tf->hob_lbal = in_be32(ioaddr->lbal_addr); tf->hob_lbam = in_be32(ioaddr->lbam_addr); tf->hob_lbah = in_be32(ioaddr->lbah_addr); + out_be32(ioaddr->ctl_addr, tf->ctl); + ap->last_ctl = tf->ctl; } } diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index fe7ef33..4054507 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -53,7 +53,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, ret = count; return ret; } -static SYSDEV_ATTR(online, 0600, show_online, store_online); +static SYSDEV_ATTR(online, 0644, show_online, store_online); static void __devinit register_cpu_control(struct cpu *cpu) { diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 92bf868..84d6aa5 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -17,8 +17,8 @@ */ -#define DAC960_DriverVersion "2.5.48" -#define DAC960_DriverDate "14 May 2006" +#define DAC960_DriverVersion "2.5.49" +#define DAC960_DriverDate "21 Aug 2007" #include @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1165,9 +1166,9 @@ static bool DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T int i; - if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask)) + if (pci_set_dma_mask(Controller->PCIDevice, DMA_32BIT_MASK)) return DAC960_Failure(Controller, "DMA mask out of range"); - Controller->BounceBufferLimit = DAC690_V1_PciDmaMask; + Controller->BounceBufferLimit = DMA_32BIT_MASK; if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) { CommandMailboxesSize = 0; @@ -1368,9 +1369,12 @@ static bool DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T dma_addr_t CommandMailboxDMA; DAC960_V2_CommandStatus_T CommandStatus; - if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask)) - return DAC960_Failure(Controller, "DMA mask out of range"); - Controller->BounceBufferLimit = DAC690_V2_PciDmaMask; + if (!pci_set_dma_mask(Controller->PCIDevice, DMA_64BIT_MASK)) + Controller->BounceBufferLimit = DMA_64BIT_MASK; + else if (!pci_set_dma_mask(Controller->PCIDevice, DMA_32BIT_MASK)) + Controller->BounceBufferLimit = DMA_32BIT_MASK; + else + return DAC960_Failure(Controller, "DMA mask out of range"); /* This is a temporary dma mapping, used only in the scope of this function */ CommandMailbox = pci_alloc_consistent(PCI_Device, diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index f5e2436..85fa9bb 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -61,13 +61,6 @@ #define DAC960_V2_MaxPhysicalDevices 272 /* - Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers - */ - -#define DAC690_V1_PciDmaMask 0xffffffff -#define DAC690_V2_PciDmaMask 0xffffffffffffffffULL - -/* Define a 32/64 bit I/O Address data type. */ diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index ea52740..786c0d9 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -184,6 +184,8 @@ static int i915_initialize(drm_device_t * dev, * private backbuffer/depthbuffer usage. */ dev_priv->use_mi_batchbuffer_start = 0; + if (IS_I965G(dev)) /* 965 doesn't support older method */ + dev_priv->use_mi_batchbuffer_start = 1; /* Allow hardware batchbuffers unless told otherwise. */ @@ -517,8 +519,13 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, if (dev_priv->use_mi_batchbuffer_start) { BEGIN_LP_RING(2); - OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); - OUT_RING(batch->start | MI_BATCH_NON_SECURE); + if (IS_I965G(dev)) { + OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); + OUT_RING(batch->start); + } else { + OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); + OUT_RING(batch->start | MI_BATCH_NON_SECURE); + } ADVANCE_LP_RING(); } else { BEGIN_LP_RING(4); @@ -735,7 +742,8 @@ static int i915_setparam(DRM_IOCTL_ARGS) switch (param.param) { case I915_SETPARAM_USE_MI_BATCHBUFFER_START: - dev_priv->use_mi_batchbuffer_start = param.value; + if (!IS_I965G(dev)) + dev_priv->use_mi_batchbuffer_start = param.value; break; case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: dev_priv->tex_lru_log_granularity = param.value; diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 85e323a..44a0717 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -282,6 +282,7 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define MI_BATCH_BUFFER_START (0x31<<23) #define MI_BATCH_BUFFER_END (0xA<<23) #define MI_BATCH_NON_SECURE (1) +#define MI_BATCH_NON_SECURE_I965 (1<<8) #define MI_WAIT_FOR_EVENT ((0x3<<23)) #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) diff --git a/drivers/char/random.c b/drivers/char/random.c index 7f52712..397c714 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -693,9 +693,14 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { - int bytes = max_t(int, random_read_wakeup_thresh / 8, - min_t(int, nbytes, sizeof(tmp))); + /* If we're limited, always leave two wakeup worth's BITS */ int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4; + int bytes = nbytes; + + /* pull at least as many as BYTES as wakeup BITS */ + bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); + /* but never more than the buffer size */ + bytes = min_t(int, bytes, sizeof(tmp)); DEBUG_ENT("going to reseed %s with %d bits " "(%d of %d requested)\n", diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 1da92a6..85a2328 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -2721,9 +2721,9 @@ static void __devexit sx_pci_remove(struct pci_dev *pdev) its because the standard requires it. So check for SUBVENDOR_ID. */ static struct pci_device_id sx_pci_tbl[] = { { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, - .subvendor = 0x0200,.subdevice = PCI_ANY_ID }, + .subvendor = PCI_ANY_ID, .subdevice = 0x0200 }, { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, - .subvendor = 0x0300,.subdevice = PCI_ANY_ID }, + .subvendor = PCI_ANY_ID, .subdevice = 0x0300 }, { 0 } }; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 8532bb7..e794527 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -96,15 +96,25 @@ static struct dbs_tuners { static inline cputime64_t get_cpu_idle_time(unsigned int cpu) { - cputime64_t retval; + cputime64_t idle_time; + cputime64_t cur_jiffies; + cputime64_t busy_time; - retval = cputime64_add(kstat_cpu(cpu).cpustat.idle, - kstat_cpu(cpu).cpustat.iowait); + cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); + busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user, + kstat_cpu(cpu).cpustat.system); - if (dbs_tuners_ins.ignore_nice) - retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice); + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.irq); + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.softirq); + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.steal); - return retval; + if (!dbs_tuners_ins.ignore_nice) { + busy_time = cputime64_add(busy_time, + kstat_cpu(cpu).cpustat.nice); + } + + idle_time = cputime64_sub(cur_jiffies, busy_time); + return idle_time; } /* @@ -325,7 +335,7 @@ static struct attribute_group dbs_attr_group = { static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) { unsigned int idle_ticks, total_ticks; - unsigned int load; + unsigned int load = 0; cputime64_t cur_jiffies; struct cpufreq_policy *policy; @@ -339,7 +349,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); total_ticks = (unsigned int) cputime64_sub(cur_jiffies, this_dbs_info->prev_cpu_wall); - this_dbs_info->prev_cpu_wall = cur_jiffies; + this_dbs_info->prev_cpu_wall = get_jiffies_64(); + if (!total_ticks) return; /* @@ -370,7 +381,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) if (tmp_idle_ticks < idle_ticks) idle_ticks = tmp_idle_ticks; } - load = (100 * (total_ticks - idle_ticks)) / total_ticks; + if (likely(total_ticks > idle_ticks)) + load = (100 * (total_ticks - idle_ticks)) / total_ticks; /* Check for frequency increase */ if (load > dbs_tuners_ins.up_threshold) { diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 96c8ac5..f1cd9d3 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -586,7 +586,7 @@ static void context_stop(struct context *ctx) break; fw_notify("context_stop: still active (0x%08x)\n", reg); - msleep(1); + mdelay(1); } } @@ -1934,14 +1934,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state) free_irq(pdev->irq, ohci); err = pci_save_state(pdev); if (err) { - fw_error("pci_save_state failed with %d", err); + fw_error("pci_save_state failed with %d\n", err); return err; } err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); - if (err) { - fw_error("pci_set_power_state failed with %d", err); - return err; - } + if (err) + fw_error("pci_set_power_state failed with %d\n", err); return 0; } @@ -1955,7 +1953,7 @@ static int pci_resume(struct pci_dev *pdev) pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) { - fw_error("pci_enable_device failed with %d", err); + fw_error("pci_enable_device failed with %d\n", err); return err; } diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index a98d391..a68f7de 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -985,6 +985,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) struct fw_unit *unit = sd->unit; struct fw_device *device = fw_device(unit->device.parent); struct sbp2_command_orb *orb; + unsigned max_payload; /* * Bidirectional commands are not yet implemented, and unknown @@ -1023,8 +1024,10 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) * specifies the max payload size as 2 ^ (max_payload + 2), so * if we set this to max_speed + 7, we get the right value. */ + max_payload = device->node->max_speed + 7; + max_payload = min(max_payload, device->card->max_receive - 1); orb->request.misc = - COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) | + COMMAND_ORB_MAX_PAYLOAD(max_payload) | COMMAND_ORB_SPEED(device->node->max_speed) | COMMAND_ORB_NOTIFY; diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 80d0121..a506a1f 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -605,8 +605,10 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) * check is sufficient to ensure we don't send response to * broadcast packets or posted writes. */ - if (request->ack != ACK_PENDING) + if (request->ack != ACK_PENDING) { + kfree(request); return; + } if (rcode == RCODE_COMPLETE) fw_fill_response(&request->response, request->request_header, diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index acdc3be..e2b9ca4 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -124,6 +124,10 @@ typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, size_t length, void *callback_data); +/* + * Important note: The callback must guarantee that either fw_send_response() + * or kfree() is called on the @request. + */ typedef void (*fw_address_callback_t)(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, @@ -228,7 +232,7 @@ struct fw_card { unsigned long reset_jiffies; unsigned long long guid; - int max_receive; + unsigned max_receive; int link_speed; int config_rom_generation; diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 9fb572f..3507113 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -882,7 +882,7 @@ static int __init lm78_isa_device_add(unsigned short address) { struct resource res = { .start = address, - .end = address + LM78_EXTENT, + .end = address + LM78_EXTENT - 1, .name = "lm78", .flags = IORESOURCE_IO, }; diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 1e21c8c..c3e716e 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -585,6 +585,8 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev) if ((err = device_create_file(dev, &dev_attr_alarms))) goto error_remove_files; + if ((err = device_create_file(dev, &dev_attr_name))) + goto error_remove_files; data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index f85b48f..dcc941a 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -740,9 +740,9 @@ store_sensor(struct device *dev, struct device_attribute *da, static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_sensor, store_sensor, 0); static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, - show_sensor, store_sensor, 0); + show_sensor, store_sensor, 1); static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, - show_sensor, store_sensor, 0); + show_sensor, store_sensor, 2); /* I2C devices get this name attribute automatically, but for ISA devices we must create it by ourselves. */ @@ -1746,7 +1746,7 @@ w83781d_isa_device_add(unsigned short address) { struct resource res = { .start = address, - .end = address + W83781D_EXTENT, + .end = address + W83781D_EXTENT - 1, .name = "w83781d", .flags = IORESOURCE_IO, }; diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 8f71b6a..ac07a05 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -1279,7 +1279,7 @@ static void __exit ieee1394_cleanup(void) unregister_chrdev_region(IEEE1394_CORE_DEV, 256); } -fs_initcall(ieee1394_init); /* same as ohci1394 */ +module_init(ieee1394_init); module_exit(ieee1394_cleanup); /* Exported symbols */ diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 5dadfd2..e65760f 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3773,7 +3773,5 @@ static int __init ohci1394_init(void) return pci_register_driver(&ohci1394_pci_driver); } -/* Register before most other device drivers. - * Useful for remote debugging via physical DMA, e.g. using firescope. */ -fs_initcall(ohci1394_init); +module_init(ohci1394_init); module_exit(ohci1394_cleanup); diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 3f873cc..c7ff28a 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -774,11 +774,6 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) SBP2_ERR("failed to register lower 4GB address range"); goto failed_alloc; } -#else - if (dma_set_mask(hi->host->device.parent, DMA_32BIT_MASK)) { - SBP2_ERR("failed to set 4GB DMA mask"); - goto failed_alloc; - } #endif } diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 1740cad..91109b4 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -109,7 +109,7 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) { struct lifebook_data *priv = psmouse->private; struct input_dev *dev1 = psmouse->dev; - struct input_dev *dev2 = priv->dev2; + struct input_dev *dev2 = priv ? priv->dev2 : NULL; unsigned char *packet = psmouse->packet; int relative_packet = packet[0] & 0x08; diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index fa17d6d..aee952f 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -1727,6 +1727,12 @@ static void svm_inject_page_fault(struct kvm_vcpu *vcpu, static int is_disabled(void) { + u64 vm_cr; + + rdmsrl(MSR_VM_CR, vm_cr); + if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE)) + return 1; + return 0; } diff --git a/drivers/kvm/svm.h b/drivers/kvm/svm.h index 5e93814..3b1b0f3 100644 --- a/drivers/kvm/svm.h +++ b/drivers/kvm/svm.h @@ -175,8 +175,11 @@ struct __attribute__ ((__packed__)) vmcb { #define SVM_CPUID_FUNC 0x8000000a #define MSR_EFER_SVME_MASK (1ULL << 12) +#define MSR_VM_CR 0xc0010114 #define MSR_VM_HSAVE_PA 0xc0010117ULL +#define SVM_VM_CR_SVM_DISABLE 4 + #define SVM_SELECTOR_S_SHIFT 4 #define SVM_SELECTOR_DPL_SHIFT 5 #define SVM_SELECTOR_P_SHIFT 7 diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 7b0fcfc..45e1c31 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -920,6 +920,8 @@ static void crypt_dtr(struct dm_target *ti) { struct crypt_config *cc = (struct crypt_config *) ti->private; + flush_workqueue(_kcryptd_workqueue); + bioset_free(cc->bs); mempool_destroy(cc->page_pool); mempool_destroy(cc->io_pool); @@ -941,9 +943,6 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, struct crypt_config *cc = ti->private; struct crypt_io *io; - if (bio_barrier(bio)) - return -EOPNOTSUPP; - io = mempool_alloc(cc->io_pool, GFP_NOIO); io->target = ti; io->base_bio = bio; diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 07e0a0c..4264f69 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -457,11 +457,6 @@ static int persistent_read_metadata(struct exception_store *store) /* * Sanity checks. */ - if (!ps->valid) { - DMWARN("snapshot is marked invalid"); - return -EINVAL; - } - if (ps->version != SNAPSHOT_DISK_VERSION) { DMWARN("unable to handle snapshot disk version %d", ps->version); @@ -469,6 +464,12 @@ static int persistent_read_metadata(struct exception_store *store) } /* + * Metadata are valid, but snapshot is invalidated + */ + if (!ps->valid) + return 1; + + /* * Read the metadata. */ r = read_exceptions(ps); diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 352c6fb..f3a7724 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -293,7 +293,10 @@ static void do_region(int rw, unsigned int region, struct io_region *where, * bvec for bio_get/set_region() and decrement bi_max_vecs * to hide it from bio_add_page(). */ - num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; + num_bvecs = dm_sector_div_up(remaining, + (PAGE_SIZE >> SECTOR_SHIFT)); + num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev), + num_bvecs); bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index de54b39..bfb2ea3 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -798,9 +798,6 @@ static int multipath_map(struct dm_target *ti, struct bio *bio, struct mpath_io *mpio; struct multipath *m = (struct multipath *) ti->private; - if (bio_barrier(bio)) - return -EOPNOTSUPP; - mpio = mempool_alloc(m->mpio_pool, GFP_NOIO); dm_bio_record(&mpio->details, bio); diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ef124b7..7113af3 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1288,12 +1288,12 @@ static int mirror_status(struct dm_target *ti, status_type_t type, for (m = 0; m < ms->nr_mirrors; m++) DMEMIT("%s ", ms->mirror[m].dev->name); - DMEMIT("%llu/%llu", + DMEMIT("%llu/%llu 0 ", (unsigned long long)ms->rh.log->type-> get_sync_count(ms->rh.log), (unsigned long long)ms->nr_regions); - sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); + sz += ms->rh.log->type->status(ms->rh.log, type, result+sz, maxlen-sz); break; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 0821a2b..3955621 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -522,9 +522,12 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) /* Metadata must only be loaded into one table at once */ r = s->store.read_metadata(&s->store); - if (r) { + if (r < 0) { ti->error = "Failed to read snapshot metadata"; goto bad6; + } else if (r > 0) { + s->valid = 0; + DMWARN("Snapshot is marked invalid."); } bio_list_init(&s->queued_bios); @@ -884,9 +887,6 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, if (!s->valid) return -EIO; - if (unlikely(bio_barrier(bio))) - return -EOPNOTSUPP; - /* FIXME: should only take write lock if we need * to copy an exception */ down_write(&s->lock); @@ -1157,9 +1157,6 @@ static int origin_map(struct dm_target *ti, struct bio *bio, struct dm_dev *dev = (struct dm_dev *) ti->private; bio->bi_bdev = dev->bdev; - if (unlikely(bio_barrier(bio))) - return -EOPNOTSUPP; - /* Only tell snapshots if this is a write */ return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 2717a35..75bd2fd 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -802,6 +802,15 @@ static int dm_request(request_queue_t *q, struct bio *bio) int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; + /* + * There is no use in forwarding any barrier request since we can't + * guarantee it is (or can be) handled by the targets correctly. + */ + if (unlikely(bio_barrier(bio))) { + bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + return 0; + } + down_read(&md->io_lock); disk_stat_inc(dm_disk(md), ios[rw]); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9eb66c1..e0029ea 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -917,6 +917,13 @@ static int make_request(request_queue_t *q, struct bio * bio) bio_list_add(&bl, mbio); } + if (unlikely(!atomic_read(&r10_bio->remaining))) { + /* the array is dead */ + md_write_end(mddev); + raid_end_bio_io(r10_bio); + return 0; + } + bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0); spin_lock_irqsave(&conf->device_lock, flags); bio_list_merge(&conf->pending_bio_list, &bl); @@ -1558,7 +1565,6 @@ static void raid10d(mddev_t *mddev) bio = r10_bio->devs[r10_bio->read_slot].bio; r10_bio->devs[r10_bio->read_slot].bio = mddev->ro ? IO_BLOCKED : NULL; - bio_put(bio); mirror = read_balance(conf, r10_bio); if (mirror == -1) { printk(KERN_ALERT "raid10: %s: unrecoverable I/O" @@ -1566,8 +1572,10 @@ static void raid10d(mddev_t *mddev) bdevname(bio->bi_bdev,b), (unsigned long long)r10_bio->sector); raid_end_bio_io(r10_bio); + bio_put(bio); } else { const int do_sync = bio_sync(r10_bio->master_bio); + bio_put(bio); rdev = conf->mirrors[mirror].rdev; if (printk_ratelimit()) printk(KERN_ERR "raid10: %s: redirecting sector %llu to" diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 02a0ea6..6bf858a 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -135,6 +135,13 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs struct flexcop_device *fc = i2c_get_adapdata(i2c_adap); int i, ret = 0; + /* Some drivers use 1 byte or 0 byte reads as probes, which this + * driver doesn't support. These probes will always fail, so this + * hack makes them always succeed. If one knew how, it would of + * course be better to actually do the read. */ + if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1) + return 1; + if (mutex_lock_interruptible(&fc->i2c_mutex)) return -ERESTARTSYS; diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 543b05e..c36e2b7 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -580,7 +580,7 @@ struct cx8802_dev * cx8802_get_device(struct inode *inode) list_for_each(list,&cx8802_devlist) { h = list_entry(list, struct cx8802_dev, devlist); - if (h->mpeg_dev->minor == minor) + if (h->mpeg_dev && h->mpeg_dev->minor == minor) return h; } diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index efc6635..5d9de5d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -622,6 +622,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ + mutex_init(&itv->serialize_lock); mutex_init(&itv->i2c_bus_lock); mutex_init(&itv->udma.lock); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index e6e56f1..65ebdda 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -650,7 +650,6 @@ struct vbi_info { /* convenience pointer to sliced struct in vbi_in union */ struct v4l2_sliced_vbi_format *sliced_in; u32 service_set_in; - u32 service_set_out; int insert_mpeg; /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. @@ -723,6 +722,7 @@ struct ivtv { int search_pack_header; spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ + struct mutex serialize_lock; /* lock used to serialize starting streams */ /* User based DMA for OSD */ struct ivtv_user_dma udma; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 57af176..dcfbaa9 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1183,6 +1183,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; + ivtv_set_osd_alpha(itv); break; } diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index ba98bf0..e83b496 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -403,6 +403,11 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) /* Mark last buffer size for Interrupt flag */ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); + if (s->type == IVTV_ENC_STREAM_TYPE_VBI) + set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + else + clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + if (ivtv_use_pio(s)) { for (i = 0; i < s->SG_length; i++) { s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src); @@ -597,7 +602,6 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) data[0], data[1], data[2]); return; } - clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); s = &itv->streams[ivtv_stream_map[data[0]]]; if (!stream_enc_dma_append(s, data)) { set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); @@ -634,7 +638,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) then start a DMA request for just the VBI data. */ if (!stream_enc_dma_append(s, data) && !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { - set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 6af88ae..d538efa 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -446,6 +446,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) if (s->v4l2dev == NULL) return -EINVAL; + /* Big serialization lock to ensure no two streams are started + simultaneously: that can give all sorts of weird results. */ + mutex_lock(&itv->serialize_lock); IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); switch (s->type) { @@ -487,6 +490,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) 0, sizeof(itv->vbi.sliced_mpeg_size)); break; default: + mutex_unlock(&itv->serialize_lock); return -EINVAL; } s->subtype = subtype; @@ -568,6 +572,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) { IVTV_DEBUG_WARN( "Error starting capture!\n"); + mutex_unlock(&itv->serialize_lock); return -EINVAL; } @@ -583,6 +588,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) /* you're live! sit back and await interrupts :) */ atomic_inc(&itv->capturing); + mutex_unlock(&itv->serialize_lock); return 0; } @@ -762,17 +768,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); - /* only run these if we're shutting down the last cap */ - if (atomic_read(&itv->capturing) - 1 == 0) { - /* event notification (off) */ - if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { - /* type: 0 = refresh */ - /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ - ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); - ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); - } - } - then = jiffies; if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { @@ -840,17 +835,30 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) /* Clear capture and no-read bits */ clear_bit(IVTV_F_S_STREAMING, &s->s_flags); + /* ensure these global cleanup actions are done only once */ + mutex_lock(&itv->serialize_lock); + if (s->type == IVTV_ENC_STREAM_TYPE_VBI) ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); if (atomic_read(&itv->capturing) > 0) { + mutex_unlock(&itv->serialize_lock); return 0; } /* Set the following Interrupt mask bits for capture */ ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); + /* event notification (off) */ + if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { + /* type: 0 = refresh */ + /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ + ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); + ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); + } + wake_up(&s->waitq); + mutex_unlock(&itv->serialize_lock); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 3ba46e0..a7282a9 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -219,31 +219,23 @@ ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) int found_cc = 0; int cc_pos = itv->vbi.cc_pos; - if (itv->vbi.service_set_out == 0) - return -EPERM; - while (count >= sizeof(struct v4l2_sliced_vbi_data)) { switch (p->id) { case V4L2_SLICED_CAPTION_525: - if (p->id == V4L2_SLICED_CAPTION_525 && - p->line == 21 && - (itv->vbi.service_set_out & - V4L2_SLICED_CAPTION_525) == 0) { - break; - } - found_cc = 1; - if (p->field) { - cc[2] = p->data[0]; - cc[3] = p->data[1]; - } else { - cc[0] = p->data[0]; - cc[1] = p->data[1]; + if (p->line == 21) { + found_cc = 1; + if (p->field) { + cc[2] = p->data[0]; + cc[3] = p->data[1]; + } else { + cc[0] = p->data[0]; + cc[1] = p->data[1]; + } } break; case V4L2_SLICED_VPS: - if (p->line == 16 && p->field == 0 && - (itv->vbi.service_set_out & V4L2_SLICED_VPS)) { + if (p->line == 16 && p->field == 0) { itv->vbi.vps[0] = p->data[2]; itv->vbi.vps[1] = p->data[8]; itv->vbi.vps[2] = p->data[9]; @@ -255,8 +247,7 @@ ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) break; case V4L2_SLICED_WSS_625: - if (p->line == 23 && p->field == 0 && - (itv->vbi.service_set_out & V4L2_SLICED_WSS_625)) { + if (p->line == 23 && p->field == 0) { /* No lock needed for WSS */ itv->vbi.wss = p->data[0] | (p->data[1] << 8); itv->vbi.wss_found = 1; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 085332a..5227978 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file) return 0; } + +static void pwc_cleanup(struct pwc_device *pdev) +{ + pwc_remove_sysfs_files(pdev->vdev); + video_unregister_device(pdev->vdev); +} + /* Note that all cleanup is done in the reverse order as in _open */ static int pwc_video_close(struct inode *inode, struct file *file) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; - int i; + int i, hint; PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); @@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file) pwc_isoc_cleanup(pdev); pwc_free_buffers(pdev); + lock_kernel(); /* Turn off LEDS and power down camera, but only when not unplugged */ - if (pdev->error_status != EPIPE) { + if (!pdev->unplugged) { /* Turn LEDs off */ if (pwc_set_leds(pdev, 0, 0) < 0) PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); @@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file) if (i < 0) PWC_ERROR("Failed to power down camera (%d)\n", i); } + pdev->vopen--; + PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); + } else { + pwc_cleanup(pdev); + /* Free memory (don't set pdev to 0 just yet) */ + kfree(pdev); + /* search device_hint[] table if we occupy a slot, by any chance */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) + if (device_hint[hint].pdev == pdev) + device_hint[hint].pdev = NULL; } - pdev->vopen--; - PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); + unlock_kernel(); + return 0; } @@ -1791,21 +1809,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf) /* Alert waiting processes */ wake_up_interruptible(&pdev->frameq); /* Wait until device is closed */ - while (pdev->vopen) - schedule(); - /* Device is now closed, so we can safely unregister it */ - PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); - pwc_remove_sysfs_files(pdev->vdev); - video_unregister_device(pdev->vdev); - - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); + if(pdev->vopen) { + pdev->unplugged = 1; + } else { + /* Device is closed, so we can safely unregister it */ + PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); + pwc_cleanup(pdev); + /* Free memory (don't set pdev to 0 just yet) */ + kfree(pdev); disconnect_out: - /* search device_hint[] table if we occupy a slot, by any chance */ - for (hint = 0; hint < MAX_DEV_HINTS; hint++) - if (device_hint[hint].pdev == pdev) - device_hint[hint].pdev = NULL; + /* search device_hint[] table if we occupy a slot, by any chance */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) + if (device_hint[hint].pdev == pdev) + device_hint[hint].pdev = NULL; + } unlock_kernel(); } diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index acbb931..40d3447 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -193,6 +193,7 @@ struct pwc_device char vsnapshot; /* snapshot mode */ char vsync; /* used by isoc handler */ char vmirror; /* for ToUCaM series */ + char unplugged; int cmd_len; unsigned char cmd_buf[13]; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 13ee550..d2915d3 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -939,16 +939,25 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc When no more controls are available 0 is returned. */ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) { - u32 ctrl_class; + u32 ctrl_class = V4L2_CTRL_ID2CLASS(id); const u32 *pctrl; - /* if no query is desired, then just return the control ID */ - if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) - return id; if (ctrl_classes == NULL) return 0; + + /* if no query is desired, then check if the ID is part of ctrl_classes */ + if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) { + /* find class */ + while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class) + ctrl_classes++; + if (*ctrl_classes == NULL) + return 0; + pctrl = *ctrl_classes; + /* find control ID */ + while (*pctrl && *pctrl != id) pctrl++; + return *pctrl ? id : 0; + } id &= V4L2_CTRL_ID_MASK; - ctrl_class = V4L2_CTRL_ID2CLASS(id); id++; /* select next control */ /* find first class that matches (or is greater than) the class of the ID */ diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index 8f6741a..1bf4cbe 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c @@ -321,12 +321,14 @@ static int wm8739_probe(struct i2c_adapter *adapter) static int wm8739_detach(struct i2c_client *client) { + struct wm8739_state *state = i2c_get_clientdata(client); int err; err = i2c_detach_client(client); if (err) return err; + kfree(state); kfree(client); return 0; } diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 4df5d30..9f7e894 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -222,12 +222,14 @@ static int wm8775_probe(struct i2c_adapter *adapter) static int wm8775_detach(struct i2c_client *client) { + struct wm8775_state *state = i2c_get_clientdata(client); int err; err = i2c_detach_client(client); if (err) { return err; } + kfree(state); kfree(client); return 0; diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 8ee0321..ab2ca63 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -908,7 +908,9 @@ static struct acpi_driver sony_nc_driver = { #define SONYPI_DEVICE_TYPE2 0x00000002 #define SONYPI_DEVICE_TYPE3 0x00000004 -#define SONY_PIC_EV_MASK 0xff +#define SONYPI_TYPE1_OFFSET 0x04 +#define SONYPI_TYPE2_OFFSET 0x12 +#define SONYPI_TYPE3_OFFSET 0x12 struct sony_pic_ioport { struct acpi_resource_io io; @@ -922,6 +924,7 @@ struct sony_pic_irq { struct sony_pic_dev { int model; + u16 evport_offset; u8 camera_power; u8 bluetooth_power; u8 wwan_power; @@ -1998,20 +2001,17 @@ end: static irqreturn_t sony_pic_irq(int irq, void *dev_id) { int i, j; - u32 port_val = 0; u8 ev = 0; u8 data_mask = 0; u8 device_event = 0; struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; - acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val, - dev->cur_ioport->io.address_length); - ev = port_val & SONY_PIC_EV_MASK; - data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8)); + ev = inb_p(dev->cur_ioport->io.minimum); + data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); - dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n", - port_val, ev, data_mask, dev->cur_ioport->io.minimum); + dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", + ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); if (ev == 0x00 || ev == 0xff) return IRQ_HANDLED; @@ -2102,6 +2102,20 @@ static int sony_pic_add(struct acpi_device *device) spic_dev.model = sony_pic_detect_device_type(); mutex_init(&spic_dev.lock); + /* model specific characteristics */ + switch(spic_dev.model) { + case SONYPI_DEVICE_TYPE1: + spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; + break; + case SONYPI_DEVICE_TYPE3: + spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; + break; + case SONYPI_DEVICE_TYPE2: + default: + spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; + break; + } + /* read _PRS resources */ result = sony_pic_possible_resources(device); if (result) { diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 451adcc..6d958a4 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -3,9 +3,9 @@ # # Core functionality. +obj-$(CONFIG_MTD) += mtd.o mtd-y := mtdcore.o mtdsuper.o mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o -obj-$(CONFIG_MTD) += $(mtd-y) obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 9c62368..6174a97 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -560,7 +560,3 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, EXPORT_SYMBOL_GPL(parse_mtd_partitions); EXPORT_SYMBOL_GPL(register_mtd_parser); EXPORT_SYMBOL_GPL(deregister_mtd_parser); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Nicolas Pitre "); -MODULE_DESCRIPTION("Generic support for partitioning of MTD devices"); diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index aca3319..9b430f2 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -70,6 +70,8 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n", mtd->index, mtd->name); + sb->s_flags = flags; + ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (ret < 0) { up_write(&sb->s_umount); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6287ffb..0af7bc8 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1233,43 +1233,31 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) return 0; } -#define BOND_INTERSECT_FEATURES \ - (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO) +#define BOND_VLAN_FEATURES \ + (NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | \ + NETIF_F_HW_VLAN_FILTER) /* * Compute the common dev->feature set available to all slaves. Some - * feature bits are managed elsewhere, so preserve feature bits set on - * master device that are not part of the examined set. + * feature bits are managed elsewhere, so preserve those feature bits + * on the master device. */ static int bond_compute_features(struct bonding *bond) { - unsigned long features = BOND_INTERSECT_FEATURES; struct slave *slave; struct net_device *bond_dev = bond->dev; + unsigned long features = bond_dev->features & ~BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; int i; bond_for_each_slave(bond, slave, i) { - features &= (slave->dev->features & BOND_INTERSECT_FEATURES); + features = netdev_compute_features(features, + slave->dev->features); if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; } - if ((features & NETIF_F_SG) && - !(features & NETIF_F_ALL_CSUM)) - features &= ~NETIF_F_SG; - - /* - * features will include NETIF_F_TSO (NETIF_F_UFO) iff all - * slave devices support NETIF_F_TSO (NETIF_F_UFO), which - * implies that all slaves also support scatter-gather - * (NETIF_F_SG), which implies that features also includes - * NETIF_F_SG. So no need to check whether we have an - * illegal combination of NETIF_F_{TSO,UFO} and - * !NETIF_F_SG - */ - - features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES); + features |= (bond_dev->features & BOND_VLAN_FEATURES); bond_dev->features = features; bond_dev->hard_header_len = max_hard_header_len; diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 42ba1c0..765fb75 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -550,6 +550,8 @@ union ring_type { /* PHY defines */ #define PHY_OUI_MARVELL 0x5043 #define PHY_OUI_CICADA 0x03f1 +#define PHY_OUI_VITESSE 0x01c1 +#define PHY_OUI_REALTEK 0x0732 #define PHYID1_OUI_MASK 0x03ff #define PHYID1_OUI_SHFT 6 #define PHYID2_OUI_MASK 0xfc00 @@ -557,12 +559,36 @@ union ring_type { #define PHYID2_MODEL_MASK 0x03f0 #define PHY_MODEL_MARVELL_E3016 0x220 #define PHY_MARVELL_E3016_INITMASK 0x0300 -#define PHY_INIT1 0x0f000 -#define PHY_INIT2 0x0e00 -#define PHY_INIT3 0x01000 -#define PHY_INIT4 0x0200 -#define PHY_INIT5 0x0004 -#define PHY_INIT6 0x02000 +#define PHY_CICADA_INIT1 0x0f000 +#define PHY_CICADA_INIT2 0x0e00 +#define PHY_CICADA_INIT3 0x01000 +#define PHY_CICADA_INIT4 0x0200 +#define PHY_CICADA_INIT5 0x0004 +#define PHY_CICADA_INIT6 0x02000 +#define PHY_VITESSE_INIT_REG1 0x1f +#define PHY_VITESSE_INIT_REG2 0x10 +#define PHY_VITESSE_INIT_REG3 0x11 +#define PHY_VITESSE_INIT_REG4 0x12 +#define PHY_VITESSE_INIT_MSK1 0xc +#define PHY_VITESSE_INIT_MSK2 0x0180 +#define PHY_VITESSE_INIT1 0x52b5 +#define PHY_VITESSE_INIT2 0xaf8a +#define PHY_VITESSE_INIT3 0x8 +#define PHY_VITESSE_INIT4 0x8f8a +#define PHY_VITESSE_INIT5 0xaf86 +#define PHY_VITESSE_INIT6 0x8f86 +#define PHY_VITESSE_INIT7 0xaf82 +#define PHY_VITESSE_INIT8 0x0100 +#define PHY_VITESSE_INIT9 0x8f82 +#define PHY_VITESSE_INIT10 0x0 +#define PHY_REALTEK_INIT_REG1 0x1f +#define PHY_REALTEK_INIT_REG2 0x19 +#define PHY_REALTEK_INIT_REG3 0x13 +#define PHY_REALTEK_INIT1 0x0000 +#define PHY_REALTEK_INIT2 0x8e00 +#define PHY_REALTEK_INIT3 0x0001 +#define PHY_REALTEK_INIT4 0xad17 + #define PHY_GIGABIT 0x0100 #define PHY_TIMEOUT 0x1 @@ -1096,6 +1122,28 @@ static int phy_init(struct net_device *dev) return PHY_ERROR; } } + if (np->phy_oui == PHY_OUI_REALTEK) { + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + } /* set advertise register */ reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); @@ -1141,14 +1189,14 @@ static int phy_init(struct net_device *dev) /* phy vendor specific configuration */ if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) { phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ); - phy_reserved &= ~(PHY_INIT1 | PHY_INIT2); - phy_reserved |= (PHY_INIT3 | PHY_INIT4); + phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2); + phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4); if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; } phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ); - phy_reserved |= PHY_INIT5; + phy_reserved |= PHY_CICADA_INIT5; if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; @@ -1156,12 +1204,106 @@ static int phy_init(struct net_device *dev) } if (np->phy_oui == PHY_OUI_CICADA) { phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ); - phy_reserved |= PHY_INIT6; + phy_reserved |= PHY_CICADA_INIT6; if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; } } + if (np->phy_oui == PHY_OUI_VITESSE) { + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK1; + phy_reserved |= PHY_VITESSE_INIT3; + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK1; + phy_reserved |= PHY_VITESSE_INIT3; + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK2; + phy_reserved |= PHY_VITESSE_INIT8; + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + } + if (np->phy_oui == PHY_OUI_REALTEK) { + /* reset could have cleared these out, set them back */ + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { + printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); + return PHY_ERROR; + } + } + /* some phys clear out pause advertisment on reset, set it back */ mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg); @@ -2925,8 +3067,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) np->nic_poll_irq = np->irqmask; mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); spin_unlock(&np->lock); + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); break; } @@ -3043,8 +3185,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) np->nic_poll_irq = np->irqmask; mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); spin_unlock(&np->lock); + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); break; } @@ -3090,8 +3232,8 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) np->nic_poll_irq |= NVREG_IRQ_TX_ALL; mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); spin_unlock_irqrestore(&np->lock, flags); + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); break; } @@ -3205,8 +3347,8 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) np->nic_poll_irq |= NVREG_IRQ_RX_ALL; mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); spin_unlock_irqrestore(&np->lock, flags); + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); break; } } @@ -3278,8 +3420,8 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) np->nic_poll_irq |= NVREG_IRQ_OTHER; mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); spin_unlock_irqrestore(&np->lock, flags); + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); break; } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 3ef0092..9a81fed 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1726,7 +1726,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb) } /* the decompressor still expects the A/C bytes in the hdr */ len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2, - skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN); + skb->len + 2, ns->data, obuff_size); if (len < 0) { /* Pass the compressed frame to pppd as an error indication. */ diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 5ec7752..84958c8 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2649,14 +2649,16 @@ rtl8169_interrupt(int irq, void *dev_instance) rtl8169_check_link_status(dev, tp, ioaddr); #ifdef CONFIG_R8169_NAPI - RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); - tp->intr_mask = ~rtl8169_napi_event; - - if (likely(netif_rx_schedule_prep(dev))) - __netif_rx_schedule(dev); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x taken in poll\n", - dev->name, status); + if (status & rtl8169_napi_event) { + RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); + tp->intr_mask = ~rtl8169_napi_event; + + if (likely(netif_rx_schedule_prep(dev))) + __netif_rx_schedule(dev); + else if (netif_msg_intr(tp)) { + printk(KERN_INFO "%s: interrupt %04x in poll\n", + dev->name, status); + } } break; #else diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index fe01b96..2e76c4a 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -96,7 +96,7 @@ static int disable_msi = 0; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); -static int idle_timeout = 0; +static int idle_timeout = 100; module_param(idle_timeout, int, 0); MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); @@ -657,8 +657,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) int i; const u8 *addr = hw->dev[port]->dev_addr; - sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); @@ -1234,6 +1234,8 @@ static int sky2_up(struct net_device *dev) if (netif_msg_ifup(sky2)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); + netif_carrier_off(dev); + /* must be power of 2 */ sky2->tx_le = pci_alloc_consistent(hw->pdev, TX_RING_SIZE * @@ -1573,7 +1575,6 @@ static int sky2_down(struct net_device *dev) /* Stop more packets from being queued */ netif_stop_queue(dev); - netif_carrier_off(dev); /* Disable port IRQ */ imask = sky2_read32(hw, B0_IMSK); @@ -1625,6 +1626,8 @@ static int sky2_down(struct net_device *dev) sky2_phy_power(hw, port, 0); + netif_carrier_off(dev); + /* turn off LED's */ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); @@ -1689,7 +1692,6 @@ static void sky2_link_up(struct sky2_port *sky2) gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); netif_carrier_on(sky2->netdev); - netif_wake_queue(sky2->netdev); /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), @@ -1741,7 +1743,6 @@ static void sky2_link_down(struct sky2_port *sky2) gma_write16(hw, port, GM_GP_CTRL, reg); netif_carrier_off(sky2->netdev); - netif_stop_queue(sky2->netdev); /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); @@ -2064,6 +2065,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, if (!(status & GMR_FS_RX_OK)) goto resubmit; + if (status >> 16 != length) + goto len_mismatch; + if (length < copybreak) skb = receive_copy(sky2, re, length); else @@ -2073,6 +2077,11 @@ resubmit: return skb; +len_mismatch: + /* Truncation of overlength packets + causes PHY length to not match MAC length */ + ++sky2->net_stats.rx_length_errors; + error: ++sky2->net_stats.rx_errors; if (status & GMR_FS_RX_FF_OV) { @@ -2427,8 +2436,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status) static int sky2_poll(struct net_device *dev0, int *budget) { struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; - int work_limit = min(dev0->quota, *budget); - int work_done = 0; + int work_done; u32 status = sky2_read32(hw, B0_Y2_SP_EISR); if (unlikely(status & Y2_IS_ERROR)) @@ -2440,18 +2448,25 @@ static int sky2_poll(struct net_device *dev0, int *budget) if (status & Y2_IS_IRQ_PHY2) sky2_phy_intr(hw, 1); - work_done = sky2_status_intr(hw, work_limit); - if (work_done < work_limit) { - netif_rx_complete(dev0); + work_done = sky2_status_intr(hw, min(dev0->quota, *budget)); + *budget -= work_done; + dev0->quota -= work_done; - /* end of interrupt, re-enables also acts as I/O synchronization */ - sky2_read32(hw, B0_Y2_SP_LISR); - return 0; - } else { - *budget -= work_done; - dev0->quota -= work_done; + /* More work? */ + if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)) return 1; + + /* Bug/Errata workaround? + * Need to kick the TX irq moderation timer. + */ + if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); } + netif_rx_complete(dev0); + + sky2_read32(hw, B0_Y2_SP_LISR); + return 0; } static irqreturn_t sky2_intr(int irq, void *dev_id) @@ -3486,10 +3501,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - /* device is off until link detection */ - netif_carrier_off(dev); - netif_stop_queue(dev); - return dev; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ef6b253..dadee85 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) unsigned long orig_trans_start = 0; mutex_lock(&bcm->mutex); + /* keep from doing and rearming periodic work if shutting down */ + if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT) + goto unlock_mutex; if (unlikely(bcm->periodic_state % 60 == 0)) { /* Periodic work will take a long time, so we want it to * be preemtible. @@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) mmiowb(); bcm->periodic_state++; spin_unlock_irqrestore(&bcm->irq_lock, flags); +unlock_mutex: mutex_unlock(&bcm->mutex); } -void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) -{ - cancel_rearming_delayed_work(&bcm->periodic_work); -} - void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { struct delayed_work *work = &bcm->periodic_work; @@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm) return err; } +void bcm43xx_cancel_work(struct bcm43xx_private *bcm) +{ + /* The system must be unlocked when this routine is entered. + * If not, the next 2 steps may deadlock */ + cancel_work_sync(&bcm->restart_work); + cancel_rearming_delayed_work(&bcm->periodic_work); +} + static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) { int ret = 0; @@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) { bcm43xx_rng_exit(bcm); bcm43xx_sysfs_unregister(bcm); - bcm43xx_periodic_tasks_delete(bcm); + + mutex_lock(&(bcm)->mutex); + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); + mutex_unlock(&(bcm)->mutex); + + bcm43xx_cancel_work(bcm); mutex_lock(&(bcm)->mutex); bcm43xx_shutdown_all_wireless_cores(bcm); @@ -4018,7 +4030,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev) err = bcm43xx_disable_interrupts_sync(bcm); assert(!err); bcm43xx_free_board(bcm); - flush_scheduled_work(); + bcm43xx_cancel_work(bcm); return 0; } @@ -4150,9 +4162,9 @@ static void bcm43xx_chip_reset(struct work_struct *work) struct bcm43xx_phyinfo *phy; int err = -ENODEV; + bcm43xx_cancel_work(bcm); mutex_lock(&(bcm)->mutex); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - bcm43xx_periodic_tasks_delete(bcm); phy = bcm43xx_current_phy(bcm); err = bcm43xx_select_wireless_core(bcm, phy->type); if (!err) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index c8f3c53..14cfbeb 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm); -void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); +void bcm43xx_cancel_work(struct bcm43xx_private *bcm); void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index c71b998..8ab5f93 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev, goto out; } - bcm43xx_periodic_tasks_delete(bcm); + bcm43xx_cancel_work(bcm); mutex_lock(&(bcm)->mutex); err = bcm43xx_select_wireless_core(bcm, phytype); if (!err) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e48fcf0..247135f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -643,20 +643,20 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); + /* Has only triggered on CardBus, fixup is in yenta_socket */ while (bus->parent) { if ((child->subordinate > bus->subordinate) || (child->number > bus->subordinate) || (child->number < bus->number) || (child->subordinate < bus->number)) { - printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) is " - "hidden behind%s bridge #%02x (-#%02x)%s\n", - child->number, child->subordinate, - bus->self->transparent ? " transparent" : " ", - bus->number, bus->subordinate, - pcibios_assign_all_busses() ? " " : - " (try 'pci=assign-busses')"); - printk(KERN_WARNING "Please report the result to " - "linux-kernel to fix this permanently\n"); + pr_debug("PCI: Bus #%02x (-#%02x) is %s" + "hidden behind%s bridge #%02x (-#%02x)\n", + child->number, child->subordinate, + (bus->number > child->subordinate && + bus->subordinate < child->number) ? + "wholly " : " partially", + bus->self->transparent ? " transparent" : " ", + bus->number, bus->subordinate); } bus = bus->parent; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 01d8f8a..749e7d8 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1640,6 +1640,9 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCN DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RD580, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RX790, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); /* Disable MSI on chipsets that are known to not support it */ diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 50cad3a..1e03bbd 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -409,6 +409,9 @@ static void socket_shutdown(struct pcmcia_socket *s) #endif s->functions = 0; + /* give socket some time to power down */ + msleep(100); + s->ops->get_status(s, &status); if (status & SS_POWERON) { printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s); diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index eb766c3..0d24c39 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -4,7 +4,7 @@ Written By: Adam Radford Modifications By: Tom Couch - Copyright (C) 2004-2006 Applied Micro Circuits Corporation. + Copyright (C) 2004-2007 Applied Micro Circuits Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -69,6 +69,7 @@ 2.26.02.008 - Free irq handler in __twa_shutdown(). Serialize reset code. Add support for 9650SE controllers. + 2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails. */ #include @@ -92,7 +93,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.008" +#define TW_DRIVER_VERSION "2.26.02.009" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -2063,11 +2064,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id pci_set_master(pdev); - retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); - if (retval) { - TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); - goto out_disable_device; - } + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) + || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) + || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); + retval = -ENODEV; + goto out_disable_device; + } host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); if (!host) { diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 5c487ff..ac65ee2 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -597,6 +597,8 @@ static int aac_cfg_open(struct inode *inode, struct file *file) static int aac_cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); } @@ -650,6 +652,8 @@ static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); } #endif diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 315ea99..a288de5 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -74,21 +74,17 @@ config SERIAL_8250_PCI depends on SERIAL_8250 && PCI default SERIAL_8250 help - Say Y here if you have PCI serial ports. - - To compile this driver as a module, choose M here: the module - will be called 8250_pci. + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. config SERIAL_8250_PNP tristate "8250/16550 PNP device support" if EMBEDDED depends on SERIAL_8250 && PNP default SERIAL_8250 help - Say Y here if you have serial ports described by PNPBIOS or ACPI. - These are typically ports built into the system board. - - To compile this driver as a module, choose M here: the module - will be called 8250_pnp. + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. config SERIAL_8250_HP300 tristate diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 96557e6..17bcca5 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -440,8 +440,16 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign { struct uart_port *port = sunhv_port; unsigned long flags; + int locked = 1; + + local_irq_save(flags); + if (port->sysrq) { + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&port->lock); + } else + spin_lock(&port->lock); - spin_lock_irqsave(&port->lock, flags); while (n > 0) { unsigned long ra = __pa(con_write_page); unsigned long page_bytes; @@ -469,7 +477,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign ra += written; } } - spin_unlock_irqrestore(&port->lock, flags); + + if (locked) + spin_unlock(&port->lock); + local_irq_restore(flags); } static inline void sunhv_console_putchar(struct uart_port *port, char c) @@ -488,7 +499,15 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig { struct uart_port *port = sunhv_port; unsigned long flags; - int i; + int i, locked = 1; + + local_irq_save(flags); + if (port->sysrq) { + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&port->lock); + } else + spin_lock(&port->lock); spin_lock_irqsave(&port->lock, flags); for (i = 0; i < n; i++) { @@ -496,7 +515,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig sunhv_console_putchar(port, '\r'); sunhv_console_putchar(port, *s++); } - spin_unlock_irqrestore(&port->lock, flags); + + if (locked) + spin_unlock(&port->lock); + local_irq_restore(flags); } static struct console sunhv_console = { diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index deb9ab4..8a0f9e4 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -860,22 +860,31 @@ static int num_channels; static void sunsab_console_putchar(struct uart_port *port, int c) { struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); sunsab_tec_wait(up); writeb(c, &up->regs->w.tic); - - spin_unlock_irqrestore(&up->port.lock, flags); } static void sunsab_console_write(struct console *con, const char *s, unsigned n) { struct uart_sunsab_port *up = &sunsab_ports[con->index]; + unsigned long flags; + int locked = 1; + + local_irq_save(flags); + if (up->port.sysrq) { + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); + } else + spin_lock(&up->port.lock); uart_console_write(&up->port, s, n, sunsab_console_putchar); sunsab_tec_wait(up); + + if (locked) + spin_unlock(&up->port.lock); + local_irq_restore(flags); } static int sunsab_console_setup(struct console *con, char *options) diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 2a63cdb..26d720b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct console *co, const char *s, unsigned int count) { struct uart_sunsu_port *up = &sunsu_ports[co->index]; + unsigned long flags; unsigned int ier; + int locked = 1; + + local_irq_save(flags); + if (up->port.sysrq) { + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); + } else + spin_lock(&up->port.lock); /* * First save the UER then disable the interrupts @@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct console *co, const char *s, */ wait_for_xmitr(up); serial_out(up, UART_IER, ier); + + if (locked) + spin_unlock(&up->port.lock); + local_irq_restore(flags); } /* diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 15b6e1c..0a3e10a 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -9,7 +9,7 @@ * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their * work there. * - * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net) */ #include @@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; unsigned long flags; + int locked = 1; + + local_irq_save(flags); + if (up->port.sysrq) { + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); + } else + spin_lock(&up->port.lock); - spin_lock_irqsave(&up->port.lock, flags); uart_console_write(&up->port, s, count, sunzilog_putchar); udelay(2); - spin_unlock_irqrestore(&up->port.lock, flags); + + if (locked) + spin_unlock(&up->port.lock); + local_irq_restore(flags); } static int __init sunzilog_console_setup(struct console *con, char *options) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 0081c1d..407fb8f 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -919,6 +919,10 @@ skip_normal_probe: return -EINVAL; } } + + /* Accept probe requests only for the control interface */ + if (intf != control_interface) + return -ENODEV; if (usb_interface_claimed(data_interface)) { /* valid in this context */ dev_dbg(&intf->dev,"The data interface isn't available"); @@ -1107,10 +1111,12 @@ static void acm_disconnect(struct usb_interface *intf) return; } if (acm->country_codes){ - device_remove_file(&intf->dev, &dev_attr_wCountryCodes); - device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate); + device_remove_file(&acm->control->dev, + &dev_attr_wCountryCodes); + device_remove_file(&acm->control->dev, + &dev_attr_iCountryCodeRelDate); } - device_remove_file(&intf->dev, &dev_attr_bmCapabilities); + device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); acm->dev = NULL; usb_set_intfdata(acm->control, NULL); usb_set_intfdata(acm->data, NULL); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2619986..61699f7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -58,7 +58,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; spin_lock(&dynids->lock); - list_add_tail(&dynids->list, &dynid->node); + list_add_tail(&dynid->node, &dynids->list); spin_unlock(&dynids->lock); if (get_driver(driver)) { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 24f10a1..a1c1a11 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1388,6 +1388,10 @@ int usb_new_device(struct usb_device *udev) udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); + /* Increment the parent's count of unsuspended children */ + if (udev->parent) + usb_autoresume_device(udev->parent); + /* Register the device. The device driver is responsible * for adding the device files to sysfs and for configuring * the device. @@ -1395,13 +1399,11 @@ int usb_new_device(struct usb_device *udev) err = device_add(&udev->dev); if (err) { dev_err(&udev->dev, "can't device_add, error %d\n", err); + if (udev->parent) + usb_autosuspend_device(udev->parent); goto fail; } - /* Increment the parent's count of unsuspended children */ - if (udev->parent) - usb_autoresume_device(udev->parent); - exit: return err; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f9fed34..68ce2de 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -623,12 +623,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char memset(buf,0,size); // Make sure we parse really received data for (i = 0; i < 3; ++i) { - /* retry on length 0 or stall; some devices are flakey */ + /* retry on length 0 or error; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (type << 8) + index, 0, buf, size, USB_CTRL_GET_TIMEOUT); - if (result == 0 || result == -EPIPE) + if (result <= 0 && result != -ETIMEDOUT) continue; if (result > 1 && ((u8 *)buf)[1] != type) { result = -EPROTO; @@ -1344,6 +1344,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, usb_dev = interface_to_usbdev(intf); alt = intf->cur_altsetting; +#ifdef CONFIG_USB_DEVICEFS + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "DEVICE=/proc/bus/usb/%03d/%03d", + usb_dev->bus->busnum, usb_dev->devnum)) + return -ENOMEM; +#endif + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PRODUCT=%x/%x/%x", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + le16_to_cpu(usb_dev->descriptor.bcdDevice))) + return -ENOMEM; + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "TYPE=%d/%d/%d", + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol)) + return -ENOMEM; + if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "INTERFACE=%d/%d/%d", diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index da1c6f7..38c4e97 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -271,26 +271,58 @@ static int debug; static __u16 vendor = FTDI_VID; static __u16 product; +struct ftdi_private { + ftdi_chip_type_t chip_type; + /* type of the device, either SIO or FT8U232AM */ + int baud_base; /* baud base clock for divisor setting */ + int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ + __u16 last_set_data_urb_value ; + /* the last data state set - needed for doing a break */ + int write_offset; /* This is the offset in the usb data block to write the serial data - + * it is different between devices + */ + int flags; /* some ASYNC_xxxx flags are supported */ + unsigned long last_dtr_rts; /* saved modem control outputs */ + wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ + char prev_status, diff_status; /* Used for TIOCMIWAIT */ + __u8 rx_flags; /* receive state flags (throttling) */ + spinlock_t rx_lock; /* spinlock for receive state */ + struct delayed_work rx_work; + struct usb_serial_port *port; + int rx_processed; + unsigned long rx_bytes; + + __u16 interface; /* FT2232C port interface (0 for FT232/245) */ + + int force_baud; /* if non-zero, force the baud rate to this value */ + int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ + + spinlock_t tx_lock; /* spinlock for transmit state */ + unsigned long tx_bytes; + unsigned long tx_outstanding_bytes; + unsigned long tx_outstanding_urbs; +}; + /* struct ftdi_sio_quirk is used by devices requiring special attention. */ struct ftdi_sio_quirk { int (*probe)(struct usb_serial *); - void (*setup)(struct usb_serial *); /* Special settings during startup. */ + void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */ }; static int ftdi_olimex_probe (struct usb_serial *serial); -static void ftdi_USB_UIRT_setup (struct usb_serial *serial); -static void ftdi_HE_TIRA1_setup (struct usb_serial *serial); +static void ftdi_USB_UIRT_setup (struct ftdi_private *priv); +static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv); static struct ftdi_sio_quirk ftdi_olimex_quirk = { .probe = ftdi_olimex_probe, }; static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { - .setup = ftdi_USB_UIRT_setup, + .port_probe = ftdi_USB_UIRT_setup, }; static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { - .setup = ftdi_HE_TIRA1_setup, + .port_probe = ftdi_HE_TIRA1_setup, }; /* @@ -567,38 +599,6 @@ static const char *ftdi_chip_name[] = { #define THROTTLED 0x01 #define ACTUALLY_THROTTLED 0x02 -struct ftdi_private { - ftdi_chip_type_t chip_type; - /* type of the device, either SIO or FT8U232AM */ - int baud_base; /* baud base clock for divisor setting */ - int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ - __u16 last_set_data_urb_value ; - /* the last data state set - needed for doing a break */ - int write_offset; /* This is the offset in the usb data block to write the serial data - - * it is different between devices - */ - int flags; /* some ASYNC_xxxx flags are supported */ - unsigned long last_dtr_rts; /* saved modem control outputs */ - wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ - char prev_status, diff_status; /* Used for TIOCMIWAIT */ - __u8 rx_flags; /* receive state flags (throttling) */ - spinlock_t rx_lock; /* spinlock for receive state */ - struct delayed_work rx_work; - struct usb_serial_port *port; - int rx_processed; - unsigned long rx_bytes; - - __u16 interface; /* FT2232C port interface (0 for FT232/245) */ - - int force_baud; /* if non-zero, force the baud rate to this value */ - int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ - - spinlock_t tx_lock; /* spinlock for transmit state */ - unsigned long tx_bytes; - unsigned long tx_outstanding_bytes; - unsigned long tx_outstanding_urbs; -}; - /* Used for TIOCMIWAIT */ #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) @@ -609,7 +609,6 @@ struct ftdi_private { /* function prototypes for a FTDI serial converter */ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); -static int ftdi_sio_attach (struct usb_serial *serial); static void ftdi_shutdown (struct usb_serial *serial); static int ftdi_sio_port_probe (struct usb_serial_port *port); static int ftdi_sio_port_remove (struct usb_serial_port *port); @@ -663,7 +662,6 @@ static struct usb_serial_driver ftdi_sio_device = { .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, .break_ctl = ftdi_break_ctl, - .attach = ftdi_sio_attach, .shutdown = ftdi_shutdown, }; @@ -1198,6 +1196,8 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id static int ftdi_sio_port_probe(struct usb_serial_port *port) { struct ftdi_private *priv; + struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); + dbg("%s",__FUNCTION__); @@ -1214,6 +1214,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) than queue a task to deliver them */ priv->flags = ASYNC_LOW_LATENCY; + if (quirk && quirk->port_probe) + quirk->port_probe(priv); + /* Increase the size of read buffers */ kfree(port->bulk_in_buffer); port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); @@ -1244,29 +1247,13 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) return 0; } -/* attach subroutine */ -static int ftdi_sio_attach (struct usb_serial *serial) -{ - /* Check for device requiring special set up. */ - struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial); - - if (quirk && quirk->setup) - quirk->setup(serial); - - return 0; -} /* ftdi_sio_attach */ - - /* Setup for the USB-UIRT device, which requires hardwired * baudrate (38400 gets mapped to 312500) */ /* Called from usbserial:serial_probe */ -static void ftdi_USB_UIRT_setup (struct usb_serial *serial) +static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) { - struct ftdi_private *priv; - dbg("%s",__FUNCTION__); - priv = usb_get_serial_port_data(serial->port[0]); priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 77; priv->force_baud = B38400; @@ -1274,13 +1261,10 @@ static void ftdi_USB_UIRT_setup (struct usb_serial *serial) /* Setup for the HE-TIRA1 device, which requires hardwired * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ -static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) +static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv) { - struct ftdi_private *priv; - dbg("%s",__FUNCTION__); - priv = usb_get_serial_port_data(serial->port[0]); priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 240; priv->force_baud = B38400; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 056e192..0f99e07 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2366,9 +2366,8 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa int status; unsigned char number = edge_port->port->number - edge_port->port->serial->minor; - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) { + if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d", edge_port->port->number, baudRate); return 0; @@ -2461,18 +2460,16 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue); - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && - (regNum == MCR))) { + if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPWriteMCR && + regNum == MCR) { dbg("SendCmdWriteUartReg - Not writing to MCR Register"); return 0; } - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && - (regNum == LCR))) { + if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPWriteLCR && + regNum == LCR) { dbg ("SendCmdWriteUartReg - Not writing to LCR Register"); return 0; } diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c index e9bbc34..1b3f658 100644 --- a/drivers/video/backlight/cr_bllcd.c +++ b/drivers/video/backlight/cr_bllcd.c @@ -174,7 +174,7 @@ static int cr_backlight_probe(struct platform_device *pdev) struct cr_panel *crp; u8 dev_en; - crp = kzalloc(sizeof(crp), GFP_KERNEL); + crp = kzalloc(sizeof(*crp), GFP_KERNEL); if (crp == NULL) return -ENOMEM; diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index ab21495..083f603 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c @@ -369,9 +369,8 @@ EXPORT_SYMBOL(mac_map_monitor_sense); * */ -int __devinit mac_find_mode(struct fb_var_screeninfo *var, - struct fb_info *info, const char *mode_option, - unsigned int default_bpp) +int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, + const char *mode_option, unsigned int default_bpp) { const struct fb_videomode *db = NULL; unsigned int dbsize = 0; diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h index babeb81..b86ba08 100644 --- a/drivers/video/macmodes.h +++ b/drivers/video/macmodes.h @@ -55,10 +55,10 @@ extern int mac_vmode_to_var(int vmode, int cmode, extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, int *cmode); extern int mac_map_monitor_sense(int sense); -extern int __devinit mac_find_mode(struct fb_var_screeninfo *var, - struct fb_info *info, - const char *mode_option, - unsigned int default_bpp); +extern int mac_find_mode(struct fb_var_screeninfo *var, + struct fb_info *info, + const char *mode_option, + unsigned int default_bpp); /* diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index c97709e..e7c8db2 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1100,13 +1100,18 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) /* only supported cards are allowed */ switch (fb->id) { case CRT_ID_VISUALIZE_EG: - /* look for a double buffering device like e.g. the - "INTERNAL_EG_DX1024" in the RDI precisionbook laptop - which won't work. The same device in non-double - buffering mode returns "INTERNAL_EG_X1024". */ - if (strstr(sti->outptr.dev_name, "EG_DX")) { - printk(KERN_WARNING - "stifb: ignoring '%s'. Disable double buffering in IPL menu.\n", + /* Visualize cards can run either in "double buffer" or + "standard" mode. Depending on the mode, the card reports + a different device name, e.g. "INTERNAL_EG_DX1024" in double + buffer mode and "INTERNAL_EG_X1024" in standard mode. + Since this driver only supports standard mode, we check + if the device name contains the string "DX" and tell the + user how to reconfigure the card. */ + if (strstr(sti->outptr.dev_name, "DX")) { + printk(KERN_WARNING "WARNING: stifb framebuffer driver does not " + "support '%s' in double-buffer mode.\n" + KERN_WARNING "WARNING: Please disable the double-buffer mode " + "in IPL menu (the PARISC-BIOS).\n", sti->outptr.dev_name); goto out_err0; } diff --git a/fs/9p/conv.c b/fs/9p/conv.c index a3ed571..923d75c 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c @@ -742,6 +742,7 @@ struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, if (err) { kfree(fc); fc = ERR_PTR(err); + goto error; } if (buf_check_overflow(bufp)) { diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index a3684dc..6f8c96f 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -235,8 +235,8 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts); switch (err) { case 0: - mntput(nd->mnt); dput(nd->dentry); + mntput(nd->mnt); nd->mnt = newmnt; nd->dentry = dget(newmnt->mnt_root); schedule_delayed_work(&afs_mntpt_expiry_timer, diff --git a/fs/direct-io.c b/fs/direct-io.c index 52bb263..6874785 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -974,6 +974,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, dio->get_block = get_block; dio->end_io = end_io; dio->map_bh.b_private = NULL; + dio->map_bh.b_state = 0; dio->final_block_in_bio = -1; dio->next_block_for_io = -1; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 83e94fe..9c6877c 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -902,8 +902,9 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) mutex_lock(&crypt_stat->cs_mutex); if (S_ISDIR(dentry->d_inode->i_mode)) crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); - else if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) - || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { + else if (S_ISREG(dentry->d_inode->i_mode) + && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) + || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) { struct vfsmount *lower_mnt; struct file *lower_file = NULL; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; diff --git a/fs/exec.c b/fs/exec.c index f20561f..3da429d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -586,18 +586,12 @@ static int de_thread(struct task_struct *tsk) int count; /* - * Tell all the sighand listeners that this sighand has - * been detached. The signalfd_detach() function grabs the - * sighand lock, if signal listeners are present on the sighand. - */ - signalfd_detach(tsk); - - /* * If we don't share sighandlers, then we aren't sharing anything * and we can just re-use it all. */ if (atomic_read(&oldsighand->count) <= 1) { BUG_ON(atomic_read(&sig->count) != 1); + signalfd_detach(tsk); exit_itimers(sig); return 0; } @@ -736,6 +730,7 @@ static int de_thread(struct task_struct *tsk) sig->flags = 0; no_thread_group: + signalfd_detach(tsk); exit_itimers(sig); if (leader) release_task(leader); @@ -890,9 +885,12 @@ int flush_old_exec(struct linux_binprm * bprm) */ current->mm->task_size = TASK_SIZE; - if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || - file_permission(bprm->file, MAY_READ) || - (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { + if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) { + suid_keys(current); + current->mm->dumpable = suid_dumpable; + current->pdeath_signal = 0; + } else if (file_permission(bprm->file, MAY_READ) || + (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { suid_keys(current); current->mm->dumpable = suid_dumpable; } @@ -983,8 +981,10 @@ void compute_creds(struct linux_binprm *bprm) { int unsafe; - if (bprm->e_uid != current->uid) + if (bprm->e_uid != current->uid) { suid_keys(current); + current->pdeath_signal = 0; + } exec_keys(current); task_lock(current); diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 9bb046d..e54eb5f 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -140,7 +140,8 @@ struct dx_frame struct dx_map_entry { u32 hash; - u32 offs; + u16 offs; + u16 size; }; #ifdef CONFIG_EXT3_INDEX @@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir, entries = (struct dx_entry *) (((char *)&root->info) + root->info.info_length); - assert(dx_get_limit(entries) == dx_root_limit(dir, - root->info.info_length)); + + if (dx_get_limit(entries) != dx_root_limit(dir, + root->info.info_length)) { + ext3_warning(dir->i_sb, __FUNCTION__, + "dx entry: limit != root limit"); + brelse(bh); + *err = ERR_BAD_DX_DIR; + goto fail; + } + dxtrace (printk("Look up %x", hash)); while (1) { count = dx_get_count(entries); - assert (count && count <= dx_get_limit(entries)); + if (!count || count > dx_get_limit(entries)) { + ext3_warning(dir->i_sb, __FUNCTION__, + "dx entry: no count or count > limit"); + brelse(bh); + *err = ERR_BAD_DX_DIR; + goto fail2; + } + p = entries + 1; q = entries + count - 1; while (p <= q) @@ -423,8 +439,15 @@ dx_probe(struct dentry *dentry, struct inode *dir, if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) goto fail2; at = entries = ((struct dx_node *) bh->b_data)->entries; - assert (dx_get_limit(entries) == dx_node_limit (dir)); + if (dx_get_limit(entries) != dx_node_limit (dir)) { + ext3_warning(dir->i_sb, __FUNCTION__, + "dx entry: limit != node limit"); + brelse(bh); + *err = ERR_BAD_DX_DIR; + goto fail2; + } frame++; + frame->bh = NULL; } fail2: while (frame >= frame_in) { @@ -432,6 +455,10 @@ fail2: frame--; } fail: + if (*err == ERR_BAD_DX_DIR) + ext3_warning(dir->i_sb, __FUNCTION__, + "Corrupt dir inode %ld, running e2fsck is " + "recommended.", dir->i_ino); return NULL; } @@ -671,6 +698,10 @@ errout: * Directory block splitting, compacting */ +/* + * Create map of hash values, offsets, and sizes, stored at end of block. + * Returns number of entries mapped. + */ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) { @@ -684,7 +715,8 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, ext3fs_dirhash(de->name, de->name_len, &h); map_tail--; map_tail->hash = h.hash; - map_tail->offs = (u32) ((char *) de - base); + map_tail->offs = (u16) ((char *) de - base); + map_tail->size = le16_to_cpu(de->rec_len); count++; cond_resched(); } @@ -694,6 +726,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, return count; } +/* Sort map by hash value */ static void dx_sort_map (struct dx_map_entry *map, unsigned count) { struct dx_map_entry *p, *q, *top = map + count - 1; @@ -1081,6 +1114,10 @@ static inline void ext3_set_de_type(struct super_block *sb, } #ifdef CONFIG_EXT3_INDEX +/* + * Move count entries from end of map between two memory locations. + * Returns pointer to last entry moved. + */ static struct ext3_dir_entry_2 * dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) { @@ -1099,6 +1136,10 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) return (struct ext3_dir_entry_2 *) (to - rec_len); } +/* + * Compact each dir entry in the range to the minimal rec_len. + * Returns pointer to last entry in range. + */ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) { struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; @@ -1121,6 +1162,11 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) return prev; } +/* + * Split a full leaf block to make room for a new dir entry. + * Allocate a new block, and move entries so that they are approx. equally full. + * Returns pointer to de in block into which the new entry will be inserted. + */ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, struct buffer_head **bh,struct dx_frame *frame, struct dx_hash_info *hinfo, int *error) @@ -1132,7 +1178,7 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, u32 hash2; struct dx_map_entry *map; char *data1 = (*bh)->b_data, *data2; - unsigned split; + unsigned split, move, size, i; struct ext3_dir_entry_2 *de = NULL, *de2; int err = 0; @@ -1160,8 +1206,19 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, count = dx_make_map ((struct ext3_dir_entry_2 *) data1, blocksize, hinfo, map); map -= count; - split = count/2; // need to adjust to actual middle dx_sort_map (map, count); + /* Split the existing block in the middle, size-wise */ + size = 0; + move = 0; + for (i = count-1; i >= 0; i--) { + /* is more than half of this entry in 2nd half of the block? */ + if (size + map[i].size/2 > blocksize/2) + break; + size += map[i].size; + move++; + } + /* map index at which we will split */ + split = count - move; hash2 = map[split].hash; continued = hash2 == map[split - 1].hash; dxtrace(printk("Split block %i at %x, %i/%i\n", diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index b9ce241..fd10229 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1445,7 +1445,7 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block, static void ext4_ext_put_in_cache(struct inode *inode, __u32 block, - __u32 len, __u32 start, int type) + __u32 len, ext4_fsblk_t start, int type) { struct ext4_ext_cache *cex; BUG_ON(len == 0); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 2811e57..7bb8d7c 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -140,7 +140,8 @@ struct dx_frame struct dx_map_entry { u32 hash; - u32 offs; + u16 offs; + u16 size; }; #ifdef CONFIG_EXT4_INDEX @@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir, entries = (struct dx_entry *) (((char *)&root->info) + root->info.info_length); - assert(dx_get_limit(entries) == dx_root_limit(dir, - root->info.info_length)); + + if (dx_get_limit(entries) != dx_root_limit(dir, + root->info.info_length)) { + ext4_warning(dir->i_sb, __FUNCTION__, + "dx entry: limit != root limit"); + brelse(bh); + *err = ERR_BAD_DX_DIR; + goto fail; + } + dxtrace (printk("Look up %x", hash)); while (1) { count = dx_get_count(entries); - assert (count && count <= dx_get_limit(entries)); + if (!count || count > dx_get_limit(entries)) { + ext4_warning(dir->i_sb, __FUNCTION__, + "dx entry: no count or count > limit"); + brelse(bh); + *err = ERR_BAD_DX_DIR; + goto fail2; + } + p = entries + 1; q = entries + count - 1; while (p <= q) @@ -423,8 +439,15 @@ dx_probe(struct dentry *dentry, struct inode *dir, if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err))) goto fail2; at = entries = ((struct dx_node *) bh->b_data)->entries; - assert (dx_get_limit(entries) == dx_node_limit (dir)); + if (dx_get_limit(entries) != dx_node_limit (dir)) { + ext4_warning(dir->i_sb, __FUNCTION__, + "dx entry: limit != node limit"); + brelse(bh); + *err = ERR_BAD_DX_DIR; + goto fail2; + } frame++; + frame->bh = NULL; } fail2: while (frame >= frame_in) { @@ -432,6 +455,10 @@ fail2: frame--; } fail: + if (*err == ERR_BAD_DX_DIR) + ext4_warning(dir->i_sb, __FUNCTION__, + "Corrupt dir inode %ld, running e2fsck is " + "recommended.", dir->i_ino); return NULL; } @@ -671,6 +698,10 @@ errout: * Directory block splitting, compacting */ +/* + * Create map of hash values, offsets, and sizes, stored at end of block. + * Returns number of entries mapped. + */ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) { @@ -684,7 +715,8 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, ext4fs_dirhash(de->name, de->name_len, &h); map_tail--; map_tail->hash = h.hash; - map_tail->offs = (u32) ((char *) de - base); + map_tail->offs = (u16) ((char *) de - base); + map_tail->size = le16_to_cpu(de->rec_len); count++; cond_resched(); } @@ -694,6 +726,7 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, return count; } +/* Sort map by hash value */ static void dx_sort_map (struct dx_map_entry *map, unsigned count) { struct dx_map_entry *p, *q, *top = map + count - 1; @@ -1079,6 +1112,10 @@ static inline void ext4_set_de_type(struct super_block *sb, } #ifdef CONFIG_EXT4_INDEX +/* + * Move count entries from end of map between two memory locations. + * Returns pointer to last entry moved. + */ static struct ext4_dir_entry_2 * dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) { @@ -1097,6 +1134,10 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) return (struct ext4_dir_entry_2 *) (to - rec_len); } +/* + * Compact each dir entry in the range to the minimal rec_len. + * Returns pointer to last entry in range. + */ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size) { struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base; @@ -1119,6 +1160,11 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size) return prev; } +/* + * Split a full leaf block to make room for a new dir entry. + * Allocate a new block, and move entries so that they are approx. equally full. + * Returns pointer to de in block into which the new entry will be inserted. + */ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, struct buffer_head **bh,struct dx_frame *frame, struct dx_hash_info *hinfo, int *error) @@ -1130,7 +1176,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, u32 hash2; struct dx_map_entry *map; char *data1 = (*bh)->b_data, *data2; - unsigned split; + unsigned split, move, size, i; struct ext4_dir_entry_2 *de = NULL, *de2; int err = 0; @@ -1158,8 +1204,19 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, count = dx_make_map ((struct ext4_dir_entry_2 *) data1, blocksize, hinfo, map); map -= count; - split = count/2; // need to adjust to actual middle dx_sort_map (map, count); + /* Split the existing block in the middle, size-wise */ + size = 0; + move = 0; + for (i = count-1; i >= 0; i--) { + /* is more than half of this entry in 2nd half of the block? */ + if (size + map[i].size/2 > blocksize/2) + break; + size += map[i].size; + move++; + } + /* map index at which we will split */ + split = count - move; hash2 = map[split].hash; continued = hash2 == map[split - 1].hash; dxtrace(printk("Split block %i at %x, %i/%i\n", diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 1facfaf..a003d50 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -887,7 +887,8 @@ restart_loop: journal->j_committing_transaction = NULL; spin_unlock(&journal->j_state_lock); - if (commit_transaction->t_checkpoint_list == NULL) { + if (commit_transaction->t_checkpoint_list == NULL && + commit_transaction->t_checkpoint_io_list == NULL) { __journal_drop_transaction(journal, commit_transaction); } else { if (journal->j_checkpoint_transactions == NULL) { diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 2856e11..c0f59d1 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -896,7 +896,8 @@ restart_loop: journal->j_committing_transaction = NULL; spin_unlock(&journal->j_state_lock); - if (commit_transaction->t_checkpoint_list == NULL) { + if (commit_transaction->t_checkpoint_list == NULL && + commit_transaction->t_checkpoint_io_list == NULL) { __jbd2_journal_drop_transaction(journal, commit_transaction); } else { if (journal->j_checkpoint_transactions == NULL) { diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 1d3b7a9..8bc727b 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -627,7 +627,7 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct inode *inode = OFNI_EDONI_2SFFJ(f); struct page *pg; - pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); if (IS_ERR(pg)) return (void *)pg; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index c9fe0ab..1b68a52 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -553,6 +553,9 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_full_dirent **prev = &dir_f->dents; uint32_t nhash = full_name_hash(name, namelen); + /* We don't actually want to reserve any space, but we do + want to be holding the alloc_sem when we write to flash */ + down(&c->alloc_sem); down(&dir_f->sem); while ((*prev) && (*prev)->nhash <= nhash) { diff --git a/fs/locks.c b/fs/locks.c index 431a8b8..6428605 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -786,7 +786,7 @@ find_conflict: if (request->fl_flags & FL_ACCESS) goto out; locks_copy_lock(new_fl, request); - locks_insert_lock(&inode->i_flock, new_fl); + locks_insert_lock(before, new_fl); new_fl = NULL; error = 0; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ca20d3c..6a5bd0d 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -181,8 +181,8 @@ void __exit unregister_nfs_fs(void) remove_shrinker(acl_shrinker); #ifdef CONFIG_NFS_V4 unregister_filesystem(&nfs4_fs_type); - nfs_unregister_sysctl(); #endif + nfs_unregister_sysctl(); unregister_filesystem(&nfs_fs_type); } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7e6aa24..9a68061 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1890,7 +1890,7 @@ nfsd_racache_init(int cache_size) raparm_hash[i].pb_head = NULL; spin_lock_init(&raparm_hash[i].pb_lock); } - nperbucket = cache_size >> RAPARM_HASH_BITS; + nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE); for (i = 0; i < cache_size - 1; i++) { if (i % nperbucket == 0) raparm_hash[j++].pb_head = raparml + i; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index ac6c964..e0cd750 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1353,7 +1353,7 @@ static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp else src_page = ERR_PTR(-EFAULT); } else { - bp->b_src_buf = buf; + bp->b_src_buf = (char *)((unsigned long)buf & PAGE_CACHE_MASK); } return src_page; diff --git a/fs/signalfd.c b/fs/signalfd.c index 3b07f26..afbe171 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -56,12 +56,18 @@ static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk) sighand = lock_task_sighand(lk->tsk, &lk->flags); rcu_read_unlock(); - if (sighand && !ctx->tsk) { + if (!sighand) + return 0; + + if (!ctx->tsk) { unlock_task_sighand(lk->tsk, &lk->flags); - sighand = NULL; + return 0; } - return sighand != NULL; + if (lk->tsk->tgid == current->tgid) + lk->tsk = current; + + return 1; } static void signalfd_unlock(struct signalfd_lockctx *lk) @@ -331,7 +337,7 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas init_waitqueue_head(&ctx->wqh); ctx->sigmask = sigmask; - ctx->tsk = current; + ctx->tsk = current->group_leader; sighand = current->sighand; /* diff --git a/fs/splice.c b/fs/splice.c index e7d7080..e263d3b 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -601,7 +601,7 @@ find_page: ret = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL); if (unlikely(ret)) - goto out; + goto out_release; } ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); @@ -657,8 +657,9 @@ find_page: */ mark_page_accessed(page); out: - page_cache_release(page); unlock_page(page); +out_release: + page_cache_release(page); out_ret: return ret; } @@ -1010,7 +1011,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); ret = do_splice_to(in, ppos, pipe, max_read_len, flags); - if (unlikely(ret < 0)) + if (unlikely(ret <= 0)) goto out_release; read_len = ret; @@ -1022,7 +1023,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, */ ret = do_splice_from(pipe, out, &out_off, read_len, flags & ~SPLICE_F_NONBLOCK); - if (unlikely(ret < 0)) + if (unlikely(ret <= 0)) goto out_release; bytes += ret; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index b502c71..1f64ce5 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -283,6 +283,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) mutex_lock(&inode->i_mutex); if (!(set = inode->i_private)) { if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) { + mutex_unlock(&inode->i_mutex); error = -ENOMEM; goto Done; } else { diff --git a/fs/timerfd.c b/fs/timerfd.c index af9eca5..61983f3 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -95,7 +95,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, { struct timerfd_ctx *ctx = file->private_data; ssize_t res; - u32 ticks = 0; + u64 ticks = 0; DECLARE_WAITQUEUE(wait, current); if (count < sizeof(ticks)) @@ -130,7 +130,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, * callback to avoid DoS attacks specifying a very * short timer period. */ - ticks = (u32) + ticks = (u64) hrtimer_forward(&ctx->tmr, hrtimer_cb_get_time(&ctx->tmr), ctx->tintv); @@ -140,7 +140,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, } spin_unlock_irq(&ctx->wqh.lock); if (ticks) - res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks); + res = put_user(ticks, (u64 __user *) buf) ? -EFAULT: sizeof(ticks); return res; } diff --git a/include/asm-avr32/atomic.h b/include/asm-avr32/atomic.h index b9c2548..7ef3862 100644 --- a/include/asm-avr32/atomic.h +++ b/include/asm-avr32/atomic.h @@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u) " mov %1, 1\n" "1:" : "=&r"(tmp), "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "rKs21"(a), "rKs21"(u) + : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result) : "cc", "memory"); return result; @@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) " mov %1, 1\n" "1:" : "=&r"(tmp), "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "r"(a), "ir"(u) + : "m"(v->counter), "r"(a), "ir"(u), "1"(result) : "cc", "memory"); } diff --git a/include/asm-i386/serial.h b/include/asm-i386/serial.h index 57a4306..bd67480 100644 --- a/include/asm-i386/serial.h +++ b/include/asm-i386/serial.h @@ -11,3 +11,19 @@ * megabits/second; but this requires the faster clock. */ #define BASE_BAUD ( 1843200 / 16 ) + +/* Standard COM flags (except for COM4, because of the 8514 problem) */ +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) +#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#endif + +#define SERIAL_PORT_DFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ diff --git a/include/asm-sparc/sfp-machine.h b/include/asm-sparc/sfp-machine.h index ecfc86a..266a42b 100644 --- a/include/asm-sparc/sfp-machine.h +++ b/include/asm-sparc/sfp-machine.h @@ -203,4 +203,10 @@ extern struct task_struct *last_task_used_math; #define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex) #endif +#ifdef CONFIG_SMP +#define FP_TRAPPING_EXCEPTIONS ((current->thread.fsr >> 23) & 0x1f) +#else +#define FP_TRAPPING_EXCEPTIONS ((last_task_used_math->thread.fsr >> 23) & 0x1f) +#endif + #endif diff --git a/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h index 89d4243..c9331b0 100644 --- a/include/asm-sparc64/sfp-machine.h +++ b/include/asm-sparc64/sfp-machine.h @@ -88,4 +88,6 @@ #define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex) +#define FP_TRAPPING_EXCEPTIONS ((current_thread_info()->xfsr[0] >> 23) & 0x1f) + #endif diff --git a/include/asm-x86_64/serial.h b/include/asm-x86_64/serial.h index 8ebd765..b0496e0 100644 --- a/include/asm-x86_64/serial.h +++ b/include/asm-x86_64/serial.h @@ -11,3 +11,19 @@ * megabits/second; but this requires the faster clock. */ #define BASE_BAUD ( 1843200 / 16 ) + +/* Standard COM flags (except for COM4, because of the 8514 problem) */ +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) +#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#endif + +#define SERIAL_PORT_DFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index f317c27..d86711d 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -7,6 +7,7 @@ header-y += raid/ header-y += spi/ header-y += sunrpc/ header-y += tc_act/ +header-y += tc_ematch/ header-y += netfilter/ header-y += netfilter_arp/ header-y += netfilter_bridge/ @@ -137,6 +138,7 @@ header-y += radeonfb.h header-y += raw.h header-y += resource.h header-y += rose.h +header-y += serial_reg.h header-y += smbno.h header-y += snmp.h header-y += sockios.h diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h index 8e2042b..2eaa142 100644 --- a/include/linux/ioprio.h +++ b/include/linux/ioprio.h @@ -47,8 +47,10 @@ enum { #define IOPRIO_NORM (4) static inline int task_ioprio(struct task_struct *task) { - WARN_ON(!ioprio_valid(task->ioprio)); - return IOPRIO_PRIO_DATA(task->ioprio); + if (ioprio_valid(task->ioprio)) + return IOPRIO_PRIO_DATA(task->ioprio); + + return IOPRIO_NORM; } static inline int task_nice_ioprio(struct task_struct *task) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3a70f55..ab210be 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1032,6 +1032,8 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); extern void linkwatch_run_queue(void); +extern int netdev_compute_features(unsigned long all, unsigned long one); + static inline int net_gso_ok(int features, int gso_type) { int feature = gso_type << NETIF_F_GSO_SHIFT; diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 43397a4..ab57cb7 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -28,6 +28,7 @@ header-y += xt_policy.h header-y += xt_realm.h header-y += xt_sctp.h header-y += xt_state.h +header-y += xt_statistic.h header-y += xt_string.h header-y += xt_tcpmss.h header-y += xt_tcpudp.h diff --git a/include/linux/netfilter_ipv4/ipt_iprange.h b/include/linux/netfilter_ipv4/ipt_iprange.h index 34ab0fb..a92fefc 100644 --- a/include/linux/netfilter_ipv4/ipt_iprange.h +++ b/include/linux/netfilter_ipv4/ipt_iprange.h @@ -1,6 +1,8 @@ #ifndef _IPT_IPRANGE_H #define _IPT_IPRANGE_H +#include + #define IPRANGE_SRC 0x01 /* Match source IP address */ #define IPRANGE_DST 0x02 /* Match destination IP address */ #define IPRANGE_SRC_INV 0x10 /* Negate the condition */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5b1c999..c1ffa1b 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -357,6 +357,9 @@ #define PCI_DEVICE_ID_ATI_RS400_166 0x5a32 #define PCI_DEVICE_ID_ATI_RS400_200 0x5a33 #define PCI_DEVICE_ID_ATI_RS480 0x5950 +#define PCI_DEVICE_ID_ATI_RD580 0x5952 +#define PCI_DEVICE_ID_ATI_RX790 0x5957 +#define PCI_DEVICE_ID_ATI_RS690 0x7910 /* ATI IXP Chipset */ #define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 #define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index 93780ab..bb46e76 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -145,13 +145,16 @@ do { \ { \ X##_e = 1; \ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ } \ else \ { \ X##_e = 0; \ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ - FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ } \ + if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ + (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ + FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ } \ else \ { \ diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h index d02eb64..a6f873b 100644 --- a/include/math-emu/soft-fp.h +++ b/include/math-emu/soft-fp.h @@ -97,12 +97,19 @@ #define FP_INHIBIT_RESULTS 0 #endif +#ifndef FP_TRAPPING_EXCEPTIONS +#define FP_TRAPPING_EXCEPTIONS 0 +#endif + #define FP_SET_EXCEPTION(ex) \ _fex |= (ex) #define FP_UNSET_EXCEPTION(ex) \ _fex &= ~(ex) +#define FP_CUR_EXCEPTIONS \ + (_fex) + #define FP_CLEAR_EXCEPTIONS \ _fex = 0 diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 3c563f0..25aa575 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc #define RFCOMM_RELEASE_ONHUP 1 #define RFCOMM_HANGUP_NOW 2 #define RFCOMM_TTY_ATTACHED 3 +#define RFCOMM_TTY_RELEASED 4 struct rfcomm_dev_req { s16 dev_id; diff --git a/include/net/tcp.h b/include/net/tcp.h index a8af9ae..06827e3 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -281,7 +281,7 @@ extern int tcp_v4_remember_stamp(struct sock *sk); extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); -extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, +extern int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size); extern ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 311f25a..4d56e16 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -577,7 +577,6 @@ static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ct struct xfrm_dst { union { - struct xfrm_dst *next; struct dst_entry dst; struct rtable rt; struct rt6_info rt6; diff --git a/init/Kconfig b/init/Kconfig index a9e99f8..5f8dba9 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -505,6 +505,7 @@ config SIGNALFD config TIMERFD bool "Enable timerfd() system call" if EMBEDDED depends on ANON_INODES + depends on BROKEN default y help Enable the timerfd() system call that allows to receive timer diff --git a/ipc/shm.c b/ipc/shm.c index 0852f20..3bdcb9a 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -716,7 +716,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) struct user_struct * user = current->user; if (!is_file_hugepages(shp->shm_file)) { err = shmem_lock(shp->shm_file, 1, user); - if (!err) { + if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ shp->shm_perm.mode |= SHM_LOCKED; shp->mlock_user = user; } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e36481e..ea37edd 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1998,19 +1998,19 @@ int __audit_signal_info(int sig, struct task_struct *t) extern uid_t audit_sig_uid; extern u32 audit_sig_sid; - if (audit_pid && t->tgid == audit_pid && - (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) { - audit_sig_pid = tsk->pid; - if (ctx) - audit_sig_uid = ctx->loginuid; - else - audit_sig_uid = tsk->uid; - selinux_get_task_sid(tsk, &audit_sig_sid); + if (audit_pid && t->tgid == audit_pid) { + if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { + audit_sig_pid = tsk->pid; + if (ctx) + audit_sig_uid = ctx->loginuid; + else + audit_sig_uid = tsk->uid; + selinux_get_task_sid(tsk, &audit_sig_sid); + } + if (!audit_signals || audit_dummy_context()) + return 0; } - if (!audit_signals) /* audit_context checked in wrapper */ - return 0; - /* optimize the common case by putting first signal recipient directly * in audit_context */ if (!ctx->target_pid) { diff --git a/kernel/futex.c b/kernel/futex.c index 45490be..9b57f7e 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2061,8 +2061,10 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, } /* * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE. + * number of waiters to wake in 'utime' if cmd == FUTEX_WAKE_OP. */ - if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) + if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE || + cmd == FUTEX_WAKE_OP) val2 = (u32) (unsigned long) utime; return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index f792136..7e52eb0 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -61,10 +61,10 @@ void compat_exit_robust_list(struct task_struct *curr) if (fetch_robust_entry(&upending, &pending, &head->list_op_pending, &pip)) return; - if (upending) + if (pending) handle_futex_death((void __user *)pending + futex_offset, curr, pip); - while (compat_ptr(uentry) != &head->list) { + while (entry != (struct robust_list __user *) &head->list) { /* * A pending lock might already be on the list, so * dont process it twice: diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index 58f35e5..96f0417 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c @@ -339,7 +339,7 @@ static const struct file_operations proc_lockdep_stats_operations = { .open = lockdep_stats_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; static int __init lockdep_proc_init(void) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index a3b7854..a686590 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -709,7 +709,8 @@ static void mark_nosave_pages(struct memory_bitmap *bm) region->end_pfn << PAGE_SHIFT); for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++) - memory_bm_set_bit(bm, pfn); + if (pfn_valid(pfn)) + memory_bm_set_bit(bm, pfn); } } diff --git a/kernel/signal.c b/kernel/signal.c index f940560..5c48ab2 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -368,7 +368,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) /* We only dequeue private signals from ourselves, we don't let * signalfd steal them */ - if (tsk == current) + if (likely(tsk == current)) signr = __dequeue_signal(&tsk->pending, mask, info); if (!signr) { signr = __dequeue_signal(&tsk->signal->shared_pending, @@ -415,7 +415,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; } - if ( signr && + if (signr && likely(tsk == current) && ((info->si_code & __SI_MASK) == __SI_TIMER) && info->si_sys_private){ /* @@ -1259,20 +1259,19 @@ struct sigqueue *sigqueue_alloc(void) void sigqueue_free(struct sigqueue *q) { unsigned long flags; + spinlock_t *lock = ¤t->sighand->siglock; + BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); /* * If the signal is still pending remove it from the - * pending queue. + * pending queue. We must hold ->siglock while testing + * q->list to serialize with collect_signal(). */ - if (unlikely(!list_empty(&q->list))) { - spinlock_t *lock = ¤t->sighand->siglock; - read_lock(&tasklist_lock); - spin_lock_irqsave(lock, flags); - if (!list_empty(&q->list)) - list_del_init(&q->list); - spin_unlock_irqrestore(lock, flags); - read_unlock(&tasklist_lock); - } + spin_lock_irqsave(lock, flags); + if (!list_empty(&q->list)) + list_del_init(&q->list); + spin_unlock_irqrestore(lock, flags); + q->flags &= ~SIGQUEUE_PREALLOC; __sigqueue_free(q); } diff --git a/kernel/sys.c b/kernel/sys.c index 872271c..28e8364 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1428,7 +1428,6 @@ asmlinkage long sys_times(struct tms __user * tbuf) * Auch. Had to add the 'did_exec' flag to conform completely to POSIX. * LBT 04.03.94 */ - asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) { struct task_struct *p; @@ -1456,7 +1455,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) if (!thread_group_leader(p)) goto out; - if (p->real_parent == group_leader) { + if (p->real_parent->tgid == group_leader->tgid) { err = -EPERM; if (task_session(p) != task_session(group_leader)) goto out; diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 8bbcfb7..7ea87d9 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -267,7 +267,7 @@ static struct file_operations timer_list_fops = { .open = timer_list_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; static int __init init_timer_list_procfs(void) diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index 3216937..7bb561d 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -391,7 +391,7 @@ static struct file_operations tstats_fops = { .read = seq_read, .write = tstats_write, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; void __init init_timer_stats(void) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 3bebf73..3831f88 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -739,18 +739,17 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu) if (cwq->thread == NULL) return; + flush_cpu_workqueue(cwq); /* - * If the caller is CPU_DEAD the single flush_cpu_workqueue() - * is not enough, a concurrent flush_workqueue() can insert a - * barrier after us. + * If the caller is CPU_DEAD and cwq->worklist was not empty, + * a concurrent flush_workqueue() can insert a barrier after us. + * However, in that case run_workqueue() won't return and check + * kthread_should_stop() until it flushes all work_struct's. * When ->worklist becomes empty it is safe to exit because no * more work_structs can be queued on this cwq: flush_workqueue * checks list_empty(), and a "normal" queue_work() can't use * a dead CPU. */ - while (flush_cpu_workqueue(cwq)) - ; - kthread_stop(cwq->thread); cwq->thread = NULL; } diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a45d1f0..5fb38f1 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -101,13 +101,20 @@ static void free_huge_page(struct page *page) static int alloc_fresh_huge_page(void) { - static int nid = 0; + static int prev_nid; struct page *page; - page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN, - HUGETLB_PAGE_ORDER); - nid = next_node(nid, node_online_map); + static DEFINE_SPINLOCK(nid_lock); + int nid; + + spin_lock(&nid_lock); + nid = next_node(prev_nid, node_online_map); if (nid == MAX_NUMNODES) nid = first_node(node_online_map); + prev_nid = nid; + spin_unlock(&nid_lock); + + page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN, + HUGETLB_PAGE_ORDER); if (page) { set_compound_page_dtor(page, free_huge_page); spin_lock(&hugetlb_lock); diff --git a/mm/mlock.c b/mm/mlock.c index 4d3fea2..7b26560 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -244,9 +244,12 @@ int user_shm_lock(size_t size, struct user_struct *user) locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; + if (lock_limit == RLIM_INFINITY) + allowed = 1; lock_limit >>= PAGE_SHIFT; spin_lock(&shmlock_user_lock); - if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK)) + if (!allowed && + locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK)) goto out; get_uid(user); user->locked_shm += locked; diff --git a/mm/readahead.c b/mm/readahead.c index 9861e88..1448e53 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -21,8 +21,16 @@ void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) } EXPORT_SYMBOL(default_unplug_io_fn); +/* + * Convienent macros for min/max read-ahead pages. + * Note that MAX_RA_PAGES is rounded down, while MIN_RA_PAGES is rounded up. + * The latter is necessary for systems with large page size(i.e. 64k). + */ +#define MAX_RA_PAGES (VM_MAX_READAHEAD*1024 / PAGE_CACHE_SIZE) +#define MIN_RA_PAGES DIV_ROUND_UP(VM_MIN_READAHEAD*1024, PAGE_CACHE_SIZE) + struct backing_dev_info default_backing_dev_info = { - .ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE, + .ra_pages = MAX_RA_PAGES, .state = 0, .capabilities = BDI_CAP_MAP_COPY, .unplug_io_fn = default_unplug_io_fn, @@ -51,7 +59,7 @@ static inline unsigned long get_max_readahead(struct file_ra_state *ra) static inline unsigned long get_min_readahead(struct file_ra_state *ra) { - return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE; + return MIN_RA_PAGES; } static inline void reset_ahead_window(struct file_ra_state *ra) diff --git a/net/802/psnap.c b/net/802/psnap.c index 04ee43e..31128cb 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -55,6 +55,9 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, .type = __constant_htons(ETH_P_SNAP), }; + if (unlikely(!pskb_may_pull(skb, 5))) + goto drop; + rcu_read_lock(); proto = find_snap_client(skb_transport_header(skb)); if (proto) { @@ -62,14 +65,18 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, skb->transport_header += 5; skb_pull_rcsum(skb, 5); rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); - } else { - skb->sk = NULL; - kfree_skb(skb); - rc = 1; } - rcu_read_unlock(); + + if (unlikely(!proto)) + goto drop; + +out: return rc; + +drop: + kfree_skb(skb); + goto out; } /* diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ec46084..0642694 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -116,12 +116,22 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev) { unsigned char *rawp = NULL; - struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data); + struct vlan_hdr *vhdr; unsigned short vid; struct net_device_stats *stats; unsigned short vlan_TCI; __be16 proto; + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + return -1; + + if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) { + kfree_skb(skb); + return -1; + } + + vhdr = (struct vlan_hdr *)(skb->data); + /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ vlan_TCI = ntohs(vhdr->h_vlan_TCI); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index b2b1cce..23ba61a 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) BT_DBG("dev %p dlc %p", dev, dlc); + write_lock_bh(&rfcomm_dev_lock); + list_del_init(&dev->list); + write_unlock_bh(&rfcomm_dev_lock); + rfcomm_dlc_lock(dlc); /* Detach DLC if it's owned by this dev */ if (dlc->owner == dev) @@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) read_lock(&rfcomm_dev_lock); dev = __rfcomm_dev_get(id); - if (dev) - rfcomm_dev_hold(dev); + + if (dev) { + if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) + dev = NULL; + else + rfcomm_dev_hold(dev); + } read_unlock(&rfcomm_dev_lock); @@ -265,6 +274,12 @@ out: dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); + if (IS_ERR(dev->tty_dev)) { + list_del(&dev->list); + kfree(dev); + return PTR_ERR(dev->tty_dev); + } + return dev->id; } @@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) { BT_DBG("dev %p", dev); - write_lock_bh(&rfcomm_dev_lock); - list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); - + set_bit(RFCOMM_TTY_RELEASED, &dev->flags); rfcomm_dev_put(dev); } @@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags); + BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags); if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) return -EPERM; @@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags); + BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); if (!(dev = rfcomm_dev_get(req.dev_id))) return -ENODEV; @@ -383,6 +395,10 @@ static int rfcomm_release_dev(void __user *arg) if (req.flags & (1 << RFCOMM_HANGUP_NOW)) rfcomm_dlc_close(dev->dlc, 0); + /* Shut down TTY synchronously before freeing rfcomm_dev */ + if (dev->tty) + tty_vhangup(dev->tty); + rfcomm_dev_del(dev); rfcomm_dev_put(dev); return 0; @@ -415,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg) list_for_each(p, &rfcomm_dev_list) { struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); + if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) + continue; (di + n)->id = dev->id; (di + n)->flags = dev->flags; (di + n)->state = dev->dlc->state; diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 5e1892d..c326602 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -179,5 +179,6 @@ void br_dev_setup(struct net_device *dev) dev->priv_flags = IFF_EBRIDGE; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; + NETIF_F_GSO_SOFTWARE | NETIF_F_NO_CSUM | + NETIF_F_GSO_ROBUST | NETIF_F_LLTX; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 849deaf..fefd7c1 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -360,35 +360,15 @@ int br_min_mtu(const struct net_bridge *br) void br_features_recompute(struct net_bridge *br) { struct net_bridge_port *p; - unsigned long features, checksum; + unsigned long features; - checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; - features = br->feature_mask & ~NETIF_F_ALL_CSUM; + features = br->feature_mask; list_for_each_entry(p, &br->port_list, list) { - unsigned long feature = p->dev->features; - - if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) - checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; - if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) - checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; - if (!(feature & NETIF_F_IP_CSUM)) - checksum = 0; - - if (feature & NETIF_F_GSO) - feature |= NETIF_F_GSO_SOFTWARE; - feature |= NETIF_F_GSO; - - features &= feature; + features = netdev_compute_features(features, p->dev->features); } - if (!(checksum & NETIF_F_ALL_CSUM)) - features &= ~NETIF_F_SG; - if (!(features & NETIF_F_SG)) - features &= ~NETIF_F_GSO_MASK; - - br->dev->features = features | checksum | NETIF_F_LLTX | - NETIF_F_GSO_ROBUST; + br->dev->features = features; } /* called with RTNL */ diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index fa77987..3ee2022 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -509,8 +509,14 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, int (*okfn)(struct sk_buff *)) { struct iphdr *iph; - __u32 len; struct sk_buff *skb = *pskb; + __u32 len = nf_bridge_encap_header_len(skb); + + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + return NF_STOLEN; + + if (unlikely(!pskb_may_pull(skb, len))) + goto out; if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) { @@ -518,8 +524,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, if (!brnf_call_ip6tables) return NF_ACCEPT; #endif - if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) - goto out; nf_bridge_pull_encap_header_rcsum(skb); return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); } @@ -532,8 +536,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, !IS_PPPOE_IP(skb)) return NF_ACCEPT; - if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) - goto out; nf_bridge_pull_encap_header_rcsum(skb); if (!pskb_may_pull(skb, sizeof(struct iphdr))) diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 031bfa4..984e9c6 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -196,10 +196,8 @@ static int __init ebt_log_init(void) ret = ebt_register_watcher(&log); if (ret < 0) return ret; - ret = nf_log_register(PF_BRIDGE, &ebt_log_logger); - if (ret < 0 && ret != -EEXIST) - ebt_unregister_watcher(&log); - return ret; + nf_log_register(PF_BRIDGE, &ebt_log_logger); + return 0; } static void __exit ebt_log_fini(void) diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 9411db6..6fec352 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -308,12 +308,8 @@ static int __init ebt_ulog_init(void) else if ((ret = ebt_register_watcher(&ulog))) sock_release(ebtulognl->sk_socket); - if (nf_log_register(PF_BRIDGE, &ebt_ulog_logger) < 0) { - printk(KERN_WARNING "ebt_ulog: not logging via ulog " - "since somebody else already registered for PF_BRIDGE\n"); - /* we cannot make module load fail here, since otherwise - * ebtables userspace would abort */ - } + if (ret == 0) + nf_log_register(PF_BRIDGE, &ebt_ulog_logger); return ret; } diff --git a/net/core/datagram.c b/net/core/datagram.c index cb056f4..029b93e 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -450,6 +450,9 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, __wsum csum; int chunk = skb->len - hlen; + if (!chunk) + return 0; + /* Skip filled elements. * Pretty silly, look at memcpy_toiovec, though 8) */ diff --git a/net/core/dev.c b/net/core/dev.c index ee051bb..1561f61 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3635,6 +3635,44 @@ static int __init netdev_dma_register(void) static int __init netdev_dma_register(void) { return -ENODEV; } #endif /* CONFIG_NET_DMA */ +/** + * netdev_compute_feature - compute conjunction of two feature sets + * @all: first feature set + * @one: second feature set + * + * Computes a new feature set after adding a device with feature set + * @one to the master device with current feature set @all. Returns + * the new feature set. + */ +int netdev_compute_features(unsigned long all, unsigned long one) +{ + /* if device needs checksumming, downgrade to hw checksumming */ + if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM)) + all ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; + + /* if device can't do all checksum, downgrade to ipv4 */ + if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM)) + all ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; + + if (one & NETIF_F_GSO) + one |= NETIF_F_GSO_SOFTWARE; + one |= NETIF_F_GSO; + + /* If even one device supports robust GSO, enable it for all. */ + if (one & NETIF_F_GSO_ROBUST) + all |= NETIF_F_GSO_ROBUST; + + all &= one | NETIF_F_LLTX; + + if (!(all & NETIF_F_ALL_CSUM)) + all &= ~NETIF_F_SG; + if (!(all & NETIF_F_SG)) + all &= ~NETIF_F_GSO_MASK; + + return all; +} +EXPORT_SYMBOL(netdev_compute_features); + /* * Initialize the DEV module. At boot time this walks the device list and * unhooks any devices that fail to initialise (normally hardware not diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 17daf4c..590a767 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -79,27 +79,27 @@ struct gen_estimator { - struct gen_estimator *next; + struct list_head list; struct gnet_stats_basic *bstats; struct gnet_stats_rate_est *rate_est; spinlock_t *stats_lock; - unsigned interval; int ewma_log; u64 last_bytes; u32 last_packets; u32 avpps; u32 avbps; + struct rcu_head e_rcu; }; struct gen_estimator_head { struct timer_list timer; - struct gen_estimator *list; + struct list_head list; }; static struct gen_estimator_head elist[EST_MAX_INTERVAL+1]; -/* Estimator array lock */ +/* Protects against NULL dereference */ static DEFINE_RWLOCK(est_lock); static void est_timer(unsigned long arg) @@ -107,13 +107,17 @@ static void est_timer(unsigned long arg) int idx = (int)arg; struct gen_estimator *e; - read_lock(&est_lock); - for (e = elist[idx].list; e; e = e->next) { + rcu_read_lock(); + list_for_each_entry_rcu(e, &elist[idx].list, list) { u64 nbytes; u32 npackets; u32 rate; spin_lock(e->stats_lock); + read_lock(&est_lock); + if (e->bstats == NULL) + goto skip; + nbytes = e->bstats->bytes; npackets = e->bstats->packets; rate = (nbytes - e->last_bytes)<<(7 - idx); @@ -125,11 +129,14 @@ static void est_timer(unsigned long arg) e->last_packets = npackets; e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log; e->rate_est->pps = (e->avpps+0x1FF)>>10; +skip: + read_unlock(&est_lock); spin_unlock(e->stats_lock); } - mod_timer(&elist[idx].timer, jiffies + ((HZ<interval = parm->interval + 2; + idx = parm->interval + 2; est->bstats = bstats; est->rate_est = rate_est; est->stats_lock = stats_lock; @@ -173,20 +185,25 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10; - est->next = elist[est->interval].list; - if (est->next == NULL) { - init_timer(&elist[est->interval].timer); - elist[est->interval].timer.data = est->interval; - elist[est->interval].timer.expires = jiffies + ((HZ<interval)/4); - elist[est->interval].timer.function = est_timer; - add_timer(&elist[est->interval].timer); + if (!elist[idx].timer.function) { + INIT_LIST_HEAD(&elist[idx].list); + setup_timer(&elist[idx].timer, est_timer, idx); } - write_lock_bh(&est_lock); - elist[est->interval].list = est; - write_unlock_bh(&est_lock); + + if (list_empty(&elist[idx].list)) + mod_timer(&elist[idx].timer, jiffies + ((HZ<list, &elist[idx].list); return 0; } +static void __gen_kill_estimator(struct rcu_head *head) +{ + struct gen_estimator *e = container_of(head, + struct gen_estimator, e_rcu); + kfree(e); +} + /** * gen_kill_estimator - remove a rate estimator * @bstats: basic statistics @@ -194,31 +211,32 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, * * Removes the rate estimator specified by &bstats and &rate_est * and deletes the timer. + * + * NOTE: Called under rtnl_mutex */ void gen_kill_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est) { int idx; - struct gen_estimator *est, **pest; + struct gen_estimator *e, *n; for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { - int killed = 0; - pest = &elist[idx].list; - while ((est=*pest) != NULL) { - if (est->rate_est != rate_est || est->bstats != bstats) { - pest = &est->next; + + /* Skip non initialized indexes */ + if (!elist[idx].timer.function) + continue; + + list_for_each_entry_safe(e, n, &elist[idx].list, list) { + if (e->rate_est != rate_est || e->bstats != bstats) continue; - } write_lock_bh(&est_lock); - *pest = est->next; + e->bstats = NULL; write_unlock_bh(&est_lock); - kfree(est); - killed++; + list_del_rcu(&e->list); + call_rcu(&e->e_rcu, __gen_kill_estimator); } - if (killed && elist[idx].list == NULL) - del_timer(&elist[idx].timer); } } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a0efdd7..5df8cf4 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -781,7 +781,6 @@ void netpoll_cleanup(struct netpoll *np) spin_unlock_irqrestore(&npinfo->rx_lock, flags); } - np->dev->npinfo = NULL; if (atomic_dec_and_test(&npinfo->refcnt)) { skb_queue_purge(&npinfo->arp_tx); skb_queue_purge(&npinfo->txq); @@ -794,6 +793,7 @@ void netpoll_cleanup(struct netpoll *np) kfree_skb(skb); } kfree(npinfo); + np->dev->npinfo = NULL; } } diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9cd3a1c..33190c3 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -111,6 +111,9 @@ * * 802.1Q/Q-in-Q support by Francesco Fondelli (FF) * + * Fixed src_mac command to set source mac of packet to value specified in + * command by Adit Ranadive + * */ #include #include @@ -1415,8 +1418,11 @@ static ssize_t pktgen_if_write(struct file *file, } if (!strcmp(name, "src_mac")) { char *v = valstr; + unsigned char old_smac[ETH_ALEN]; unsigned char *m = pkt_dev->src_mac; + memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN); + len = strn_len(&user_buffer[i], sizeof(valstr) - 1); if (len < 0) { return len; @@ -1445,6 +1451,10 @@ static ssize_t pktgen_if_write(struct file *file, } } + /* Set up Src MAC */ + if (compare_ether_addr(old_smac, pkt_dev->src_mac)) + memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN); + sprintf(pg_result, "OK: srcmac"); return count; } diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 248d20f..d29b88f 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -298,7 +298,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) int rc; ccid2_pr_debug("allocating more space in history\n"); - rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL); + rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, gfp_any()); BUG_ON(rc); /* XXX what do we do? */ next = hctx->ccid2hctx_seqh->ccid2s_next; diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index ab41c18..d46e453 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -815,7 +815,7 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) for (ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) { if (dn_idx < skip_naddr) - goto cont; + continue; if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR, diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index cc8110b..afb6c66 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -271,8 +271,11 @@ ieee80211softmac_assoc_work(struct work_struct *work) */ dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); - if (ieee80211softmac_start_scan(mac)) + if (ieee80211softmac_start_scan(mac)) { dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); + mac->associnfo.associating = 0; + mac->associnfo.associated = 0; + } goto out; } else { mac->associnfo.associating = 0; diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index f13937b..d054e92 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -74,8 +74,8 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, struct ieee80211softmac_auth_queue_item *authptr; int length = 0; +check_assoc_again: mutex_lock(&sm->associnfo.mutex); - /* Check if we're already associating to this or another network * If it's another network, cancel and start over with our new network * If it's our network, ignore the change, we're already doing it! @@ -98,13 +98,18 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, cancel_delayed_work(&authptr->work); sm->associnfo.bssvalid = 0; sm->associnfo.bssfixed = 0; - flush_scheduled_work(); sm->associnfo.associating = 0; sm->associnfo.associated = 0; + /* We must unlock to avoid deadlocks with the assoc workqueue + * on the associnfo.mutex */ + mutex_unlock(&sm->associnfo.mutex); + flush_scheduled_work(); + /* Avoid race! Check assoc status again. Maybe someone started an + * association while we flushed. */ + goto check_assoc_again; } } - sm->associnfo.static_essid = 0; sm->associnfo.assoc_wait = 0; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 041fba3..90b241c 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -831,7 +831,7 @@ const struct proto_ops inet_stream_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, - .sendmsg = inet_sendmsg, + .sendmsg = tcp_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, .sendpage = tcp_sendpage, diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 6da8ff5..c79a24e 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -46,7 +46,7 @@ static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr) memcpy(daddr, optptr+optlen-4, 4); /* Fall through */ default: - memset(optptr+2, 0, optlen-2); + memset(optptr, 0, optlen); } l -= optlen; optptr += optlen; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index abf6352..0dcc245 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1194,7 +1194,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { if (ip_idx < s_ip_idx) - goto cont; + continue; if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR, NLM_F_MULTI) <= 0) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index dbeacd8..def007e 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -836,12 +836,16 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return inet_diag_get_exact(skb, nlh); } +static DEFINE_MUTEX(inet_diag_mutex); + static void inet_diag_rcv(struct sock *sk, int len) { unsigned int qlen = 0; do { + mutex_lock(&inet_diag_mutex); netlink_run_queue(sk, &qlen, &inet_diag_rcv_msg); + mutex_unlock(&inet_diag_mutex); } while (qlen); } diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index a42c5cd..361be2b 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -477,10 +477,8 @@ static int __init ipt_log_init(void) ret = xt_register_target(&ipt_log_reg); if (ret < 0) return ret; - ret = nf_log_register(PF_INET, &ipt_log_logger); - if (ret < 0 && ret != -EEXIST) - xt_unregister_target(&ipt_log_reg); - return ret; + nf_log_register(PF_INET, &ipt_log_logger); + return 0; } static void __exit ipt_log_fini(void) diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index f4fc657..474b4ce 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -189,25 +189,13 @@ icmp_error_message(struct sk_buff *skb, h = nf_conntrack_find_get(&innertuple, NULL); if (!h) { - /* Locally generated ICMPs will match inverted if they - haven't been SNAT'ed yet */ - /* FIXME: NAT code has to handle half-done double NAT --RR */ - if (hooknum == NF_IP_LOCAL_OUT) - h = nf_conntrack_find_get(&origtuple, NULL); - - if (!h) { - DEBUGP("icmp_error_message: no match\n"); - return -NF_ACCEPT; - } - - /* Reverse direction from that found */ - if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) - *ctinfo += IP_CT_IS_REPLY; - } else { - if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) - *ctinfo += IP_CT_IS_REPLY; + DEBUGP("icmp_error_message: no match\n"); + return -NF_ACCEPT; } + if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) + *ctinfo += IP_CT_IS_REPLY; + /* Update skb to refer to this connection */ skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; skb->nfctinfo = *ctinfo; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 450f44b..11ff182 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -658,9 +658,10 @@ static inline int select_size(struct sock *sk) return tmp; } -int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, +int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size) { + struct sock *sk = sock->sk; struct iovec *iov; struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 69f9f1e..5bfda70 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -102,11 +102,14 @@ int sysctl_tcp_abc __read_mostly; #define FLAG_DATA_LOST 0x80 /* SACK detected data lossage. */ #define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/ #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ +#define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ +#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */ #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) #define FLAG_CA_ALERT (FLAG_DATA_SACKED|FLAG_ECE) #define FLAG_FORWARD_PROGRESS (FLAG_ACKED|FLAG_DATA_SACKED) +#define FLAG_ANY_PROGRESS (FLAG_FORWARD_PROGRESS|FLAG_SND_UNA_ADVANCED) #define IsReno(tp) ((tp)->rx_opt.sack_ok == 0) #define IsFack(tp) ((tp)->rx_opt.sack_ok & 2) @@ -964,12 +967,14 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ /* Check for D-SACK. */ if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) { + flag |= FLAG_DSACKING_ACK; found_dup_sack = 1; tp->rx_opt.sack_ok |= 4; NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV); } else if (num_sacks > 1 && !after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) && !before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) { + flag |= FLAG_DSACKING_ACK; found_dup_sack = 1; tp->rx_opt.sack_ok |= 4; NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV); @@ -1398,7 +1403,9 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) * waiting for the first ACK and did not get it)... */ if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) { - tp->retrans_out += tcp_skb_pcount(skb); + /* For some reason this R-bit might get cleared? */ + if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) + tp->retrans_out += tcp_skb_pcount(skb); /* ...enter this if branch just for the first segment */ flag |= FLAG_DATA_ACKED; } else { @@ -1849,19 +1856,22 @@ static inline u32 tcp_cwnd_min(const struct sock *sk) } /* Decrease cwnd each second ack. */ -static void tcp_cwnd_down(struct sock *sk) +static void tcp_cwnd_down(struct sock *sk, int flag) { struct tcp_sock *tp = tcp_sk(sk); int decr = tp->snd_cwnd_cnt + 1; - tp->snd_cwnd_cnt = decr&1; - decr >>= 1; + if ((flag&(FLAG_ANY_PROGRESS|FLAG_DSACKING_ACK)) || + (IsReno(tp) && !(flag&FLAG_NOT_DUP))) { + tp->snd_cwnd_cnt = decr&1; + decr >>= 1; - if (decr && tp->snd_cwnd > tcp_cwnd_min(sk)) - tp->snd_cwnd -= decr; + if (decr && tp->snd_cwnd > tcp_cwnd_min(sk)) + tp->snd_cwnd -= decr; - tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1); - tp->snd_cwnd_stamp = tcp_time_stamp; + tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1); + tp->snd_cwnd_stamp = tcp_time_stamp; + } } /* Nothing was retransmitted or returned timestamp is less @@ -2058,7 +2068,7 @@ static void tcp_try_to_open(struct sock *sk, int flag) } tcp_moderate_cwnd(tp); } else { - tcp_cwnd_down(sk); + tcp_cwnd_down(sk, flag); } } @@ -2107,7 +2117,9 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); - int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP)); + int is_dupack = !(flag&(FLAG_SND_UNA_ADVANCED|FLAG_NOT_DUP)); + int do_lost = is_dupack || ((flag&FLAG_DATA_SACKED) && + (tp->fackets_out > tp->reordering)); /* Some technical things: * 1. Reno does not count dupacks (sacked_out) automatically. */ @@ -2191,7 +2203,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, int acked = prior_packets - tp->packets_out; if (IsReno(tp)) tcp_remove_reno_sacks(sk, acked); - is_dupack = tcp_try_undo_partial(sk, acked); + do_lost = tcp_try_undo_partial(sk, acked); } break; case TCP_CA_Loss: @@ -2256,9 +2268,9 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, tcp_set_ca_state(sk, TCP_CA_Recovery); } - if (is_dupack || tcp_head_timedout(sk)) + if (do_lost || tcp_head_timedout(sk)) tcp_update_scoreboard(sk); - tcp_cwnd_down(sk); + tcp_cwnd_down(sk, flag); tcp_xmit_retransmit_queue(sk); } @@ -2766,6 +2778,9 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) if (before(ack, prior_snd_una)) goto old_ack; + if (after(ack, prior_snd_una)) + flag |= FLAG_SND_UNA_ADVANCED; + if (sysctl_tcp_abc) { if (icsk->icsk_ca_state < TCP_CA_CWR) tp->bytes_acked += ack - prior_snd_una; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 354721d..fa36e1a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2434,7 +2434,6 @@ struct proto tcp_prot = { .shutdown = tcp_shutdown, .setsockopt = tcp_setsockopt, .getsockopt = tcp_getsockopt, - .sendmsg = tcp_sendmsg, .recvmsg = tcp_recvmsg, .backlog_rcv = tcp_v4_do_rcv, .hash = tcp_v4_hash, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f96ed76..a908e50 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1021,7 +1021,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, hiscore.rule++; } if (ipv6_saddr_preferred(score.addr_type) || - (((ifa_result->flags & + (((ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { score.attrs |= IPV6_SADDR_SCORE_PREFERRED; if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { @@ -2472,6 +2472,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_unlock_bh(&idev->lock); __ipv6_ifa_notify(RTM_DELADDR, ifa); + atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); in6_ifa_put(ifa); write_lock_bh(&idev->lock); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 6dd3772..b1a7755 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -487,7 +487,7 @@ const struct proto_ops inet6_stream_ops = { .shutdown = inet_shutdown, /* ok */ .setsockopt = sock_common_setsockopt, /* ok */ .getsockopt = sock_common_getsockopt, /* ok */ - .sendmsg = inet_sendmsg, /* ok */ + .sendmsg = tcp_sendmsg, /* ok */ .recvmsg = sock_common_recvmsg, /* ok */ .mmap = sock_no_mmap, .sendpage = tcp_sendpage, diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 9b81264..2f49578 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -66,6 +66,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev) break; } read_unlock_bh(&idev->lock); + in6_dev_put(idev); } rcu_read_unlock(); return onlink; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index e9bcce9..c956037 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -604,7 +604,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) read_lock(&raw_v6_lock); if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { - while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, + while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr, IP6CB(skb)->iif))) { rawv6_err(sk, skb, NULL, type, code, inner_offset, info); sk = sk_next(sk); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4704b5f..4233a95 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -790,7 +790,7 @@ slow_path: /* * Copy a block of the IP datagram. */ - if (skb_copy_bits(skb, ptr, skb_transport_header(skb), len)) + if (skb_copy_bits(skb, ptr, skb_transport_header(frag), len)) BUG(); left -= len; @@ -1423,8 +1423,9 @@ void ip6_flush_pending_frames(struct sock *sk) struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { - IP6_INC_STATS(ip6_dst_idev(skb->dst), - IPSTATS_MIB_OUTDISCARDS); + if (skb->dst) + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index a0902fb..31f9252 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -962,8 +962,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) dsfield = ipv4_get_dsfield(iph); if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) - fl.fl6_flowlabel |= ntohl(((__u32)iph->tos << IPV6_TCLASS_SHIFT) - & IPV6_TCLASS_MASK); + fl.fl6_flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) + & IPV6_TCLASS_MASK; err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu); if (err != 0) { diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index aa3d07c..f329029 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -825,7 +825,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, return 0; len = min_t(unsigned int, len, ipv6_optlen(hdr)); - if (copy_to_user(optval, hdr, len)); + if (copy_to_user(optval, hdr, len)) return -EFAULT; return ipv6_optlen(hdr); } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0358e60..73a894a 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -736,7 +736,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) * so fail our DAD process */ addrconf_dad_failure(ifp); - goto out; + return; } else { /* * This is not a dad solicitation. diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 5bb9cd3..a7a2517 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -490,10 +490,8 @@ static int __init ip6t_log_init(void) ret = xt_register_target(&ip6t_log_reg); if (ret < 0) return ret; - ret = nf_log_register(PF_INET6, &ip6t_logger); - if (ret < 0 && ret != -EEXIST) - xt_unregister_target(&ip6t_log_reg); - return ret; + nf_log_register(PF_INET6, &ip6t_logger); + return 0; } static void __exit ip6t_log_fini(void) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index a58459a..fc5cb83 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -858,11 +858,10 @@ back_from_confirm: ip6_flush_pending_frames(sk); else if (!(msg->msg_flags & MSG_MORE)) err = rawv6_push_pending_frames(sk, &fl, rp); + release_sock(sk); } done: dst_release(dst); - if (!inet->hdrincl) - release_sock(sk); out: fl6_sock_release(flowlabel); return err<0?err:len; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 193d9d6..9b81cbc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -644,6 +644,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) if (tp->md5sig_info->entries6 == 0) { kfree(tp->md5sig_info->keys6); tp->md5sig_info->keys6 = NULL; + tp->md5sig_info->alloced6 = 0; tcp_free_md5sig_pool(); @@ -2134,7 +2135,6 @@ struct proto tcpv6_prot = { .shutdown = tcp_shutdown, .setsockopt = tcp_setsockopt, .getsockopt = tcp_getsockopt, - .sendmsg = tcp_sendmsg, .recvmsg = tcp_recvmsg, .backlog_rcv = tcp_v6_do_rcv, .hash = tcp_v6_hash, diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 0d3254b..6e41ba5 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -460,7 +460,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, SCTP_CONNTRACK_NONE, sch->type); /* Invalid: delete conntrack */ - if (newconntrack == SCTP_CONNTRACK_MAX) { + if (newconntrack == SCTP_CONNTRACK_NONE || + newconntrack == SCTP_CONNTRACK_MAX) { DEBUGP("nf_conntrack_sctp: invalid new deleting.\n"); return 0; } diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index e5c840c..230e35c 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c @@ -55,7 +55,7 @@ static void rfkill_task_handler(struct work_struct *work) static void rfkill_schedule_toggle(struct rfkill_task *task) { - unsigned int flags; + unsigned long flags; spin_lock_irqsave(&task->lock, flags); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index bec600a..7a6b0b7 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -290,11 +290,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) wd->qdisc->flags &= ~TCQ_F_THROTTLED; smp_wmb(); - if (spin_trylock(&dev->queue_lock)) { - qdisc_run(dev); - spin_unlock(&dev->queue_lock); - } else - netif_schedule(dev); + netif_schedule(dev); return HRTIMER_NORESTART; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 2c29394..2164b51 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -875,6 +875,10 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) dev = dev_get_by_index(addr->v6.sin6_scope_id); if (!dev) return 0; + if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) { + dev_put(dev); + return 0; + } dev_put(dev); } af = opt->pf->af; diff --git a/net/socket.c b/net/socket.c index f453019..0010da0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1169,7 +1169,7 @@ static int __sock_create(int family, int type, int protocol, module_put(pf->owner); err = security_socket_post_create(sock, family, type, protocol, kern); if (err) - goto out_release; + goto out_sock_release; *res = sock; return 0; diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 099a983..805e725 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -760,11 +760,12 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) new->h.flavour = &svcauthops_gss; new->pseudoflavor = pseudoflavor; + stat = 0; test = auth_domain_lookup(name, &new->h); - if (test != &new->h) { /* XXX Duplicate registration? */ - auth_domain_put(&new->h); - /* dangling ref-count... */ - goto out; + if (test != &new->h) { /* Duplicate registration */ + auth_domain_put(test); + kfree(new->h.name); + goto out_free_dom; } return 0; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 5baf48d..80a0091 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1090,7 +1090,8 @@ svc_tcp_accept(struct svc_sock *svsk) serv->sv_name); printk(KERN_NOTICE "%s: last TCP connect from %s\n", - serv->sv_name, buf); + serv->sv_name, __svc_print_addr(sin, + buf, sizeof(buf))); } /* * Always select the oldest socket. It's not fair, @@ -1572,7 +1573,8 @@ svc_age_temp_sockets(unsigned long closure) if (!test_and_set_bit(SK_OLD, &svsk->sk_flags)) continue; - if (atomic_read(&svsk->sk_inuse) || test_bit(SK_BUSY, &svsk->sk_flags)) + if (atomic_read(&svsk->sk_inuse) > 1 + || test_bit(SK_BUSY, &svsk->sk_flags)) continue; atomic_inc(&svsk->sk_inuse); list_move(le, &to_be_aged); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 157bfbd..b48f06f 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2141,7 +2141,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, if (last == first) break; - last = last->u.next; + last = (struct xfrm_dst *)last->u.dst.next; last->child_mtu_cached = mtu; } diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 1199baf..45550d2 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -64,7 +64,7 @@ static void check_stdin(void) } } -static void conf_askvalue(struct symbol *sym, const char *def) +static int conf_askvalue(struct symbol *sym, const char *def) { enum symbol_type type = sym_get_type(sym); tristate val; @@ -79,7 +79,7 @@ static void conf_askvalue(struct symbol *sym, const char *def) printf("%s\n", def); line[0] = '\n'; line[1] = 0; - return; + return 0; } switch (input_mode) { @@ -89,23 +89,23 @@ static void conf_askvalue(struct symbol *sym, const char *def) case set_random: if (sym_has_value(sym)) { printf("%s\n", def); - return; + return 0; } break; case ask_new: case ask_silent: if (sym_has_value(sym)) { printf("%s\n", def); - return; + return 0; } check_stdin(); case ask_all: fflush(stdout); fgets(line, 128, stdin); - return; + return 1; case set_default: printf("%s\n", def); - return; + return 1; default: break; } @@ -115,7 +115,7 @@ static void conf_askvalue(struct symbol *sym, const char *def) case S_HEX: case S_STRING: printf("%s\n", def); - return; + return 1; default: ; } @@ -166,6 +166,7 @@ static void conf_askvalue(struct symbol *sym, const char *def) break; } printf("%s", line); + return 1; } int conf_string(struct menu *menu) @@ -179,7 +180,8 @@ int conf_string(struct menu *menu) def = sym_get_string_value(sym); if (sym_get_string_value(sym)) printf("[%s] ", def); - conf_askvalue(sym, def); + if (!conf_askvalue(sym, def)) + return 0; switch (line[0]) { case '\n': break; @@ -236,7 +238,8 @@ static int conf_sym(struct menu *menu) if (sym->help) printf("/?"); printf("] "); - conf_askvalue(sym, sym_get_string_value(sym)); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; strip(line); switch (line[0]) { diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index f057430..9b5656d 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -481,53 +482,54 @@ static void free_all_reserved_pages(void) #define SND_MEM_PROC_FILE "driver/snd-page-alloc" static struct proc_dir_entry *snd_mem_proc; -static int snd_mem_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int snd_mem_proc_read(struct seq_file *seq, void *offset) { - int len = 0; long pages = snd_allocated_pages >> (PAGE_SHIFT-12); struct snd_mem_list *mem; int devno; static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" }; mutex_lock(&list_mutex); - len += snprintf(page + len, count - len, - "pages : %li bytes (%li pages per %likB)\n", - pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); + seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", + pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); devno = 0; list_for_each_entry(mem, &mem_list_head, list) { devno++; - len += snprintf(page + len, count - len, - "buffer %d : ID %08x : type %s\n", - devno, mem->id, types[mem->buffer.dev.type]); - len += snprintf(page + len, count - len, - " addr = 0x%lx, size = %d bytes\n", - (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes); + seq_printf(seq, "buffer %d : ID %08x : type %s\n", + devno, mem->id, types[mem->buffer.dev.type]); + seq_printf(seq, " addr = 0x%lx, size = %d bytes\n", + (unsigned long)mem->buffer.addr, + (int)mem->buffer.bytes); } mutex_unlock(&list_mutex); - return len; + return 0; +} + +static int snd_mem_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, snd_mem_proc_read, NULL); } /* FIXME: for pci only - other bus? */ #ifdef CONFIG_PCI #define gettoken(bufp) strsep(bufp, " \t\n") -static int snd_mem_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, + size_t count, loff_t * ppos) { char buf[128]; char *token, *p; - if (count > ARRAY_SIZE(buf) - 1) - count = ARRAY_SIZE(buf) - 1; + if (count > sizeof(buf) - 1) + return -EINVAL; if (copy_from_user(buf, buffer, count)) return -EFAULT; - buf[ARRAY_SIZE(buf) - 1] = '\0'; + buf[count] = '\0'; p = buf; token = gettoken(&p); if (! token || *token == '#') - return (int)count; + return count; if (strcmp(token, "add") == 0) { char *endp; int vendor, device, size, buffers; @@ -548,7 +550,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer, (buffers = simple_strtol(token, NULL, 0)) <= 0 || buffers > 4) { printk(KERN_ERR "snd-page-alloc: invalid proc write format\n"); - return (int)count; + return count; } vendor &= 0xffff; device &= 0xffff; @@ -560,7 +562,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer, if (pci_set_dma_mask(pci, mask) < 0 || pci_set_consistent_dma_mask(pci, mask) < 0) { printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device); - return (int)count; + return count; } } for (i = 0; i < buffers; i++) { @@ -570,7 +572,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer, size, &dmab) < 0) { printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); pci_dev_put(pci); - return (int)count; + return count; } snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); } @@ -596,9 +598,21 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer, free_all_reserved_pages(); else printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n"); - return (int)count; + return count; } #endif /* CONFIG_PCI */ + +static const struct file_operations snd_mem_proc_fops = { + .owner = THIS_MODULE, + .open = snd_mem_proc_open, + .read = seq_read, +#ifdef CONFIG_PCI + .write = snd_mem_proc_write, +#endif + .llseek = seq_lseek, + .release = single_release, +}; + #endif /* CONFIG_PROC_FS */ /* @@ -609,12 +623,8 @@ static int __init snd_mem_init(void) { #ifdef CONFIG_PROC_FS snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL); - if (snd_mem_proc) { - snd_mem_proc->read_proc = snd_mem_proc_read; -#ifdef CONFIG_PCI - snd_mem_proc->write_proc = snd_mem_proc_write; -#endif - } + if (snd_mem_proc) + snd_mem_proc->proc_fops = &snd_mem_proc_fops; #endif return 0; }