diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt index fafcd47..afe596d 100644 --- a/Documentation/usb/proc_usb_info.txt +++ b/Documentation/usb/proc_usb_info.txt @@ -1,12 +1,17 @@ /proc/bus/usb filesystem output =============================== -(version 2003.05.30) +(version 2010.09.13) The usbfs filesystem for USB devices is traditionally mounted at /proc/bus/usb. It provides the /proc/bus/usb/devices file, as well as the /proc/bus/usb/BBB/DDD files. +In many modern systems the usbfs filsystem isn't used at all. Instead +USB device nodes are created under /dev/usb/ or someplace similar. The +"devices" file is available in debugfs, typically as +/sys/kernel/debug/usb/devices. + **NOTE**: If /proc/bus/usb appears empty, and a host controller driver has been linked, then you need to mount the @@ -106,8 +111,8 @@ Legend: Topology info: -T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd -| | | | | | | | |__MaxChildren +T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd +| | | | | | | | |__MaxChildren | | | | | | | |__Device Speed in Mbps | | | | | | |__DeviceNumber | | | | | |__Count of devices at this level @@ -120,8 +125,13 @@ T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd Speed may be: 1.5 Mbit/s for low speed USB 12 Mbit/s for full speed USB - 480 Mbit/s for high speed USB (added for USB 2.0) + 480 Mbit/s for high speed USB (added for USB 2.0); + also used for Wireless USB, which has no fixed speed + 5000 Mbit/s for SuperSpeed USB (added for USB 3.0) + For reasons lost in the mists of time, the Port number is always + too low by 1. For example, a device plugged into port 4 will + show up with "Port=03". Bandwidth info: B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd @@ -291,7 +301,7 @@ Here's an example, from a system which has a UHCI root hub, an external hub connected to the root hub, and a mouse and a serial converter connected to the external hub. -T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0000 ProdID=0000 Rev= 0.00 @@ -301,21 +311,21 @@ C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms -T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0451 ProdID=1446 Rev= 1.00 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms -T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=04b4 ProdID=0001 Rev= 0.00 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms -T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0565 ProdID=0001 Rev= 1.08 S: Manufacturer=Peracom Networks, Inc. @@ -330,12 +340,12 @@ E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms Selecting only the "T:" and "I:" lines from this (for example, by using "procusb ti"), we have: -T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 -T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub -T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse -T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial diff --git a/MAINTAINERS b/MAINTAINERS index 502b380..52bec00 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5306,7 +5306,6 @@ F: arch/alpha/kernel/srm_env.c STABLE BRANCH M: Greg Kroah-Hartman -M: Chris Wright L: stable@kernel.org S: Maintained diff --git a/Makefile b/Makefile index 833008c..3889155 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 34 -EXTRAVERSION = .10 +EXTRAVERSION = .11 NAME = Sheep on Meth # *DOCUMENTATION* diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 33ff678..73bb15c 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -311,7 +311,7 @@ asmlinkage long sys_oabi_semtimedop(int semid, long err; int i; - if (nsops < 1) + if (nsops < 1 || nsops > SEMOPM) return -EINVAL; sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); if (!sops) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index a0220dc..6871c1b 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1859,7 +1859,8 @@ ia64_mca_cpu_init(void *cpu_data) data = mca_bootmem(); first_time = 0; } else - data = __get_free_pages(GFP_KERNEL, get_order(sz)); + data = (void *)__get_free_pages(GFP_KERNEL, + get_order(sz)); if (!data) panic("Could not allocate MCA memory for cpu %d\n", cpu); diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 4d4536e..9c271be 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -509,7 +509,7 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * use the GART mapped mode. */ static u64 -tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) +tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags) { u64 mapaddr; diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index 02b7a03..8b3db1c 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -300,6 +300,8 @@ void __init paging_init(void) zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT; free_area_init_node(i, zones_size, m68k_memory[i].addr >> PAGE_SHIFT, NULL); + if (node_present_pages(i)) + node_set_state(i, N_NORMAL_MEMORY); } } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index f4f4d70..7fd8aad 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -266,8 +266,10 @@ static void __init setup_bootmem(void) } memset(pfnnid_map, 0xff, sizeof(pfnnid_map)); - for (i = 0; i < npmem_ranges; i++) + for (i = 0; i < npmem_ranges; i++) { + node_set_state(i, N_NORMAL_MEMORY); node_set_online(i); + } #endif /* diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index bb2465b..22b527b 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -367,7 +367,7 @@ INSTALL := install extra-installed := $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y)) hostprogs-installed := $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs-y)) wrapper-installed := $(DESTDIR)$(WRAPPER_BINDIR)/wrapper -dts-installed := $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(obj)/dts/*.dts)) +dts-installed := $(patsubst $(dtstree)/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(dtstree)/*.dts)) all-installed := $(extra-installed) $(hostprogs-installed) $(wrapper-installed) $(dts-installed) diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 7fe3b30..49d7c96 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -78,6 +78,7 @@ #define APIC_DEST_LOGICAL 0x00800 #define APIC_DEST_PHYSICAL 0x00000 #define APIC_DM_FIXED 0x00000 +#define APIC_DM_FIXED_MASK 0x00700 #define APIC_DM_LOWEST 0x00100 #define APIC_DM_SMI 0x00200 #define APIC_DM_REMRD 0x00300 diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 5928fc0..ad6338e 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -82,11 +82,15 @@ #define MSR_IA32_MC0_ADDR 0x00000402 #define MSR_IA32_MC0_MISC 0x00000403 +#define MSR_AMD64_MC0_MASK 0xc0010044 + #define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) #define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x)) #define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x)) #define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x)) +#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) + /* These are consecutive and not in the normal 4er MCE bank block */ #define MSR_IA32_MC0_CTL2 0x00000280 #define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 6757357..7eb1dd7 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -1031,4 +1031,23 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, return ratio; } +/* + * AMD errata checking + */ +#ifdef CONFIG_CPU_SUP_AMD +extern const int amd_erratum_400[]; +extern bool cpu_has_amd_erratum(const int *); + +#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } +#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 } +#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ + ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) +#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff) +#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff) +#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff) + +#else +#define cpu_has_amd_erratum(x) (false) +#endif /* CONFIG_CPU_SUP_AMD */ + #endif /* _ASM_X86_PROCESSOR_H */ diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index daaacab..982aa32 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -12,4 +12,42 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall, struct timespec *ts); void pvclock_resume(void); +/* + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, + * yielding a 64-bit result. + */ +static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) +{ + u64 product; +#ifdef __i386__ + u32 tmp1, tmp2; +#endif + + if (shift < 0) + delta >>= -shift; + else + delta <<= shift; + +#ifdef __i386__ + __asm__ ( + "mul %5 ; " + "mov %4,%%eax ; " + "mov %%edx,%4 ; " + "mul %5 ; " + "xor %5,%5 ; " + "add %4,%%eax ; " + "adc %5,%%edx ; " + : "=A" (product), "=r" (tmp1), "=r" (tmp2) + : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); +#elif defined(__x86_64__) + __asm__ ( + "mul %%rdx ; shrd $32,%%rdx,%%rax" + : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) ); +#else +#error implement me! +#endif + + return product; +} + #endif /* _ASM_X86_PVCLOCK_H */ diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e485825..770346d 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -565,6 +565,32 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } } #endif + + /* + * Family 0x12 and above processors have APIC timer + * running in deep C states. + */ + if (c->x86 > 0x11) + set_cpu_cap(c, X86_FEATURE_ARAT); + + /* + * Disable GART TLB Walk Errors on Fam10h. We do this here + * because this is always needed when GART is enabled, even in a + * kernel which has no MCE support built in. + */ + if (c->x86 == 0x10) { + /* + * BIOS should disable GartTlbWlk Errors themself. If + * it doesn't do it here as suggested by the BKDG. + * + * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012 + */ + u64 mask; + + rdmsrl(MSR_AMD64_MCx_MASK(4), mask); + mask |= (1 << 10); + wrmsrl(MSR_AMD64_MCx_MASK(4), mask); + } } #ifdef CONFIG_X86_32 @@ -609,3 +635,68 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = { }; cpu_dev_register(amd_cpu_dev); + +/* + * AMD errata checking + * + * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or + * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that + * have an OSVW id assigned, which it takes as first argument. Both take a + * variable number of family-specific model-stepping ranges created by + * AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const + * int[] in arch/x86/include/asm/processor.h. + * + * Example: + * + * const int amd_erratum_319[] = + * AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2), + * AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0), + * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); + */ + +const int amd_erratum_400[] = + AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), + AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); + + +bool cpu_has_amd_erratum(const int *erratum) +{ + struct cpuinfo_x86 *cpu = ¤t_cpu_data; + int osvw_id = *erratum++; + u32 range; + u32 ms; + + /* + * If called early enough that current_cpu_data hasn't been initialized + * yet, fall back to boot_cpu_data. + */ + if (cpu->x86 == 0) + cpu = &boot_cpu_data; + + if (cpu->x86_vendor != X86_VENDOR_AMD) + return false; + + if (osvw_id >= 0 && osvw_id < 65536 && + cpu_has(cpu, X86_FEATURE_OSVW)) { + u64 osvw_len; + + rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len); + if (osvw_id < osvw_len) { + u64 osvw_bits; + + rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6), + osvw_bits); + return osvw_bits & (1ULL << (osvw_id & 0x3f)); + } + } + + /* OSVW unavailable or ID unknown, match family-model-stepping range */ + ms = (cpu->x86_model << 4) | cpu->x86_mask; + while ((range = *erratum++)) + if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && + (ms >= AMD_MODEL_RANGE_START(range)) && + (ms <= AMD_MODEL_RANGE_END(range))) + return true; + + return false; +} diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index f80ff85..1bdce34 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -469,6 +469,7 @@ recurse: out_free: if (b) { kobject_put(&b->kobj); + list_del(&b->miscj); kfree(b); } return err; diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 81c499e..493b668 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -293,18 +293,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c) */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); + h = lvtthmr_init; /* * The initial value of thermal LVT entries on all APs always reads * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI * sequence to them and LVT registers are reset to 0s except for * the mask bits which are set to 1s when APs receive INIT IPI. - * Always restore the value that BIOS has programmed on AP based on - * BSP's info we saved since BIOS is always setting the same value - * for all threads/cores + * If BIOS takes over the thermal interrupt and sets its interrupt + * delivery mode to SMI (not fixed), it restores the value that the + * BIOS has programmed on AP based on BSP's info we saved since BIOS + * is always setting the same value for all threads/cores. */ - apic_write(APIC_LVTTHMR, lvtthmr_init); + if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED) + apic_write(APIC_LVTTHMR, lvtthmr_init); - h = lvtthmr_init; if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { printk(KERN_DEBUG diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index e253288..34b4e2f 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -263,14 +263,24 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ /* * HACK! - * We use this same function to initialize the mtrrs on boot. - * The state of the boot cpu's mtrrs has been saved, and we want - * to replicate across all the APs. - * If we're doing that @reg is set to something special... + * + * We use this same function to initialize the mtrrs during boot, + * resume, runtime cpu online and on an explicit request to set a + * specific MTRR. + * + * During boot or suspend, the state of the boot cpu's mtrrs has been + * saved, and we want to replicate that across all the cpus that come + * online (either at the end of boot or resume or during a runtime cpu + * online). If we're doing that, @reg is set to something special and on + * this cpu we still do mtrr_if->set_all(). During boot/resume, this + * is unnecessary if at this point we are still on the cpu that started + * the boot/resume sequence. But there is no guarantee that we are still + * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be + * sure that we are in sync with everyone else. */ if (reg != ~0U) mtrr_if->set(reg, base, size, type); - else if (!mtrr_aps_delayed_init) + else mtrr_if->set_all(); /* Wait for the others */ diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index e1af7c0..ed47400 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -66,7 +66,6 @@ struct microcode_amd { unsigned int mpb[0]; }; -#define UCODE_MAX_SIZE 2048 #define UCODE_CONTAINER_SECTION_HDR 8 #define UCODE_CONTAINER_HEADER_SIZE 12 @@ -155,6 +154,37 @@ static int apply_microcode_amd(int cpu) return 0; } +static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + unsigned int max_size, actual_size; + +#define F1XH_MPB_MAX_SIZE 2048 +#define F14H_MPB_MAX_SIZE 1824 +#define F15H_MPB_MAX_SIZE 4096 + + switch (c->x86) { + case 0x14: + max_size = F14H_MPB_MAX_SIZE; + break; + case 0x15: + max_size = F15H_MPB_MAX_SIZE; + break; + default: + max_size = F1XH_MPB_MAX_SIZE; + break; + } + + actual_size = buf[4] + (buf[5] << 8); + + if (actual_size > size || actual_size > max_size) { + pr_err("section size mismatch\n"); + return 0; + } + + return actual_size; +} + static int get_ucode_data(void *to, const u8 *from, size_t n) { memcpy(to, from, n); @@ -162,37 +192,29 @@ static int get_ucode_data(void *to, const u8 *from, size_t n) } static void * -get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) +get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size) { - unsigned int total_size; - u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; - void *mc; + void *mc = NULL; + unsigned int actual_size = 0; - if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR)) - return NULL; - - if (section_hdr[0] != UCODE_UCODE_TYPE) { + if (buf[0] != UCODE_UCODE_TYPE) { pr_err("error: invalid type field in container file section header\n"); - return NULL; + goto out; } - total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); + actual_size = verify_ucode_size(cpu, buf, size); + if (!actual_size) + goto out; - if (total_size > size || total_size > UCODE_MAX_SIZE) { - pr_err("error: size mismatch\n"); - return NULL; - } + mc = vmalloc(actual_size); + if (!mc) + goto out; - mc = vmalloc(UCODE_MAX_SIZE); - if (mc) { - memset(mc, 0, UCODE_MAX_SIZE); - if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, - total_size)) { - vfree(mc); - mc = NULL; - } else - *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; - } + memset(mc, 0, actual_size); + get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size); + *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR; + +out: return mc; } @@ -258,7 +280,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) unsigned int uninitialized_var(mc_size); struct microcode_header_amd *mc_header; - mc = get_next_ucode(ucode_ptr, leftover, &mc_size); + mc = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size); if (!mc) break; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 0415c3e..efabf8f 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -525,42 +525,6 @@ static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c) return (edx & MWAIT_EDX_C1); } -/* - * Check for AMD CPUs, where APIC timer interrupt does not wake up CPU from C1e. - * For more information see - * - Erratum #400 for NPT family 0xf and family 0x10 CPUs - * - Erratum #365 for family 0x11 (not affected because C1e not in use) - */ -static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c) -{ - u64 val; - if (c->x86_vendor != X86_VENDOR_AMD) - goto no_c1e_idle; - - /* Family 0x0f models < rev F do not have C1E */ - if (c->x86 == 0x0F && c->x86_model >= 0x40) - return 1; - - if (c->x86 == 0x10) { - /* - * check OSVW bit for CPUs that are not affected - * by erratum #400 - */ - if (cpu_has(c, X86_FEATURE_OSVW)) { - rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val); - if (val >= 2) { - rdmsrl(MSR_AMD64_OSVW_STATUS, val); - if (!(val & BIT(1))) - goto no_c1e_idle; - } - } - return 1; - } - -no_c1e_idle: - return 0; -} - static cpumask_var_t c1e_mask; static int c1e_detected; @@ -638,7 +602,8 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) */ printk(KERN_INFO "using mwait in idle threads.\n"); pm_idle = mwait_idle; - } else if (check_c1e_idle(c)) { + } else if (cpu_has_amd_erratum(amd_erratum_400)) { + /* E400: APIC timer interrupt does not wake up CPU from C1e */ printk(KERN_INFO "using C1E aware idle routine\n"); pm_idle = c1e_idle; } else diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index b12fe8d..929047c 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c @@ -74,7 +74,8 @@ static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift) static u64 pvclock_get_nsec_offset(struct pvclock_shadow_time *shadow) { u64 delta = native_read_tsc() - shadow->tsc_timestamp; - return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift); + return pvclock_scale_delta(delta, shadow->tsc_to_nsec_mul, + shadow->tsc_shift); } /* diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S index 648fe47..f35eec7 100644 --- a/arch/x86/lib/semaphore_32.S +++ b/arch/x86/lib/semaphore_32.S @@ -36,7 +36,7 @@ */ #ifdef CONFIG_SMP ENTRY(__write_lock_failed) - CFI_STARTPROC simple + CFI_STARTPROC FRAME 2: LOCK_PREFIX addl $ RW_LOCK_BIAS,(%eax) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 914f046..6adff93 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1641,9 +1641,6 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { pte_t pte; - if (pfn > max_pfn_mapped) - max_pfn_mapped = pfn; - if (!pte_none(pte_page[pteidx])) continue; @@ -1687,6 +1684,12 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, pud_t *l3; pmd_t *l2; + /* max_pfn_mapped is the last pfn mapped in the initial memory + * mappings. Considering that on Xen after the kernel mappings we + * have the mappings of some pages that don't exist in pfn space, we + * set max_pfn_mapped to the last real pfn mapped. */ + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); + /* Zap identity mapping */ init_level4_pgt[0] = __pgd(0); @@ -1750,9 +1753,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, { pmd_t *kernel_pmd; - max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + - xen_start_info->nr_pt_frames * PAGE_SIZE + - 512*1024); + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index d246654..3eede79 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -502,8 +502,10 @@ int blk_register_queue(struct gendisk *disk) return ret; ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue"); - if (ret < 0) + if (ret < 0) { + blk_trace_remove_sysfs(dev); return ret; + } kobject_uevent(&q->kobj, KOBJ_ADD); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 1d266e2..0dfa468 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1104,9 +1104,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, struct request_queue *q = sdev->request_queue; void *buf; - /* set the min alignment and padding */ - blk_queue_update_dma_alignment(sdev->request_queue, - ATA_DMA_PAD_SZ - 1); + sdev->sector_size = ATA_SECT_SIZE; + + /* set DMA padding */ blk_queue_update_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1); @@ -1120,12 +1120,24 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); } else { - /* ATA devices must be sector aligned */ - blk_queue_update_dma_alignment(sdev->request_queue, - ATA_SECT_SIZE - 1); sdev->manage_start_stop = 1; } + /* + * ata_pio_sectors() expects buffer for each sector to not cross + * page boundary. Enforce it by requiring buffers to be sector + * aligned, which works iff sector_size is not larger than + * PAGE_SIZE. ATAPI devices also need the alignment as + * IDENTIFY_PACKET is executed as ATA_PROT_PIO. + */ + if (sdev->sector_size > PAGE_SIZE) + ata_dev_printk(dev, KERN_WARNING, + "sector_size=%u > PAGE_SIZE, PIO may malfunction\n", + sdev->sector_size); + + blk_queue_update_dma_alignment(sdev->request_queue, + ATA_SECT_SIZE - 1); + if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 3613422..6ba851b 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -695,7 +695,7 @@ void solos_bh(unsigned long card_arg) size); } if (atmdebug) { - dev_info(&card->dev->dev, "Received: device %d\n", port); + dev_info(&card->dev->dev, "Received: port %d\n", port); dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", size, le16_to_cpu(header->vpi), le16_to_cpu(header->vci)); @@ -1015,8 +1015,15 @@ static uint32_t fpga_tx(struct solos_card *card) /* Clean up and free oldskb now it's gone */ if (atmdebug) { + struct pkt_hdr *header = (void *)oldskb->data; + int size = le16_to_cpu(header->size); + + skb_pull(oldskb, sizeof(*header)); dev_info(&card->dev->dev, "Transmitted: port %d\n", port); + dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", + size, le16_to_cpu(header->vpi), + le16_to_cpu(header->vci)); print_buffer(oldskb); } diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index c5d4111..37a2d4f 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -173,6 +173,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) printk("Sending %x - down to controller\n", c->busaddr ); #endif /* CCISS_DEBUG */ writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); + readl(h->vaddr + SA5_REQUEST_PORT_OFFSET); h->commands_outstanding++; if ( h->commands_outstanding > h->max_outstanding) h->max_outstanding = h->commands_outstanding; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6fcb971..0eb6d1b 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -59,9 +59,21 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple MacBookPro 7,1 */ + { USB_DEVICE(0x05ac, 0x8213) }, + /* Apple iMac11,1 */ { USB_DEVICE(0x05ac, 0x8215) }, + /* Apple MacBookPro8,2 */ + { USB_DEVICE(0x05ac, 0x821a) }, + + /* Apple MacBookPro6,2 */ + { USB_DEVICE(0x05ac, 0x8218) }, + + /* Apple MacBookAir3,1, MacBookAir3,2 */ + { USB_DEVICE(0x05ac, 0x821b) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index fc8cf7a..4365717 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -119,7 +119,7 @@ static int i8k_smm(struct smm_regs *regs) int eax = regs->eax; #if defined(CONFIG_X86_64) - asm("pushq %%rax\n\t" + asm volatile("pushq %%rax\n\t" "movl 0(%%rax),%%edx\n\t" "pushq %%rdx\n\t" "movl 4(%%rax),%%ebx\n\t" @@ -145,7 +145,7 @@ static int i8k_smm(struct smm_regs *regs) : "a"(regs) : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); #else - asm("pushl %%eax\n\t" + asm volatile("pushl %%eax\n\t" "movl 0(%%eax),%%edx\n\t" "push %%edx\n\t" "movl 4(%%eax),%%ebx\n\t" @@ -166,7 +166,8 @@ static int i8k_smm(struct smm_regs *regs) "movl %%edx,0(%%eax)\n\t" "lahf\n\t" "shrl $8,%%eax\n\t" - "andl $1,%%eax\n":"=a"(rc) + "andl $1,%%eax\n" + :"=a"(rc) : "a"(regs) : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); #endif diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 6ab5381..7f95fec 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -956,7 +956,7 @@ int tpm_open(struct inode *inode, struct file *file) return -EBUSY; } - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); + chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL); if (chip->data_buffer == NULL) { clear_bit(0, &chip->is_open); put_device(chip->dev); diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 1d56983..b913bf1 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -131,7 +131,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, case ATOM_IIO_MOVE_INDEX: temp &= ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << - CU8(base + 2)); + CU8(base + 3)); temp |= ((index >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + @@ -141,7 +141,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, case ATOM_IIO_MOVE_DATA: temp &= ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << - CU8(base + 2)); + CU8(base + 3)); temp |= ((data >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + @@ -151,7 +151,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, case ATOM_IIO_MOVE_ATTR: temp &= ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << - CU8(base + 2)); + CU8(base + 3)); temp |= ((ctx-> io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index bba05d0..1a2bb2a 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -59,6 +59,27 @@ struct apple_key_translation { u8 flags; }; +static const struct apple_key_translation macbookair_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, + { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, + { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, + { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, + { KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, + { KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, + { KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY }, + { KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY }, + { KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, + { KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, + { KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, + { } +}; + static const struct apple_key_translation apple_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, { KEY_ENTER, KEY_INSERT }, @@ -157,10 +178,15 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, if (fnmode) { int do_translate; - trans = apple_find_translation((hid->product < 0x21d || - hid->product >= 0x300) ? - powerbook_fn_keys : apple_fn_keys, - usage->code); + if(hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) { + trans = apple_find_translation(macbookair_fn_keys, usage->code); + } else if (hid->product < 0x21d || hid->product >= 0x300) { + trans = apple_find_translation(powerbook_fn_keys, usage->code); + } else { + trans = apple_find_translation(apple_fn_keys, usage->code); + } + if (trans) { if (test_bit(usage->code, asc->pressed_fn)) do_translate = 1; @@ -439,6 +465,18 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0010efa..07ddda5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1284,6 +1284,12 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -1715,6 +1721,12 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b681cbf..fe054d6 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -92,6 +92,12 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index f085c18..7765a6b 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -148,6 +148,24 @@ static const char *temperature_sensors_sets[][41] = { /* Set 18: MacBook Pro 2,2 */ { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0", "Th0H", "Th1H", "Tm0P", "Ts0P", NULL }, +/* Set 19: Macbook Pro 5,3 */ + { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", + "TG0F", "TG0H", "TG0P", "TG0T", "TN0D", "TN0P", "TTF0", "Th2H", + "Tm0P", "Ts0P", "Ts0S", NULL }, +/* Set 20: MacBook Pro 5,4 */ + { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TN0D", + "TN0P", "TTF0", "Th2H", "Ts0P", "Ts0S", NULL }, +/* Set 21: MacBook Pro 6,2 */ + { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", "TC0P", "TC1C", "TG0D", + "TG0P", "TG0T", "TMCD", "TP0P", "TPCD", "Th1H", "Th2H", "Tm0P", + "Ts0P", "Ts0S", NULL }, +/* Set 22: MacBook Pro 7,1 */ + { "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S", + "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL }, +/* Set 23: MacBook Air 3,1 */ + { "TB0T", "TB1T", "TB2T", "TC0D", "TC0E", "TC0P", "TC1E", "TCZ3", + "TCZ4", "TCZ5", "TG0E", "TG1E", "TG2E", "TGZ3", "TGZ4", "TGZ5", + "TH0F", "TH0O", "TM0P" }, }; /* List of keys used to read/write fan speeds */ @@ -1363,11 +1381,25 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 0, .light = 0, .temperature_set = 17 }, /* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */ { .accelerometer = 1, .light = 1, .temperature_set = 18 }, +/* MacBook Pro 5,3: accelerometer, backlight and temperature set 19 */ + { .accelerometer = 1, .light = 1, .temperature_set = 19 }, +/* MacBook Pro 5,4: accelerometer, backlight and temperature set 20 */ + { .accelerometer = 1, .light = 1, .temperature_set = 20 }, +/* MacBook Pro 6,2: accelerometer, backlight and temperature set 21 */ + { .accelerometer = 1, .light = 1, .temperature_set = 21 }, +/* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */ + { .accelerometer = 1, .light = 1, .temperature_set = 22 }, +/* MacBook Air 3,1: accelerometer, backlight and temperature set 23 */ + { .accelerometer = 0, .light = 0, .temperature_set = 23 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". * So we need to put "Apple MacBook Pro" before "Apple MacBook". */ static __initdata struct dmi_system_id applesmc_whitelist[] = { + { applesmc_dmi_match, "Apple MacBook Air 3", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3") }, + &applesmc_dmi_data[23]}, { applesmc_dmi_match, "Apple MacBook Air 2", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") }, @@ -1376,6 +1408,22 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, &applesmc_dmi_data[7]}, + { applesmc_dmi_match, "Apple MacBook Pro 7", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7") }, + &applesmc_dmi_data[22]}, + { applesmc_dmi_match, "Apple MacBook Pro 5,4", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4") }, + &applesmc_dmi_data[20]}, + { applesmc_dmi_match, "Apple MacBook Pro 5,3", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3") }, + &applesmc_dmi_data[19]}, + { applesmc_dmi_match, "Apple MacBook Pro 6", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6") }, + &applesmc_dmi_data[21]}, { applesmc_dmi_match, "Apple MacBook Pro 5", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 112b4ee..a0c19c2 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -183,7 +183,6 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; int fingers; - static int old_fingers; if (etd->fw_version < 0x020000) { /* @@ -201,10 +200,13 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) } if (etd->jumpy_cursor) { - /* Discard packets that are likely to have bogus coordinates */ - if (fingers > old_fingers) { + if (fingers != 1) { + etd->single_finger_reports = 0; + } else if (etd->single_finger_reports < 2) { + /* Discard first 2 reports of one finger, bogus */ + etd->single_finger_reports++; elantech_debug("elantech.c: discarding packet\n"); - goto discard_packet_v1; + return; } } @@ -236,9 +238,6 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) } input_sync(dev); - - discard_packet_v1: - old_fingers = fingers; } /* @@ -575,6 +574,24 @@ static struct attribute_group elantech_attr_group = { .attrs = elantech_attrs, }; +static bool elantech_is_signature_valid(const unsigned char *param) +{ + static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; + int i; + + if (param[0] == 0) + return false; + + if (param[1] == 0) + return true; + + for (i = 0; i < ARRAY_SIZE(rates); i++) + if (param[2] == rates[i]) + return false; + + return true; +} + /* * Use magic knock to detect Elantech touchpad */ @@ -618,7 +635,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", param[0], param[1], param[2]); - if (param[0] == 0 || param[1] != 0) { + if (!elantech_is_signature_valid(param)) { if (!force_elantech) { pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); return -1; @@ -716,14 +733,14 @@ int elantech_init(struct psmouse *psmouse) etd->capabilities = param[0]; /* - * This firmware seems to suffer from misreporting coordinates when + * This firmware suffers from misreporting coordinates when * a touch action starts causing the mouse cursor or scrolled page * to jump. Enable a workaround. */ - if (etd->fw_version == 0x020022) { - pr_info("elantech.c: firmware version 2.0.34 detected, " + if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { + pr_info("elantech.c: firmware version 2.0.34/2.6.0 detected, " "enabling jumpy cursor workaround\n"); - etd->jumpy_cursor = 1; + etd->jumpy_cursor = true; } if (elantech_set_absolute_mode(psmouse)) { diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index ac57bde..aa4aac5 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -100,10 +100,11 @@ struct elantech_data { unsigned char reg_26; unsigned char debug; unsigned char capabilities; - unsigned char paritycheck; - unsigned char jumpy_cursor; + bool paritycheck; + bool jumpy_cursor; unsigned char hw_version; - unsigned int fw_version; + unsigned int fw_version; + unsigned int single_finger_reports; unsigned char parity[256]; }; diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 227c020..4f3e3ce 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -38,7 +38,7 @@ MODULE_PARM_DESC(debug, DEBSTATUS); #define DRIVER_VERSION "0.1" -#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" +#define DRIVER_NAME "flexcop-pci" #define DRIVER_AUTHOR "Patrick Boettcher " struct flexcop_pci { diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 34eab05..f9052be 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -794,6 +794,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { { 0x7a13, KEY_VOLUMEDOWN }, { 0x7a40, KEY_POWER }, { 0x7a41, KEY_MUTE }, + + /* Key codes for the Elgato EyeTV Diversity silver remote, + set dvb_usb_dib0700_ir_proto=0 */ + { 0x4501, KEY_POWER }, + { 0x4502, KEY_MUTE }, + { 0x4503, KEY_1 }, + { 0x4504, KEY_2 }, + { 0x4505, KEY_3 }, + { 0x4506, KEY_4 }, + { 0x4507, KEY_5 }, + { 0x4508, KEY_6 }, + { 0x4509, KEY_7 }, + { 0x450a, KEY_8 }, + { 0x450b, KEY_9 }, + { 0x450c, KEY_LAST }, + { 0x450d, KEY_0 }, + { 0x450e, KEY_ENTER }, + { 0x450f, KEY_RED }, + { 0x4510, KEY_CHANNELUP }, + { 0x4511, KEY_GREEN }, + { 0x4512, KEY_VOLUMEDOWN }, + { 0x4513, KEY_OK }, + { 0x4514, KEY_VOLUMEUP }, + { 0x4515, KEY_YELLOW }, + { 0x4516, KEY_CHANNELDOWN }, + { 0x4517, KEY_BLUE }, + { 0x4518, KEY_LEFT }, /* Skip backwards */ + { 0x4519, KEY_PLAYPAUSE }, + { 0x451a, KEY_RIGHT }, /* Skip forward */ + { 0x451b, KEY_REWIND }, + { 0x451c, KEY_L }, /* Live */ + { 0x451d, KEY_FASTFORWARD }, + { 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */ + { 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */ + { 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */ + { 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */ + { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */ }; /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ @@ -2049,6 +2086,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, + { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DIVERSITY) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -2393,7 +2431,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { } }, - .num_device_descs = 6, + .num_device_descs = 7, .devices = { { "DiBcom STK7070PD reference design", { &dib0700_usb_id_table[17], NULL }, @@ -2419,7 +2457,11 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Sony PlayTV", { &dib0700_usb_id_table[44], NULL }, { NULL }, - } + }, + { "Elgato EyeTV Diversity", + { &dib0700_usb_id_table[68], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index ae8b57a..71dfc7c 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -288,6 +288,7 @@ #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_SONY_PLAYTV 0x0003 #define USB_PID_MYGICA_D689 0xd811 +#define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 #define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index cbf8087..8e86f20 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1430,9 +1430,9 @@ static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, sn9c102_show_i2c_val, sn9c102_store_i2c_val); -static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); -static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); -static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); +static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green); +static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue); +static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red); static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL); diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index e4ca590..4267a4d 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -580,7 +580,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) ab3100_get_priv.ab3100 = ab3100; ab3100_get_priv.mode = false; ab3100_get_reg_file = debugfs_create_file("get_reg", - S_IWUGO, ab3100_dir, &ab3100_get_priv, + S_IWUSR, ab3100_dir, &ab3100_get_priv, &ab3100_get_set_reg_fops); if (!ab3100_get_reg_file) { err = -ENOMEM; @@ -590,7 +590,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) ab3100_set_priv.ab3100 = ab3100; ab3100_set_priv.mode = true; ab3100_set_reg_file = debugfs_create_file("set_reg", - S_IWUGO, ab3100_dir, &ab3100_set_priv, + S_IWUSR, ab3100_dir, &ab3100_set_priv, &ab3100_get_set_reg_fops); if (!ab3100_set_reg_file) { err = -ENOMEM; diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 46b3439..16d7179 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c @@ -249,11 +249,11 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev, static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL); static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL); -static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO, ep93xx_pwm_get_freq, ep93xx_pwm_set_freq); -static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO, ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent); -static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO, +static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO, ep93xx_pwm_get_invert, ep93xx_pwm_set_invert); static struct attribute *ep93xx_pwm_attrs[] = { diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 3168ebd..3e22f98 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1057,6 +1057,17 @@ void mmc_rescan(struct work_struct *work) container_of(work, struct mmc_host, detect.work); u32 ocr; int err; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + + if (host->rescan_disable) { + spin_unlock_irqrestore(&host->lock, flags); + return; + } + + spin_unlock_irqrestore(&host->lock, flags); + mmc_bus_get(host); @@ -1267,19 +1278,6 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); - if (err == -ENOSYS || !host->bus_ops->resume) { - /* - * We simply "remove" the card in this case. - * It will be redetected on resume. - */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_release_host(host); - host->pm_flags = 0; - err = 0; - } } mmc_bus_put(host); @@ -1311,28 +1309,61 @@ int mmc_resume_host(struct mmc_host *host) printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_release_host(host); - /* no need to bother upper layers */ err = 0; } } mmc_bus_put(host); - /* - * We add a slight delay here so that resume can progress - * in parallel. - */ - mmc_detect_change(host, 1); - return err; } - EXPORT_SYMBOL(mmc_resume_host); +/* Do the card removal on suspend if card is assumed removeable + * Do that in pm notifier while userspace isn't yet frozen, so we will be able + to sync the card. +*/ +int mmc_pm_notify(struct notifier_block *notify_block, + unsigned long mode, void *unused) +{ + struct mmc_host *host = container_of( + notify_block, struct mmc_host, pm_notify); + unsigned long flags; + + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 1; + spin_unlock_irqrestore(&host->lock, flags); + cancel_delayed_work_sync(&host->detect); + + if (!host->bus_ops || host->bus_ops->suspend) + break; + + mmc_claim_host(host); + + if (host->bus_ops->remove) + host->bus_ops->remove(host); + + mmc_detach_bus(host); + mmc_release_host(host); + host->pm_flags = 0; + break; + + case PM_POST_SUSPEND: + case PM_POST_HIBERNATION: + + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 0; + spin_unlock_irqrestore(&host->lock, flags); + mmc_detect_change(host, 0); + + } + + return 0; +} #endif static int __init mmc_init(void) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 4735390..d80cfdc 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -85,6 +86,9 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); +#ifdef CONFIG_PM + host->pm_notify.notifier_call = mmc_pm_notify; +#endif /* * By default, hosts do not support SGIO or large requests. @@ -133,6 +137,7 @@ int mmc_add_host(struct mmc_host *host) #endif mmc_start_host(host); + register_pm_notifier(&host->pm_notify); return 0; } @@ -149,6 +154,7 @@ EXPORT_SYMBOL(mmc_add_host); */ void mmc_remove_host(struct mmc_host *host) { + unregister_pm_notifier(&host->pm_notify); mmc_stop_host(host); #ifdef CONFIG_DEBUG_FS diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 6701af6..e907447 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -653,6 +653,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( host->ioaddr = pci_ioremap_bar(pdev, bar); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); + ret = -ENOMEM; goto release; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9d4fdfa..be410d7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1268,6 +1268,13 @@ static void sdhci_tasklet_finish(unsigned long param) host = (struct sdhci_host*)param; + /* + * If this tasklet gets rescheduled while running, it will + * be run again afterwards but without any active request. + */ + if (!host->mrq) + return; + spin_lock_irqsave(&host->lock, flags); del_timer(&host->timer); @@ -1279,7 +1286,7 @@ static void sdhci_tasklet_finish(unsigned long param) * upon error conditions. */ if (!(host->flags & SDHCI_DEVICE_DEAD) && - (mrq->cmd->error || + ((mrq->cmd && mrq->cmd->error) || (mrq->data && (mrq->data->error || (mrq->data->stop && mrq->data->stop->error))) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 12b280a..263324b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -141,7 +141,7 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o -obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o +obj-$(CONFIG_NE_H8300) += ne-h8300.o obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o @@ -213,7 +213,7 @@ obj-$(CONFIG_SC92031) += sc92031.o obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_ETH16I) += eth16i.o -obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o +obj-$(CONFIG_ZORRO8390) += zorro8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o obj-$(CONFIG_EQUALIZER) += eql.o @@ -225,7 +225,7 @@ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o obj-$(CONFIG_DECLANCE) += declance.o obj-$(CONFIG_ATARILANCE) += atarilance.o obj-$(CONFIG_A2065) += a2065.o -obj-$(CONFIG_HYDRA) += hydra.o 8390.o +obj-$(CONFIG_HYDRA) += hydra.o obj-$(CONFIG_ARIADNE) += ariadne.o obj-$(CONFIG_CS89x0) += cs89x0.o obj-$(CONFIG_MACSONIC) += macsonic.o diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 0ddf4c6..9a002f1 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2466,6 +2466,10 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) goto out; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 0d42b38..e9154ab 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -368,6 +368,10 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) goto out; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0075514..af8eec1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2645,6 +2645,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack if (!slave || !slave_do_arp_validate(bond, slave)) goto out_unlock; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out_unlock; + if (!pskb_may_pull(skb, arp_hdr_len(dev))) goto out_unlock; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 13e34d2..d61af66 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -787,6 +787,70 @@ static const struct net_device_ops e1000_netdev_ops = { }; /** + * e1000_init_hw_struct - initialize members of hw struct + * @adapter: board private struct + * @hw: structure used by e1000_hw.c + * + * Factors out initialization of the e1000_hw struct to its own function + * that can be called very early at init (just after struct allocation). + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + * Returns negative error codes if MAC type setup fails. + */ +static int e1000_init_hw_struct(struct e1000_adapter *adapter, + struct e1000_hw *hw) +{ + struct pci_dev *pdev = adapter->pdev; + + /* PCI config space info */ + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_id = pdev->subsystem_device; + hw->revision_id = pdev->revision; + + pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); + + hw->max_frame_size = adapter->netdev->mtu + + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; + + /* identify the MAC */ + if (e1000_set_mac_type(hw)) { + DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); + return -EIO; + } + + switch (hw->mac_type) { + default: + break; + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + hw->phy_init_script = 1; + break; + } + + e1000_set_media_type(hw); + e1000_get_bus_info(hw); + + hw->wait_autoneg_complete = false; + hw->tbi_compatibility_en = true; + hw->adaptive_ifs = true; + + /* Copper options */ + + if (hw->media_type == e1000_media_type_copper) { + hw->mdix = AUTO_ALL_MODES; + hw->disable_polarity_correction = false; + hw->master_slave = E1000_MASTER_SLAVE; + } + + return 0; +} + +/** * e1000_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in e1000_pci_tbl @@ -823,22 +887,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (err) return err; - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - pci_using_dac = 1; - } else { - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - E1000_ERR("No usable DMA configuration, " - "aborting\n"); - goto err_dma; - } - } - pci_using_dac = 0; - } - err = pci_request_selected_regions(pdev, bars, e1000_driver_name); if (err) goto err_pci_reg; @@ -882,6 +930,32 @@ static int __devinit e1000_probe(struct pci_dev *pdev, } } + /* make ready for any if (hw->...) below */ + err = e1000_init_hw_struct(adapter, hw); + if (err) + goto err_sw_init; + + /* + * there is a workaround being applied below that limits + * 64-bit DMA addresses to 64-bit hardware. There are some + * 32-bit adapters that Tx hang when given 64-bit DMA addresses + */ + pci_using_dac = 0; + if ((hw->bus_type == e1000_bus_type_pcix) && + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + /* + * according to DMA-API-HOWTO, coherent calls will always + * succeed if the set call did + */ + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); + pci_using_dac = 1; + } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + } else { + pr_err("No usable DMA config, aborting\n"); + goto err_dma; + } + netdev->netdev_ops = &e1000_netdev_ops; e1000_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; @@ -956,8 +1030,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (!is_valid_ether_addr(netdev->perm_addr)) DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); - e1000_get_bus_info(hw); - init_timer(&adapter->tx_fifo_stall_timer); adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall; adapter->tx_fifo_stall_timer.data = (unsigned long)adapter; @@ -1070,6 +1142,7 @@ err_eeprom: iounmap(hw->flash_address); kfree(adapter->tx_ring); kfree(adapter->rx_ring); +err_dma: err_sw_init: iounmap(hw->hw_addr); err_ioremap: @@ -1077,7 +1150,6 @@ err_ioremap: err_alloc_etherdev: pci_release_selected_regions(pdev, bars); err_pci_reg: -err_dma: pci_disable_device(pdev); return err; } @@ -1129,62 +1201,12 @@ static void __devexit e1000_remove(struct pci_dev *pdev) * @adapter: board private structure to initialize * * e1000_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). + * e1000_init_hw_struct MUST be called before this function **/ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - - /* PCI config space info */ - - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - hw->revision_id = pdev->revision; - - pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - hw->max_frame_size = netdev->mtu + - ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; - - /* identify the MAC */ - - if (e1000_set_mac_type(hw)) { - DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); - return -EIO; - } - - switch (hw->mac_type) { - default: - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - hw->phy_init_script = 1; - break; - } - - e1000_set_media_type(hw); - - hw->wait_autoneg_complete = false; - hw->tbi_compatibility_en = true; - hw->adaptive_ifs = true; - - /* Copper options */ - - if (hw->media_type == e1000_media_type_copper) { - hw->mdix = AUTO_ALL_MODES; - hw->disable_polarity_correction = false; - hw->master_slave = E1000_MASTER_SLAVE; - } adapter->num_tx_queues = 1; adapter->num_rx_queues = 1; diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 8b5e157..a626012 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -274,6 +274,16 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + /* + * Reset the PHY before any acccess to it. Doing so, ensures that + * the PHY is in a known good state before we read/write PHY registers. + * The generic reset is sufficient here, because we haven't determined + * the PHY type yet. + */ + ret_val = e1000e_phy_hw_reset_generic(hw); + if (ret_val) + goto out; + phy->id = e1000_phy_unknown; ret_val = e1000e_get_phy_id(hw); if (ret_val) diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 75b099c..f97da2a 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c @@ -53,15 +53,20 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->duplex = -1; } - cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full - | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half - | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half - | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - - cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg - | ADVERTISED_FIBRE); + if (cmd->speed == SPEED_10000) { + cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); + cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); + cmd->port = PORT_FIBRE; + } else { + cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full + | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full + | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg + | SUPPORTED_TP); + cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg + | ADVERTISED_TP); + cmd->port = PORT_TP; + } - cmd->port = PORT_FIBRE; cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE; return 0; diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 24724b4..4b6cb8a 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -97,15 +97,15 @@ static const struct net_device_ops hydra_netdev_ops = { .ndo_open = hydra_open, .ndo_stop = hydra_close, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; @@ -124,7 +124,7 @@ static int __devinit hydra_init(struct zorro_dev *z) 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, }; - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return -ENOMEM; diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index debeee2..f7ae284 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -126,7 +126,6 @@ struct igbvf_buffer { unsigned int page_offset; }; }; - struct page *page; }; union igbvf_desc { diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index ecde087..649b8db6 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3600,6 +3600,7 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp) dma_free_coherent(&pdev->dev, bytes, ss->fw_stats, ss->fw_stats_bus); ss->fw_stats = NULL; + netif_napi_del(&ss->napi); } } kfree(mgp->ss); diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index 7bd6662..31da04f 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -167,7 +167,7 @@ static void cleanup_card(struct net_device *dev) #ifndef MODULE struct net_device * __init ne_probe(int unit) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = ____alloc_ei_netdev(0); int err; if (!dev) @@ -197,15 +197,15 @@ static const struct net_device_ops ne_netdev_ops = { .ndo_open = ne_open, .ndo_stop = ne_close, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; @@ -638,7 +638,7 @@ int init_module(void) int err; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = ____alloc_ei_netdev(0); if (!dev) break; if (io[this_dev]) { diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 8969615..2605f3d 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -852,7 +852,9 @@ static int slip_open(struct tty_struct *tty) /* Done. We have linked the TTY line to a channel. */ rtnl_unlock(); tty->receive_room = 65536; /* We don't flow control */ - return sl->dev->base_addr; + + /* TTY layer expects 0 on success */ + return 0; err_free_bufs: sl_free_bufs(sl); diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index f549309..cf4529c 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -324,7 +324,7 @@ static int bdx_fw_load(struct bdx_priv *priv) ENTER; master = READ_REG(priv, regINIT_SEMAPHORE); if (!READ_REG(priv, regINIT_STATUS) && master) { - rc = request_firmware(&fw, "tehuti/firmware.bin", &priv->pdev->dev); + rc = request_firmware(&fw, "tehuti/bdx.bin", &priv->pdev->dev); if (rc) goto out; bdx_tx_push_desc_safe(priv, (char *)fw->data, fw->size); @@ -2518,4 +2518,4 @@ module_exit(bdx_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(BDX_DRV_DESC); -MODULE_FIRMWARE("tehuti/firmware.bin"); +MODULE_FIRMWARE("tehuti/bdx.bin"); diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index dc94445..b18cda4 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -326,13 +326,13 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) { static const char ifname[] = "usbpn%d"; const struct usb_cdc_union_desc *union_header = NULL; - const struct usb_cdc_header_desc *phonet_header = NULL; const struct usb_host_interface *data_desc; struct usb_interface *data_intf; struct usb_device *usbdev = interface_to_usbdev(intf); struct net_device *dev; struct usbpn_dev *pnd; u8 *data; + int phonet = 0; int len, err; data = intf->altsetting->extra; @@ -353,10 +353,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) (struct usb_cdc_union_desc *)data; break; case 0xAB: - if (phonet_header || dlen < 5) - break; - phonet_header = - (struct usb_cdc_header_desc *)data; + phonet = 1; break; } } @@ -364,7 +361,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) len -= dlen; } - if (!union_header || !phonet_header) + if (!union_header || !phonet) return -EINVAL; data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f5b5d74..2cc49dd 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -448,6 +448,20 @@ static void skb_recv_done(struct virtqueue *rvq) } } +static void virtnet_napi_enable(struct virtnet_info *vi) +{ + napi_enable(&vi->napi); + + /* If all buffers were filled by other side before we napi_enabled, we + * won't get another interrupt, so process any outstanding packets + * now. virtnet_poll wants re-enable the queue, so we disable here. + * We synchronize against interrupts via NAPI_STATE_SCHED */ + if (napi_schedule_prep(&vi->napi)) { + vi->rvq->vq_ops->disable_cb(vi->rvq); + __napi_schedule(&vi->napi); + } +} + static void refill_work(struct work_struct *work) { struct virtnet_info *vi; @@ -456,7 +470,7 @@ static void refill_work(struct work_struct *work) vi = container_of(work, struct virtnet_info, refill.work); napi_disable(&vi->napi); still_empty = !try_fill_recv(vi, GFP_KERNEL); - napi_enable(&vi->napi); + virtnet_napi_enable(vi); /* In theory, this can happen: if we don't get any buffers in * we will *never* try to fill again. */ @@ -642,16 +656,7 @@ static int virtnet_open(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); - napi_enable(&vi->napi); - - /* If all buffers were filled by other side before we napi_enabled, we - * won't get another interrupt, so process any outstanding packets - * now. virtnet_poll wants re-enable the queue, so we disable here. - * We synchronize against interrupts via NAPI_STATE_SCHED */ - if (napi_schedule_prep(&vi->napi)) { - vi->rvq->vq_ops->disable_cb(vi->rvq); - __napi_schedule(&vi->napi); - } + virtnet_napi_enable(vi); return 0; } diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 3935c44..df7cddd 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -290,6 +290,9 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data) { /* toggle the LRO feature*/ netdev->features ^= NETIF_F_LRO; + /* Update private LRO flag */ + adapter->lro = lro_requested; + /* update harware LRO capability accordingly */ if (lro_requested) adapter->shared->devRead.misc.uptFeatures &= UPT1_F_LRO; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 115e1ae..b9585fb 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1090,6 +1090,8 @@ static int ath9k_start(struct ieee80211_hw *hw) "Starting driver with initial channel: %d MHz\n", curchan->center_freq); + ath9k_ps_wakeup(sc); + mutex_lock(&sc->mutex); if (ath9k_wiphy_started(sc)) { @@ -1199,6 +1201,8 @@ static int ath9k_start(struct ieee80211_hw *hw) mutex_unlock: mutex_unlock(&sc->mutex); + ath9k_ps_restore(sc); + return r; } diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 248c670..5c2cfe6 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -195,6 +195,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {APL9_WORLD, CTL_ETSI, CTL_ETSI}, {APL3_FCCA, CTL_FCC, CTL_FCC}, + {APL7_FCCA, CTL_FCC, CTL_FCC}, {APL1_ETSIC, CTL_FCC, CTL_ETSI}, {APL2_ETSIC, CTL_FCC, CTL_ETSI}, {APL2_APLD, CTL_FCC, NO_CTL}, diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index fa40fdf..b8900f0 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1538,7 +1538,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) dmaaddr = meta->dmaaddr; goto drop_recycle_buffer; } - if (unlikely(len > ring->rx_buffersize)) { + if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) { /* The data did not fit into one descriptor buffer * and is split over multiple buffers. * This should never happen, as we try to allocate buffers diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index dc91944..a9282d7 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -163,7 +163,7 @@ struct b43_dmadesc_generic { /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 #define B43_RXRING_SLOTS 64 -#define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN +#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN) /* Pointer poison */ #define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM)) diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index 4e56b7b..4808dc7 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c @@ -163,6 +163,7 @@ static int b43_sdio_probe(struct sdio_func *func, err_free_ssb: kfree(sdio); err_disable_func: + sdio_claim_host(func); sdio_disable_func(func); err_release_host: sdio_release_host(func); @@ -175,7 +176,9 @@ static void b43_sdio_remove(struct sdio_func *func) struct b43_sdio *sdio = sdio_get_drvdata(func); ssb_bus_unregister(&sdio->ssb); + sdio_claim_host(func); sdio_disable_func(func); + sdio_release_host(func); kfree(sdio); sdio_set_drvdata(func, NULL); } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e950153..92a5f9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1234,11 +1234,15 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - iwl_tx_status(priv, tx_info->skb[0]); + + if (WARN_ON_ONCE(tx_info->skb == NULL)) + continue; hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; - if (hdr && ieee80211_is_data_qos(hdr->frame_control)) + if (ieee80211_is_data_qos(hdr->frame_control)) nfreed++; + + iwl_tx_status(priv, tx_info->skb[0]); tx_info->skb[0] = NULL; if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index cdb9b96..91bafae 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1267,8 +1267,8 @@ int lbs_execute_next_command(struct lbs_private *priv) cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); - list_del(&cmdnode->list); spin_lock_irqsave(&priv->driver_lock, flags); + list_del(&cmdnode->list); lbs_complete_command(priv, cmdnode, 0); spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1280,8 +1280,8 @@ int lbs_execute_next_command(struct lbs_private *priv) (priv->psstate == PS_STATE_PRE_SLEEP)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); - list_del(&cmdnode->list); spin_lock_irqsave(&priv->driver_lock, flags); + list_del(&cmdnode->list); lbs_complete_command(priv, cmdnode, 0); spin_unlock_irqrestore(&priv->driver_lock, flags); priv->needtowakeup = 1; @@ -1294,7 +1294,9 @@ int lbs_execute_next_command(struct lbs_private *priv) "EXEC_NEXT_CMD: sending EXIT_PS\n"); } } + spin_lock_irqsave(&priv->driver_lock, flags); list_del(&cmdnode->list); + spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", le16_to_cpu(cmd->command)); lbs_submit_command(priv, cmdnode); diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 9a57d14..3317906d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ + {USB_DEVICE(0x0bf8, 0x1007)}, /* Fujitsu E-5400 USB */ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ {USB_DEVICE(0x0db0, 0x6826)}, /* MSI UB54G (MS-6826) */ {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ @@ -68,6 +69,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */ + {USB_DEVICE(0x2001, 0x3762)}, /* Conceptronic C54U */ {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */ {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */ diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index db89d65..8db2132 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -703,7 +703,7 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_tx_info *p54info; struct p54_hdr *hdr; struct p54_tx_data *txhdr; - unsigned int padding, len, extra_len; + unsigned int padding, len, extra_len = 0; int i, j, ridx; u16 hdr_flags = 0, aid = 0; u8 rate, queue = 0, crypt_offset = 0; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8ebb705..2961228 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -348,6 +348,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, int timeout; u32 mask; u16 reg; + enum cipher curr_cipher; if (crypto->cmd == SET_KEY) { /* @@ -358,6 +359,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, mask = TXRX_CSR0_KEY_ID.bit_mask; rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); + curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM); reg &= mask; if (reg && reg == mask) @@ -366,6 +368,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); key->hw_key_idx += reg ? ffz(reg) : 0; + /* + * Hardware requires that all keys use the same cipher + * (e.g. TKIP-only, AES-only, but not TKIP+AES). + * If this is not the first key, compare the cipher with the + * first one and fall back to SW crypto if not the same. + */ + if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher) + return -EOPNOTSUPP; /* * The encryption key doesn't fit within the CSR cache, diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 81c753a..25e720c 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -125,7 +125,7 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z, board = z->resource.start; ioaddr = board+cards[i].offset; - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return -ENOMEM; if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) { @@ -145,15 +145,15 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z, static const struct net_device_ops zorro8390_netdev_ops = { .ndo_open = zorro8390_open, .ndo_stop = zorro8390_close, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cb23aa2..e610cfe 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -212,6 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); if (pdev) { + pdev->current_state = PCI_D0; slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); pci_dev_put(pdev); } diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3507692..67e2f60 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -383,7 +383,7 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_DMAR_DEFAULT_ON*/ -static int __initdata dmar_map_gfx = 1; +static int dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; @@ -1848,7 +1848,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) ret = iommu_attach_domain(domain, iommu); if (ret) { - domain_exit(domain); + free_domain_mem(domain); goto error; } @@ -3261,9 +3261,15 @@ static int device_notifier(struct notifier_block *nb, if (!domain) return 0; - if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) + if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) { domain_remove_one_dev_info(domain, pdev); + if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && + !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) && + list_empty(&domain->devices)) + domain_exit(domain); + } + return 0; } @@ -3412,6 +3418,11 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, domain->iommu_count--; domain_update_iommu_cap(domain); spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); + + spin_lock_irqsave(&iommu->lock, tmp_flags); + clear_bit(domain->id, iommu->domain_ids); + iommu->domains[domain->id] = NULL; + spin_unlock_irqrestore(&iommu->lock, tmp_flags); } spin_unlock_irqrestore(&device_domain_lock, flags); @@ -3751,6 +3762,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; + + /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ + if (dev->revision == 0x07) { + printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); + dmar_map_gfx = 0; + } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 6110601..0fb56e0 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -83,6 +83,12 @@ static const struct dmi_system_id __initdata dell_device_table[] = { }, }, { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/ + }, + }, + { .ident = "Dell Computer Corporation", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), @@ -628,4 +634,5 @@ MODULE_AUTHOR("Matthew Garrett "); MODULE_DESCRIPTION("Dell laptop driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*"); +MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*"); MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*"); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 06b8566..fad05bd 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -483,7 +483,7 @@ ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, static struct bin_attribute ds1511_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }, .size = DS1511_RAM_MAX, .read = ds1511_nvram_read, diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0cb2331..7d05fe5 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -63,7 +63,7 @@ static struct dasd_discipline dasd_eckd_discipline; static struct ccw_device_id dasd_eckd_ids[] = { { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), .driver_info = 0x1}, { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), .driver_info = 0x2}, - { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), .driver_info = 0x3}, + { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3380, 0), .driver_info = 0x3}, { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), .driver_info = 0x4}, { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), .driver_info = 0x5}, { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), .driver_info = 0x6}, diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index e8a0bc3..6faf472 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -285,13 +285,11 @@ static struct request *get_req(struct scsi_device *sdev, int cmd, switch (cmd) { case MODE_SELECT: len = sizeof(short_trespass); - rq->cmd_flags |= REQ_RW; rq->cmd[1] = 0x10; rq->cmd[4] = len; break; case MODE_SELECT_10: len = sizeof(long_trespass); - rq->cmd_flags |= REQ_RW; rq->cmd[1] = 0x10; rq->cmd[8] = len; break; diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 99e4478..1d2e162 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -3669,6 +3669,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * For each user buffer, create a mirror buffer and copy in */ for (i = 0; i < ioc->sge_count; i++) { + if (!ioc->sgl[i].iov_len) + continue; + kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev, ioc->sgl[i].iov_len, &buf_handle, GFP_KERNEL); diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 87cf0d2..8d98f09 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -988,7 +988,7 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, u32 chain_offset; u32 chain_length; u32 chain_flags; - u32 sges_left; + int sges_left; u32 sges_in_segment; u32 sgl_flags; u32 sgl_flags_last_element; @@ -1009,7 +1009,7 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, sg_scmd = scsi_sglist(scmd); sges_left = scsi_dma_map(scmd); - if (!sges_left) { + if (sges_left < 0) { sdev_printk(KERN_ERR, scmd->device, "pci_map_sg" " failed: request for %d bytes!\n", scsi_bufflen(scmd)); return -ENOMEM; diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 53aefff..bdb7259 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3528,6 +3528,9 @@ static long pmcraid_ioctl_passthrough( rc = -EFAULT; goto out_free_buffer; } + } else if (request_size < 0) { + rc = -EINVAL; + goto out_free_buffer; } /* check if we have any additional command parameters */ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c2a9e12..725f3cd 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -400,10 +400,15 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) static void scsi_run_queue(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; - struct Scsi_Host *shost = sdev->host; + struct Scsi_Host *shost; LIST_HEAD(starved_list); unsigned long flags; + /* if the device is dead, sdev will be NULL, so no queue to run */ + if (!sdev) + return; + + shost = sdev->host; if (scsi_target(sdev)->single_lun) scsi_single_lun_run(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 02be251..ed3b52f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -319,14 +319,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) kfree(evt); } - if (sdev->request_queue) { - sdev->request_queue->queuedata = NULL; - /* user context needed to free queue */ - scsi_free_queue(sdev->request_queue); - /* temporary expedient, try to catch use of queue lock - * after free of sdev */ - sdev->request_queue = NULL; - } + /* NULL queue means the device can't be used */ + sdev->request_queue = NULL; scsi_target_reap(scsi_target(sdev)); @@ -964,6 +958,12 @@ void __scsi_remove_device(struct scsi_device *sdev) if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); transport_destroy_device(dev); + + /* cause the request function to reject all I/O requests */ + sdev->request_queue->queuedata = NULL; + + /* Freeing the queue signals to block that we're done */ + scsi_free_queue(sdev->request_queue); put_device(dev); } diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 7f5a6a8..3b00e90 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -390,9 +390,9 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, len = (desc_ptr[2] << 8) + desc_ptr[3]; /* skip past overall descriptor */ desc_ptr += len + 4; - if (ses_dev->page10) - addl_desc_ptr = ses_dev->page10 + 8; } + if (ses_dev->page10) + addl_desc_ptr = ses_dev->page10 + 8; type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; components = 0; for (i = 0; i < types; i++, type_ptr += 4) { diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index eacb588..6d2028e 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -383,12 +383,13 @@ static void imx_start_tx(struct uart_port *port) static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = dev_id; - unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; + unsigned int val; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); writel(USR1_RTSD, sport->port.membase + USR1); + val = readl(sport->port.membase + USR1) & USR1_RTSS; uart_handle_cts_change(&sport->port, !!val); wake_up_interruptible(&sport->port.state->port.delta_msr_wait); diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c index e69e9ee..d0b435e 100644 --- a/drivers/staging/hv/Channel.c +++ b/drivers/staging/hv/Channel.c @@ -76,14 +76,14 @@ static void VmbusChannelSetEvent(struct vmbus_channel *Channel) if (Channel->OfferMsg.MonitorAllocated) { /* Each u32 represents 32 channels */ - set_bit(Channel->OfferMsg.ChildRelId & 31, + sync_set_bit(Channel->OfferMsg.ChildRelId & 31, (unsigned long *) gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5)); monitorPage = gVmbusConnection.MonitorPages; monitorPage++; /* Get the child to parent monitor page */ - set_bit(Channel->MonitorBit, + sync_set_bit(Channel->MonitorBit, (unsigned long *)&monitorPage->TriggerGroup [Channel->MonitorGroup].Pending); @@ -103,7 +103,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel) if (Channel->OfferMsg.MonitorAllocated) { /* Each u32 represents 32 channels */ - clear_bit(Channel->OfferMsg.ChildRelId & 31, + sync_clear_bit(Channel->OfferMsg.ChildRelId & 31, (unsigned long *)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5)); @@ -111,7 +111,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel) (struct hv_monitor_page *)gVmbusConnection.MonitorPages; monitorPage++; /* Get the child to parent monitor page */ - clear_bit(Channel->MonitorBit, + sync_clear_bit(Channel->MonitorBit, (unsigned long *)&monitorPage->TriggerGroup [Channel->MonitorGroup].Pending); } diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c index e0ea9cf..e39d422 100644 --- a/drivers/staging/hv/Connection.c +++ b/drivers/staging/hv/Connection.c @@ -285,7 +285,7 @@ void VmbusOnEvents(void) for (dword = 0; dword < maxdword; dword++) { if (recvInterruptPage[dword]) { for (bit = 0; bit < 32; bit++) { - if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) { + if (sync_test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) { relid = (dword << 5) + bit; DPRINT_DBG(VMBUS, "event detected for relid - %d", relid); @@ -330,7 +330,7 @@ int VmbusSetEvent(u32 childRelId) DPRINT_ENTER(VMBUS); /* Each u32 represents 32 channels */ - set_bit(childRelId & 31, + sync_set_bit(childRelId & 31, (unsigned long *)gVmbusConnection.SendInterruptPage + (childRelId >> 5)); diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index 2f84bf7..0680868 100644 --- a/drivers/staging/hv/Vmbus.c +++ b/drivers/staging/hv/Vmbus.c @@ -255,7 +255,7 @@ static int VmbusOnISR(struct hv_driver *drv) event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ - if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { + if (sync_test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]); ret |= 0x2; } diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h index 05ad2c9..5a37cce 100644 --- a/drivers/staging/hv/VmbusPrivate.h +++ b/drivers/staging/hv/VmbusPrivate.h @@ -32,6 +32,7 @@ #include "ChannelInterface.h" #include "RingBuffer.h" #include +#include /* diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index d6940f4..5d77f11 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -44,6 +44,7 @@ struct net_device_context { /* point back to our device context */ struct vm_device *device_ctx; struct net_device_stats stats; + struct work_struct work; }; struct netvsc_driver_context { @@ -274,6 +275,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj, { struct vm_device *device_ctx = to_vm_device(device_obj); struct net_device *net = dev_get_drvdata(&device_ctx->device); + struct net_device_context *ndev_ctx; DPRINT_ENTER(NETVSC_DRV); @@ -287,6 +289,8 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj, netif_carrier_on(net); netif_wake_queue(net); netif_notify_peers(net); + ndev_ctx = netdev_priv(net); + schedule_work(&ndev_ctx->work); } else { netif_carrier_off(net); netif_stop_queue(net); @@ -388,6 +392,25 @@ static const struct net_device_ops device_ops = { .ndo_set_mac_address = eth_mac_addr, }; +/* + * Send GARP packet to network peers after migrations. + * After Quick Migration, the network is not immediately operational in the + * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add + * another netif_notify_peers() into a scheduled work, otherwise GARP packet + * will not be sent after quick migration, and cause network disconnection. + */ +static void netvsc_send_garp(struct work_struct *w) +{ + struct net_device_context *ndev_ctx; + struct net_device *net; + + msleep(20); + ndev_ctx = container_of(w, struct net_device_context, work); + net = dev_get_drvdata(&ndev_ctx->device_ctx->device); + netif_notify_peers(net); +} + + static int netvsc_probe(struct device *device) { struct driver_context *driver_ctx = @@ -418,6 +441,7 @@ static int netvsc_probe(struct device *device) net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = device_ctx; dev_set_drvdata(device, net); + INIT_WORK(&net_device_ctx->work, netvsc_send_garp); /* Notify the netvsc driver of the new device */ ret = net_drv_obj->Base.OnDeviceAdd(device_obj, &device_info); diff --git a/drivers/staging/rtl8192su/r8192S_firmware.c b/drivers/staging/rtl8192su/r8192S_firmware.c index 752a3f1..f7dd7e7 100644 --- a/drivers/staging/rtl8192su/r8192S_firmware.c +++ b/drivers/staging/rtl8192su/r8192S_firmware.c @@ -31,44 +31,46 @@ // Code size // Created by Roger, 2008.04.10. // -bool FirmwareDownloadCode(struct net_device *dev, u8 * code_virtual_address,u32 buffer_len) +bool FirmwareDownloadCode(struct net_device *dev, + u8 *code_virtual_address, + u32 buffer_len) { - struct r8192_priv *priv = ieee80211_priv(dev); - bool rt_status = true; - u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; //Fragmentation might be required in 90/92 but not in 92S - u16 frag_length, frag_offset = 0; - struct sk_buff *skb; - unsigned char *seg_ptr; - cb_desc *tcb_desc; - u8 bLastIniPkt = 0; - u16 ExtraDescOffset = 0; - - - RT_TRACE(COMP_FIRMWARE, "--->FirmwareDownloadCode()\n" ); - - //MAX_TRANSMIT_BUFFER_SIZE - if(buffer_len >= MAX_FIRMWARE_CODE_SIZE-USB_HWDESC_HEADER_LEN) - { - RT_TRACE(COMP_ERR, "Size over MAX_FIRMWARE_CODE_SIZE! \n"); + struct r8192_priv *priv = ieee80211_priv(dev); + bool rt_status = true; + /* Fragmentation might be required in 90/92 but not in 92S */ + u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; + u16 frag_length, frag_offset = 0; + struct sk_buff *skb; + unsigned char *seg_ptr; + cb_desc *tcb_desc; + u8 bLastIniPkt = 0; + u16 ExtraDescOffset = 0; + + if (buffer_len >= MAX_FIRMWARE_CODE_SIZE - USB_HWDESC_HEADER_LEN) { + RT_TRACE(COMP_ERR, "(%s): Firmware exceeds" + " MAX_FIRMWARE_CODE_SIZE\n", __func__); goto cmdsend_downloadcode_fail; } - ExtraDescOffset = USB_HWDESC_HEADER_LEN; - do { if((buffer_len-frag_offset) > frag_threshold) - { frag_length = frag_threshold + ExtraDescOffset; + else { + frag_length = (u16)(buffer_len - + frag_offset + ExtraDescOffset); + bLastIniPkt = 1; } - else - { - frag_length = (u16)(buffer_len - frag_offset + ExtraDescOffset); - bLastIniPkt = 1; - } - - /* Allocate skb buffer to contain firmware info and tx descriptor info. */ + /* + * Allocate skb buffer to contain firmware info + * and tx descriptor info. + */ skb = dev_alloc_skb(frag_length); - memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + if (skb == NULL) { + RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n", + __func__); + goto cmdsend_downloadcode_fail; + } + memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; @@ -76,73 +78,60 @@ bool FirmwareDownloadCode(struct net_device *dev, u8 * code_virtual_address,u32 tcb_desc->bLastIniPkt = bLastIniPkt; skb_reserve(skb, ExtraDescOffset); - seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length-ExtraDescOffset)); - memcpy(seg_ptr, code_virtual_address+frag_offset, (u32)(frag_length-ExtraDescOffset)); - tcb_desc->txbuf_size= frag_length; + seg_ptr = (u8 *)skb_put(skb, + (u32)(frag_length - ExtraDescOffset)); - if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ - (priv->ieee80211->queue_stop) ) - { + memcpy(seg_ptr, code_virtual_address + frag_offset, + (u32)(frag_length-ExtraDescOffset)); + + tcb_desc->txbuf_size = frag_length; + + if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || + (priv->ieee80211->queue_stop)) { RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); - } - else - { - priv->ieee80211->softmac_hard_start_xmit(skb,dev); - } + } else + priv->ieee80211->softmac_hard_start_xmit(skb, dev); frag_offset += (frag_length - ExtraDescOffset); - }while(frag_offset < buffer_len); - + } while (frag_offset < buffer_len); return rt_status ; - cmdsend_downloadcode_fail: rt_status = false; - RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n"); + RT_TRACE(COMP_ERR, "(%s): failed\n", __func__); return rt_status; - } -RT_STATUS -FirmwareEnableCPU(struct net_device *dev) +RT_STATUS FirmwareEnableCPU(struct net_device *dev) { + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + u8 tmpU1b, CPUStatus = 0; + u16 tmpU2b; + u32 iCheckTime = 200; - RT_STATUS rtStatus = RT_STATUS_SUCCESS; - u8 tmpU1b, CPUStatus = 0; - u16 tmpU2b; - u32 iCheckTime = 200; - - RT_TRACE(COMP_FIRMWARE, "-->FirmwareEnableCPU()\n" ); - // Enable CPU. + /* Enable CPU. */ tmpU1b = read_nic_byte(dev, SYS_CLKR); - write_nic_byte(dev, SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL)); //AFE source - + /* AFE source */ + write_nic_byte(dev, SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL)); tmpU2b = read_nic_word(dev, SYS_FUNC_EN); write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN)); - - //Polling IMEM Ready after CPU has refilled. - do - { + /* Poll IMEM Ready after CPU has refilled. */ + do { CPUStatus = read_nic_byte(dev, TCR); - if(CPUStatus& IMEM_RDY) - { - RT_TRACE(COMP_FIRMWARE, "IMEM Ready after CPU has refilled.\n"); + if (CPUStatus & IMEM_RDY) + /* success */ break; - } - - //usleep(100); udelay(100); - }while(iCheckTime--); - - if(!(CPUStatus & IMEM_RDY)) - return RT_STATUS_FAILURE; - - RT_TRACE(COMP_FIRMWARE, "<--FirmwareEnableCPU(): rtStatus(%#x)\n", rtStatus); + } while (iCheckTime--); + if (!(CPUStatus & IMEM_RDY)) { + RT_TRACE(COMP_ERR, "(%s): failed to enable CPU\n", __func__); + rtStatus = RT_STATUS_FAILURE; + } return rtStatus; } diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 04d9b85..a813a7b 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -26,6 +26,7 @@ #include #include +#include #undef LOOP_TEST #undef DUMP_RX @@ -112,28 +113,30 @@ u32 rt_global_debug_component = \ #define CAM_CONTENT_COUNT 8 static const struct usb_device_id rtl8192_usb_id_tbl[] = { - /* Realtek */ - {USB_DEVICE(0x0bda, 0x8171)}, - {USB_DEVICE(0x0bda, 0x8192)}, - {USB_DEVICE(0x0bda, 0x8709)}, - /* Corega */ - {USB_DEVICE(0x07aa, 0x0043)}, - /* Belkin */ - {USB_DEVICE(0x050d, 0x805E)}, - {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */ - /* Sitecom */ - {USB_DEVICE(0x0df6, 0x0031)}, - {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */ - /* EnGenius */ - {USB_DEVICE(0x1740, 0x9201)}, - /* Dlink */ - {USB_DEVICE(0x2001, 0x3301)}, - /* Zinwell */ - {USB_DEVICE(0x5a57, 0x0290)}, - /* Guillemot */ - {USB_DEVICE(0x06f8, 0xe031)}, - //92SU + {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */ {USB_DEVICE(0x0bda, 0x8172)}, + {USB_DEVICE(0x0bda, 0x8173)}, + {USB_DEVICE(0x0bda, 0x8174)}, + {USB_DEVICE(0x0bda, 0x8712)}, + {USB_DEVICE(0x0bda, 0x8713)}, + {USB_DEVICE(0x07aa, 0x0047)}, + {USB_DEVICE(0x07d1, 0x3303)}, + {USB_DEVICE(0x07d1, 0x3302)}, + {USB_DEVICE(0x07d1, 0x3300)}, + {USB_DEVICE(0x1740, 0x9603)}, + {USB_DEVICE(0x1740, 0x9605)}, + {USB_DEVICE(0x050d, 0x815F)}, + {USB_DEVICE(0x06f8, 0xe031)}, + {USB_DEVICE(0x7392, 0x7611)}, + {USB_DEVICE(0x7392, 0x7612)}, + {USB_DEVICE(0x7392, 0x7622)}, + {USB_DEVICE(0x0DF6, 0x0045)}, + {USB_DEVICE(0x0E66, 0x0015)}, + {USB_DEVICE(0x0E66, 0x0016)}, + {USB_DEVICE(0x0b05, 0x1786)}, + /* these are not in the official list */ + {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */ + {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */ {} }; @@ -161,6 +164,8 @@ MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); static int __devinit rtl8192_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf); +static const struct net_device_ops rtl8192_netdev_ops; +static struct notifier_block proc_netdev_notifier; static struct usb_driver rtl8192_usb_driver = { .name = RTL819xU_MODULE_NAME, /* Driver name */ @@ -960,15 +965,24 @@ static int proc_get_stats_rx(char *page, char **start, return len; } -void rtl8192_proc_module_init(void) +int rtl8192_proc_module_init(void) { + int ret; + RT_TRACE(COMP_INIT, "Initializing proc filesystem"); rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net); + if (!rtl8192_proc) + return -ENOMEM; + ret = register_netdevice_notifier(&proc_netdev_notifier); + if (ret) + remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); + return ret; } void rtl8192_proc_module_remove(void) { + unregister_netdevice_notifier(&proc_netdev_notifier); remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); } @@ -996,8 +1010,7 @@ void rtl8192_proc_remove_one(struct net_device *dev) remove_proc_entry("registers-e", priv->dir_dev); // remove_proc_entry("cck-registers",priv->dir_dev); // remove_proc_entry("ofdm-registers",priv->dir_dev); - //remove_proc_entry(dev->name, rtl8192_proc); - remove_proc_entry("wlan0", rtl8192_proc); + remove_proc_entry(priv->dir_dev->name, rtl8192_proc); priv->dir_dev = NULL; } } @@ -1114,6 +1127,25 @@ void rtl8192_proc_init_one(struct net_device *dev) dev->name); } } + +static int proc_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *net_dev = ptr; + + if (net_dev->netdev_ops == &rtl8192_netdev_ops && + event == NETDEV_CHANGENAME) { + rtl8192_proc_remove_one(net_dev); + rtl8192_proc_init_one(net_dev); + } + + return NOTIFY_DONE; +} + +static struct notifier_block proc_netdev_notifier = { + .notifier_call = proc_netdev_event, +}; + /**************************************************************************** -----------------------------MISC STUFF------------------------- *****************************************************************************/ @@ -1278,7 +1310,6 @@ static int rtl8192_rx_initiate(struct net_device*dev) kfree_skb(skb); break; } -// printk("nomal packet IN request!\n"); usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb), RX_URB_SIZE, rtl8192_rx_isr, skb); @@ -1292,7 +1323,6 @@ static int rtl8192_rx_initiate(struct net_device*dev) /* command packet rx procedure */ while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) { -// printk("command packet IN request!\n"); skb = __dev_alloc_skb(RX_URB_SIZE ,GFP_KERNEL); if (!skb) break; @@ -7528,35 +7558,63 @@ static int __init rtl8192_usb_module_init(void) ret = ieee80211_crypto_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret); - return ret; + goto fail_crypto; } ret = ieee80211_crypto_tkip_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", ret); - return ret; + goto fail_crypto_tkip; } ret = ieee80211_crypto_ccmp_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", ret); - return ret; + goto fail_crypto_ccmp; } ret = ieee80211_crypto_wep_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret); - return ret; + goto fail_crypto_wep; } printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n"); printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n"); RT_TRACE(COMP_INIT, "Initializing module"); RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT); - rtl8192_proc_module_init(); - return usb_register(&rtl8192_usb_driver); + + ret = rtl8192_proc_module_init(); + if (ret) { + pr_err("rtl8192_proc_module_init() failed %d\n", ret); + goto fail_proc; + } + + ret = usb_register(&rtl8192_usb_driver); + if (ret) { + pr_err("usb_register() failed %d\n", ret); + goto fail_usb; + } + + return 0; + +fail_usb: + rtl8192_proc_module_remove(); +fail_proc: + ieee80211_crypto_wep_exit(); +fail_crypto_wep: + ieee80211_crypto_ccmp_exit(); +fail_crypto_ccmp: + ieee80211_crypto_tkip_exit(); +fail_crypto_tkip: + ieee80211_crypto_deinit(); +fail_crypto: +#ifdef CONFIG_IEEE80211_DEBUG + ieee80211_debug_exit(); +#endif + return ret; } diff --git a/drivers/staging/rtl8192su/r819xU_cmdpkt.c b/drivers/staging/rtl8192su/r819xU_cmdpkt.c index 3ebfe79..e69c3b4 100644 --- a/drivers/staging/rtl8192su/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192su/r819xU_cmdpkt.c @@ -56,6 +56,12 @@ SendTxCommandPacket( //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4); + if (skb == NULL) { + RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n", + __func__); + rtStatus = false; + return rtStatus; + } memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index bc26740..16a7df1 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -170,33 +170,23 @@ static int tweak_set_configuration_cmd(struct urb *urb) static int tweak_reset_device_cmd(struct urb *urb) { - struct usb_ctrlrequest *req; - __u16 value; - __u16 index; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - value = le16_to_cpu(req->wValue); - index = le16_to_cpu(req->wIndex); - - usbip_uinfo("reset_device (port %d) to %s\n", index, - dev_name(&urb->dev->dev)); + struct stub_priv *priv = (struct stub_priv *) urb->context; + struct stub_device *sdev = priv->sdev; - /* all interfaces should be owned by usbip driver, so just reset it. */ - ret = usb_lock_device_for_reset(urb->dev, NULL); - if (ret < 0) { - dev_err(&urb->dev->dev, "lock for reset\n"); - return ret; - } - - /* try to reset the device */ - ret = usb_reset_device(urb->dev); - if (ret < 0) - dev_err(&urb->dev->dev, "device reset\n"); + usbip_uinfo("reset_device %s\n", dev_name(&urb->dev->dev)); - usb_unlock_device(urb->dev); - - return ret; + /* + * usb_lock_device_for_reset caused a deadlock: it causes the driver + * to unbind. In the shutdown the rx thread is signalled to shut down + * but this thread is pending in the usb_lock_device_for_reset. + * + * Instead queue the reset. + * + * Unfortunatly an existing usbip connection will be dropped due to + * driver unbinding. + */ + usb_queue_reset_device(sdev->interface); + return 0; } /* diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c index d7136e2..b7a493c 100644 --- a/drivers/staging/usbip/stub_tx.c +++ b/drivers/staging/usbip/stub_tx.c @@ -169,7 +169,6 @@ static int stub_send_ret_submit(struct stub_device *sdev) struct stub_priv *priv, *tmp; struct msghdr msg; - struct kvec iov[3]; size_t txsize; size_t total_size = 0; @@ -179,28 +178,73 @@ static int stub_send_ret_submit(struct stub_device *sdev) struct urb *urb = priv->urb; struct usbip_header pdu_header; void *iso_buffer = NULL; + struct kvec *iov = NULL; + int iovnum = 0; txsize = 0; memset(&pdu_header, 0, sizeof(pdu_header)); memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - usbip_dbg_stub_tx("setup txdata urb %p\n", urb); + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + iovnum = 2 + urb->number_of_packets; + else + iovnum = 2; + + iov = kzalloc(iovnum * sizeof(struct kvec), GFP_KERNEL); + if (!iov) { + usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); + return -1; + } + + iovnum = 0; /* 1. setup usbip_header */ setup_ret_submit_pdu(&pdu_header, urb); + usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n", + pdu_header.base.seqnum, urb); + /*usbip_dump_header(pdu_header);*/ usbip_header_correct_endian(&pdu_header, 1); - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); + iov[iovnum].iov_base = &pdu_header; + iov[iovnum].iov_len = sizeof(pdu_header); + iovnum++; txsize += sizeof(pdu_header); /* 2. setup transfer buffer */ - if (usb_pipein(urb->pipe) && urb->actual_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->actual_length; + if (usb_pipein(urb->pipe) && + usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS && + urb->actual_length > 0) { + iov[iovnum].iov_base = urb->transfer_buffer; + iov[iovnum].iov_len = urb->actual_length; + iovnum++; txsize += urb->actual_length; + } else if (usb_pipein(urb->pipe) && + usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { + /* + * For isochronous packets: actual length is the sum of + * the actual length of the individual, packets, but as + * the packet offsets are not changed there will be + * padding between the packets. To optimally use the + * bandwidth the padding is not transmitted. + */ + + int i; + for (i = 0; i < urb->number_of_packets; i++) { + iov[iovnum].iov_base = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + iov[iovnum].iov_len = urb->iso_frame_desc[i].actual_length; + iovnum++; + txsize += urb->iso_frame_desc[i].actual_length; + } + + if (txsize != sizeof(pdu_header) + urb->actual_length) { + dev_err(&sdev->interface->dev, + "actual length of urb (%d) does not match iso packet sizes (%d)\n", + urb->actual_length, txsize-sizeof(pdu_header)); + kfree(iov); + usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); + return -1; + } } /* 3. setup iso_packet_descriptor */ @@ -211,32 +255,34 @@ static int stub_send_ret_submit(struct stub_device *sdev) if (!iso_buffer) { usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); + kfree(iov); return -1; } - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; + iov[iovnum].iov_base = iso_buffer; + iov[iovnum].iov_len = len; txsize += len; + iovnum++; } - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, - 3, txsize); + ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, + iov, iovnum, txsize); if (ret != txsize) { dev_err(&sdev->interface->dev, "sendmsg failed!, retval %d for %zd\n", ret, txsize); + kfree(iov); kfree(iso_buffer); usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); return -1; } + kfree(iov); kfree(iso_buffer); - usbip_dbg_stub_tx("send txdata\n"); total_size += txsize; } - spin_lock_irqsave(&sdev->priv_lock, flags); list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index e3fa421..707b57d 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -334,10 +334,11 @@ void usbip_dump_header(struct usbip_header *pdu) usbip_udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); break; case USBIP_RET_SUBMIT: - usbip_udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n", + usbip_udbg("RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n", pdu->u.ret_submit.status, pdu->u.ret_submit.actual_length, pdu->u.ret_submit.start_frame, + pdu->u.ret_submit.number_of_packets, pdu->u.ret_submit.error_count); case USBIP_RET_UNLINK: usbip_udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); @@ -605,6 +606,7 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, rpdu->status = urb->status; rpdu->actual_length = urb->actual_length; rpdu->start_frame = urb->start_frame; + rpdu->number_of_packets = urb->number_of_packets; rpdu->error_count = urb->error_count; } else { /* vhci_rx.c */ @@ -612,6 +614,7 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, urb->status = rpdu->status; urb->actual_length = rpdu->actual_length; urb->start_frame = rpdu->start_frame; + urb->number_of_packets = rpdu->number_of_packets; urb->error_count = rpdu->error_count; } } @@ -680,11 +683,13 @@ static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, cpu_to_be32s(&pdu->status); cpu_to_be32s(&pdu->actual_length); cpu_to_be32s(&pdu->start_frame); + cpu_to_be32s(&pdu->number_of_packets); cpu_to_be32s(&pdu->error_count); } else { be32_to_cpus(&pdu->status); be32_to_cpus(&pdu->actual_length); be32_to_cpus(&pdu->start_frame); + cpu_to_be32s(&pdu->number_of_packets); be32_to_cpus(&pdu->error_count); } } @@ -810,6 +815,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) int size = np * sizeof(*iso); int i; int ret; + int total_length = 0; if (!usb_pipeisoc(urb->pipe)) return 0; @@ -839,19 +845,75 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) return -EPIPE; } + for (i = 0; i < np; i++) { iso = buff + (i * sizeof(*iso)); usbip_iso_pakcet_correct_endian(iso, 0); usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); + total_length += urb->iso_frame_desc[i].actual_length; } kfree(buff); + if (total_length != urb->actual_length) { + dev_err(&urb->dev->dev, + "total length of iso packets (%d) not equal to actual length of buffer (%d)\n", + total_length, urb->actual_length); + + if (ud->side == USBIP_STUB) + usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); + else + usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); + + return -EPIPE; + } + return ret; } EXPORT_SYMBOL_GPL(usbip_recv_iso); +/* + * This functions restores the padding which was removed for optimizing + * the bandwidth during transfer over tcp/ip + * + * buffer and iso packets need to be stored and be in propeper endian in urb + * before calling this function + */ +int usbip_pad_iso(struct usbip_device *ud, struct urb *urb) +{ + int np = urb->number_of_packets; + int i; + int ret; + int actualoffset = urb->actual_length; + + if (!usb_pipeisoc(urb->pipe)) + return 0; + + /* if no packets or length of data is 0, then nothing to unpack */ + if (np == 0 || urb->actual_length == 0) + return 0; + + /* + * if actual_length is transfer_buffer_length then no padding is + * present. + */ + if (urb->actual_length == urb->transfer_buffer_length) + return 0; + + /* + * loop over all packets from last to first (to prevent overwritting + * memory when padding) and move them into the proper place + */ + for (i = np-1; i > 0; i--) { + actualoffset -= urb->iso_frame_desc[i].actual_length; + memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset, + urb->transfer_buffer + actualoffset, + urb->iso_frame_desc[i].actual_length); + } + return ret; +} +EXPORT_SYMBOL_GPL(usbip_pad_iso); /* some members of urb must be substituted before. */ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h index 6f1dcb1..c7c6c81 100644 --- a/drivers/staging/usbip/usbip_common.h +++ b/drivers/staging/usbip/usbip_common.h @@ -393,6 +393,8 @@ void usbip_header_correct_endian(struct usbip_header *pdu, int send); int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); /* some members of urb must be substituted before. */ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); +/* some members of urb must be substituted before. */ +int usbip_pad_iso(struct usbip_device *ud, struct urb *urb); void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index bdbedd2..a1ac1b8 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -99,6 +99,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, if (usbip_recv_iso(ud, urb) < 0) return; + /* restore the padding in iso packets */ + if (usbip_pad_iso(ud, urb) < 0) + return; if (usbip_dbg_flag_vhci_rx) usbip_dump_urb(urb); diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 19bc03a..0ce4230 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -65,8 +65,8 @@ #define ALLOW_SERIAL_NUMBER static const char *format_topo = -/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */ -"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n"; +/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */ +"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n"; static const char *format_string_manufacturer = /* S: Manufacturer=xxxx */ @@ -219,7 +219,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, break; case USB_ENDPOINT_XFER_INT: type = "Int."; - if (speed == USB_SPEED_HIGH) + if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER) interval = 1 << (desc->bInterval - 1); else interval = desc->bInterval; @@ -227,7 +227,8 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, default: /* "can't happen" */ return start; } - interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000; + interval *= (speed == USB_SPEED_HIGH || + speed == USB_SPEED_SUPER) ? 125 : 1000; if (interval % 1000) unit = 'u'; else { @@ -517,11 +518,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, speed = "1.5"; break; case USB_SPEED_UNKNOWN: /* usb 1.1 root hub code */ case USB_SPEED_FULL: - speed = "12 "; break; + speed = "12"; break; + case USB_SPEED_WIRELESS: /* Wireless has no real fixed speed */ case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_SUPER: + speed = "5000"; break; default: - speed = "?? "; + speed = "??"; } data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, @@ -537,8 +541,9 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, if (level == 0) { int max; - /* high speed reserves 80%, full/low reserves 90% */ - if (usbdev->speed == USB_SPEED_HIGH) + /* super/high speed reserves 80%, full/low reserves 90% */ + if (usbdev->speed == USB_SPEED_HIGH || + usbdev->speed == USB_SPEED_SUPER) max = 800; else max = FRAME_TIME_MAX_USECS_ALLOC; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index d1d4bb1..781c573 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1246,24 +1246,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) static void scan_async (struct ehci_hcd *ehci) { + bool stopped; struct ehci_qh *qh; enum ehci_timer_action action = TIMER_IO_WATCHDOG; ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: + stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); qh = ehci->async->qh_next.qh; if (likely (qh != NULL)) { do { /* clean any finished work for this qh */ - if (!list_empty (&qh->qtd_list) - && qh->stamp != ehci->stamp) { + if (!list_empty(&qh->qtd_list) && (stopped || + qh->stamp != ehci->stamp)) { int temp; /* unlinks could happen here; completion * reporting drops the lock. rescan using * the latest schedule, but don't rescan - * qhs we already finished (no looping). + * qhs we already finished (no looping) + * unless the controller is stopped. */ qh = qh_get (qh); qh->stamp = ehci->stamp; @@ -1284,9 +1287,9 @@ rescan: */ if (list_empty(&qh->qtd_list) && qh->qh_state == QH_STATE_LINKED) { - if (!ehci->reclaim - && ((ehci->stamp - qh->stamp) & 0x1fff) - >= (EHCI_SHRINK_FRAMES * 8)) + if (!ehci->reclaim && (stopped || + ((ehci->stamp - qh->stamp) & 0x1fff) + >= EHCI_SHRINK_FRAMES * 8)) start_unlink_async(ehci, qh); else action = TIMER_ASYNC_SHRINK; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index e560dd4..54a538d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -520,6 +520,63 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud return 0; } +/* + * Convert interval expressed as 2^(bInterval - 1) == interval into + * straight exponent value 2^n == interval. + * + */ +static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + unsigned int interval; + + interval = clamp_val(ep->desc.bInterval, 1, 16) - 1; + if (interval != ep->desc.bInterval - 1) + dev_warn(&udev->dev, + "ep %#x - rounding interval to %d microframes\n", + ep->desc.bEndpointAddress, + 1 << interval); + + return interval; +} + +/* + * Convert bInterval expressed in microframes (in 1-255 range) to exponent of + * microframes, rounded down to nearest power of 2. + */ +static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, + struct usb_host_endpoint *ep, unsigned int desc_interval, + unsigned int min_exponent, unsigned int max_exponent) +{ + unsigned int interval; + + interval = fls(desc_interval) - 1; + interval = clamp_val(interval, min_exponent, max_exponent); + if ((1 << interval) != desc_interval) + dev_warn(&udev->dev, + "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", + ep->desc.bEndpointAddress, + 1 << interval, + desc_interval); + + return interval; +} + +static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + return xhci_microframes_to_exponent(udev, ep, + ep->desc.bInterval, 0, 15); +} + + +static unsigned int xhci_parse_frame_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + return xhci_microframes_to_exponent(udev, ep, + ep->desc.bInterval * 8, 3, 10); +} + /* Return the polling or NAK interval. * * The polling interval is expressed in "microframes". If xHCI's Interval field @@ -537,45 +594,38 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, case USB_SPEED_HIGH: /* Max NAK rate */ if (usb_endpoint_xfer_control(&ep->desc) || - usb_endpoint_xfer_bulk(&ep->desc)) - interval = ep->desc.bInterval; + usb_endpoint_xfer_bulk(&ep->desc)) { + interval = xhci_parse_microframe_interval(udev, ep); + break; + } /* Fall through - SS and HS isoc/int have same decoding */ + case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(&ep->desc) || - usb_endpoint_xfer_isoc(&ep->desc)) { - if (ep->desc.bInterval == 0) - interval = 0; - else - interval = ep->desc.bInterval - 1; - if (interval > 15) - interval = 15; - if (interval != ep->desc.bInterval + 1) - dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n", - ep->desc.bEndpointAddress, 1 << interval); + usb_endpoint_xfer_isoc(&ep->desc)) { + interval = xhci_parse_exponent_interval(udev, ep); } break; - /* Convert bInterval (in 1-255 frames) to microframes and round down to - * nearest power of 2. - */ + case USB_SPEED_FULL: + if (usb_endpoint_xfer_int(&ep->desc)) { + interval = xhci_parse_exponent_interval(udev, ep); + break; + } + /* + * Fall through for isochronous endpoint interval decoding + * since it uses the same rules as low speed interrupt + * endpoints. + */ + case USB_SPEED_LOW: if (usb_endpoint_xfer_int(&ep->desc) || - usb_endpoint_xfer_isoc(&ep->desc)) { - interval = fls(8*ep->desc.bInterval) - 1; - if (interval > 10) - interval = 10; - if (interval < 3) - interval = 3; - if ((1 << interval) != 8*ep->desc.bInterval) - dev_warn(&udev->dev, - "ep %#x - rounding interval" - " to %d microframes, " - "ep desc says %d microframes\n", - ep->desc.bEndpointAddress, - 1 << interval, - 8*ep->desc.bInterval); + usb_endpoint_xfer_isoc(&ep->desc)) { + + interval = xhci_parse_frame_interval(udev, ep); } break; + default: BUG(); } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ea389e9..a51358b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -232,7 +232,7 @@ struct xhci_op_regs { * notification type that matches a bit set in this bit field. */ #define DEV_NOTE_MASK (0xffff) -#define ENABLE_DEV_NOTE(x) (1 << x) +#define ENABLE_DEV_NOTE(x) (1 << (x)) /* Most of the device notification types should only be used for debug. * SW does need to pay attention to function wake notifications. */ @@ -579,11 +579,11 @@ struct xhci_ep_ctx { #define EP_STATE_STOPPED 3 #define EP_STATE_ERROR 4 /* Mult - Max number of burtst within an interval, in EP companion desc. */ -#define EP_MULT(p) ((p & 0x3) << 8) +#define EP_MULT(p) (((p) & 0x3) << 8) /* bits 10:14 are Max Primary Streams */ /* bit 15 is Linear Stream Array */ /* Interval - period between requests to an endpoint - 125u increments. */ -#define EP_INTERVAL(p) ((p & 0xff) << 16) +#define EP_INTERVAL(p) (((p) & 0xff) << 16) #define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) /* ep_info2 bitmasks */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 05dcaa0..7d0107a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -155,6 +155,8 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = { * /sys/bus/usb/ftdi_sio/new_id, then send patch/report! */ static struct usb_device_id id_table_combined [] = { + { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, @@ -529,6 +531,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, { USB_DEVICE(OCT_VID, OCT_US101_PID) }, + { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID), .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk }, { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID), @@ -790,6 +793,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) }, { USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) }, { USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 73d8c79..aaeb159 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -300,6 +300,8 @@ * Hameg HO820 and HO870 interface (using VID 0x0403) */ #define HAMEG_HO820_PID 0xed74 +#define HAMEG_HO730_PID 0xed73 +#define HAMEG_HO720_PID 0xed72 #define HAMEG_HO870_PID 0xed71 /* @@ -579,6 +581,7 @@ /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ /* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ /* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ +#define OCT_DK201_PID 0x0103 /* OCT DK201 USB docking station */ #define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ /* @@ -1146,3 +1149,11 @@ */ #define QIHARDWARE_VID 0x20B7 #define MILKYMISTONE_JTAGSERIAL_PID 0x0713 + +/* + * CTI GmbH RS485 Converter http://www.cti-lean.com/ + */ +/* USB-485-Mini*/ +#define FTDI_CTI_MINI_PID 0xF608 +/* USB-Nano-485*/ +#define FTDI_CTI_NANO_PID 0xF60B diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e8323de..335dbed 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -402,6 +402,16 @@ static int option_resume(struct usb_serial *serial); #define CELOT_VENDOR_ID 0x211f #define CELOT_PRODUCT_CT680M 0x6801 +/* ONDA Communication vendor id */ +#define ONDA_VENDOR_ID 0x1ee8 + +/* ONDA MT825UP HSDPA 14.2 modem */ +#define ONDA_MT825UP 0x000b + +/* Samsung products */ +#define SAMSUNG_VENDOR_ID 0x04e8 +#define SAMSUNG_PRODUCT_GT_B3730 0x6889 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -955,6 +965,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ + { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ + { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730/GT-B3710 LTE USB modem.*/ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c index 1b5d3fe..0f5268e 100644 --- a/drivers/video/backlight/mbp_nvidia_bl.c +++ b/drivers/video/backlight/mbp_nvidia_bl.c @@ -290,6 +290,24 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { }, .driver_data = (void *)&nvidia_chipset_data, }, + { + .callback = mbp_dmi_match, + .ident = "MacBookAir 3,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,1"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, + { + .callback = mbp_dmi_match, + .ident = "MacBookAir 3,2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,2"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, { } }; diff --git a/fs/aio.c b/fs/aio.c index 94b6cd6..2600146 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -512,7 +512,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) ctx->reqs_active--; if (unlikely(!ctx->reqs_active && ctx->dead)) - wake_up(&ctx->wait); + wake_up_all(&ctx->wait); } static void aio_fput_routine(struct work_struct *data) @@ -1225,7 +1225,7 @@ static void io_destroy(struct kioctx *ioctx) * by other CPUs at this point. Right now, we rely on the * locking done by the above calls to ensure this consistency. */ - wake_up(&ioctx->wait); + wake_up_all(&ioctx->wait); put_ioctx(ioctx); /* once for the lookup */ } diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 34ddda8..9158c07 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -469,17 +469,22 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd) befs_data_stream *data = &befs_ino->i_data.ds; befs_off_t len = data->size; - befs_debug(sb, "Follow long symlink"); - - link = kmalloc(len, GFP_NOFS); - if (!link) { - link = ERR_PTR(-ENOMEM); - } else if (befs_read_lsymlink(sb, data, link, len) != len) { - kfree(link); - befs_error(sb, "Failed to read entire long symlink"); + if (len == 0) { + befs_error(sb, "Long symlink with illegal length"); link = ERR_PTR(-EIO); } else { - link[len - 1] = '\0'; + befs_debug(sb, "Follow long symlink"); + + link = kmalloc(len, GFP_NOFS); + if (!link) { + link = ERR_PTR(-ENOMEM); + } else if (befs_read_lsymlink(sb, data, link, len) != len) { + kfree(link); + befs_error(sb, "Failed to read entire long symlink"); + link = ERR_PTR(-EIO); + } else { + link[len - 1] = '\0'; + } } } else { link = befs_ino->i_data.symlink; diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 746a724..a79a910 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1184,6 +1184,8 @@ struct btrfs_root { #define BTRFS_INODE_NOATIME (1 << 9) #define BTRFS_INODE_DIRSYNC (1 << 10) +#define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31) + /* some macros to generate set/get funcs for the struct fields. This * assumes there is a lefoo_to_cpu for every type, so lets make a simple * one for u8: @@ -2185,6 +2187,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); int btrfs_find_orphan_roots(struct btrfs_root *tree_root); int btrfs_set_root_node(struct btrfs_root_item *item, struct extent_buffer *node); +void btrfs_check_and_init_root_item(struct btrfs_root_item *item); + /* dir-item.c */ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index feca041..fa46c2d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1146,8 +1146,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, root->commit_root = btrfs_root_node(root); BUG_ON(!root->node); out: - if (location->objectid != BTRFS_TREE_LOG_OBJECTID) + if (location->objectid != BTRFS_TREE_LOG_OBJECTID) { root->ref_cows = 1; + btrfs_check_and_init_root_item(&root->root_item); + } return root; } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e9d0535..e624555 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -286,6 +286,10 @@ static noinline int create_subvol(struct btrfs_root *root, inode_item->nbytes = cpu_to_le64(root->leafsize); inode_item->mode = cpu_to_le32(S_IFDIR | 0755); + root_item.flags = 0; + root_item.byte_limit = 0; + inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT); + btrfs_set_root_bytenr(&root_item, leaf->start); btrfs_set_root_generation(&root_item, trans->transid); btrfs_set_root_level(&root_item, 0); diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 67fa2d2..3174255 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -459,3 +459,21 @@ again: btrfs_free_path(path); return 0; } + +/* + * Old btrfs forgets to init root_item->flags and root_item->byte_limit + * for subvolumes. To work around this problem, we steal a bit from + * root_item->inode_item->flags, and use it to indicate if those fields + * have been properly initialized. + */ +void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item) +{ + u64 inode_flags = le64_to_cpu(root_item->inode.flags); + + if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) { + inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT; + root_item->inode.flags = cpu_to_le64(inode_flags); + root_item->flags = 0; + root_item->byte_limit = 0; + } +} diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2cb1160..5110e70 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -805,6 +805,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); + btrfs_check_and_init_root_item(new_root_item); old = btrfs_lock_root_node(root); btrfs_cow_block(trans, root, old, NULL, 0, &old); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8db7b14..c04ebb1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "compat.h" #include "ctree.h" @@ -1908,6 +1909,9 @@ int btrfs_balance(struct btrfs_root *dev_root) if (dev_root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + mutex_lock(&dev_root->fs_info->volume_mutex); dev_root = dev_root->fs_info->dev_root; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d9566bf..1f6aae0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -800,8 +800,7 @@ static int cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol) { - char *value; - char *data; + char *value, *data, *end; unsigned int temp_len, i, j; char separator[2]; short int override_uid = -1; @@ -844,6 +843,7 @@ cifs_parse_mount_options(char *options, const char *devname, if (!options) return 1; + end = options + strlen(options); if (strncmp(options, "sep=", 4) == 0) { if (options[4] != 0) { separator[0] = options[4]; @@ -908,6 +908,7 @@ cifs_parse_mount_options(char *options, const char *devname, the only illegal character in a password is null */ if ((value[temp_len] == 0) && + (value + temp_len < end) && (value[temp_len+1] == separator[0])) { /* reinsert comma */ value[temp_len] = separator[0]; @@ -2253,6 +2254,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon, 0 /* not legacy */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + + if (rc == -EOPNOTSUPP || rc == -EINVAL) + rc = SMBQueryInformation(xid, tcon, full_path, pfile_info, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(pfile_info); return rc; } @@ -2555,7 +2561,7 @@ try_mount_again: remote_path_check: /* check if a whole path (including prepath) is not remote */ - if (!rc && cifs_sb->prepathlen && tcon) { + if (!rc && tcon) { /* build_path_to_root works only when we have a valid tcon */ full_path = cifs_build_path_to_root(cifs_sb); if (full_path == NULL) { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 49b47c3..da3e83f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -793,8 +793,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); - if (!inode) - return ERR_PTR(-ENOMEM); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } if (rc && cifs_sb->tcon->ipc) { cFYI(1, ("ipc connection - fake read inode")); @@ -805,13 +807,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; } else if (rc) { - kfree(full_path); - _FreeXid(xid); iget_failed(inode); - return ERR_PTR(rc); + inode = ERR_PTR(rc); } - +out: kfree(full_path); /* can not call macro FreeXid here since in a void func * TODO: This is no longer true diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index c7d78c0..ff4f5b1 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -906,7 +906,9 @@ ssetup_ntlmssp_authenticate: } /* BB check if Unicode and decode strings */ - if (smb_buf->Flags2 & SMBFLG2_UNICODE) { + if (bytes_remaining == 0) { + /* no string area to decode, do nothing */ + } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { /* unicode string area must be word-aligned */ if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { ++bcc_ptr; diff --git a/fs/compat.c b/fs/compat.c index 6490d21..633e63c 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1376,6 +1376,10 @@ static int compat_count(compat_uptr_t __user *argv, int max) argv++; if (i++ >= max) return -E2BIG; + + if (fatal_signal_pending(current)) + return -ERESTARTNOHAND; + cond_resched(); } } return i; @@ -1417,6 +1421,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, while (len > 0) { int offset, bytes_to_copy; + if (fatal_signal_pending(current)) { + ret = -ERESTARTNOHAND; + goto out; + } + cond_resched(); + offset = pos % PAGE_SIZE; if (offset == 0) offset = PAGE_SIZE; @@ -1433,18 +1443,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, if (!kmapped_page || kpos != (pos & PAGE_MASK)) { struct page *page; -#ifdef CONFIG_STACK_GROWSUP - ret = expand_stack_downwards(bprm->vma, pos); - if (ret < 0) { - /* We've exceed the stack rlimit. */ - ret = -E2BIG; - goto out; - } -#endif - ret = get_user_pages(current, bprm->mm, pos, - 1, 1, 1, &page, NULL); - if (ret <= 0) { - /* We've exceed the stack rlimit. */ + page = get_arg_page(bprm, pos, 1); + if (!page) { ret = -E2BIG; goto out; } @@ -1565,8 +1565,10 @@ int compat_do_execve(char * filename, return retval; out: - if (bprm->mm) + if (bprm->mm) { + acct_arg_size(bprm, 0); mmput(bprm->mm); + } out_file: if (bprm->file) { diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 89c5476..d6e9355 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1543,6 +1543,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, printk(KERN_ERR "Could not find key with description: [%s]\n", sig); rc = process_request_key_err(PTR_ERR(*auth_tok_key)); + (*auth_tok_key) = NULL; goto out; } (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key); diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 2ee9a3a..eb1a0c9 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -377,6 +377,11 @@ static int ecryptfs_write_begin(struct file *file, && (pos != 0)) zero_user(page, 0, PAGE_CACHE_SIZE); out: + if (unlikely(rc)) { + unlock_page(page); + page_cache_release(page); + *pagep = NULL; + } return rc; } diff --git a/fs/exec.c b/fs/exec.c index b5cf64a..11cfcce 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -158,7 +158,7 @@ out: #ifdef CONFIG_MMU -static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) +void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) { struct mm_struct *mm = current->mm; long diff = (long)(pages - bprm->vma_pages); @@ -173,7 +173,7 @@ static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) up_write(&mm->mmap_sem); } -static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, +struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { struct page *page; @@ -291,11 +291,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) #else -static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) +void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) { } -static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, +struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { struct page *page; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 4eced51..904f3e4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5573,13 +5573,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, /* if nrblocks are contiguous */ if (chunk) { /* - * With N contiguous data blocks, it need at most - * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks - * 2 dindirect blocks - * 1 tindirect block + * With N contiguous data blocks, we need at most + * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks, + * 2 dindirect blocks, and 1 tindirect block */ - indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); - return indirects + 3; + return DIV_ROUND_UP(nrblocks, + EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4; } /* * if nrblocks are not contiguous, worse case, each block touch diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 6dbcbad..f9358a2 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -637,15 +637,40 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, unsigned blocksize, iblock, pos; struct buffer_head *bh, *dibh; struct page *page; - void *kaddr; - struct gfs2_quota *qp; - s64 value; - int err = -EIO; + void *kaddr, *ptr; + struct gfs2_quota q, *qp; + int err, nbytes; u64 size; if (gfs2_is_stuffed(ip)) gfs2_unstuff_dinode(ip, NULL); - + + memset(&q, 0, sizeof(struct gfs2_quota)); + err = gfs2_internal_read(ip, NULL, (char *)&q, &loc, sizeof(q)); + if (err < 0) + return err; + + err = -EIO; + qp = &q; + qp->qu_value = be64_to_cpu(qp->qu_value); + qp->qu_value += change; + qp->qu_value = cpu_to_be64(qp->qu_value); + qd->qd_qb.qb_value = qp->qu_value; + if (fdq) { + if (fdq->d_fieldmask & FS_DQ_BSOFT) { + qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit); + qd->qd_qb.qb_warn = qp->qu_warn; + } + if (fdq->d_fieldmask & FS_DQ_BHARD) { + qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit); + qd->qd_qb.qb_limit = qp->qu_limit; + } + } + + /* Write the quota into the quota file on disk */ + ptr = qp; + nbytes = sizeof(struct gfs2_quota); +get_a_page: page = grab_cache_page(mapping, index); if (!page) return -ENOMEM; @@ -667,7 +692,10 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, if (!buffer_mapped(bh)) { gfs2_block_map(inode, iblock, bh, 1); if (!buffer_mapped(bh)) - goto unlock; + goto unlock_out; + /* If it's a newly allocated disk block for quota, zero it */ + if (buffer_new(bh)) + zero_user(page, pos - blocksize, bh->b_size); } if (PageUptodate(page)) @@ -677,32 +705,34 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, ll_rw_block(READ_META, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) - goto unlock; + goto unlock_out; } gfs2_trans_add_bh(ip->i_gl, bh, 0); kaddr = kmap_atomic(page, KM_USER0); - qp = kaddr + offset; - value = (s64)be64_to_cpu(qp->qu_value) + change; - qp->qu_value = cpu_to_be64(value); - qd->qd_qb.qb_value = qp->qu_value; - if (fdq) { - if (fdq->d_fieldmask & FS_DQ_BSOFT) { - qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit); - qd->qd_qb.qb_warn = qp->qu_warn; - } - if (fdq->d_fieldmask & FS_DQ_BHARD) { - qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit); - qd->qd_qb.qb_limit = qp->qu_limit; - } - } + if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE) + nbytes = PAGE_CACHE_SIZE - offset; + memcpy(kaddr + offset, ptr, nbytes); flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); + unlock_page(page); + page_cache_release(page); + + /* If quota straddles page boundary, we need to update the rest of the + * quota at the beginning of the next page */ + if ((offset + sizeof(struct gfs2_quota)) > PAGE_CACHE_SIZE) { + ptr = ptr + nbytes; + nbytes = sizeof(struct gfs2_quota) - nbytes; + offset = 0; + index++; + goto get_a_page; + } + /* Update the disk inode timestamp and size (if extended) */ err = gfs2_meta_inode_buffer(ip, &dibh); if (err) - goto unlock; + goto out; size = loc + sizeof(struct gfs2_quota); if (size > inode->i_size) { @@ -715,7 +745,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, brelse(dibh); mark_inode_dirty(inode); -unlock: +out: + return err; +unlock_out: unlock_page(page); page_cache_release(page); return err; @@ -779,8 +811,10 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) * rgrp since it won't be allocated during the transaction */ al->al_requested = 1; - /* +1 in the end for block requested above for unstuffing */ - blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1; + /* +3 in the end for unstuffing block, inode size update block + * and another block in case quota straddles page boundary and + * two blocks need to be updated instead of 1 */ + blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3; if (nalloc) al->al_requested += nalloc * (data_blocks + ind_blocks); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 50a56ed..b0299c0 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -793,9 +793,10 @@ out: return ret; } -static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) +static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) { struct nfs_inode *nfsi = NFS_I(inode); + unsigned long ret = 0; if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) && (fattr->valid & NFS_ATTR_FATTR_CHANGE) @@ -803,25 +804,32 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) nfsi->change_attr = fattr->change_attr; if (S_ISDIR(inode->i_mode)) nfsi->cache_validity |= NFS_INO_INVALID_DATA; + ret |= NFS_INO_INVALID_ATTR; } /* If we have atomic WCC data, we may update some attributes */ if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) && (fattr->valid & NFS_ATTR_FATTR_CTIME) - && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) - memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); + && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { + memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); + ret |= NFS_INO_INVALID_ATTR; + } if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) && (fattr->valid & NFS_ATTR_FATTR_MTIME) && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { - memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); - if (S_ISDIR(inode->i_mode)) - nfsi->cache_validity |= NFS_INO_INVALID_DATA; + memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); + if (S_ISDIR(inode->i_mode)) + nfsi->cache_validity |= NFS_INO_INVALID_DATA; + ret |= NFS_INO_INVALID_ATTR; } if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) && (fattr->valid & NFS_ATTR_FATTR_SIZE) && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) - && nfsi->npages == 0) - i_size_write(inode, nfs_size_to_loff_t(fattr->size)); + && nfsi->npages == 0) { + i_size_write(inode, nfs_size_to_loff_t(fattr->size)); + ret |= NFS_INO_INVALID_ATTR; + } + return ret; } /** @@ -1115,7 +1123,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | NFS_INO_REVAL_PAGECACHE); /* Do atomic weak cache consistency updates */ - nfs_wcc_update_inode(inode, fattr); + invalid |= nfs_wcc_update_inode(inode, fattr); /* More cache consistency checks */ if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 071fced..8dd3309 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "nfs4_fs.h" #include "delegation.h" @@ -3241,6 +3242,35 @@ static void buf_to_pages(const void *buf, size_t buflen, } } +static int buf_to_pages_noslab(const void *buf, size_t buflen, + struct page **pages, unsigned int *pgbase) +{ + struct page *newpage, **spages; + int rc = 0; + size_t len; + spages = pages; + + do { + len = min_t(size_t, PAGE_CACHE_SIZE, buflen); + newpage = alloc_page(GFP_KERNEL); + + if (newpage == NULL) + goto unwind; + memcpy(page_address(newpage), buf, len); + buf += len; + buflen -= len; + *pages++ = newpage; + rc++; + } while (buflen != 0); + + return rc; + +unwind: + for(; rc > 0; rc--) + __free_page(spages[rc-1]); + return -ENOMEM; +} + struct nfs4_cached_acl { int cached; size_t len; @@ -3407,13 +3437,23 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl .rpc_argp = &arg, .rpc_resp = &res, }; - int ret; + int ret, i; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; + i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); + if (i < 0) + return i; nfs_inode_return_delegation(inode); - buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); ret = nfs4_call_sync(server, &msg, &arg, &res, 1); + + /* + * Free each page after tx, so the only ref left is + * held by the network stack + */ + for (; i > 0; i--) + put_page(pages[i-1]); + nfs_access_zap_cache(inode); nfs_zap_acl_cache(inode); return ret; diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 6c5ed51..c03bdcc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1399,7 +1399,7 @@ static void nfs4_state_manager(struct nfs_client *clp) int status = 0; /* Ensure exclusive access to NFSv4 state */ - for(;;) { + do { if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { /* We're going to have to re-establish a clientid */ status = nfs4_reclaim_lease(clp); @@ -1482,7 +1482,7 @@ static void nfs4_state_manager(struct nfs_client *clp) break; if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) break; - } + } while (atomic_read(&clp->cl_count) > 1); return; out_error: printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ae570b0..85958a1 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1989,6 +1989,15 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) if (error < 0) goto out; + /* + * noac is a special case. It implies -o sync, but that's not + * necessarily reflected in the mtab options. do_remount_sb + * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the + * remount options, so we have to explicitly reset it. + */ + if (data->flags & NFS_MOUNT_NOAC) + *flags |= MS_SYNCHRONOUS; + /* compare new mount options with old ones */ error = nfs_compare_remount_data(nfss, data); out: diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 0c6d816..7c831a2 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -38,7 +38,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) exp_readlock(); nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); fh_put(&fh); - rqstp->rq_client = NULL; exp_readunlock(); /* We return nlm error codes as nlm doesn't know * about nfsd, but nfsd does know about nlm.. diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 054b50b..7de2873 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1387,7 +1387,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out; if (!(iap->ia_valid & ATTR_MODE)) iap->ia_mode = 0; - err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); + err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC); if (err) goto out; @@ -1409,6 +1409,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, if (IS_ERR(dchild)) goto out_nfserr; + /* If file doesn't exist, check for permissions to create one */ + if (!dchild->d_inode) { + err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); + if (err) + goto out; + } + err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); if (err) goto out; diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 30292df..584e0b0 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -72,10 +72,9 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) /* * check to see if the page is mapped already (no holes) */ - if (PageMappedToDisk(page)) { - unlock_page(page); + if (PageMappedToDisk(page)) goto mapped; - } + if (page_has_buffers(page)) { struct buffer_head *bh, *head; int fully_mapped = 1; @@ -90,7 +89,6 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (fully_mapped) { SetPageMappedToDisk(page); - unlock_page(page); goto mapped; } } @@ -105,16 +103,18 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_SIGBUS; ret = block_page_mkwrite(vma, vmf, nilfs_get_block); - if (unlikely(ret)) { + if (ret != VM_FAULT_LOCKED) { nilfs_transaction_abort(inode->i_sb); return ret; } + nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode, + 1 << (PAGE_SHIFT - inode->i_blkbits)); nilfs_transaction_commit(inode->i_sb); mapped: SetPageChecked(page); wait_on_page_writeback(page); - return 0; + return VM_FAULT_LOCKED; } static const struct vm_operations_struct nilfs_file_vm_ops = { diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index e504ab7..3de08db 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -1035,6 +1035,12 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno, ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos, &cluster_start, &cluster_end); + /* treat the write as new if the a hole/lseek spanned across + * the page boundary. + */ + new = new | ((i_size_read(inode) <= page_offset(page)) && + (page_offset(page) <= user_pos)); + if (page == wc->w_target_page) { map_from = user_pos & (PAGE_CACHE_SIZE - 1); map_to = map_from + user_len; diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 91babda..9b40337 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c @@ -312,6 +312,15 @@ is_gpt_valid(struct block_device *bdev, u64 lba, goto fail; } + /* Check the GUID Partition Table header size */ + if (le32_to_cpu((*gpt)->header_size) > + bdev_logical_block_size(bdev)) { + pr_debug("GUID Partition Table Header size is wrong: %u > %u\n", + le32_to_cpu((*gpt)->header_size), + bdev_logical_block_size(bdev)); + goto fail; + } + /* Check the GUID Partition Table CRC */ origcrc = le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; @@ -350,6 +359,12 @@ is_gpt_valid(struct block_device *bdev, u64 lba, goto fail; } + /* Check that sizeof_partition_entry has the correct value */ + if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { + pr_debug("GUID Partitition Entry Size check failed.\n"); + goto fail; + } + if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) goto fail; diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c index c05c17bc..9ddca58 100644 --- a/fs/partitions/osf.c +++ b/fs/partitions/osf.c @@ -10,10 +10,13 @@ #include "check.h" #include "osf.h" +#define MAX_OSF_PARTITIONS 18 + int osf_partition(struct parsed_partitions *state, struct block_device *bdev) { int i; int slot = 1; + unsigned int npartitions; Sector sect; unsigned char *data; struct disklabel { @@ -45,7 +48,7 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev) u8 p_fstype; u8 p_frag; __le16 p_cpg; - } d_partitions[8]; + } d_partitions[MAX_OSF_PARTITIONS]; } * label; struct d_partition * partition; @@ -63,7 +66,12 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev) put_dev_sector(sect); return 0; } - for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { + npartitions = le16_to_cpu(label->d_npartitions); + if (npartitions > MAX_OSF_PARTITIONS) { + put_dev_sector(sect); + return 0; + } + for (i = 0 ; i < npartitions; i++, partition++) { if (slot == state->limit) break; if (le32_to_cpu(partition->p_size)) diff --git a/fs/proc/base.c b/fs/proc/base.c index 8418fcc..268f00d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2871,11 +2871,16 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi /* for the /proc/ directory itself, after non-process stuff has been done */ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { - unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; - struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); + unsigned int nr; + struct task_struct *reaper; struct tgid_iter iter; struct pid_namespace *ns; + if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) + goto out_no_task; + nr = filp->f_pos - FIRST_PROCESS_ENTRY; + + reaper = get_proc_task(filp->f_path.dentry->d_inode); if (!reaper) goto out_no_task; diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 788b580..0d465c7 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -411,7 +411,7 @@ EXPORT_SYMBOL(dquot_acquire); */ int dquot_commit(struct dquot *dquot) { - int ret = 0, ret2 = 0; + int ret = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); mutex_lock(&dqopt->dqio_mutex); @@ -423,15 +423,10 @@ int dquot_commit(struct dquot *dquot) spin_unlock(&dq_list_lock); /* Inactive dquot can be only if there was error during read/init * => we have better not writing it */ - if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); - if (info_dirty(&dqopt->info[dquot->dq_type])) { - ret2 = dqopt->ops[dquot->dq_type]->write_file_info( - dquot->dq_sb, dquot->dq_type); - } - if (ret >= 0) - ret = ret2; - } + else + ret = -EIO; out_sem: mutex_unlock(&dqopt->dqio_mutex); return ret; diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 5ea4ad8..e9f6f9b 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -112,6 +112,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) SetPageDirty(page); unlock_page(page); + put_page(page); } return 0; diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c index 12b933a..a37d445 100644 --- a/fs/squashfs/dir.c +++ b/fs/squashfs/dir.c @@ -172,6 +172,11 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto failed_read; + while (dir_count--) { /* * Read directory entry. @@ -183,6 +188,10 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto failed_read; + err = squashfs_read_metadata(inode->i_sb, dire->name, &block, &offset, size); if (err < 0) diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index 5266bd8..4fa484d 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c @@ -174,6 +174,11 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto data_error; + while (dir_count--) { /* * Read directory entry. @@ -185,6 +190,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto data_error; + err = squashfs_read_metadata(dir->i_sb, dire->name, &block, &offset, size); if (err < 0) @@ -226,6 +235,9 @@ exit_lookup: d_add(dentry, inode); return ERR_PTR(0); +data_error: + err = -EIO; + read_failure: ERROR("Unable to read directory block [%llx:%x]\n", squashfs_i(dir)->start + msblk->directory_table, diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 37fa7ed..de01f28 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -519,7 +519,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) size_t sz; if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) - goto out; + return 0; INIT_LIST_HEAD(&list); diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index c2a68ba..a0c09fc 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -961,11 +961,39 @@ void dbg_dump_index(struct ubifs_info *c) void dbg_save_space_info(struct ubifs_info *c) { struct ubifs_debug_info *d = c->dbg; - - ubifs_get_lp_stats(c, &d->saved_lst); + int freeable_cnt; spin_lock(&c->space_lock); + memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); + + /* + * We use a dirty hack here and zero out @c->freeable_cnt, because it + * affects the free space calculations, and UBIFS might not know about + * all freeable eraseblocks. Indeed, we know about freeable eraseblocks + * only when we read their lprops, and we do this only lazily, upon the + * need. So at any given point of time @c->freeable_cnt might be not + * exactly accurate. + * + * Just one example about the issue we hit when we did not zero + * @c->freeable_cnt. + * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the + * amount of free space in @d->saved_free + * 2. We re-mount R/W, which makes UBIFS to read the "lsave" + * information from flash, where we cache LEBs from various + * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()' + * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()' + * -> 'ubifs_get_pnode()' -> 'update_cats()' + * -> 'ubifs_add_to_cat()'). + * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt + * becomes %1. + * 4. We calculate the amount of free space when the re-mount is + * finished in 'dbg_check_space_info()' and it does not match + * @d->saved_free. + */ + freeable_cnt = c->freeable_cnt; + c->freeable_cnt = 0; d->saved_free = ubifs_get_free_space_nolock(c); + c->freeable_cnt = freeable_cnt; spin_unlock(&c->space_lock); } @@ -982,12 +1010,15 @@ int dbg_check_space_info(struct ubifs_info *c) { struct ubifs_debug_info *d = c->dbg; struct ubifs_lp_stats lst; - long long avail, free; + long long free; + int freeable_cnt; spin_lock(&c->space_lock); - avail = ubifs_calc_available(c, c->min_idx_lebs); + freeable_cnt = c->freeable_cnt; + c->freeable_cnt = 0; + free = ubifs_get_free_space_nolock(c); + c->freeable_cnt = freeable_cnt; spin_unlock(&c->space_lock); - free = ubifs_get_free_space(c); if (free != d->saved_free) { ubifs_err("free space changed from %lld to %lld", @@ -2656,19 +2687,19 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) } fname = "dump_lprops"; - dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; d->dfs_dump_lprops = dent; fname = "dump_budg"; - dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; d->dfs_dump_budg = dent; fname = "dump_tnc"; - dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; d->dfs_dump_tnc = dent; diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 5692cf7..1a411fd 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1312,6 +1312,9 @@ int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync) dbg_gen("syncing inode %lu", inode->i_ino); + if (inode->i_sb->s_flags & MS_RDONLY) + return 0; + /* * VFS has already synchronized dirty pages for this inode. Synchronize * the inode unless this is a 'datasync()' call. diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index ad7f67b..ead230e 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -1270,10 +1270,9 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) lnum = branch->lnum; offs = branch->offs; pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS); - if (!pnode) { - err = -ENOMEM; - goto out; - } + if (!pnode) + return -ENOMEM; + if (lnum == 0) { /* * This pnode was not written which just means that the LEB diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 109c6ea..b712ed6 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -300,6 +300,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) goto out_free; } memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); + + /* + * We had to recover the master node, which means there was an + * unclean reboot. However, it is possible that the master node + * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. + * E.g., consider the following chain of events: + * + * 1. UBIFS was cleanly unmounted, so the master node is clean + * 2. UBIFS is being mounted R/W and starts changing the master + * node in the first (%UBIFS_MST_LNUM). A power cut happens, + * so this LEB ends up with some amount of garbage at the + * end. + * 3. UBIFS is being mounted R/O. We reach this place and + * recover the master node from the second LEB + * (%UBIFS_MST_LNUM + 1). But we cannot update the media + * because we are being mounted R/O. We have to defer the + * operation. + * 4. However, this master node (@c->mst_node) is marked as + * clean (since the step 1). And if we just return, the + * mount code will be confused and won't recover the master + * node when it is re-mounter R/W later. + * + * Thus, to force the recovery by marking the master node as + * dirty. + */ + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); } else { /* Write the recovered master node */ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 39798c6..074b620 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -60,6 +60,10 @@ struct linux_binprm{ unsigned long loader, exec; }; +extern void acct_arg_size(struct linux_binprm *bprm, unsigned long pages); +extern struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + int write); + #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0 #define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 43eaf5c..18d9eb3 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -121,6 +121,7 @@ struct mmc_host { unsigned int f_min; unsigned int f_max; u32 ocr_avail; + struct notifier_block pm_notify; #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ @@ -180,6 +181,7 @@ struct mmc_host { /* Only used with MMC_CAP_DISABLE */ int enabled; /* host is enabled */ + int rescan_disable; /* disable card detection */ int nesting_cnt; /* "enable" nesting count */ int en_dis_recurs; /* detect recursion */ unsigned int disable_delay; /* disable delay in msecs */ @@ -254,6 +256,7 @@ int mmc_card_can_sleep(struct mmc_host *host); int mmc_host_enable(struct mmc_host *host); int mmc_host_disable(struct mmc_host *host); int mmc_host_lazy_disable(struct mmc_host *host); +int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); static inline void mmc_set_disable_delay(struct mmc_host *host, unsigned int disable_delay) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0af14f2..0899edf 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1261,9 +1261,12 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen) static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset) { + if (!pskb_may_pull(skb, hlen)) + return NULL; + NAPI_GRO_CB(skb)->frag0 = NULL; NAPI_GRO_CB(skb)->frag0_len = 0; - return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; + return skb->data + offset; } static inline void *skb_gro_mac_header(struct sk_buff *skb) diff --git a/include/linux/pid.h b/include/linux/pid.h index 49f1c2f..ec9f2df 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -117,7 +117,7 @@ extern struct pid *find_vpid(int nr); */ extern struct pid *find_get_pid(int nr); extern struct pid *find_ge_pid(int nr, struct pid_namespace *); -int next_pidmap(struct pid_namespace *pid_ns, int last); +int next_pidmap(struct pid_namespace *pid_ns, unsigned int last); extern struct pid *alloc_pid(struct pid_namespace *ns); extern void free_pid(struct pid *pid); diff --git a/include/net/sock.h b/include/net/sock.h index 721c7b3..b365fc2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -255,7 +255,6 @@ struct sock { struct sk_buff *head; struct sk_buff *tail; int len; - int limit; } sk_backlog; wait_queue_head_t *sk_sleep; struct dst_entry *sk_dst_cache; @@ -604,10 +603,20 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) skb->next = NULL; } +/* + * Take into account size of receive queue and backlog queue + */ +static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb) +{ + unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc); + + return qsize + skb->truesize > sk->sk_rcvbuf; +} + /* The per-socket spinlock must be held here. */ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb) { - if (sk->sk_backlog.len >= max(sk->sk_backlog.limit, sk->sk_rcvbuf << 1)) + if (sk_rcvqueues_full(sk, skb)) return -ENOBUFS; __sk_add_backlog(sk, skb); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index d80b6db..558fa2f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -451,7 +451,7 @@ static inline int scsi_device_qas(struct scsi_device *sdev) } static inline int scsi_device_enclosure(struct scsi_device *sdev) { - return sdev->inquiry[6] & (1<<6); + return sdev->inquiry ? (sdev->inquiry[6] & (1<<6)) : 1; } static inline int scsi_device_protection(struct scsi_device *sdev) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c0922a0..b93c659 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -46,25 +46,25 @@ /* platform domain */ #define SND_SOC_DAPM_INPUT(wname) \ { .id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0} + .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_OUTPUT(wname) \ { .id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0} + .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_MIC(wname, wevent) \ { .id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} #define SND_SOC_DAPM_HP(wname, wevent) \ { .id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_SPK(wname, wevent) \ { .id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_LINE(wname, wevent) \ { .id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} /* path domain */ @@ -161,11 +161,11 @@ /* events that are pre and post DAPM */ #define SND_SOC_DAPM_PRE(wname, wevent) \ { .id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_POST(wname, wevent) \ { .id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \ - .num_kcontrols = 0, .event = wevent, \ + .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD} /* stream domain */ diff --git a/init/Kconfig b/init/Kconfig index 5fe94b8..04e486cf 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1052,6 +1052,7 @@ config SLAB per cpu and per node queues. config SLUB + depends on BROKEN || NUMA || !DISCONTIGMEM bool "SLUB (Unqueued Allocator)" help SLUB is a slab allocator that minimizes cache line usage diff --git a/init/main.c b/init/main.c index 5c85402..df0e20b 100644 --- a/init/main.c +++ b/init/main.c @@ -421,18 +421,26 @@ static void __init setup_command_line(char *command_line) * gcc-3.4 accidentally inlines this function, so use noinline. */ +static __initdata DECLARE_COMPLETION(kthreadd_done); + static noinline void __init_refok rest_init(void) __releases(kernel_lock) { int pid; rcu_scheduler_starting(); + /* + * We need to spawn init first so that it obtains pid-1, however + * the init task will end up wanting to create kthreads, which, if + * we schedule it before we create kthreadd, will OOPS. + */ kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); numa_default_policy(); pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); rcu_read_lock(); kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); rcu_read_unlock(); + complete(&kthreadd_done); unlock_kernel(); /* @@ -853,6 +861,10 @@ static noinline int init_post(void) static int __init kernel_init(void * unused) { + /* + * Wait until kthreadd is all set-up. + */ + wait_for_completion(&kthreadd_done); lock_kernel(); /* diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 11f3515..0887213 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -976,10 +976,8 @@ static void gdb_cmd_query(struct kgdb_state *ks) switch (remcom_in_buffer[1]) { case 's': case 'f': - if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) { - error_packet(remcom_out_buffer, -EINVAL); + if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) break; - } i = 0; remcom_out_buffer[0] = 'm'; @@ -1020,10 +1018,9 @@ static void gdb_cmd_query(struct kgdb_state *ks) pack_threadid(remcom_out_buffer + 2, thref); break; case 'T': - if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) { - error_packet(remcom_out_buffer, -EINVAL); + if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) break; - } + ks->threadid = 0; ptr = remcom_in_buffer + 17; kgdb_hex2long(&ptr, &ks->threadid); diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 2357b19..b203546 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -57,7 +57,8 @@ static atomic_t nr_task_events __read_mostly; */ int sysctl_perf_event_paranoid __read_mostly = 1; -int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */ +/* Minimum for 128 pages + 1 for the user control page */ +int sysctl_perf_event_mlock __read_mostly = 516; /* 'free' kb per user */ /* * max perf event sample rate diff --git a/kernel/pid.c b/kernel/pid.c index aebb30d..af8dbf7 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -183,11 +183,14 @@ static int alloc_pidmap(struct pid_namespace *pid_ns) return -1; } -int next_pidmap(struct pid_namespace *pid_ns, int last) +int next_pidmap(struct pid_namespace *pid_ns, unsigned int last) { int offset; struct pidmap *map, *end; + if (last >= PID_MAX_LIMIT) + return -1; + offset = (last + 1) & BITS_PER_PAGE_MASK; map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE]; end = &pid_ns->pidmap[PIDMAP_ENTRIES]; diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 11281d5..5e21645 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -292,16 +292,18 @@ ret: static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) { struct listener_list *listeners; - struct listener *s, *tmp; + struct listener *s, *tmp, *s2; unsigned int cpu; if (!cpumask_subset(mask, cpu_possible_mask)) return -EINVAL; + s = NULL; if (isadd == REGISTER) { for_each_cpu(cpu, mask) { - s = kmalloc_node(sizeof(struct listener), GFP_KERNEL, - cpu_to_node(cpu)); + if (!s) + s = kmalloc_node(sizeof(struct listener), + GFP_KERNEL, cpu_to_node(cpu)); if (!s) goto cleanup; s->pid = pid; @@ -310,9 +312,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) listeners = &per_cpu(listener_array, cpu); down_write(&listeners->sem); + list_for_each_entry_safe(s2, tmp, &listeners->list, list) { + if (s2->pid == pid) + goto next_cpu; + } list_add(&s->list, &listeners->list); + s = NULL; +next_cpu: up_write(&listeners->sem); } + kfree(s); return 0; } diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 1f5dde6..db24c5c 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -638,8 +638,8 @@ int clocksource_register(struct clocksource *cs) mutex_lock(&clocksource_mutex); clocksource_enqueue(cs); - clocksource_select(); clocksource_enqueue_watchdog(cs); + clocksource_select(); mutex_unlock(&clocksource_mutex); return 0; } diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 2030f62..0f888cb 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -523,10 +523,11 @@ static void tick_broadcast_init_next_event(struct cpumask *mask, */ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { + int cpu = smp_processor_id(); + /* Set it up only once ! */ if (bc->event_handler != tick_handle_oneshot_broadcast) { int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC; - int cpu = smp_processor_id(); bc->event_handler = tick_handle_oneshot_broadcast; clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); @@ -552,6 +553,15 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) tick_broadcast_set_event(tick_next_period, 1); } else bc->next_event.tv64 = KTIME_MAX; + } else { + /* + * The first cpu which switches to oneshot mode sets + * the bit for all other cpus which are in the general + * (periodic) broadcast mask. So the bit is set and + * would prevent the first broadcast enter after this + * to program the bc device. + */ + tick_broadcast_clear_oneshot(cpu); } } diff --git a/mm/mremap.c b/mm/mremap.c index 10d5f62..97de5ae 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -274,9 +274,16 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr, if (old_len > vma->vm_end - addr) goto Efault; - if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { - if (new_len > old_len) + /* Need to be careful about a growing mapping */ + if (new_len > old_len) { + unsigned long pgoff; + + if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) goto Efault; + pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; + pgoff += vma->vm_pgoff; + if (pgoff + (new_len >> PAGE_SHIFT) < pgoff) + goto Einval; } if (vma->vm_flags & VM_LOCKED) { diff --git a/mm/shmem.c b/mm/shmem.c index eef4ebe..0203cda 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2701,5 +2701,6 @@ int shmem_zero_setup(struct vm_area_struct *vma) fput(vma->vm_file); vma->vm_file = file; vma->vm_ops = &shmem_vm_ops; + vma->vm_flags |= VM_CAN_NONLINEAR; return 0; } diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index eb100ce..12c350c 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1392,7 +1392,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, ax25_cb *ax25; int err = 0; - memset(fsa, 0, sizeof(fsa)); + memset(fsa, 0, sizeof(*fsa)); lock_sock(sk); ax25 = ax25_sk(sk); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 9753b69..b21e319 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2746,7 +2746,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Reject if config buffer is too small. */ len = cmd_len - sizeof(*req); - if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { + if (len < 0 || l2cap_pi(sk)->conf_len + len > + sizeof(l2cap_pi(sk)->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, L2CAP_CONF_REJECT, flags), rsp); diff --git a/net/can/bcm.c b/net/can/bcm.c index dd23fb1..a6445fd 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1426,9 +1426,14 @@ static int bcm_init(struct sock *sk) static int bcm_release(struct socket *sock) { struct sock *sk = sock->sk; - struct bcm_sock *bo = bcm_sk(sk); + struct bcm_sock *bo; struct bcm_op *op, *next; + if (sk == NULL) + return 0; + + bo = bcm_sk(sk); + /* remove bcm_ops, timer, rx_unregister(), etc. */ unregister_netdevice_notifier(&bo->notifier); diff --git a/net/can/raw.c b/net/can/raw.c index da99cf1..9dd45ea 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -281,7 +281,12 @@ static int raw_init(struct sock *sk) static int raw_release(struct socket *sock) { struct sock *sk = sock->sk; - struct raw_sock *ro = raw_sk(sk); + struct raw_sock *ro; + + if (!sk) + return 0; + + ro = raw_sk(sk); unregister_netdevice_notifier(&ro->notifier); diff --git a/net/core/dev.c b/net/core/dev.c index 3095934..bcd5f6e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2822,6 +2822,8 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) { __skb_pull(skb, skb_headlen(skb)); skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); + skb->dev = napi->dev; + skb->skb_iif = 0; napi->skb = skb; } @@ -5691,6 +5693,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char */ call_netdevice_notifiers(NETDEV_UNREGISTER, dev); call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); + rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); /* * Flush the unicast and multicast chains diff --git a/net/core/sock.c b/net/core/sock.c index cf3b9aa..78b7087 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -327,6 +327,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) skb->dev = NULL; + if (sk_rcvqueues_full(sk, skb)) { + atomic_inc(&sk->sk_drops); + goto discard_and_relse; + } if (nested) bh_lock_sock_nested(sk); else @@ -1885,7 +1889,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_allocation = GFP_KERNEL; sk->sk_rcvbuf = sysctl_rmem_default; sk->sk_sndbuf = sysctl_wmem_default; - sk->sk_backlog.limit = sk->sk_rcvbuf << 1; sk->sk_state = TCP_CLOSE; sk_set_socket(sk, sock); diff --git a/net/dccp/options.c b/net/dccp/options.c index 1b08cae..b4a853e 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -131,6 +131,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ break; + if (len == 0) + goto out_invalid_option; rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, *value, value + 1, len - 1); if (rc) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 7403b9b..99366cb 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc) return 0; if (cc == len) return 1; - if (op->yes < 4) + if (op->yes < 4 || op->yes & 3) return 0; len -= op->yes; bc += op->yes; @@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc) static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { - const unsigned char *bc = bytecode; + const void *bc = bytecode; int len = bytecode_len; while (len > 0) { - struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; + const struct inet_diag_bc_op *op = bc; //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); switch (op->code) { @@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; case INET_DIAG_BC_JMP: - if (op->no < 4 || op->no > len + 4) + if (op->no < 4 || op->no > len + 4 || op->no & 3) return -EINVAL; if (op->no < len && !valid_cc(bytecode, bytecode_len, len - op->no)) return -EINVAL; break; case INET_DIAG_BC_NOP: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; break; default: return -EINVAL; } + if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) + return -EINVAL; bc += op->yes; len -= op->yes; } diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index ab82840..e8bd977 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -663,8 +663,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input, char buffer[PROC_WRITELEN+1]; unsigned long nodenum; - if (copy_from_user(buffer, input, PROC_WRITELEN)) + if (size > PROC_WRITELEN) + return -EIO; + if (copy_from_user(buffer, input, size)) return -EFAULT; + buffer[size] = 0; if (*buffer == '+') { nodenum = simple_strtoul(buffer+1, NULL, 10); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index fd510bc..ff6a18e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1410,6 +1410,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) goto drop; } + + if (sk_rcvqueues_full(sk, skb)) + goto drop; + rc = 0; bh_lock_sock(sk); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 844ffc5..34ad669 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -408,9 +408,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) dev->type == ARPHRD_TUNNEL6 || dev->type == ARPHRD_SIT || dev->type == ARPHRD_NONE) { - printk(KERN_INFO - "%s: Disabled Privacy Extensions\n", - dev->name); ndev->cnf.use_tempaddr = -1; } else { in6_dev_hold(ndev); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index be5e5a1..479f926 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -590,6 +590,10 @@ static void flush_stack(struct sock **stack, unsigned int count, sk = stack[i]; if (skb1) { + if (sk_rcvqueues_full(sk, skb)) { + kfree_skb(skb1); + goto drop; + } bh_lock_sock(sk); if (!sock_owned_by_user(sk)) udpv6_queue_rcv_skb(sk, skb1); @@ -765,6 +769,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, /* deliver */ + if (sk_rcvqueues_full(sk, skb)) { + sock_put(sk); + goto discard; + } bh_lock_sock(sk); if (!sock_owned_by_user(sk)) udpv6_queue_rcv_skb(sk, skb); @@ -1314,7 +1322,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) skb->ip_summed = CHECKSUM_NONE; /* Check if there is enough headroom to insert fragment header. */ - if ((skb_headroom(skb) < frag_hdr_sz) && + if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) goto out; diff --git a/net/irda/iriap.c b/net/irda/iriap.c index b6fd6d1..26272fe 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, n = 1; name_len = fp[n++]; + + IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); + memcpy(name, fp+n, name_len); n+=name_len; name[name_len] = '\0'; attr_len = fp[n++]; + + IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); + memcpy(attr, fp+n, attr_len); n+=attr_len; attr[attr_len] = '\0'; diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 6a1a202..ab5bee2 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c @@ -106,6 +106,9 @@ irnet_ctrl_write(irnet_socket * ap, while(isspace(start[length - 1])) length--; + DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5, + -EINVAL, CTRL_ERROR, "Invalid nickname.\n"); + /* Copy the name for later reuse */ memcpy(ap->rname, start + 5, length - 5); ap->rname[length - 5] = '\0'; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fb12cec..8899c78 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -239,6 +239,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, memcpy(sta->sta.addr, addr, ETH_ALEN); sta->local = local; sta->sdata = sdata; + sta->last_rx = jiffies; if (sta_prepare_rate_control(local, sta, gfp)) { kfree(sta); diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abb..174d51c 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -290,10 +290,15 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * facilities->source_ndigis = 0; facilities->dest_ndigis = 0; for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { - if (pt[6] & AX25_HBIT) + if (pt[6] & AX25_HBIT) { + if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) + return -1; memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); - else + } else { + if (facilities->source_ndigis >= ROSE_MAX_DIGIS) + return -1; memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); + } } } p += l + 2; @@ -333,6 +338,11 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac case 0xC0: l = p[1]; + + /* Prevent overflows*/ + if (l < 10 || l > 20) + return -1; + if (*p == FAC_CCITT_DEST_NSAP) { memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); memcpy(callsign, p + 12, l - 10); @@ -373,12 +383,16 @@ int rose_parse_facilities(unsigned char *p, switch (*p) { case FAC_NATIONAL: /* National */ len = rose_parse_national(p + 1, facilities, facilities_len - 1); + if (len < 0) + return 0; facilities_len -= len + 1; p += len + 1; break; case FAC_CCITT: /* CCITT */ len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); + if (len < 0) + return 0; facilities_len -= len + 1; p += len + 1; break; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7f28df5..8375609 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3720,9 +3720,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) SCTP_DBG_OBJCNT_INC(sock); - /* Set socket backlog limit. */ - sk->sk_backlog.limit = sysctl_sctp_rmem[1]; - local_bh_disable(); percpu_counter_inc(&sctp_sockets_allocated); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b613cb7..9bfb685 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1324,10 +1324,11 @@ static void xs_tcp_state_change(struct sock *sk) if (!(xprt = xprt_from_sock(sk))) goto out; dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); - dprintk("RPC: state %x conn %d dead %d zapped %d\n", + dprintk("RPC: state %x conn %d dead %d zapped %d sk_shutdown %d\n", sk->sk_state, xprt_connected(xprt), sock_flag(sk, SOCK_DEAD), - sock_flag(sk, SOCK_ZAPPED)); + sock_flag(sk, SOCK_ZAPPED), + sk->sk_shutdown); switch (sk->sk_state) { case TCP_ESTABLISHED: @@ -1798,10 +1799,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra { unsigned int state = transport->inet->sk_state; - if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) - return; - if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) - return; + if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) { + /* we don't need to abort the connection if the socket + * hasn't undergone a shutdown + */ + if (transport->inet->sk_shutdown == 0) + return; + dprintk("RPC: %s: TCP_CLOSEd and sk_shutdown set to %d\n", + __func__, transport->inet->sk_shutdown); + } + if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) { + /* we don't need to abort the connection if the socket + * hasn't undergone a shutdown + */ + if (transport->inet->sk_shutdown == 0) + return; + dprintk("RPC: %s: ESTABLISHED/SYN_SENT " + "sk_shutdown set to %d\n", + __func__, transport->inet->sk_shutdown); + } xs_abort_connection(xprt, transport); } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 207a119..0b7148b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -503,6 +503,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *, int, int); static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, struct msghdr *, size_t); +static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, + struct msghdr *, size_t, int); static const struct proto_ops unix_stream_ops = { .family = PF_UNIX, @@ -562,7 +564,7 @@ static const struct proto_ops unix_seqpacket_ops = { .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = unix_seqpacket_sendmsg, - .recvmsg = unix_dgram_recvmsg, + .recvmsg = unix_seqpacket_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; @@ -1666,6 +1668,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock, return unix_dgram_sendmsg(kiocb, sock, msg, len); } +static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t size, + int flags) +{ + struct sock *sk = sock->sk; + + if (sk->sk_state != TCP_ESTABLISHED) + return -ENOTCONN; + + return unix_dgram_recvmsg(iocb, sock, msg, size, flags); +} + static void unix_copy_addr(struct msghdr *msg, struct sock *sk) { struct unix_sock *u = unix_sk(sk); diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 9960d1c..7f97e3f 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -330,7 +330,7 @@ static int conf_choice(struct menu *menu) } if (!child) continue; - if (line[strlen(line) - 1] == '?') { + if (line[0] && line[strlen(line) - 1] == '?') { print_help(child); continue; } diff --git a/sound/core/init.c b/sound/core/init.c index ec4a50c..82f350e 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -848,6 +848,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENOMEM; mfile->file = file; mfile->disconnected_f_op = NULL; + INIT_LIST_HEAD(&mfile->shutdown_list); spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); @@ -883,6 +884,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) list_for_each_entry(mfile, &card->files_list, list) { if (mfile->file == file) { list_del(&mfile->list); + spin_lock(&shutdown_lock); + list_del(&mfile->shutdown_list); + spin_unlock(&shutdown_lock); if (mfile->disconnected_f_op) fops_put(mfile->disconnected_f_op); found = mfile; diff --git a/sound/oss/dev_table.h b/sound/oss/dev_table.h index b7617be..0199a31 100644 --- a/sound/oss/dev_table.h +++ b/sound/oss/dev_table.h @@ -271,7 +271,7 @@ struct synth_operations void (*reset) (int dev); void (*hw_control) (int dev, unsigned char *event); int (*load_patch) (int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag); + int count, int pmgr_flag); void (*aftertouch) (int dev, int voice, int pressure); void (*controller) (int dev, int voice, int ctrl_num, int value); void (*panning) (int dev, int voice, int value); diff --git a/sound/oss/midi_synth.c b/sound/oss/midi_synth.c index 3bc7104..2292c23 100644 --- a/sound/oss/midi_synth.c +++ b/sound/oss/midi_synth.c @@ -476,7 +476,7 @@ EXPORT_SYMBOL(midi_synth_hw_control); int midi_synth_load_patch(int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag) + int count, int pmgr_flag) { int orig_dev = synth_devs[dev]->midi_dev; @@ -491,39 +491,37 @@ midi_synth_load_patch(int dev, int format, const char __user *addr, if (!prefix_cmd(orig_dev, 0xf0)) return 0; + /* Invalid patch format */ if (format != SYSEX_PATCH) - { -/* printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/ return -EINVAL; - } + + /* Patch header too short */ if (count < hdr_size) - { -/* printk("MIDI Error: Patch header too short\n");*/ return -EINVAL; - } + count -= hdr_size; /* - * Copy the header from user space but ignore the first bytes which have - * been transferred already. + * Copy the header from user space */ - if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs)) + if (copy_from_user(&sysex, addr, hdr_size)) return -EFAULT; - - if (count < sysex.len) - { -/* printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/ + + /* Sysex record too short */ + if ((unsigned)count < (unsigned)sysex.len) sysex.len = count; - } - left = sysex.len; - src_offs = 0; + + left = sysex.len; + src_offs = 0; for (i = 0; i < left && !signal_pending(current); i++) { unsigned char data; - get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i])); + if (get_user(data, + (unsigned char __user *)(addr + hdr_size + i))) + return -EFAULT; eox_seen = (i > 0 && data & 0x80); /* End of sysex */ diff --git a/sound/oss/midi_synth.h b/sound/oss/midi_synth.h index 6bc9d00..b64ddd6 100644 --- a/sound/oss/midi_synth.h +++ b/sound/oss/midi_synth.h @@ -8,7 +8,7 @@ int midi_synth_open (int dev, int mode); void midi_synth_close (int dev); void midi_synth_hw_control (int dev, unsigned char *event); int midi_synth_load_patch (int dev, int format, const char __user * addr, - int offs, int count, int pmgr_flag); + int count, int pmgr_flag); void midi_synth_panning (int dev, int channel, int pressure); void midi_synth_aftertouch (int dev, int channel, int pressure); void midi_synth_controller (int dev, int channel, int ctrl_num, int value); diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 938c48c..407cd67 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -820,7 +820,7 @@ static void opl3_hw_control(int dev, unsigned char *event) } static int opl3_load_patch(int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag) + int count, int pmgr_flag) { struct sbi_instrument ins; @@ -830,11 +830,7 @@ static int opl3_load_patch(int dev, int format, const char __user *addr, return -EINVAL; } - /* - * What the fuck is going on here? We leave junk in the beginning - * of ins and then check the field pretty close to that beginning? - */ - if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs)) + if (copy_from_user(&ins, addr, sizeof(ins))) return -EFAULT; if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) @@ -849,6 +845,10 @@ static int opl3_load_patch(int dev, int format, const char __user *addr, static void opl3_panning(int dev, int voice, int value) { + + if (voice < 0 || voice >= devc->nr_voice) + return; + devc->voc[voice].panning = value; } @@ -1066,8 +1066,15 @@ static int opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info static void opl3_setup_voice(int dev, int voice, int chn) { - struct channel_info *info = - &synth_devs[dev]->chn_info[chn]; + struct channel_info *info; + + if (voice < 0 || voice >= devc->nr_voice) + return; + + if (chn < 0 || chn > 15) + return; + + info = &synth_devs[dev]->chn_info[chn]; opl3_set_instr(dev, voice, info->pgm_num); diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index e85789e..a0072a9 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c @@ -241,7 +241,7 @@ int sequencer_write(int dev, struct file *file, const char __user *buf, int coun return -ENXIO; fmt = (*(short *) &event_rec[0]) & 0xffff; - err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0); + err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0); if (err < 0) return err; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index c7fba53..d6a40e2 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -229,6 +229,7 @@ MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force)."); #define ES_REG_1371_CODEC 0x14 /* W/R: Codec Read/Write register address */ #define ES_1371_CODEC_RDY (1<<31) /* codec ready */ #define ES_1371_CODEC_WIP (1<<30) /* codec register access in progress */ +#define EV_1938_CODEC_MAGIC (1<<26) #define ES_1371_CODEC_PIRD (1<<23) /* codec read/write select register */ #define ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0)) #define ES_1371_CODEC_READS(a) ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD) @@ -603,12 +604,18 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, #ifdef CHIP1371 +static inline bool is_ev1938(struct ensoniq *ensoniq) +{ + return ensoniq->pci->device == 0x8938; +} + static void snd_es1371_codec_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { struct ensoniq *ensoniq = ac97->private_data; - unsigned int t, x; + unsigned int t, x, flag; + flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; mutex_lock(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { @@ -630,7 +637,8 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, 0x00010000) break; } - outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC)); + outl(ES_1371_CODEC_WRITE(reg, val) | flag, + ES_REG(ensoniq, 1371_CODEC)); /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); @@ -647,8 +655,9 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, unsigned short reg) { struct ensoniq *ensoniq = ac97->private_data; - unsigned int t, x, fail = 0; + unsigned int t, x, flag, fail = 0; + flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; __again: mutex_lock(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { @@ -671,7 +680,8 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, 0x00010000) break; } - outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC)); + outl(ES_1371_CODEC_READS(reg) | flag, + ES_REG(ensoniq, 1371_CODEC)); /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); @@ -683,6 +693,11 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, /* now wait for the stinkin' data (RDY) */ for (t = 0; t < POLL_COUNT; t++) { if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { + if (is_ev1938(ensoniq)) { + for (t = 0; t < 100; t++) + inl(ES_REG(ensoniq, CONTROL)); + x = inl(ES_REG(ensoniq, 1371_CODEC)); + } mutex_unlock(&ensoniq->src_mutex); return ES_1371_CODEC_READ(x); } diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 350ee8a..5f08464 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -65,6 +65,7 @@ struct cs_spec { /* available models */ enum { + CS420X_MBP53, CS420X_MBP55, CS420X_IMAC27, CS420X_AUTO, @@ -838,7 +839,8 @@ static void cs_automute(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, hp_present ? 0 : PIN_OUT); } - if (spec->board_config == CS420X_MBP55 || + if (spec->board_config == CS420X_MBP53 || + spec->board_config == CS420X_MBP55 || spec->board_config == CS420X_IMAC27) { unsigned int gpio = hp_present ? 0x02 : 0x08; snd_hda_codec_write(codec, 0x01, 0, @@ -1080,6 +1082,7 @@ static int cs_parse_auto_config(struct hda_codec *codec) } static const char *cs420x_models[CS420X_MODELS] = { + [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", [CS420X_AUTO] = "auto", @@ -1087,7 +1090,10 @@ static const char *cs420x_models[CS420X_MODELS] = { static struct snd_pci_quirk cs420x_cfg_tbl[] = { + SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), + SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), + SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), {} /* terminator */ }; @@ -1097,6 +1103,20 @@ struct cs_pincfg { u32 val; }; +static struct cs_pincfg mbp53_pincfgs[] = { + { 0x09, 0x012b4050 }, + { 0x0a, 0x90100141 }, + { 0x0b, 0x90100140 }, + { 0x0c, 0x018b3020 }, + { 0x0d, 0x90a00110 }, + { 0x0e, 0x400000f0 }, + { 0x0f, 0x01cbe030 }, + { 0x10, 0x014be060 }, + { 0x12, 0x400000f0 }, + { 0x15, 0x400000f0 }, + {} /* terminator */ +}; + static struct cs_pincfg mbp55_pincfgs[] = { { 0x09, 0x012b4030 }, { 0x0a, 0x90100121 }, @@ -1126,6 +1146,7 @@ static struct cs_pincfg imac27_pincfgs[] = { }; static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { + [CS420X_MBP53] = mbp53_pincfgs, [CS420X_MBP55] = mbp55_pincfgs, [CS420X_IMAC27] = imac27_pincfgs, }; @@ -1158,6 +1179,7 @@ static int patch_cs420x(struct hda_codec *codec) switch (spec->board_config) { case CS420X_IMAC27: + case CS420X_MBP53: case CS420X_MBP55: /* GPIO1 = headphones */ /* GPIO3 = speakers */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8070ba2..d388680 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1148,7 +1148,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) case 0x10ec0883: case 0x10ec0885: case 0x10ec0887: - case 0x10ec0889: + /*case 0x10ec0889:*/ /* this causes an SPDIF problem */ alc889_coef_init(codec); break; case 0x10ec0888: diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 789f44f..31efa21 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,8 @@ #define DBG(fmt...) #endif +#define IS_G4DA (of_machine_is_compatible("PowerMac3,4")) + /* i2c address for tumbler */ #define TAS_I2C_ADDR 0x34 @@ -1134,7 +1137,8 @@ static long tumbler_find_device(const char *device, const char *platform, gp->inactive_val = (*base) ? 0x4 : 0x5; } else { const u32 *prop = NULL; - gp->active_state = 0; + gp->active_state = IS_G4DA + && !strncmp(device, "keywest-gpio1", 13); gp->active_val = 0x4; gp->inactive_val = 0x5; /* Here are some crude hacks to extract the GPIO polarity and @@ -1312,6 +1316,9 @@ static int __devinit tumbler_init(struct snd_pmac *chip) if (irq <= NO_IRQ) irq = tumbler_find_device("line-output-detect", NULL, &mix->line_detect, 1); + if (IS_G4DA && irq <= NO_IRQ) + irq = tumbler_find_device("keywest-gpio16", + NULL, &mix->line_detect, 1); mix->lineout_irq = irq; tumbler_reset_audio(chip); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e1f225a..db6122f 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -701,12 +701,12 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKL", "Input Switch", "MIXINL" }, { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output Mixer" }, + { "SPKL", "Output Switch", "Left Output PGA" }, { "SPKL", NULL, "TOCLK" }, { "SPKR", "Input Switch", "MIXINR" }, { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output Mixer" }, + { "SPKR", "Output Switch", "Right Output PGA" }, { "SPKR", NULL, "TOCLK" }, { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, @@ -728,8 +728,8 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKOUTRP", NULL, "SPKR Driver" }, { "SPKOUTRN", NULL, "SPKR Driver" }, - { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, - { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, + { "Left Headphone Mux", "Mixer", "Left Output PGA" }, + { "Right Headphone Mux", "Mixer", "Right Output PGA" }, { "Headphone PGA", NULL, "Left Headphone Mux" }, { "Headphone PGA", NULL, "Right Headphone Mux" }, diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index ff0b2a8..5ae1eae 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c @@ -128,6 +128,9 @@ snd_emux_init_hwdep(struct snd_emux *emu) strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; hw->ops.ioctl = snd_emux_hwdep_ioctl; + /* The ioctl parameter types are compatible between 32- and + * 64-bit architectures, so use the same function. */ + hw->ops.ioctl_compat = snd_emux_hwdep_ioctl; hw->exclusive = 1; hw->private_data = emu; if ((err = snd_card_register(emu->card)) < 0) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index bc0f670..429bace 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -541,6 +541,9 @@ endif ifdef NO_DEMANGLE BASIC_CFLAGS += -DNO_DEMANGLE +else ifdef HAVE_CPLUS_DEMANGLE + EXTLIBS += -liberty + BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE else has_bfd := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y")