From: Greg Kroah-Hartman Date: Mon, 5 Aug 2013 02:02:15 +0000 (+0800) Subject: 3.10-stable patches X-Git-Tag: v3.0.90~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5709a1b274d37b694c4a2294fe15c08271ec3e58;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: alsa-compress-fix-the-return-value-for-sndrv_compress_version.patch alsa-hda-fix-missing-fixup-for-mac-mini-with-stac9221.patch arm-7784-1-mm-ensure-smp-alternates-assemble-to-exactly-4-bytes-with-thumb-2.patch arm-7790-1-fix-deferred-mm-switch-on-vivt-processors.patch arm-7791-1-a.out-remove-partial-a.out-support.patch atl1c-fix-misuse-of-netdev_alloc_skb-in-refilling-rx-ring.patch dma-pl330-fix-cyclic-transfers.patch hwmon-max6697-fix-max6581-ideality.patch iwlwifi-add-dell-sku-for-5150-hmc.patch iwlwifi-mvm-fix-bug-in-scan-ssid.patch iwlwifi-mvm-fix-flushing-not-started-aggregation-sessions.patch iwlwifi-mvm-fix-l2p-ba-ressources-leak.patch iwlwifi-mvm-refuse-connection-to-aps-with-bi-16.patch iwlwifi-pcie-clear-rfkill-interrupt-in-ampg.patch parisc-agp-parisc-agp-allow-binding-of-user-memory-to-the-agp-gart.patch parisc-fix-cache-routines-to-ignore-vma-s-with-an-invalid-pfn.patch parisc-fix-interrupt-routing-for-c8000-serial-ports.patch powerpc-vphn-topology-change-updates-all-siblings.patch powerpc-windfarm-fix-noisy-slots-fan-on-xserve-rm31.patch serial-arc_uart-fix-module-alias.patch serial-mxs-auart-fix-race-condition-in-interrupt-handler.patch serial-mxs-auart-increase-time-to-wait-for-transmitter-to-become-idle.patch usb-mos7840-fix-device-type-detection.patch usb-mos7840-fix-pointer-casts.patch usb-mos7840-fix-race-in-led-handling.patch usb-mos7840-fix-race-in-register-handling.patch --- diff --git a/queue-3.10/alsa-compress-fix-the-return-value-for-sndrv_compress_version.patch b/queue-3.10/alsa-compress-fix-the-return-value-for-sndrv_compress_version.patch new file mode 100644 index 00000000000..34a8e5e4d01 --- /dev/null +++ b/queue-3.10/alsa-compress-fix-the-return-value-for-sndrv_compress_version.patch @@ -0,0 +1,33 @@ +From a8d30608eaed6cc759b8e2e8a8bbbb42591f797f Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Mon, 29 Jul 2013 15:10:22 +0530 +Subject: ALSA: compress: fix the return value for SNDRV_COMPRESS_VERSION + +From: Vinod Koul + +commit a8d30608eaed6cc759b8e2e8a8bbbb42591f797f upstream. + +the return value of SNDRV_COMPRESS_VERSION always return default -ENOTTY as the +return value was never updated for this call +assign return value from put_user() + +Reported-by: Haynes +Signed-off-by: Vinod Koul +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/core/compress_offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -743,7 +743,7 @@ static long snd_compr_ioctl(struct file + mutex_lock(&stream->device->lock); + switch (_IOC_NR(cmd)) { + case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION): +- put_user(SNDRV_COMPRESS_VERSION, ++ retval = put_user(SNDRV_COMPRESS_VERSION, + (int __user *)arg) ? -EFAULT : 0; + break; + case _IOC_NR(SNDRV_COMPRESS_GET_CAPS): diff --git a/queue-3.10/alsa-hda-fix-missing-fixup-for-mac-mini-with-stac9221.patch b/queue-3.10/alsa-hda-fix-missing-fixup-for-mac-mini-with-stac9221.patch new file mode 100644 index 00000000000..dc90bd2b656 --- /dev/null +++ b/queue-3.10/alsa-hda-fix-missing-fixup-for-mac-mini-with-stac9221.patch @@ -0,0 +1,49 @@ +From 697aebab78a88c6b164cfb74d19b86817d2ccd82 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 1 Aug 2013 08:38:27 +0200 +Subject: ALSA: hda - Fix missing fixup for Mac Mini with STAC9221 + +From: Takashi Iwai + +commit 697aebab78a88c6b164cfb74d19b86817d2ccd82 upstream. + +A fixup for Apple Mac Mini was lost during the adaption to the generic +parser because the fallback for the generic ID 8384:7680 was dropped, +and it resulted in the silence output (and maybe other problems). + +Unfortunately, just adding the missing subsystem ID wasn't enough, in +this case. The subsystem ID of this machine is 0000:0100 (what Apple +thought...?), and since snd_hda_pick_fixup() doesn't take the vendor +id zero into account, the driver ignored this entry. Now it's fixed +to regard the vendor id zero as a valid value. + +Reported-and-tested-by: Linus Torvalds +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/hda_auto_parser.c | 2 +- + sound/pci/hda/patch_sigmatel.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/sound/pci/hda/hda_auto_parser.c ++++ b/sound/pci/hda/hda_auto_parser.c +@@ -860,7 +860,7 @@ void snd_hda_pick_fixup(struct hda_codec + } + } + if (id < 0 && quirk) { +- for (q = quirk; q->subvendor; q++) { ++ for (q = quirk; q->subvendor || q->subdevice; q++) { + unsigned int vendorid = + q->subdevice | (q->subvendor << 16); + unsigned int mask = 0xffff0000 | q->subdevice_mask; +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -2815,6 +2815,7 @@ static const struct hda_pintbl ecs202_pi + + /* codec SSIDs for Intel Mac sharing the same PCI SSID 8384:7680 */ + static const struct snd_pci_quirk stac922x_intel_mac_fixup_tbl[] = { ++ SND_PCI_QUIRK(0x0000, 0x0100, "Mac Mini", STAC_INTEL_MAC_V3), + SND_PCI_QUIRK(0x106b, 0x0800, "Mac", STAC_INTEL_MAC_V1), + SND_PCI_QUIRK(0x106b, 0x0600, "Mac", STAC_INTEL_MAC_V2), + SND_PCI_QUIRK(0x106b, 0x0700, "Mac", STAC_INTEL_MAC_V2), diff --git a/queue-3.10/arm-7784-1-mm-ensure-smp-alternates-assemble-to-exactly-4-bytes-with-thumb-2.patch b/queue-3.10/arm-7784-1-mm-ensure-smp-alternates-assemble-to-exactly-4-bytes-with-thumb-2.patch new file mode 100644 index 00000000000..01d71ce382a --- /dev/null +++ b/queue-3.10/arm-7784-1-mm-ensure-smp-alternates-assemble-to-exactly-4-bytes-with-thumb-2.patch @@ -0,0 +1,74 @@ +From bf3f0f332f76a85ff3a0b393aaded5a8533769c0 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Mon, 15 Jul 2013 14:26:19 +0100 +Subject: ARM: 7784/1: mm: ensure SMP alternates assemble to exactly 4 bytes with Thumb-2 + +From: Will Deacon + +commit bf3f0f332f76a85ff3a0b393aaded5a8533769c0 upstream. + +Commit ae8a8b9553bd ("ARM: 7691/1: mm: kill unused TLB_CAN_READ_FROM_L1_CACHE +and use ALT_SMP instead") added early function returns for page table +cache flushing operations on ARMv7 SMP CPUs. + +Unfortunately, when targetting Thumb-2, these `mov pc, lr' sequences +assemble to 2 bytes which can lead to corruption of the instruction +stream after code patching. + +This patch fixes the alternates to use wide (32-bit) instructions for +Thumb-2, therefore ensuring that the patching code works correctly. + +Signed-off-by: Will Deacon +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mm/proc-v7-2level.S | 2 +- + arch/arm/mm/proc-v7-3level.S | 2 +- + arch/arm/mm/proc-v7.S | 11 ++++++----- + 3 files changed, 8 insertions(+), 7 deletions(-) + +--- a/arch/arm/mm/proc-v7-2level.S ++++ b/arch/arm/mm/proc-v7-2level.S +@@ -110,7 +110,7 @@ ENTRY(cpu_v7_set_pte_ext) + ARM( str r3, [r0, #2048]! ) + THUMB( add r0, r0, #2048 ) + THUMB( str r3, [r0] ) +- ALT_SMP(mov pc,lr) ++ ALT_SMP(W(nop)) + ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte + #endif + mov pc, lr +--- a/arch/arm/mm/proc-v7-3level.S ++++ b/arch/arm/mm/proc-v7-3level.S +@@ -73,7 +73,7 @@ ENTRY(cpu_v7_set_pte_ext) + tst r3, #1 << (55 - 32) @ L_PTE_DIRTY + orreq r2, #L_PTE_RDONLY + 1: strd r2, r3, [r0] +- ALT_SMP(mov pc, lr) ++ ALT_SMP(W(nop)) + ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte + #endif + mov pc, lr +--- a/arch/arm/mm/proc-v7.S ++++ b/arch/arm/mm/proc-v7.S +@@ -75,13 +75,14 @@ ENTRY(cpu_v7_do_idle) + ENDPROC(cpu_v7_do_idle) + + ENTRY(cpu_v7_dcache_clean_area) +- ALT_SMP(mov pc, lr) @ MP extensions imply L1 PTW +- ALT_UP(W(nop)) +- dcache_line_size r2, r3 +-1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry ++ ALT_SMP(W(nop)) @ MP extensions imply L1 PTW ++ ALT_UP_B(1f) ++ mov pc, lr ++1: dcache_line_size r2, r3 ++2: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, r2 + subs r1, r1, r2 +- bhi 1b ++ bhi 2b + dsb + mov pc, lr + ENDPROC(cpu_v7_dcache_clean_area) diff --git a/queue-3.10/arm-7790-1-fix-deferred-mm-switch-on-vivt-processors.patch b/queue-3.10/arm-7790-1-fix-deferred-mm-switch-on-vivt-processors.patch new file mode 100644 index 00000000000..e4eacce0c98 --- /dev/null +++ b/queue-3.10/arm-7790-1-fix-deferred-mm-switch-on-vivt-processors.patch @@ -0,0 +1,91 @@ +From bdae73cd374e28db544fdd9b77de689a36e3c129 Mon Sep 17 00:00:00 2001 +From: Catalin Marinas +Date: Tue, 23 Jul 2013 16:15:36 +0100 +Subject: ARM: 7790/1: Fix deferred mm switch on VIVT processors + +From: Catalin Marinas + +commit bdae73cd374e28db544fdd9b77de689a36e3c129 upstream. + +As of commit b9d4d42ad9 (ARM: Remove __ARCH_WANT_INTERRUPTS_ON_CTXSW on +pre-ARMv6 CPUs), the mm switching on VIVT processors is done in the +finish_arch_post_lock_switch() function to avoid whole cache flushing +with interrupts disabled. The need for deferred mm switch is stored as a +thread flag (TIF_SWITCH_MM). However, with preemption enabled, we can +have another thread switch before finish_arch_post_lock_switch(). If the +new thread has the same mm as the previous 'next' thread, the scheduler +will not call switch_mm() and the TIF_SWITCH_MM flag won't be set for +the new thread. + +This patch moves the switch pending flag to the mm_context_t structure +since this is specific to the mm rather than thread. + +Signed-off-by: Catalin Marinas +Reported-by: Marc Kleine-Budde +Tested-by: Marc Kleine-Budde +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/include/asm/mmu.h | 2 ++ + arch/arm/include/asm/mmu_context.h | 20 ++++++++++++++++---- + arch/arm/include/asm/thread_info.h | 1 - + 3 files changed, 18 insertions(+), 5 deletions(-) + +--- a/arch/arm/include/asm/mmu.h ++++ b/arch/arm/include/asm/mmu.h +@@ -6,6 +6,8 @@ + typedef struct { + #ifdef CONFIG_CPU_HAS_ASID + atomic64_t id; ++#else ++ int switch_pending; + #endif + unsigned int vmalloc_seq; + unsigned long sigpage; +--- a/arch/arm/include/asm/mmu_context.h ++++ b/arch/arm/include/asm/mmu_context.h +@@ -55,7 +55,7 @@ static inline void check_and_switch_cont + * on non-ASID CPUs, the old mm will remain valid until the + * finish_arch_post_lock_switch() call. + */ +- set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM); ++ mm->context.switch_pending = 1; + else + cpu_switch_mm(mm->pgd, mm); + } +@@ -64,9 +64,21 @@ static inline void check_and_switch_cont + finish_arch_post_lock_switch + static inline void finish_arch_post_lock_switch(void) + { +- if (test_and_clear_thread_flag(TIF_SWITCH_MM)) { +- struct mm_struct *mm = current->mm; +- cpu_switch_mm(mm->pgd, mm); ++ struct mm_struct *mm = current->mm; ++ ++ if (mm && mm->context.switch_pending) { ++ /* ++ * Preemption must be disabled during cpu_switch_mm() as we ++ * have some stateful cache flush implementations. Check ++ * switch_pending again in case we were preempted and the ++ * switch to this mm was already done. ++ */ ++ preempt_disable(); ++ if (mm->context.switch_pending) { ++ mm->context.switch_pending = 0; ++ cpu_switch_mm(mm->pgd, mm); ++ } ++ preempt_enable_no_resched(); + } + } + +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -156,7 +156,6 @@ extern int vfp_restore_user_hwstate(stru + #define TIF_USING_IWMMXT 17 + #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ + #define TIF_RESTORE_SIGMASK 20 +-#define TIF_SWITCH_MM 22 /* deferred switch_mm */ + + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/queue-3.10/arm-7791-1-a.out-remove-partial-a.out-support.patch b/queue-3.10/arm-7791-1-a.out-remove-partial-a.out-support.patch new file mode 100644 index 00000000000..5f8a0f41e95 --- /dev/null +++ b/queue-3.10/arm-7791-1-a.out-remove-partial-a.out-support.patch @@ -0,0 +1,177 @@ +From acfdd4b1f7590d02e9bae3b73bdbbc4a31b05d38 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Thu, 25 Jul 2013 11:44:48 +0100 +Subject: ARM: 7791/1: a.out: remove partial a.out support + +From: Will Deacon + +commit acfdd4b1f7590d02e9bae3b73bdbbc4a31b05d38 upstream. + +a.out support on ARM requires that argc, argv and envp are passed in +r0-r2 respectively, which requires hacking load_aout_binary to +prevent argc being clobbered by the return code. Whilst mainline kernels +do set the registers up in start_thread, the aout loader has never +carried the hack in mainline. + +Initialising the registers in this way actually goes against the libc +expectations for ELF binaries, where argc, argv and envp are passed on +the stack, with r0 being used to hold a pointer to an exit function for +cleaning up after the dynamic linker if required. If the pointer is +NULL, then it is ignored. When execing an ELF binary, Linux currently +zeroes r0, then sets it to argc and then finally clobbers it with the +return value of the execve syscall, so we actually end up with: + + r0 = 0 + stack[0] = argc + r1 = stack[1] = argv + r2 = stack[2] = envp + +libc treats r1 and r2 as undefined. The clobbering of r0 by sys_execve +works for user-spawned threads, but when executing an ELF binary from a +kernel thread (via call_usermodehelper), the execve is performed on the +ret_from_fork path, which restores r0 from the saved pt_regs, resulting +in argc being presented to the C library. This has horrible consequences +when the application exits, since we have an exit function registered +using argc, resulting in a jump to hyperspace. + +This patch solves the problem by removing the partial a.out support from +arch/arm/ altogether. + +Signed-off-by: Will Deacon +Cc: Ashish Sangwan +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/Kconfig | 1 + arch/arm/include/asm/a.out-core.h | 45 -------------------------------------- + arch/arm/include/asm/processor.h | 4 --- + arch/arm/include/uapi/asm/Kbuild | 1 + arch/arm/include/uapi/asm/a.out.h | 34 ---------------------------- + 5 files changed, 85 deletions(-) + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -19,7 +19,6 @@ config ARM + select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER + select HARDIRQS_SW_RESEND +- select HAVE_AOUT + select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL + select HAVE_ARCH_KGDB + select HAVE_ARCH_SECCOMP_FILTER +--- a/arch/arm/include/asm/a.out-core.h ++++ /dev/null +@@ -1,45 +0,0 @@ +-/* a.out coredump register dumper +- * +- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. +- * Written by David Howells (dhowells@redhat.com) +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public Licence +- * as published by the Free Software Foundation; either version +- * 2 of the Licence, or (at your option) any later version. +- */ +- +-#ifndef _ASM_A_OUT_CORE_H +-#define _ASM_A_OUT_CORE_H +- +-#ifdef __KERNEL__ +- +-#include +-#include +- +-/* +- * fill in the user structure for an a.out core dump +- */ +-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) +-{ +- struct task_struct *tsk = current; +- +- dump->magic = CMAGIC; +- dump->start_code = tsk->mm->start_code; +- dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1); +- +- dump->u_tsize = (tsk->mm->end_code - tsk->mm->start_code) >> PAGE_SHIFT; +- dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; +- dump->u_ssize = 0; +- +- memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg)); +- +- if (dump->start_stack < 0x04000000) +- dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; +- +- dump->regs = *regs; +- dump->u_fpvalid = dump_fpu (regs, &dump->u_fp); +-} +- +-#endif /* __KERNEL__ */ +-#endif /* _ASM_A_OUT_CORE_H */ +--- a/arch/arm/include/asm/processor.h ++++ b/arch/arm/include/asm/processor.h +@@ -54,7 +54,6 @@ struct thread_struct { + + #define start_thread(regs,pc,sp) \ + ({ \ +- unsigned long *stack = (unsigned long *)sp; \ + memset(regs->uregs, 0, sizeof(regs->uregs)); \ + if (current->personality & ADDR_LIMIT_32BIT) \ + regs->ARM_cpsr = USR_MODE; \ +@@ -65,9 +64,6 @@ struct thread_struct { + regs->ARM_cpsr |= PSR_ENDSTATE; \ + regs->ARM_pc = pc & ~1; /* pc */ \ + regs->ARM_sp = sp; /* sp */ \ +- regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ +- regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ +- regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ + nommu_start_thread(regs); \ + }) + +--- a/arch/arm/include/uapi/asm/Kbuild ++++ b/arch/arm/include/uapi/asm/Kbuild +@@ -1,7 +1,6 @@ + # UAPI Header export list + include include/uapi/asm-generic/Kbuild.asm + +-header-y += a.out.h + header-y += byteorder.h + header-y += fcntl.h + header-y += hwcap.h +--- a/arch/arm/include/uapi/asm/a.out.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-#ifndef __ARM_A_OUT_H__ +-#define __ARM_A_OUT_H__ +- +-#include +-#include +- +-struct exec +-{ +- __u32 a_info; /* Use macros N_MAGIC, etc for access */ +- __u32 a_text; /* length of text, in bytes */ +- __u32 a_data; /* length of data, in bytes */ +- __u32 a_bss; /* length of uninitialized data area for file, in bytes */ +- __u32 a_syms; /* length of symbol table data in file, in bytes */ +- __u32 a_entry; /* start address */ +- __u32 a_trsize; /* length of relocation info for text, in bytes */ +- __u32 a_drsize; /* length of relocation info for data, in bytes */ +-}; +- +-/* +- * This is always the same +- */ +-#define N_TXTADDR(a) (0x00008000) +- +-#define N_TRSIZE(a) ((a).a_trsize) +-#define N_DRSIZE(a) ((a).a_drsize) +-#define N_SYMSIZE(a) ((a).a_syms) +- +-#define M_ARM 103 +- +-#ifndef LIBRARY_START_TEXT +-#define LIBRARY_START_TEXT (0x00c00000) +-#endif +- +-#endif /* __A_OUT_GNU_H__ */ diff --git a/queue-3.10/atl1c-fix-misuse-of-netdev_alloc_skb-in-refilling-rx-ring.patch b/queue-3.10/atl1c-fix-misuse-of-netdev_alloc_skb-in-refilling-rx-ring.patch new file mode 100644 index 00000000000..f5f4b45604e --- /dev/null +++ b/queue-3.10/atl1c-fix-misuse-of-netdev_alloc_skb-in-refilling-rx-ring.patch @@ -0,0 +1,44 @@ +From ebe7fdbaf3e90ea22feade6c9f5e50f42b23b6d8 Mon Sep 17 00:00:00 2001 +From: Neil Horman +Date: Fri, 26 Jul 2013 12:47:14 -0400 +Subject: atl1c: Fix misuse of netdev_alloc_skb in refilling rx ring + +From: Neil Horman + +commit ebe7fdbaf3e90ea22feade6c9f5e50f42b23b6d8 upstream. + +atl1c uses netdev_alloc_skb to refill its rx dma ring, but that call makes no +guarantees about the suitability of the memory for use in DMA. As a result +we've gotten reports of atl1c drivers occasionally hanging and needing to be +reset: +https://bugzilla.kernel.org/show_bug.cgi?id=54021 + +Fix this by modifying the call to use the internal version __netdev_alloc_skb, +where you can set the gfp_mask explicitly to include GFP_DMA. + +Tested by two reporters in the above bug, who have the hardware to validate it. +Both report immediate cessation of the problem with this patch + +Signed-off-by: Neil Horman +CC: Jay Cliburn +CC: "David S. Miller" +Tested-by: Luis Henriques +Tested-by: Vincent Alquier +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -1660,7 +1660,7 @@ static int atl1c_alloc_rx_buffer(struct + while (next_info->flags & ATL1C_BUFFER_FREE) { + rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); + +- skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len); ++ skb = __netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len, GFP_ATOMIC|GFP_DMA); + if (unlikely(!skb)) { + if (netif_msg_rx_err(adapter)) + dev_warn(&pdev->dev, "alloc rx buffer failed\n"); diff --git a/queue-3.10/dma-pl330-fix-cyclic-transfers.patch b/queue-3.10/dma-pl330-fix-cyclic-transfers.patch new file mode 100644 index 00000000000..f9c5ceacd43 --- /dev/null +++ b/queue-3.10/dma-pl330-fix-cyclic-transfers.patch @@ -0,0 +1,144 @@ +From fc51446021f42aca8906e701fc2292965aafcb15 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Tue, 23 Jul 2013 10:24:50 +0200 +Subject: dma: pl330: Fix cyclic transfers + +From: Lars-Peter Clausen + +commit fc51446021f42aca8906e701fc2292965aafcb15 upstream. + +Allocate a descriptor for each period of a cyclic transfer, not just the first. +Also since the callback needs to be called for each finished period make sure to +initialize the callback and callback_param fields of each descriptor in a cyclic +transfer. + +Signed-off-by: Lars-Peter Clausen +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/dma/pl330.c | 93 +++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 67 insertions(+), 26 deletions(-) + +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2527,6 +2527,10 @@ static dma_cookie_t pl330_tx_submit(stru + /* Assign cookies to all nodes */ + while (!list_empty(&last->node)) { + desc = list_entry(last->node.next, struct dma_pl330_desc, node); ++ if (pch->cyclic) { ++ desc->txd.callback = last->txd.callback; ++ desc->txd.callback_param = last->txd.callback_param; ++ } + + dma_cookie_assign(&desc->txd); + +@@ -2710,45 +2714,82 @@ static struct dma_async_tx_descriptor *p + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags, void *context) + { +- struct dma_pl330_desc *desc; ++ struct dma_pl330_desc *desc = NULL, *first = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); ++ struct dma_pl330_dmac *pdmac = pch->dmac; ++ unsigned int i; + dma_addr_t dst; + dma_addr_t src; + +- desc = pl330_get_desc(pch); +- if (!desc) { +- dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n", +- __func__, __LINE__); ++ if (len % period_len != 0) + return NULL; +- } + +- switch (direction) { +- case DMA_MEM_TO_DEV: +- desc->rqcfg.src_inc = 1; +- desc->rqcfg.dst_inc = 0; +- desc->req.rqtype = MEMTODEV; +- src = dma_addr; +- dst = pch->fifo_addr; +- break; +- case DMA_DEV_TO_MEM: +- desc->rqcfg.src_inc = 0; +- desc->rqcfg.dst_inc = 1; +- desc->req.rqtype = DEVTOMEM; +- src = pch->fifo_addr; +- dst = dma_addr; +- break; +- default: ++ if (!is_slave_direction(direction)) { + dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n", + __func__, __LINE__); + return NULL; + } + +- desc->rqcfg.brst_size = pch->burst_sz; +- desc->rqcfg.brst_len = 1; ++ for (i = 0; i < len / period_len; i++) { ++ desc = pl330_get_desc(pch); ++ if (!desc) { ++ dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n", ++ __func__, __LINE__); + +- pch->cyclic = true; ++ if (!first) ++ return NULL; ++ ++ spin_lock_irqsave(&pdmac->pool_lock, flags); ++ ++ while (!list_empty(&first->node)) { ++ desc = list_entry(first->node.next, ++ struct dma_pl330_desc, node); ++ list_move_tail(&desc->node, &pdmac->desc_pool); ++ } ++ ++ list_move_tail(&first->node, &pdmac->desc_pool); ++ ++ spin_unlock_irqrestore(&pdmac->pool_lock, flags); ++ ++ return NULL; ++ } ++ ++ switch (direction) { ++ case DMA_MEM_TO_DEV: ++ desc->rqcfg.src_inc = 1; ++ desc->rqcfg.dst_inc = 0; ++ desc->req.rqtype = MEMTODEV; ++ src = dma_addr; ++ dst = pch->fifo_addr; ++ break; ++ case DMA_DEV_TO_MEM: ++ desc->rqcfg.src_inc = 0; ++ desc->rqcfg.dst_inc = 1; ++ desc->req.rqtype = DEVTOMEM; ++ src = pch->fifo_addr; ++ dst = dma_addr; ++ break; ++ default: ++ break; ++ } + +- fill_px(&desc->px, dst, src, period_len); ++ desc->rqcfg.brst_size = pch->burst_sz; ++ desc->rqcfg.brst_len = 1; ++ fill_px(&desc->px, dst, src, period_len); ++ ++ if (!first) ++ first = desc; ++ else ++ list_add_tail(&desc->node, &first->node); ++ ++ dma_addr += period_len; ++ } ++ ++ if (!desc) ++ return NULL; ++ ++ pch->cyclic = true; ++ desc->txd.flags = flags; + + return &desc->txd; + } diff --git a/queue-3.10/hwmon-max6697-fix-max6581-ideality.patch b/queue-3.10/hwmon-max6697-fix-max6581-ideality.patch new file mode 100644 index 00000000000..1658acf5f2e --- /dev/null +++ b/queue-3.10/hwmon-max6697-fix-max6581-ideality.patch @@ -0,0 +1,37 @@ +From 5c52add19733eb36d8619713312f5604efef3502 Mon Sep 17 00:00:00 2001 +From: Vivien Didelot +Date: Tue, 30 Jul 2013 17:14:34 -0400 +Subject: hwmon: (max6697) fix MAX6581 ideality + +From: Vivien Didelot + +commit 5c52add19733eb36d8619713312f5604efef3502 upstream. + +Without this patch, the values for ideality (register 0x4b) and ideality +selection mask (register 0x4c) are inverted. + +Signed-off-by: Vivien Didelot +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/max6697.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/max6697.c ++++ b/drivers/hwmon/max6697.c +@@ -605,12 +605,12 @@ static int max6697_init_chip(struct i2c_ + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY, +- pdata->ideality_mask >> 1); ++ pdata->ideality_value); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(client, + MAX6581_REG_IDEALITY_SELECT, +- pdata->ideality_value); ++ pdata->ideality_mask >> 1); + if (ret < 0) + return ret; + } diff --git a/queue-3.10/iwlwifi-add-dell-sku-for-5150-hmc.patch b/queue-3.10/iwlwifi-add-dell-sku-for-5150-hmc.patch new file mode 100644 index 00000000000..15a76676e77 --- /dev/null +++ b/queue-3.10/iwlwifi-add-dell-sku-for-5150-hmc.patch @@ -0,0 +1,31 @@ +From a1923f1d4723e5757cefdd60f7c7ab30e472007a Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Thu, 18 Jul 2013 19:11:26 +0300 +Subject: iwlwifi: add DELL SKU for 5150 HMC + +From: Emmanuel Grumbach + +commit a1923f1d4723e5757cefdd60f7c7ab30e472007a upstream. + +This SKU was missing in the list of supported devices + +https://bugzilla.kernel.org/show_bug.cgi?id=60577 + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/pcie/drv.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/iwlwifi/pcie/drv.c +@@ -129,6 +129,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca + {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ + {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ + {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ ++ {IWL_PCI_DEVICE(0x423C, 0x1326, iwl5150_abg_cfg)}, /* Half Mini Card */ + + {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ + {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ diff --git a/queue-3.10/iwlwifi-mvm-fix-bug-in-scan-ssid.patch b/queue-3.10/iwlwifi-mvm-fix-bug-in-scan-ssid.patch new file mode 100644 index 00000000000..3530b028a58 --- /dev/null +++ b/queue-3.10/iwlwifi-mvm-fix-bug-in-scan-ssid.patch @@ -0,0 +1,34 @@ +From fe04e83706037802c502ea41c0d1799ec35fc0d7 Mon Sep 17 00:00:00 2001 +From: David Spinadel +Date: Thu, 4 Jul 2013 15:17:48 +0300 +Subject: iwlwifi: mvm: fix bug in scan ssid + +From: David Spinadel + +commit fe04e83706037802c502ea41c0d1799ec35fc0d7 upstream. + +Increment index in each iteration. Without this increment we are +overriding the added SSIDs and we will send only the last SSId +and (n_ssids - 1) broadcast probes. + +Signed-off-by: David Spinadel +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/mvm/scan.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/mvm/scan.c ++++ b/drivers/net/wireless/iwlwifi/mvm/scan.c +@@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(stru + { + int fw_idx, req_idx; + +- fw_idx = 0; +- for (req_idx = req->n_ssids - 1; req_idx > 0; req_idx--) { ++ for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0; ++ req_idx--, fw_idx++) { + cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; + cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; + memcpy(cmd->direct_scan[fw_idx].ssid, diff --git a/queue-3.10/iwlwifi-mvm-fix-flushing-not-started-aggregation-sessions.patch b/queue-3.10/iwlwifi-mvm-fix-flushing-not-started-aggregation-sessions.patch new file mode 100644 index 00000000000..702d4800c96 --- /dev/null +++ b/queue-3.10/iwlwifi-mvm-fix-flushing-not-started-aggregation-sessions.patch @@ -0,0 +1,76 @@ +From b6658ff80c43bcf84be0bbe371c88af1452e7776 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 24 Jul 2013 13:55:51 +0200 +Subject: iwlwifi: mvm: fix flushing not started aggregation sessions + +From: Johannes Berg + +commit b6658ff80c43bcf84be0bbe371c88af1452e7776 upstream. + +When a not fully started aggregation session is destroyed +and flushed, we get a warning, e.g. + + WARNING: at drivers/net/wireless/iwlwifi/pcie/tx.c:1142 iwl_trans_pcie_txq_disable+0x11c/0x160 + queue 16 not used + Modules linked in: [...] + Pid: 5135, comm: hostapd Tainted: G W O 3.5.0 #10 + Call Trace: + wlan0: driver sets block=0 for sta 00:03:7f:10:44:d3 + [] warn_slowpath_common+0x72/0xa0 + [] warn_slowpath_fmt+0x47/0x50 + [] iwl_trans_pcie_txq_disable+0x11c/0x160 [iwlwifi] + [] iwl_mvm_sta_tx_agg_flush+0xe9/0x150 [iwlmvm] + [] iwl_mvm_mac_ampdu_action+0xf3/0x1e0 [iwlmvm] + [] ___ieee80211_stop_tx_ba_session+0x193/0x920 [mac80211] + [] __ieee80211_stop_tx_ba_session+0x48/0x70 [mac80211] + [] ieee80211_sta_tear_down_BA_sessions+0x4f/0x80 [mac80211] + [] __sta_info_destroy+0x66/0x370 [mac80211] + [] sta_info_destroy_addr_bss+0x44/0x70 [mac80211] + [] ieee80211_del_station+0x26/0x50 [mac80211] + [] nl80211_del_station+0x85/0x200 [cfg80211] + +when a station deauthenticated from us without fully setting +up the aggregation session. + +Fix this by checking the aggregation state before removing +the hardware queue. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/mvm/sta.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/mvm/sta.c ++++ b/drivers/net/wireless/iwlwifi/mvm/sta.c +@@ -898,6 +898,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_ + struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; + u16 txq_id; ++ enum iwl_mvm_agg_state old_state; + + /* + * First set the agg state to OFF to avoid calling +@@ -907,13 +908,17 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_ + txq_id = tid_data->txq_id; + IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n", + mvmsta->sta_id, tid, txq_id, tid_data->state); ++ old_state = tid_data->state; + tid_data->state = IWL_AGG_OFF; + spin_unlock_bh(&mvmsta->lock); + +- if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) +- IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); ++ if (old_state >= IWL_AGG_ON) { ++ if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) ++ IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); ++ ++ iwl_trans_txq_disable(mvm->trans, tid_data->txq_id); ++ } + +- iwl_trans_txq_disable(mvm->trans, tid_data->txq_id); + mvm->queue_to_mac80211[tid_data->txq_id] = + IWL_INVALID_MAC80211_QUEUE; + diff --git a/queue-3.10/iwlwifi-mvm-fix-l2p-ba-ressources-leak.patch b/queue-3.10/iwlwifi-mvm-fix-l2p-ba-ressources-leak.patch new file mode 100644 index 00000000000..aa4f02d2c11 --- /dev/null +++ b/queue-3.10/iwlwifi-mvm-fix-l2p-ba-ressources-leak.patch @@ -0,0 +1,37 @@ +From 93a426673fbfeae7fa6b27008828e2ac4c08dbee Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Tue, 2 Jul 2013 13:35:35 +0300 +Subject: iwlwifi: mvm: fix L2P BA ressources leak + +From: Emmanuel Grumbach + +commit 93a426673fbfeae7fa6b27008828e2ac4c08dbee upstream. + +We didn't release the Rx AMPDU ressources properly. +This bug led to firmware assert after 16 BA sessions. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/mvm/sta.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/mvm/sta.c ++++ b/drivers/net/wireless/iwlwifi/mvm/sta.c +@@ -621,8 +621,12 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *m + cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); + cmd.sta_id = mvm_sta->sta_id; + cmd.add_modify = STA_MODE_MODIFY; +- cmd.add_immediate_ba_tid = (u8) tid; +- cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); ++ if (start) { ++ cmd.add_immediate_ba_tid = (u8) tid; ++ cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); ++ } else { ++ cmd.remove_immediate_ba_tid = (u8) tid; ++ } + cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID : + STA_MODIFY_REMOVE_BA_TID; + diff --git a/queue-3.10/iwlwifi-mvm-refuse-connection-to-aps-with-bi-16.patch b/queue-3.10/iwlwifi-mvm-refuse-connection-to-aps-with-bi-16.patch new file mode 100644 index 00000000000..8dc0d6555c3 --- /dev/null +++ b/queue-3.10/iwlwifi-mvm-refuse-connection-to-aps-with-bi-16.patch @@ -0,0 +1,55 @@ +From 48bc13072109ea58465542aa1ee31b4e1065468a Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 4 Jul 2013 15:55:29 +0200 +Subject: iwlwifi: mvm: refuse connection to APs with BI < 16 + +From: Johannes Berg + +commit 48bc13072109ea58465542aa1ee31b4e1065468a upstream. + +Due to a firmware bug, it crashes when the beacon interval +is smaller than 16. Avoid this by refusing the station state +change creating the AP station, causing mac80211 to abandon +the attempt to connect to the AP, and eventually wpa_s to +blacklist it. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/mvm/mac80211.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +@@ -987,6 +987,21 @@ static int iwl_mvm_mac_sta_state(struct + mutex_lock(&mvm->mutex); + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) { ++ /* ++ * Firmware bug - it'll crash if the beacon interval is less ++ * than 16. We can't avoid connecting at all, so refuse the ++ * station state change, this will cause mac80211 to abandon ++ * attempts to connect to this AP, and eventually wpa_s will ++ * blacklist the AP... ++ */ ++ if (vif->type == NL80211_IFTYPE_STATION && ++ vif->bss_conf.beacon_int < 16) { ++ IWL_ERR(mvm, ++ "AP %pM beacon interval is %d, refusing due to firmware bug!\n", ++ sta->addr, vif->bss_conf.beacon_int); ++ ret = -EINVAL; ++ goto out_unlock; ++ } + ret = iwl_mvm_add_sta(mvm, vif, sta); + } else if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_AUTH) { +@@ -1015,6 +1030,7 @@ static int iwl_mvm_mac_sta_state(struct + } else { + ret = -EIO; + } ++ out_unlock: + mutex_unlock(&mvm->mutex); + + return ret; diff --git a/queue-3.10/iwlwifi-pcie-clear-rfkill-interrupt-in-ampg.patch b/queue-3.10/iwlwifi-pcie-clear-rfkill-interrupt-in-ampg.patch new file mode 100644 index 00000000000..fd465be2ee0 --- /dev/null +++ b/queue-3.10/iwlwifi-pcie-clear-rfkill-interrupt-in-ampg.patch @@ -0,0 +1,49 @@ +From a53ee0a308b16e392e0219c585b10f329345766b Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Thu, 25 Jul 2013 13:14:34 +0300 +Subject: iwlwifi: pcie: clear RFKILL interrupt in AMPG + +From: Emmanuel Grumbach + +commit a53ee0a308b16e392e0219c585b10f329345766b upstream. + +If we forget to do so, we can't send HCMD to firmware while +the NIC is in RFKILL state. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/iwl-prph.h | 2 ++ + drivers/net/wireless/iwlwifi/pcie/rx.c | 8 ++++++++ + 2 files changed, 10 insertions(+) + +--- a/drivers/net/wireless/iwlwifi/iwl-prph.h ++++ b/drivers/net/wireless/iwlwifi/iwl-prph.h +@@ -97,6 +97,8 @@ + + #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) + ++#define APMG_RTC_INT_STT_RFKILL (0x10000000) ++ + /* Device system time */ + #define DEVICE_SYSTEM_TIME_REG 0xA0206C + +--- a/drivers/net/wireless/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/rx.c +@@ -886,6 +886,14 @@ irqreturn_t iwl_pcie_irq_handler(int irq + + iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); + if (hw_rfkill) { ++ /* ++ * Clear the interrupt in APMG if the NIC is going down. ++ * Note that when the NIC exits RFkill (else branch), we ++ * can't access prph and the NIC will be reset in ++ * start_hw anyway. ++ */ ++ iwl_write_prph(trans, APMG_RTC_INT_STT_REG, ++ APMG_RTC_INT_STT_RFKILL); + set_bit(STATUS_RFKILL, &trans_pcie->status); + if (test_and_clear_bit(STATUS_HCMD_ACTIVE, + &trans_pcie->status)) diff --git a/queue-3.10/parisc-agp-parisc-agp-allow-binding-of-user-memory-to-the-agp-gart.patch b/queue-3.10/parisc-agp-parisc-agp-allow-binding-of-user-memory-to-the-agp-gart.patch new file mode 100644 index 00000000000..a2286f544df --- /dev/null +++ b/queue-3.10/parisc-agp-parisc-agp-allow-binding-of-user-memory-to-the-agp-gart.patch @@ -0,0 +1,54 @@ +From 06f0cce43a32bd2357cea1d8733bba48693d556b Mon Sep 17 00:00:00 2001 +From: Alex Ivanov +Date: Wed, 10 Jul 2013 21:14:55 +0200 +Subject: parisc: agp/parisc-agp: allow binding of user memory to the AGP GART + +From: Alex Ivanov + +commit 06f0cce43a32bd2357cea1d8733bba48693d556b upstream. + +Allow binding of user memory to the AGP GART on systems with HP +Quicksilver AGP bus. This resolves 'bind memory failed' error seen in +dmesg: + + [29.365973] [TTM] AGP Bind memory failed. + … + [29.367030] [drm] Forcing AGP to PCI mode + +The system doesn't more fail to bind the memory, and hence not falling +back to the PCI mode (if other failures aren't detected). + +This is just a simple write down from the following patches: +agp/amd-k7: Allow binding user memory to the AGP GART +agp/hp-agp: Allow binding user memory to the AGP GART + +Signed-off-by: Alex Ivanov +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/agp/parisc-agp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/char/agp/parisc-agp.c ++++ b/drivers/char/agp/parisc-agp.c +@@ -129,7 +129,8 @@ parisc_agp_insert_memory(struct agp_memo + off_t j, io_pg_start; + int io_pg_count; + +- if (type != 0 || mem->type != 0) { ++ if (type != mem->type || ++ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) { + return -EINVAL; + } + +@@ -175,7 +176,8 @@ parisc_agp_remove_memory(struct agp_memo + struct _parisc_agp_info *info = &parisc_agp_info; + int i, io_pg_start, io_pg_count; + +- if (type != 0 || mem->type != 0) { ++ if (type != mem->type || ++ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) { + return -EINVAL; + } + diff --git a/queue-3.10/parisc-fix-cache-routines-to-ignore-vma-s-with-an-invalid-pfn.patch b/queue-3.10/parisc-fix-cache-routines-to-ignore-vma-s-with-an-invalid-pfn.patch new file mode 100644 index 00000000000..30f09e24e92 --- /dev/null +++ b/queue-3.10/parisc-fix-cache-routines-to-ignore-vma-s-with-an-invalid-pfn.patch @@ -0,0 +1,216 @@ +From 50861f5a02dbf939c27d35a26c472885e2844188 Mon Sep 17 00:00:00 2001 +From: John David Anglin +Date: Tue, 23 Jul 2013 12:27:52 -0400 +Subject: parisc: Fix cache routines to ignore vma's with an invalid pfn + +From: John David Anglin + +commit 50861f5a02dbf939c27d35a26c472885e2844188 upstream. + +The parisc architecture does not have a pte special bit. As a result, +special mappings are handled with the VM_PFNMAP and VM_MIXEDMAP flags. +VM_MIXEDMAP mappings may or may not have a "struct page" backing. When +pfn_valid() is false, there is no "struct page" backing. Otherwise, they +are treated as normal pages. + +The FireGL driver uses the VM_MIXEDMAP without a backing "struct page". +This treatment caused a panic due to a TLB data miss in +update_mmu_cache. This appeared to be in the code generated for +page_address(). We were in fact using a very circular bit of code to +determine the physical address of the PFN in various cache routines. +This wasn't valid when there was no "struct page" backing. The needed +address can in fact be determined simply from the PFN itself without +using the "struct page". + +The attached patch updates update_mmu_cache(), flush_cache_mm(), +flush_cache_range() and flush_cache_page() to check pfn_valid() and to +directly compute the PFN physical and virtual addresses. + +Signed-off-by: John David Anglin +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/parisc/kernel/cache.c | 133 +++++++++++++++++++++++---------------------- + 1 file changed, 70 insertions(+), 63 deletions(-) + +--- a/arch/parisc/kernel/cache.c ++++ b/arch/parisc/kernel/cache.c +@@ -71,18 +71,27 @@ flush_cache_all_local(void) + } + EXPORT_SYMBOL(flush_cache_all_local); + ++/* Virtual address of pfn. */ ++#define pfn_va(pfn) __va(PFN_PHYS(pfn)) ++ + void + update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) + { +- struct page *page = pte_page(*ptep); ++ unsigned long pfn = pte_pfn(*ptep); ++ struct page *page; + +- if (pfn_valid(page_to_pfn(page)) && page_mapping(page) && +- test_bit(PG_dcache_dirty, &page->flags)) { ++ /* We don't have pte special. As a result, we can be called with ++ an invalid pfn and we don't need to flush the kernel dcache page. ++ This occurs with FireGL card in C8000. */ ++ if (!pfn_valid(pfn)) ++ return; + +- flush_kernel_dcache_page(page); ++ page = pfn_to_page(pfn); ++ if (page_mapping(page) && test_bit(PG_dcache_dirty, &page->flags)) { ++ flush_kernel_dcache_page_addr(pfn_va(pfn)); + clear_bit(PG_dcache_dirty, &page->flags); + } else if (parisc_requires_coherency()) +- flush_kernel_dcache_page(page); ++ flush_kernel_dcache_page_addr(pfn_va(pfn)); + } + + void +@@ -495,44 +504,42 @@ static inline pte_t *get_ptep(pgd_t *pgd + + void flush_cache_mm(struct mm_struct *mm) + { ++ struct vm_area_struct *vma; ++ pgd_t *pgd; ++ + /* Flushing the whole cache on each cpu takes forever on + rp3440, etc. So, avoid it if the mm isn't too big. */ +- if (mm_total_size(mm) < parisc_cache_flush_threshold) { +- struct vm_area_struct *vma; +- +- if (mm->context == mfsp(3)) { +- for (vma = mm->mmap; vma; vma = vma->vm_next) { +- flush_user_dcache_range_asm(vma->vm_start, +- vma->vm_end); +- if (vma->vm_flags & VM_EXEC) +- flush_user_icache_range_asm( +- vma->vm_start, vma->vm_end); +- } +- } else { +- pgd_t *pgd = mm->pgd; +- +- for (vma = mm->mmap; vma; vma = vma->vm_next) { +- unsigned long addr; ++ if (mm_total_size(mm) >= parisc_cache_flush_threshold) { ++ flush_cache_all(); ++ return; ++ } + +- for (addr = vma->vm_start; addr < vma->vm_end; +- addr += PAGE_SIZE) { +- pte_t *ptep = get_ptep(pgd, addr); +- if (ptep != NULL) { +- pte_t pte = *ptep; +- __flush_cache_page(vma, addr, +- page_to_phys(pte_page(pte))); +- } +- } +- } ++ if (mm->context == mfsp(3)) { ++ for (vma = mm->mmap; vma; vma = vma->vm_next) { ++ flush_user_dcache_range_asm(vma->vm_start, vma->vm_end); ++ if ((vma->vm_flags & VM_EXEC) == 0) ++ continue; ++ flush_user_icache_range_asm(vma->vm_start, vma->vm_end); + } + return; + } + +-#ifdef CONFIG_SMP +- flush_cache_all(); +-#else +- flush_cache_all_local(); +-#endif ++ pgd = mm->pgd; ++ for (vma = mm->mmap; vma; vma = vma->vm_next) { ++ unsigned long addr; ++ ++ for (addr = vma->vm_start; addr < vma->vm_end; ++ addr += PAGE_SIZE) { ++ unsigned long pfn; ++ pte_t *ptep = get_ptep(pgd, addr); ++ if (!ptep) ++ continue; ++ pfn = pte_pfn(*ptep); ++ if (!pfn_valid(pfn)) ++ continue; ++ __flush_cache_page(vma, addr, PFN_PHYS(pfn)); ++ } ++ } + } + + void +@@ -556,33 +563,32 @@ flush_user_icache_range(unsigned long st + void flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) + { +- BUG_ON(!vma->vm_mm->context); ++ unsigned long addr; ++ pgd_t *pgd; + +- if ((end - start) < parisc_cache_flush_threshold) { +- if (vma->vm_mm->context == mfsp(3)) { +- flush_user_dcache_range_asm(start, end); +- if (vma->vm_flags & VM_EXEC) +- flush_user_icache_range_asm(start, end); +- } else { +- unsigned long addr; +- pgd_t *pgd = vma->vm_mm->pgd; ++ BUG_ON(!vma->vm_mm->context); + +- for (addr = start & PAGE_MASK; addr < end; +- addr += PAGE_SIZE) { +- pte_t *ptep = get_ptep(pgd, addr); +- if (ptep != NULL) { +- pte_t pte = *ptep; +- flush_cache_page(vma, +- addr, pte_pfn(pte)); +- } +- } +- } +- } else { +-#ifdef CONFIG_SMP ++ if ((end - start) >= parisc_cache_flush_threshold) { + flush_cache_all(); +-#else +- flush_cache_all_local(); +-#endif ++ return; ++ } ++ ++ if (vma->vm_mm->context == mfsp(3)) { ++ flush_user_dcache_range_asm(start, end); ++ if (vma->vm_flags & VM_EXEC) ++ flush_user_icache_range_asm(start, end); ++ return; ++ } ++ ++ pgd = vma->vm_mm->pgd; ++ for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) { ++ unsigned long pfn; ++ pte_t *ptep = get_ptep(pgd, addr); ++ if (!ptep) ++ continue; ++ pfn = pte_pfn(*ptep); ++ if (pfn_valid(pfn)) ++ __flush_cache_page(vma, addr, PFN_PHYS(pfn)); + } + } + +@@ -591,9 +597,10 @@ flush_cache_page(struct vm_area_struct * + { + BUG_ON(!vma->vm_mm->context); + +- flush_tlb_page(vma, vmaddr); +- __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); +- ++ if (pfn_valid(pfn)) { ++ flush_tlb_page(vma, vmaddr); ++ __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn)); ++ } + } + + #ifdef CONFIG_PARISC_TMPALIAS diff --git a/queue-3.10/parisc-fix-interrupt-routing-for-c8000-serial-ports.patch b/queue-3.10/parisc-fix-interrupt-routing-for-c8000-serial-ports.patch new file mode 100644 index 00000000000..7b2cf3fa344 --- /dev/null +++ b/queue-3.10/parisc-fix-interrupt-routing-for-c8000-serial-ports.patch @@ -0,0 +1,137 @@ +From dd5e6d6a3db09b16b7c222943977865eead88cc3 Mon Sep 17 00:00:00 2001 +From: Thomas Bogendoerfer +Date: Tue, 30 Jul 2013 02:02:16 +0200 +Subject: parisc: Fix interrupt routing for C8000 serial ports + +From: Thomas Bogendoerfer + +commit dd5e6d6a3db09b16b7c222943977865eead88cc3 upstream. + +We can't use dev->mod_index for selecting the interrupt routing entry, +because it's not an index into interrupt routing table. It will be even +wrong on a machine with 2 CPUs (4 cores). But all needed information is +contained in the PAT entries for the serial ports. mod[0] contains the +iosapic address and mod_info has some indications for the interrupt +input (at least it looks like it). This patch implements the searching +for the right iosapic and uses this interrupt input information. + +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/parisc/include/asm/parisc-device.h | 3 ++ + arch/parisc/kernel/inventory.c | 1 + drivers/parisc/iosapic.c | 38 ++++++++++++++++++++++---------- + drivers/tty/serial/8250/8250_gsc.c | 3 -- + 4 files changed, 32 insertions(+), 13 deletions(-) + +--- a/arch/parisc/include/asm/parisc-device.h ++++ b/arch/parisc/include/asm/parisc-device.h +@@ -23,6 +23,7 @@ struct parisc_device { + /* generic info returned from pdc_pat_cell_module() */ + unsigned long mod_info; /* PAT specific - Misc Module info */ + unsigned long pmod_loc; /* physical Module location */ ++ unsigned long mod0; + #endif + u64 dma_mask; /* DMA mask for I/O */ + struct device dev; +@@ -61,4 +62,6 @@ parisc_get_drvdata(struct parisc_device + + extern struct bus_type parisc_bus_type; + ++int iosapic_serial_irq(struct parisc_device *dev); ++ + #endif /*_ASM_PARISC_PARISC_DEVICE_H_*/ +--- a/arch/parisc/kernel/inventory.c ++++ b/arch/parisc/kernel/inventory.c +@@ -211,6 +211,7 @@ pat_query_module(ulong pcell_loc, ulong + /* REVISIT: who is the consumer of this? not sure yet... */ + dev->mod_info = pa_pdc_cell->mod_info; /* pass to PAT_GET_ENTITY() */ + dev->pmod_loc = pa_pdc_cell->mod_location; ++ dev->mod0 = pa_pdc_cell->mod[0]; + + register_parisc_device(dev); /* advertise device */ + +--- a/drivers/parisc/iosapic.c ++++ b/drivers/parisc/iosapic.c +@@ -811,18 +811,28 @@ int iosapic_fixup_irq(void *isi_obj, str + return pcidev->irq; + } + +-static struct iosapic_info *first_isi = NULL; ++static struct iosapic_info *iosapic_list; + + #ifdef CONFIG_64BIT +-int iosapic_serial_irq(int num) ++int iosapic_serial_irq(struct parisc_device *dev) + { +- struct iosapic_info *isi = first_isi; +- struct irt_entry *irte = NULL; /* only used if PAT PDC */ ++ struct iosapic_info *isi; ++ struct irt_entry *irte; + struct vector_info *vi; +- int isi_line; /* line used by device */ ++ int cnt; ++ int intin; ++ ++ intin = (dev->mod_info >> 24) & 15; + + /* lookup IRT entry for isi/slot/pin set */ +- irte = &irt_cell[num]; ++ for (cnt = 0; cnt < irt_num_entry; cnt++) { ++ irte = &irt_cell[cnt]; ++ if (COMPARE_IRTE_ADDR(irte, dev->mod0) && ++ irte->dest_iosapic_intin == intin) ++ break; ++ } ++ if (cnt >= irt_num_entry) ++ return 0; /* no irq found, force polling */ + + DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n", + irte, +@@ -834,11 +844,17 @@ int iosapic_serial_irq(int num) + irte->src_seg_id, + irte->dest_iosapic_intin, + (u32) irte->dest_iosapic_addr); +- isi_line = irte->dest_iosapic_intin; ++ ++ /* search for iosapic */ ++ for (isi = iosapic_list; isi; isi = isi->isi_next) ++ if (isi->isi_hpa == dev->mod0) ++ break; ++ if (!isi) ++ return 0; /* no iosapic found, force polling */ + + /* get vector info for this input line */ +- vi = isi->isi_vector + isi_line; +- DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", isi_line, vi); ++ vi = isi->isi_vector + intin; ++ DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", iosapic_intin, vi); + + /* If this IRQ line has already been setup, skip it */ + if (vi->irte) +@@ -941,8 +957,8 @@ void *iosapic_register(unsigned long hpa + vip->irqline = (unsigned char) cnt; + vip->iosapic = isi; + } +- if (!first_isi) +- first_isi = isi; ++ isi->isi_next = iosapic_list; ++ iosapic_list = isi; + return isi; + } + +--- a/drivers/tty/serial/8250/8250_gsc.c ++++ b/drivers/tty/serial/8250/8250_gsc.c +@@ -31,9 +31,8 @@ static int __init serial_init_chip(struc + int err; + + #ifdef CONFIG_64BIT +- extern int iosapic_serial_irq(int cellnum); + if (!dev->irq && (dev->id.sversion == 0xad)) +- dev->irq = iosapic_serial_irq(dev->mod_index-1); ++ dev->irq = iosapic_serial_irq(dev); + #endif + + if (!dev->irq) { diff --git a/queue-3.10/powerpc-vphn-topology-change-updates-all-siblings.patch b/queue-3.10/powerpc-vphn-topology-change-updates-all-siblings.patch new file mode 100644 index 00000000000..a6ca80e118a --- /dev/null +++ b/queue-3.10/powerpc-vphn-topology-change-updates-all-siblings.patch @@ -0,0 +1,155 @@ +From 3be7db6ab45b21345386d1a466da133b19cde5e4 Mon Sep 17 00:00:00 2001 +From: Robert Jennings +Date: Wed, 24 Jul 2013 20:13:21 -0500 +Subject: powerpc: VPHN topology change updates all siblings + +From: Robert Jennings + +commit 3be7db6ab45b21345386d1a466da133b19cde5e4 upstream. + +When an associativity level change is found for one thread, the +siblings threads need to be updated as well. This is done today +for PRRN in stage_topology_update() but is missing for VPHN in +update_cpu_associativity_changes_mask(). This patch will correctly +update all thread siblings during a topology change. + +Without this patch a topology update can result in a CPU in +init_sched_groups_power() getting stuck indefinitely in a loop. + +This loop is built in build_sched_groups(). As a result of the thread +moving to a node separate from its siblings the struct sched_group will +have its next pointer set to point to itself rather than the sched_group +struct of the next thread. This happens because we have a domain without +the SD_OVERLAP flag, which is correct, and a topology that doesn't conform +with reality (threads on the same core assigned to different numa nodes). +When this list is traversed by init_sched_groups_power() it will reach +the thread's sched_group structure and loop indefinitely; the cpu will +be stuck at this point. + +The bug was exposed when VPHN was enabled in commit b7abef0 (v3.9). + +Reported-by: Jan Stancek +Signed-off-by: Robert Jennings +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/include/asm/smp.h | 4 ++ + arch/powerpc/mm/numa.c | 59 ++++++++++++++++++++++++++++++----------- + 2 files changed, 48 insertions(+), 15 deletions(-) + +--- a/arch/powerpc/include/asm/smp.h ++++ b/arch/powerpc/include/asm/smp.h +@@ -145,6 +145,10 @@ extern void __cpu_die(unsigned int cpu); + #define smp_setup_cpu_maps() + static inline void inhibit_secondary_onlining(void) {} + static inline void uninhibit_secondary_onlining(void) {} ++static inline const struct cpumask *cpu_sibling_mask(int cpu) ++{ ++ return cpumask_of(cpu); ++} + + #endif /* CONFIG_SMP */ + +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1319,7 +1320,8 @@ static int update_cpu_associativity_chan + } + } + if (changed) { +- cpumask_set_cpu(cpu, changes); ++ cpumask_or(changes, changes, cpu_sibling_mask(cpu)); ++ cpu = cpu_last_thread_sibling(cpu); + } + } + +@@ -1427,7 +1429,7 @@ static int update_cpu_topology(void *dat + if (!data) + return -EINVAL; + +- cpu = get_cpu(); ++ cpu = smp_processor_id(); + + for (update = data; update; update = update->next) { + if (cpu != update->cpu) +@@ -1447,12 +1449,12 @@ static int update_cpu_topology(void *dat + */ + int arch_update_cpu_topology(void) + { +- unsigned int cpu, changed = 0; ++ unsigned int cpu, sibling, changed = 0; + struct topology_update_data *updates, *ud; + unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; + cpumask_t updated_cpus; + struct device *dev; +- int weight, i = 0; ++ int weight, new_nid, i = 0; + + weight = cpumask_weight(&cpu_associativity_changes_mask); + if (!weight) +@@ -1465,19 +1467,46 @@ int arch_update_cpu_topology(void) + cpumask_clear(&updated_cpus); + + for_each_cpu(cpu, &cpu_associativity_changes_mask) { +- ud = &updates[i++]; +- ud->cpu = cpu; +- vphn_get_associativity(cpu, associativity); +- ud->new_nid = associativity_to_nid(associativity); +- +- if (ud->new_nid < 0 || !node_online(ud->new_nid)) +- ud->new_nid = first_online_node; ++ /* ++ * If siblings aren't flagged for changes, updates list ++ * will be too short. Skip on this update and set for next ++ * update. ++ */ ++ if (!cpumask_subset(cpu_sibling_mask(cpu), ++ &cpu_associativity_changes_mask)) { ++ pr_info("Sibling bits not set for associativity " ++ "change, cpu%d\n", cpu); ++ cpumask_or(&cpu_associativity_changes_mask, ++ &cpu_associativity_changes_mask, ++ cpu_sibling_mask(cpu)); ++ cpu = cpu_last_thread_sibling(cpu); ++ continue; ++ } + +- ud->old_nid = numa_cpu_lookup_table[cpu]; +- cpumask_set_cpu(cpu, &updated_cpus); ++ /* Use associativity from first thread for all siblings */ ++ vphn_get_associativity(cpu, associativity); ++ new_nid = associativity_to_nid(associativity); ++ if (new_nid < 0 || !node_online(new_nid)) ++ new_nid = first_online_node; ++ ++ if (new_nid == numa_cpu_lookup_table[cpu]) { ++ cpumask_andnot(&cpu_associativity_changes_mask, ++ &cpu_associativity_changes_mask, ++ cpu_sibling_mask(cpu)); ++ cpu = cpu_last_thread_sibling(cpu); ++ continue; ++ } + +- if (i < weight) +- ud->next = &updates[i]; ++ for_each_cpu(sibling, cpu_sibling_mask(cpu)) { ++ ud = &updates[i++]; ++ ud->cpu = sibling; ++ ud->new_nid = new_nid; ++ ud->old_nid = numa_cpu_lookup_table[sibling]; ++ cpumask_set_cpu(sibling, &updated_cpus); ++ if (i < weight) ++ ud->next = &updates[i]; ++ } ++ cpu = cpu_last_thread_sibling(cpu); + } + + stop_machine(update_cpu_topology, &updates[0], &updated_cpus); diff --git a/queue-3.10/powerpc-windfarm-fix-noisy-slots-fan-on-xserve-rm31.patch b/queue-3.10/powerpc-windfarm-fix-noisy-slots-fan-on-xserve-rm31.patch new file mode 100644 index 00000000000..3c5490a0baa --- /dev/null +++ b/queue-3.10/powerpc-windfarm-fix-noisy-slots-fan-on-xserve-rm31.patch @@ -0,0 +1,52 @@ +From fe956a1d4081ce1a959f87df397a15e252201f10 Mon Sep 17 00:00:00 2001 +From: Aaro Koskinen +Date: Sun, 21 Jul 2013 03:30:11 +0300 +Subject: powerpc/windfarm: Fix noisy slots-fan on Xserve (rm31) + +From: Aaro Koskinen + +commit fe956a1d4081ce1a959f87df397a15e252201f10 upstream. + +slots-fan on G5 Xserve is always running at full speed with windfarm_rm31 +driver, resulting in a very high acoustic noise level. It seems the fan +parameters are incorrect, and have been copied from the Drive Bay fan +(RPM, not present on rm31) of the legacy therm_pm72 driver. This patch +changes the parameters to match the Slots fan (PWM) of therm_pm72. With +the patch, slots-fan speed drops from 99% to 19% during normal use, +and slots-temp settle to ~42'C. + +Signed-off-by: Aaro Koskinen +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/macintosh/windfarm_rm31.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/macintosh/windfarm_rm31.c ++++ b/drivers/macintosh/windfarm_rm31.c +@@ -439,15 +439,15 @@ static void backside_setup_pid(void) + + /* Slots fan */ + static const struct wf_pid_param slots_param = { +- .interval = 5, +- .history_len = 2, +- .gd = 30 << 20, +- .gp = 5 << 20, +- .gr = 0, +- .itarget = 40 << 16, +- .additive = 1, +- .min = 300, +- .max = 4000, ++ .interval = 1, ++ .history_len = 20, ++ .gd = 0, ++ .gp = 0, ++ .gr = 0x00100000, ++ .itarget = 3200000, ++ .additive = 0, ++ .min = 20, ++ .max = 100, + }; + + static void slots_fan_tick(void) diff --git a/queue-3.10/serial-arc_uart-fix-module-alias.patch b/queue-3.10/serial-arc_uart-fix-module-alias.patch new file mode 100644 index 00000000000..5667a1a731b --- /dev/null +++ b/queue-3.10/serial-arc_uart-fix-module-alias.patch @@ -0,0 +1,30 @@ +From d5a12ea7a9e58d9e5c19d25cb668aadb396423ec Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Sun, 21 Jul 2013 10:14:15 +0800 +Subject: serial: arc_uart: Fix module alias + +From: Axel Lin + +commit d5a12ea7a9e58d9e5c19d25cb668aadb396423ec upstream. + +Platform drivers use "platform:" prefix in module alias. +Also use DRIVER_NAME in MODULE_ALIAS to make module autoloading work. + +Signed-off-by: Axel Lin +Acked-by: Vineet Gupta +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/arc_uart.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/arc_uart.c ++++ b/drivers/tty/serial/arc_uart.c +@@ -773,6 +773,6 @@ module_init(arc_serial_init); + module_exit(arc_serial_exit); + + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("plat-arcfpga/uart"); ++MODULE_ALIAS("platform:" DRIVER_NAME); + MODULE_AUTHOR("Vineet Gupta"); + MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver"); diff --git a/queue-3.10/serial-mxs-auart-fix-race-condition-in-interrupt-handler.patch b/queue-3.10/serial-mxs-auart-fix-race-condition-in-interrupt-handler.patch new file mode 100644 index 00000000000..d3233e9832c --- /dev/null +++ b/queue-3.10/serial-mxs-auart-fix-race-condition-in-interrupt-handler.patch @@ -0,0 +1,60 @@ +From d970d7fe65adff5efe75b4a73c4ffc9be57089f7 Mon Sep 17 00:00:00 2001 +From: Uwe Kleine-König +Date: Thu, 4 Jul 2013 11:28:51 +0200 +Subject: serial/mxs-auart: fix race condition in interrupt handler + +From: Uwe Kleine-König + +commit d970d7fe65adff5efe75b4a73c4ffc9be57089f7 upstream. + +The handler needs to ack the pending events before actually handling them. +Otherwise a new event might come in after it it considered non-pending or +handled and is acked then without being handled. So this event is only +noticed when the next interrupt happens. + +Without this patch an i.MX28 based machine running an rt-patched kernel +regularly hangs during boot. + +Signed-off-by: Uwe Kleine-König +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/mxs-auart.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/tty/serial/mxs-auart.c ++++ b/drivers/tty/serial/mxs-auart.c +@@ -678,11 +678,18 @@ static void mxs_auart_settermios(struct + + static irqreturn_t mxs_auart_irq_handle(int irq, void *context) + { +- u32 istatus, istat; ++ u32 istat; + struct mxs_auart_port *s = context; + u32 stat = readl(s->port.membase + AUART_STAT); + +- istatus = istat = readl(s->port.membase + AUART_INTR); ++ istat = readl(s->port.membase + AUART_INTR); ++ ++ /* ack irq */ ++ writel(istat & (AUART_INTR_RTIS ++ | AUART_INTR_TXIS ++ | AUART_INTR_RXIS ++ | AUART_INTR_CTSMIS), ++ s->port.membase + AUART_INTR_CLR); + + if (istat & AUART_INTR_CTSMIS) { + uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS); +@@ -702,12 +709,6 @@ static irqreturn_t mxs_auart_irq_handle( + istat &= ~AUART_INTR_TXIS; + } + +- writel(istatus & (AUART_INTR_RTIS +- | AUART_INTR_TXIS +- | AUART_INTR_RXIS +- | AUART_INTR_CTSMIS), +- s->port.membase + AUART_INTR_CLR); +- + return IRQ_HANDLED; + } + diff --git a/queue-3.10/serial-mxs-auart-increase-time-to-wait-for-transmitter-to-become-idle.patch b/queue-3.10/serial-mxs-auart-increase-time-to-wait-for-transmitter-to-become-idle.patch new file mode 100644 index 00000000000..8a8ec82b531 --- /dev/null +++ b/queue-3.10/serial-mxs-auart-increase-time-to-wait-for-transmitter-to-become-idle.patch @@ -0,0 +1,71 @@ +From 079a036f4283e2b0e5c26080b8c5112bc0cc1831 Mon Sep 17 00:00:00 2001 +From: Uwe Kleine-König +Date: Fri, 28 Jun 2013 11:49:41 +0200 +Subject: serial/mxs-auart: increase time to wait for transmitter to become idle + +From: Uwe Kleine-König + +commit 079a036f4283e2b0e5c26080b8c5112bc0cc1831 upstream. + +Without this patch the driver waits ~1 ms for the UART to become idle. At +115200n8 this time is (theoretically) enough to transfer 11.5 characters +(= 115200 bits/s / (10 Bits/char) * 1ms). As the mxs-auart has a fifo size +of 16 characters the clock is gated too early. The problem is worse for +lower baud rates. + +This only happens to really shut down the transmitter in the middle of a +transfer if /dev/ttyAPPx isn't opened in userspace (e.g. by a getty) but +was at least once (because the bootloader doesn't disable the transmitter). + +So increase the timeout to 20 ms which should be enough for 9600n8, too. +Moreover skip gating the clock if the timeout is elapsed. + +Signed-off-by: Uwe Kleine-König +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/mxs-auart.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/drivers/tty/serial/mxs-auart.c ++++ b/drivers/tty/serial/mxs-auart.c +@@ -851,7 +851,7 @@ auart_console_write(struct console *co, + struct mxs_auart_port *s; + struct uart_port *port; + unsigned int old_ctrl0, old_ctrl2; +- unsigned int to = 1000; ++ unsigned int to = 20000; + + if (co->index >= MXS_AUART_PORTS || co->index < 0) + return; +@@ -872,18 +872,23 @@ auart_console_write(struct console *co, + + uart_console_write(port, str, count, mxs_auart_console_putchar); + +- /* +- * Finally, wait for transmitter to become empty +- * and restore the TCR +- */ ++ /* Finally, wait for transmitter to become empty ... */ + while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) { ++ udelay(1); + if (!to--) + break; +- udelay(1); + } + +- writel(old_ctrl0, port->membase + AUART_CTRL0); +- writel(old_ctrl2, port->membase + AUART_CTRL2); ++ /* ++ * ... and restore the TCR if we waited long enough for the transmitter ++ * to be idle. This might keep the transmitter enabled although it is ++ * unused, but that is better than to disable it while it is still ++ * transmitting. ++ */ ++ if (!(readl(port->membase + AUART_STAT) & AUART_STAT_BUSY)) { ++ writel(old_ctrl0, port->membase + AUART_CTRL0); ++ writel(old_ctrl2, port->membase + AUART_CTRL2); ++ } + + clk_disable(s->clk); + } diff --git a/queue-3.10/series b/queue-3.10/series index e9a483ef95d..6ab3edde42d 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -8,3 +8,29 @@ arm-move-signal-handlers-into-a-vdso-like-page.patch arm-make-vectors-page-inaccessible-from-userspace.patch arm-fix-a-cockup-in-48be69a02-arm-move-signal-handlers-into-a-vdso-like-page.patch arm-fix-nommu-builds-with-48be69a02-arm-move-signal-handlers-into-a-vdso-like-page.patch +powerpc-windfarm-fix-noisy-slots-fan-on-xserve-rm31.patch +arm-7784-1-mm-ensure-smp-alternates-assemble-to-exactly-4-bytes-with-thumb-2.patch +arm-7790-1-fix-deferred-mm-switch-on-vivt-processors.patch +arm-7791-1-a.out-remove-partial-a.out-support.patch +powerpc-vphn-topology-change-updates-all-siblings.patch +parisc-agp-parisc-agp-allow-binding-of-user-memory-to-the-agp-gart.patch +parisc-fix-cache-routines-to-ignore-vma-s-with-an-invalid-pfn.patch +parisc-fix-interrupt-routing-for-c8000-serial-ports.patch +hwmon-max6697-fix-max6581-ideality.patch +alsa-hda-fix-missing-fixup-for-mac-mini-with-stac9221.patch +alsa-compress-fix-the-return-value-for-sndrv_compress_version.patch +serial-mxs-auart-fix-race-condition-in-interrupt-handler.patch +serial-arc_uart-fix-module-alias.patch +serial-mxs-auart-increase-time-to-wait-for-transmitter-to-become-idle.patch +dma-pl330-fix-cyclic-transfers.patch +usb-mos7840-fix-race-in-register-handling.patch +usb-mos7840-fix-device-type-detection.patch +usb-mos7840-fix-race-in-led-handling.patch +usb-mos7840-fix-pointer-casts.patch +iwlwifi-mvm-fix-l2p-ba-ressources-leak.patch +iwlwifi-mvm-fix-bug-in-scan-ssid.patch +iwlwifi-mvm-refuse-connection-to-aps-with-bi-16.patch +iwlwifi-add-dell-sku-for-5150-hmc.patch +iwlwifi-mvm-fix-flushing-not-started-aggregation-sessions.patch +iwlwifi-pcie-clear-rfkill-interrupt-in-ampg.patch +atl1c-fix-misuse-of-netdev_alloc_skb-in-refilling-rx-ring.patch diff --git a/queue-3.10/usb-mos7840-fix-device-type-detection.patch b/queue-3.10/usb-mos7840-fix-device-type-detection.patch new file mode 100644 index 00000000000..9110b06eb89 --- /dev/null +++ b/queue-3.10/usb-mos7840-fix-device-type-detection.patch @@ -0,0 +1,144 @@ +From 40c24f2893ba0ba7df485871f6aac0c197ceef5b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 26 Jul 2013 11:55:18 +0200 +Subject: USB: mos7840: fix device-type detection + +From: Johan Hovold + +commit 40c24f2893ba0ba7df485871f6aac0c197ceef5b upstream. + +Fix race in device-type detection introduced by commit 0eafe4de ("USB: +serial: mos7840: add support for MCS7810 devices") which used a static +variable to hold the device type. + +Move type detection to probe and use serial data to store the device +type. + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 75 ++++++++++++++++++++----------------------- + 1 file changed, 35 insertions(+), 40 deletions(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -187,8 +187,6 @@ enum mos7840_flag { + MOS7840_FLAG_CTRL_BUSY, + }; + +-static int device_type; +- + static const struct usb_device_id id_table[] = { + {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, + {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, +@@ -839,18 +837,6 @@ static void mos7840_bulk_out_data_callba + /************************************************************************/ + /* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */ + /************************************************************************/ +-#ifdef MCSSerialProbe +-static int mos7840_serial_probe(struct usb_serial *serial, +- const struct usb_device_id *id) +-{ +- +- /*need to implement the mode_reg reading and updating\ +- structures usb_serial_ device_type\ +- (i.e num_ports, num_bulkin,bulkout etc) */ +- /* Also we can update the changes attach */ +- return 1; +-} +-#endif + + /***************************************************************************** + * mos7840_open +@@ -2216,38 +2202,48 @@ static int mos7810_check(struct usb_seri + return 0; + } + +-static int mos7840_calc_num_ports(struct usb_serial *serial) ++static int mos7840_probe(struct usb_serial *serial, ++ const struct usb_device_id *id) + { +- __u16 data = 0x00; ++ u16 product = serial->dev->descriptor.idProduct; + u8 *buf; +- int mos7840_num_ports; ++ int device_type; ++ ++ if (product == MOSCHIP_DEVICE_ID_7810 || ++ product == MOSCHIP_DEVICE_ID_7820) { ++ device_type = product; ++ goto out; ++ } + + buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL); +- if (buf) { +- usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), ++ if (!buf) ++ return -ENOMEM; ++ ++ usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf, + VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); +- data = *buf; +- kfree(buf); +- } + +- if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 || +- serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) { +- device_type = serial->dev->descriptor.idProduct; +- } else { +- /* For a MCS7840 device GPIO0 must be set to 1 */ +- if ((data & 0x01) == 1) +- device_type = MOSCHIP_DEVICE_ID_7840; +- else if (mos7810_check(serial)) +- device_type = MOSCHIP_DEVICE_ID_7810; +- else +- device_type = MOSCHIP_DEVICE_ID_7820; +- } ++ /* For a MCS7840 device GPIO0 must be set to 1 */ ++ if (buf[0] & 0x01) ++ device_type = MOSCHIP_DEVICE_ID_7840; ++ else if (mos7810_check(serial)) ++ device_type = MOSCHIP_DEVICE_ID_7810; ++ else ++ device_type = MOSCHIP_DEVICE_ID_7820; ++ ++ kfree(buf); ++out: ++ usb_set_serial_data(serial, (void *)device_type); ++ ++ return 0; ++} ++ ++static int mos7840_calc_num_ports(struct usb_serial *serial) ++{ ++ int device_type = (int)usb_get_serial_data(serial); ++ int mos7840_num_ports; + + mos7840_num_ports = (device_type >> 4) & 0x000F; +- serial->num_bulk_in = mos7840_num_ports; +- serial->num_bulk_out = mos7840_num_ports; +- serial->num_ports = mos7840_num_ports; + + return mos7840_num_ports; + } +@@ -2255,6 +2251,7 @@ static int mos7840_calc_num_ports(struct + static int mos7840_port_probe(struct usb_serial_port *port) + { + struct usb_serial *serial = port->serial; ++ int device_type = (int)usb_get_serial_data(serial); + struct moschip_port *mos7840_port; + int status; + int pnum; +@@ -2513,9 +2510,7 @@ static struct usb_serial_driver moschip7 + .throttle = mos7840_throttle, + .unthrottle = mos7840_unthrottle, + .calc_num_ports = mos7840_calc_num_ports, +-#ifdef MCSSerialProbe +- .probe = mos7840_serial_probe, +-#endif ++ .probe = mos7840_probe, + .ioctl = mos7840_ioctl, + .set_termios = mos7840_set_termios, + .break_ctl = mos7840_break, diff --git a/queue-3.10/usb-mos7840-fix-pointer-casts.patch b/queue-3.10/usb-mos7840-fix-pointer-casts.patch new file mode 100644 index 00000000000..8f0e08438ea --- /dev/null +++ b/queue-3.10/usb-mos7840-fix-pointer-casts.patch @@ -0,0 +1,51 @@ +From 683a0e4d7971c3186dc4d429027debfe309129aa Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Sat, 27 Jul 2013 13:34:42 +0200 +Subject: USB: mos7840: fix pointer casts + +From: Johan Hovold + +commit 683a0e4d7971c3186dc4d429027debfe309129aa upstream. + +Silence compiler warnings on 64-bit systems introduced by commit +05cf0dec ("USB: mos7840: fix race in led handling") which uses the +usb-serial data pointer to temporarily store the device type during +probe but failed to add the required casts. + +[gregkh - change uintptr_t to unsigned long] + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -2236,14 +2236,14 @@ static int mos7840_probe(struct usb_seri + + kfree(buf); + out: +- usb_set_serial_data(serial, (void *)device_type); ++ usb_set_serial_data(serial, (void *)(unsigned long)device_type); + + return 0; + } + + static int mos7840_calc_num_ports(struct usb_serial *serial) + { +- int device_type = (int)usb_get_serial_data(serial); ++ int device_type = (unsigned long)usb_get_serial_data(serial); + int mos7840_num_ports; + + mos7840_num_ports = (device_type >> 4) & 0x000F; +@@ -2254,7 +2254,7 @@ static int mos7840_calc_num_ports(struct + static int mos7840_port_probe(struct usb_serial_port *port) + { + struct usb_serial *serial = port->serial; +- int device_type = (int)usb_get_serial_data(serial); ++ int device_type = (unsigned long)usb_get_serial_data(serial); + struct moschip_port *mos7840_port; + int status; + int pnum; diff --git a/queue-3.10/usb-mos7840-fix-race-in-led-handling.patch b/queue-3.10/usb-mos7840-fix-race-in-led-handling.patch new file mode 100644 index 00000000000..bb0d4f40936 --- /dev/null +++ b/queue-3.10/usb-mos7840-fix-race-in-led-handling.patch @@ -0,0 +1,167 @@ +From 05cf0dec5ccc696a7636c84b265b477173498156 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 26 Jul 2013 11:55:19 +0200 +Subject: USB: mos7840: fix race in led handling + +From: Johan Hovold + +commit 05cf0dec5ccc696a7636c84b265b477173498156 upstream. + +Fix race in LED handling introduced by commit 0eafe4de ("USB: serial: +mos7840: add support for MCS7810 devices") which reused the port control +urb for manipulating the LED without making sure that the urb is not +already in use. This could lead to the control urb being manipulated +while in flight. + +Fix by adding a dedicated LED urb and ctrlrequest along with a LED-busy +flag to handle concurrency. + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 59 ++++++++++++++++++++++++++----------------- + 1 file changed, 37 insertions(+), 22 deletions(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -185,6 +185,7 @@ + + enum mos7840_flag { + MOS7840_FLAG_CTRL_BUSY, ++ MOS7840_FLAG_LED_BUSY, + }; + + static const struct usb_device_id id_table[] = { +@@ -240,9 +241,10 @@ struct moschip_port { + + /* For device(s) with LED indicator */ + bool has_led; +- bool led_flag; + struct timer_list led_timer1; /* Timer for LED on */ + struct timer_list led_timer2; /* Timer for LED off */ ++ struct urb *led_urb; ++ struct usb_ctrlrequest *led_dr; + + unsigned long flags; + }; +@@ -542,7 +544,7 @@ static void mos7840_set_led_async(struct + __u16 reg) + { + struct usb_device *dev = mcs->port->serial->dev; +- struct usb_ctrlrequest *dr = mcs->dr; ++ struct usb_ctrlrequest *dr = mcs->led_dr; + + dr->bRequestType = MCS_WR_RTYPE; + dr->bRequest = MCS_WRREQ; +@@ -550,10 +552,10 @@ static void mos7840_set_led_async(struct + dr->wIndex = cpu_to_le16(reg); + dr->wLength = cpu_to_le16(0); + +- usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0), ++ usb_fill_control_urb(mcs->led_urb, dev, usb_sndctrlpipe(dev, 0), + (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL); + +- usb_submit_urb(mcs->control_urb, GFP_ATOMIC); ++ usb_submit_urb(mcs->led_urb, GFP_ATOMIC); + } + + static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg, +@@ -579,7 +581,19 @@ static void mos7840_led_flag_off(unsigne + { + struct moschip_port *mcs = (struct moschip_port *) arg; + +- mcs->led_flag = false; ++ clear_bit_unlock(MOS7840_FLAG_LED_BUSY, &mcs->flags); ++} ++ ++static void mos7840_led_activity(struct usb_serial_port *port) ++{ ++ struct moschip_port *mos7840_port = usb_get_serial_port_data(port); ++ ++ if (test_and_set_bit_lock(MOS7840_FLAG_LED_BUSY, &mos7840_port->flags)) ++ return; ++ ++ mos7840_set_led_async(mos7840_port, 0x0301, MODEM_CONTROL_REGISTER); ++ mod_timer(&mos7840_port->led_timer1, ++ jiffies + msecs_to_jiffies(LED_ON_MS)); + } + + /***************************************************************************** +@@ -779,14 +793,8 @@ static void mos7840_bulk_in_callback(str + return; + } + +- /* Turn on LED */ +- if (mos7840_port->has_led && !mos7840_port->led_flag) { +- mos7840_port->led_flag = true; +- mos7840_set_led_async(mos7840_port, 0x0301, +- MODEM_CONTROL_REGISTER); +- mod_timer(&mos7840_port->led_timer1, +- jiffies + msecs_to_jiffies(LED_ON_MS)); +- } ++ if (mos7840_port->has_led) ++ mos7840_led_activity(port); + + mos7840_port->read_urb_busy = true; + retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); +@@ -1467,13 +1475,8 @@ static int mos7840_write(struct tty_stru + data1 = urb->transfer_buffer; + dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress); + +- /* Turn on LED */ +- if (mos7840_port->has_led && !mos7840_port->led_flag) { +- mos7840_port->led_flag = true; +- mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301); +- mod_timer(&mos7840_port->led_timer1, +- jiffies + msecs_to_jiffies(LED_ON_MS)); +- } ++ if (mos7840_port->has_led) ++ mos7840_led_activity(port); + + /* send it down the pipe */ + status = usb_submit_urb(urb, GFP_ATOMIC); +@@ -2429,6 +2432,14 @@ static int mos7840_port_probe(struct usb + if (device_type == MOSCHIP_DEVICE_ID_7810) { + mos7840_port->has_led = true; + ++ mos7840_port->led_urb = usb_alloc_urb(0, GFP_KERNEL); ++ mos7840_port->led_dr = kmalloc(sizeof(*mos7840_port->led_dr), ++ GFP_KERNEL); ++ if (!mos7840_port->led_urb || !mos7840_port->led_dr) { ++ status = -ENOMEM; ++ goto error; ++ } ++ + init_timer(&mos7840_port->led_timer1); + mos7840_port->led_timer1.function = mos7840_led_off; + mos7840_port->led_timer1.expires = +@@ -2441,8 +2452,6 @@ static int mos7840_port_probe(struct usb + jiffies + msecs_to_jiffies(LED_OFF_MS); + mos7840_port->led_timer2.data = (unsigned long)mos7840_port; + +- mos7840_port->led_flag = false; +- + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); + } +@@ -2464,6 +2473,8 @@ out: + } + return 0; + error: ++ kfree(mos7840_port->led_dr); ++ usb_free_urb(mos7840_port->led_urb); + kfree(mos7840_port->dr); + kfree(mos7840_port->ctrl_buf); + usb_free_urb(mos7840_port->control_urb); +@@ -2484,6 +2495,10 @@ static int mos7840_port_remove(struct us + + del_timer_sync(&mos7840_port->led_timer1); + del_timer_sync(&mos7840_port->led_timer2); ++ ++ usb_kill_urb(mos7840_port->led_urb); ++ usb_free_urb(mos7840_port->led_urb); ++ kfree(mos7840_port->led_dr); + } + usb_kill_urb(mos7840_port->control_urb); + usb_free_urb(mos7840_port->control_urb); diff --git a/queue-3.10/usb-mos7840-fix-race-in-register-handling.patch b/queue-3.10/usb-mos7840-fix-race-in-register-handling.patch new file mode 100644 index 00000000000..ed11b8e23ad --- /dev/null +++ b/queue-3.10/usb-mos7840-fix-race-in-register-handling.patch @@ -0,0 +1,84 @@ +From d8a083cc746664916d9d36ed9e4d08a29525f245 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 26 Jul 2013 11:55:17 +0200 +Subject: USB: mos7840: fix race in register handling + +From: Johan Hovold + +commit d8a083cc746664916d9d36ed9e4d08a29525f245 upstream. + +Fix race in mos7840_get_reg which unconditionally manipulated the +control urb (which may already be in use) by adding a control-urb busy +flag. + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -183,6 +183,10 @@ + #define LED_ON_MS 500 + #define LED_OFF_MS 500 + ++enum mos7840_flag { ++ MOS7840_FLAG_CTRL_BUSY, ++}; ++ + static int device_type; + + static const struct usb_device_id id_table[] = { +@@ -241,6 +245,8 @@ struct moschip_port { + bool led_flag; + struct timer_list led_timer1; /* Timer for LED on */ + struct timer_list led_timer2; /* Timer for LED off */ ++ ++ unsigned long flags; + }; + + /* +@@ -467,10 +473,10 @@ static void mos7840_control_callback(str + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); +- return; ++ goto out; + default: + dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); +- return; ++ goto out; + } + + dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); +@@ -483,6 +489,8 @@ static void mos7840_control_callback(str + mos7840_handle_new_msr(mos7840_port, regval); + else if (mos7840_port->MsrLsr == 1) + mos7840_handle_new_lsr(mos7840_port, regval); ++out: ++ clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mos7840_port->flags); + } + + static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, +@@ -493,6 +501,9 @@ static int mos7840_get_reg(struct moschi + unsigned char *buffer = mcs->ctrl_buf; + int ret; + ++ if (test_and_set_bit_lock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags)) ++ return -EBUSY; ++ + dr->bRequestType = MCS_RD_RTYPE; + dr->bRequest = MCS_RDREQ; + dr->wValue = cpu_to_le16(Wval); /* 0 */ +@@ -504,6 +515,9 @@ static int mos7840_get_reg(struct moschi + mos7840_control_callback, mcs); + mcs->control_urb->transfer_buffer_length = 2; + ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); ++ if (ret) ++ clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags); ++ + return ret; + } +