From 2a01bb3885c9145dbb7583d5aa5f5d5504f6f46f Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 11 Apr 2012 08:15:29 -0400 Subject: panic: Make panic_on_oops configurable Several distros set this by default by patching panic_on_oops. It seems to fit with the BOOTPARAM_{HARD,SOFT}_PANIC options though, so let's add a Kconfig entry and reduce some more upstream delta. Signed-off-by: Kyle McMartin Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20120411121529.GH26688@redacted.bos.redhat.com Signed-off-by: Ingo Molnar diff --git a/kernel/panic.c b/kernel/panic.c index 8ed89a1..b6215b7 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -27,7 +27,7 @@ #define PANIC_TIMER_STEP 100 #define PANIC_BLINK_SPD 18 -int panic_on_oops; +int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE; static unsigned long tainted_mask; static int pause_on_oops; static int pause_on_oops_flag; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 6777153..91858cd 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -228,6 +228,26 @@ config BOOTPARAM_SOFTLOCKUP_PANIC_VALUE default 0 if !BOOTPARAM_SOFTLOCKUP_PANIC default 1 if BOOTPARAM_SOFTLOCKUP_PANIC +config PANIC_ON_OOPS + bool "Panic on Oops" if EXPERT + default n + help + Say Y here to enable the kernel to panic when it oopses. This + has the same effect as setting oops=panic on the kernel command + line. + + This feature is useful to ensure that the kernel does not do + anything erroneous after an oops which could result in data + corruption or other issues. + + Say N if unsure. + +config PANIC_ON_OOPS_VALUE + int + range 0 1 + default 0 if !PANIC_ON_OOPS + default 1 if PANIC_ON_OOPS + config DETECT_HUNG_TASK bool "Detect Hung Tasks" depends on DEBUG_KERNEL -- cgit v0.10.2 From 62be73eafaa045d3233337303fb140f7f8a61135 Mon Sep 17 00:00:00 2001 From: Seiji Aguchi Date: Tue, 15 May 2012 17:35:09 -0400 Subject: kdump: Execute kmsg_dump(KMSG_DUMP_PANIC) after smp_send_stop() This patch moves kmsg_dump(KMSG_DUMP_PANIC) below smp_send_stop(), to serialize the crash-logging process via smp_send_stop() and to thus retrieve a more stable crash image of all CPUs stopped. Signed-off-by: Seiji Aguchi Acked-by: Don Zickus Cc: dle-develop@lists.sourceforge.net Cc: Satoru Moriya Cc: Tony Luck Cc: a.p.zijlstra@chello.nl Link: http://lkml.kernel.org/r/5C4C569E8A4B9B42A84A977CF070A35B2E4D7A5CE2@USINDEVS01.corp.hds.com Signed-off-by: Ingo Molnar diff --git a/kernel/panic.c b/kernel/panic.c index b6215b7..d2a5f4e 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -108,8 +108,6 @@ void panic(const char *fmt, ...) */ crash_kexec(NULL); - kmsg_dump(KMSG_DUMP_PANIC); - /* * Note smp_send_stop is the usual smp shutdown function, which * unfortunately means it may not be hardened to work in a panic @@ -117,6 +115,8 @@ void panic(const char *fmt, ...) */ smp_send_stop(); + kmsg_dump(KMSG_DUMP_PANIC); + atomic_notifier_call_chain(&panic_notifier_list, 0, buf); bust_spinlocks(0); -- cgit v0.10.2 From 936c163ab260b83b10d434715bf6bcd43b99d620 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 13:03:20 +0900 Subject: sh: arch/sh/kernel/process.c needs asm/fpu.h for unlazy_fpu(). Linus tried to fix up sh fallout from the x86 fpu state cleanup merge and failed. Add the missing include to get it building again. CC arch/sh/kernel/process.o arch/sh/kernel/process.c: In function 'arch_dup_task_struct': arch/sh/kernel/process.c:23:2: error: implicit declaration of function 'unlazy_fpu' Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 9b7a459..055d91b 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -4,6 +4,7 @@ #include #include #include +#include struct kmem_cache *task_xstate_cachep = NULL; unsigned int xstate_size; -- cgit v0.10.2 From 3a9485da969c1c23400430470db17c819ef51d7b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 May 2012 15:07:47 +0900 Subject: sh64: Fix up fallout from generic init_task conversion. In the generic init_task migration sh64 silently lost its fake_swapper_regs definition, resulting in link errors. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 4264583..602545b 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -33,6 +33,7 @@ #include struct task_struct *last_task_used_math = NULL; +struct pt_regs fake_swapper_regs = { 0, }; void show_regs(struct pt_regs *regs) { -- cgit v0.10.2 From 2e5ad6b9c45d43cc4e7b8ac5ded1c55a7c4a3893 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 23 May 2012 12:53:11 -0400 Subject: xen/hvc: Collapse error logic. All of the error paths are doing the same logic. In which case we might as well collapse them in one path. CC: stable@kernel.org Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index d3d91da..afc7fc2 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -216,22 +216,16 @@ static int xen_hvm_console_init(void) return 0; r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); - if (r < 0) { - kfree(info); - return -ENODEV; - } + if (r < 0) + goto err; info->evtchn = v; hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); - if (r < 0) { - kfree(info); - return -ENODEV; - } + if (r < 0) + goto err; mfn = v; info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE); - if (info->intf == NULL) { - kfree(info); - return -ENODEV; - } + if (info->intf == NULL) + goto err; info->vtermno = HVC_COOKIE; spin_lock(&xencons_lock); @@ -239,6 +233,9 @@ static int xen_hvm_console_init(void) spin_unlock(&xencons_lock); return 0; +err: + kfree(info); + return -ENODEV; } static int xen_pv_console_init(void) -- cgit v0.10.2 From a32c88b9386ce3df87f28dd46bdc3776cd6edf75 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 23 May 2012 12:55:38 -0400 Subject: xen/hvc: Fix error cases around HVM_PARAM_CONSOLE_PFN We weren't resetting the parameter to be passed in to a known default. Nor were we checking the return value of hvm_get_parameter. CC: stable@kernel.org Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index afc7fc2..3277f0e 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -219,7 +219,8 @@ static int xen_hvm_console_init(void) if (r < 0) goto err; info->evtchn = v; - hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); + v = 0; + r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); if (r < 0) goto err; mfn = v; -- cgit v0.10.2 From 5842f5768599094758931b74190cdf93641a8e35 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 23 May 2012 12:56:59 -0400 Subject: xen/hvc: Check HVM_PARAM_CONSOLE_[EVTCHN|PFN] for correctness. We need to make sure that those parameters are setup to be correct. As such the value of 0 is deemed invalid and we find that we bail out. The hypervisor sets by default all of them to be zero and when the hypercall is done does a simple: a.value = d->arch.hvm_domain.params[a.index]; Which means that if the Xen toolstack forgot to setup the proper HVM_PARAM_CONSOLE_EVTCHN (or the PFN one), we would get the default value of 0 and use that. CC: stable@kernel.org Fixes-Oracle-Bug: 14091238 Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 3277f0e..944eaeb 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -214,14 +214,19 @@ static int xen_hvm_console_init(void) /* already configured */ if (info->intf != NULL) return 0; - + /* + * If the toolstack (or the hypervisor) hasn't set these values, the + * default value is 0. Even though mfn = 0 and evtchn = 0 are + * theoretically correct values, in practice they never are and they + * mean that a legacy toolstack hasn't initialized the pv console correctly. + */ r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); - if (r < 0) + if (r < 0 || v == 0) goto err; info->evtchn = v; v = 0; r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); - if (r < 0) + if (r < 0 || v == 0) goto err; mfn = v; info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE); -- cgit v0.10.2 From ec3d753c5f77ecce0f5d3b8ab603b54b4fd2a106 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 28 May 2012 11:01:44 +0900 Subject: sh: convert to kbuild asm-generic support. Straightforward change to get rid of all of the header wrapper stubs. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 7beb423..09d1e60 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -1,5 +1,34 @@ include include/asm-generic/Kbuild.asm +generic-y += bitsperlong.h +generic-y += cputime.h +generic-y += current.h +generic-y += div64.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += fcntl.h +generic-y += ioctl.h +generic-y += ipcbuf.h +generic-y += irq_regs.h +generic-y += local.h +generic-y += param.h +generic-y += parport.h +generic-y += percpu.h +generic-y += poll.h +generic-y += mman.h +generic-y += msgbuf.h +generic-y += resource.h +generic-y += sembuf.h +generic-y += serial.h +generic-y += shmbuf.h +generic-y += siginfo.h +generic-y += socket.h +generic-y += statfs.h +generic-y += termbits.h +generic-y += termios.h +generic-y += ucontext.h +generic-y += xor.h + header-y += cachectl.h header-y += cpu-features.h header-y += hw_breakpoint.h diff --git a/arch/sh/include/asm/bitsperlong.h b/arch/sh/include/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0..0000000 --- a/arch/sh/include/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/cputime.h b/arch/sh/include/asm/cputime.h deleted file mode 100644 index 6ca395d..0000000 --- a/arch/sh/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __SH_CPUTIME_H -#define __SH_CPUTIME_H - -#include - -#endif /* __SH_CPUTIME_H */ diff --git a/arch/sh/include/asm/current.h b/arch/sh/include/asm/current.h deleted file mode 100644 index 4c51401..0000000 --- a/arch/sh/include/asm/current.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/div64.h b/arch/sh/include/asm/div64.h deleted file mode 100644 index 6cd978c..0000000 --- a/arch/sh/include/asm/div64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/emergency-restart.h b/arch/sh/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c4..0000000 --- a/arch/sh/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/sh/include/asm/errno.h b/arch/sh/include/asm/errno.h deleted file mode 100644 index 51cf6f9..0000000 --- a/arch/sh/include/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH_ERRNO_H -#define __ASM_SH_ERRNO_H - -#include - -#endif /* __ASM_SH_ERRNO_H */ diff --git a/arch/sh/include/asm/fcntl.h b/arch/sh/include/asm/fcntl.h deleted file mode 100644 index 46ab12d..0000000 --- a/arch/sh/include/asm/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/ioctl.h b/arch/sh/include/asm/ioctl.h deleted file mode 100644 index b279fe0..0000000 --- a/arch/sh/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/ipcbuf.h b/arch/sh/include/asm/ipcbuf.h deleted file mode 100644 index 84c7e51..0000000 --- a/arch/sh/include/asm/ipcbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/irq_regs.h b/arch/sh/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b..0000000 --- a/arch/sh/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/local.h b/arch/sh/include/asm/local.h deleted file mode 100644 index 9ed9b9c..0000000 --- a/arch/sh/include/asm/local.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH_LOCAL_H -#define __ASM_SH_LOCAL_H - -#include - -#endif /* __ASM_SH_LOCAL_H */ - diff --git a/arch/sh/include/asm/mman.h b/arch/sh/include/asm/mman.h deleted file mode 100644 index 8eebf89..0000000 --- a/arch/sh/include/asm/mman.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/msgbuf.h b/arch/sh/include/asm/msgbuf.h deleted file mode 100644 index 809134c..0000000 --- a/arch/sh/include/asm/msgbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/param.h b/arch/sh/include/asm/param.h deleted file mode 100644 index 965d454..0000000 --- a/arch/sh/include/asm/param.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/parport.h b/arch/sh/include/asm/parport.h deleted file mode 100644 index cf252af..0000000 --- a/arch/sh/include/asm/parport.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/percpu.h b/arch/sh/include/asm/percpu.h deleted file mode 100644 index 4db4b39..0000000 --- a/arch/sh/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ARCH_SH_PERCPU -#define __ARCH_SH_PERCPU - -#include - -#endif /* __ARCH_SH_PERCPU */ diff --git a/arch/sh/include/asm/poll.h b/arch/sh/include/asm/poll.h deleted file mode 100644 index c98509d..0000000 --- a/arch/sh/include/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/resource.h b/arch/sh/include/asm/resource.h deleted file mode 100644 index 9c2499a..0000000 --- a/arch/sh/include/asm/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH_RESOURCE_H -#define __ASM_SH_RESOURCE_H - -#include - -#endif /* __ASM_SH_RESOURCE_H */ diff --git a/arch/sh/include/asm/sembuf.h b/arch/sh/include/asm/sembuf.h deleted file mode 100644 index 7673b83..0000000 --- a/arch/sh/include/asm/sembuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/serial.h b/arch/sh/include/asm/serial.h deleted file mode 100644 index a0cb0ca..0000000 --- a/arch/sh/include/asm/serial.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/shmbuf.h b/arch/sh/include/asm/shmbuf.h deleted file mode 100644 index 83c05fc..0000000 --- a/arch/sh/include/asm/shmbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/siginfo.h b/arch/sh/include/asm/siginfo.h deleted file mode 100644 index 813040e..0000000 --- a/arch/sh/include/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH_SIGINFO_H -#define __ASM_SH_SIGINFO_H - -#include - -#endif /* __ASM_SH_SIGINFO_H */ diff --git a/arch/sh/include/asm/socket.h b/arch/sh/include/asm/socket.h deleted file mode 100644 index 6b71384..0000000 --- a/arch/sh/include/asm/socket.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/statfs.h b/arch/sh/include/asm/statfs.h deleted file mode 100644 index 9202a02..0000000 --- a/arch/sh/include/asm/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH_STATFS_H -#define __ASM_SH_STATFS_H - -#include - -#endif /* __ASM_SH_STATFS_H */ diff --git a/arch/sh/include/asm/termbits.h b/arch/sh/include/asm/termbits.h deleted file mode 100644 index 3935b10..0000000 --- a/arch/sh/include/asm/termbits.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/termios.h b/arch/sh/include/asm/termios.h deleted file mode 100644 index 280d78a..0000000 --- a/arch/sh/include/asm/termios.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/ucontext.h b/arch/sh/include/asm/ucontext.h deleted file mode 100644 index 9bc07b9..0000000 --- a/arch/sh/include/asm/ucontext.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/xor.h b/arch/sh/include/asm/xor.h deleted file mode 100644 index c82eb12..0000000 --- a/arch/sh/include/asm/xor.h +++ /dev/null @@ -1 +0,0 @@ -#include -- cgit v0.10.2 From 5e152e6c4b0da84c66cad56597b42c4ecedb0448 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 23 May 2012 13:28:44 -0400 Subject: xen/events: Add WARN_ON when quick lookup found invalid type. All of the bind_XYZ_to_irq do a quick lookup to see if the event exists. And if it does, then the initialized IRQ number is returned instead of initializing a new IRQ number. This patch adds an extra logic to check that the type returned is proper one and that there is an IRQ handler setup for it. This patch has the benefit of being able to find drivers that are doing something naught. [v1: Enhanced based on Stefano's review] Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/xen/events.c b/drivers/xen/events.c index faae2f9..af8b8fb 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -827,6 +827,9 @@ int bind_evtchn_to_irq(unsigned int evtchn) handle_edge_irq, "event"); xen_irq_info_evtchn_init(irq, evtchn); + } else { + struct irq_info *info = info_for_irq(irq); + WARN_ON(info == NULL || info->type != IRQT_EVTCHN); } out: @@ -862,6 +865,9 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) xen_irq_info_ipi_init(cpu, irq, evtchn, ipi); bind_evtchn_to_cpu(evtchn, cpu); + } else { + struct irq_info *info = info_for_irq(irq); + WARN_ON(info == NULL || info->type != IRQT_IPI); } out: @@ -939,6 +945,9 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) xen_irq_info_virq_init(cpu, irq, evtchn, virq); bind_evtchn_to_cpu(evtchn, cpu); + } else { + struct irq_info *info = info_for_irq(irq); + WARN_ON(info == NULL || info->type != IRQT_VIRQ); } out: -- cgit v0.10.2 From 780dbcd0eedec6528d777b668019dabb36badf1a Mon Sep 17 00:00:00 2001 From: "Zhang, Yang Z" Date: Tue, 22 May 2012 08:40:16 +0000 Subject: xen/pci: Check for PCI bridge before using it. Some SR-IOV devices may use more than one bus number, but there is no real bridges because that have internal routing mechanism. So need to check whether the bridge is existing before using it. Signed-off-by: Yang Zhang Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c index b84bf0b..18fff88 100644 --- a/drivers/xen/pci.c +++ b/drivers/xen/pci.c @@ -59,7 +59,7 @@ static int xen_add_device(struct device *dev) #ifdef CONFIG_ACPI handle = DEVICE_ACPI_HANDLE(&pci_dev->dev); - if (!handle) + if (!handle && pci_dev->bus->bridge) handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge); #ifdef CONFIG_PCI_IOV if (!handle && pci_dev->is_virtfn) -- cgit v0.10.2 From 58b7b53a36b0be8081fbfc91aeea24b83c20ca1b Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 29 May 2012 12:36:43 -0400 Subject: xen/balloon: Subtract from xen_released_pages the count that is populated. We did not take into account that xen_released_pages would be used outside the initial E820 parsing code. As such we would did not subtract from xen_released_pages the count of pages that we had populated back (instead we just did a simple extra_pages = released - populated). The balloon driver uses xen_released_pages to set the initial current_pages count. If this is wrong (too low) then when a new (higher) target is set, the balloon driver will request too many pages from Xen." This fixes errors such as: (XEN) memory.c:133:d0 Could not allocate order=0 extent: id=0 memflags=0 (51 of 512) during bootup and free_memory : 0 where the free_memory should be 128. Acked-by: David Vrabel [v1: Per David's review made the git commit better] Signed-off-by: Konrad Rzeszutek Wilk diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 3ebba07..a4790bf 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -371,7 +371,8 @@ char * __init xen_memory_setup(void) populated = xen_populate_chunk(map, memmap.nr_entries, max_pfn, &last_pfn, xen_released_pages); - extra_pages += (xen_released_pages - populated); + xen_released_pages -= populated; + extra_pages += xen_released_pages; if (last_pfn > max_pfn) { max_pfn = min(MAX_DOMAIN_PAGES, last_pfn); -- cgit v0.10.2 From 121daad8fd1dce63076fa55aaedd5dc3f981b334 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Thu, 31 May 2012 20:53:08 +1000 Subject: hwrng: atmel-rng - fix race condition leading to repeated bits Data valid gets cleared by reading the ISR (status register) and NOT from reading ODATA (data register). A new data word can become available between checking ISR and reading ODATA, causing us to reuse the same data word next time atmel_trng_read() gets called, if that happens before the following data word is ready. With this fixed, rngtest no longer complains of 'Continous run' errors. Before: rngtest -c 1000 < /dev/hwrng rngtest 3 Copyright (c) 2004 by Henrique de Moraes Holschuh This is free software; see the source for copying conditions. There is NO warr. rngtest: starting FIPS tests... rngtest: bits received from input: 20000032 rngtest: FIPS 140-2 successes: 923 rngtest: FIPS 140-2 failures: 77 rngtest: FIPS 140-2(2001-10-10) Monobit: 0 rngtest: FIPS 140-2(2001-10-10) Poker: 0 rngtest: FIPS 140-2(2001-10-10) Runs: 1 rngtest: FIPS 140-2(2001-10-10) Long run: 0 rngtest: FIPS 140-2(2001-10-10) Continuous run: 76 rngtest: input channel speed: (min=721.402; avg=46003.510; max=49321.338)Kibitss rngtest: FIPS tests speed: (min=11.442; avg=12.714; max=12.801)Mibits/s rngtest: Program run time: 1931860 microseconds After: rngtest -c 1000 < /dev/hwrng rngtest 3 Copyright (c) 2004 by Henrique de Moraes Holschuh This is free software; see the source for copying conditions. There is NO warr. rngtest: starting FIPS tests... rngtest: bits received from input: 20000032 rngtest: FIPS 140-2 successes: 1000 rngtest: FIPS 140-2 failures: 0 rngtest: FIPS 140-2(2001-10-10) Monobit: 0 rngtest: FIPS 140-2(2001-10-10) Poker: 0 rngtest: FIPS 140-2(2001-10-10) Runs: 0 rngtest: FIPS 140-2(2001-10-10) Long run: 0 rngtest: FIPS 140-2(2001-10-10) Continuous run: 0 rngtest: input channel speed: (min=777.518; avg=36988.482; max=43115.342)Kibitss rngtest: FIPS tests speed: (min=11.951; avg=12.715; max=12.887)Mibits/s rngtest: Program run time: 2035543 microseconds Cc: stable@vger.kernel.org Signed-off-by: Peter Korsgaard Reported-by: George Pontis Acked-by: Nicolas Ferre Signed-off-by: Herbert Xu diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index f518b99..6289f0e 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -36,6 +36,13 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, /* data ready? */ if (readl(trng->base + TRNG_ODATA) & 1) { *data = readl(trng->base + TRNG_ODATA); + /* + ensure data ready is only set again AFTER the next data + word is ready in case it got set between checking ISR + and reading ODATA, so we don't risk re-reading the + same word + */ + readl(trng->base + TRNG_ISR); return 4; } else return 0; -- cgit v0.10.2 From 7c8d51848a88aafdb68f42b6b650c83485ea2f84 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 30 May 2012 01:43:08 +0200 Subject: crypto: aesni-intel - fix unaligned cbc decrypt for x86-32 The 32 bit variant of cbc(aes) decrypt is using instructions requiring 128 bit aligned memory locations but fails to ensure this constraint in the code. Fix this by loading the data into intermediate registers with load unaligned instructions. This fixes reported general protection faults related to aesni. References: https://bugzilla.kernel.org/show_bug.cgi?id=43223 Reported-by: Daniel Cc: stable@kernel.org [v2.6.39+] Signed-off-by: Mathias Krause Signed-off-by: Herbert Xu diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index be6d9e3..3470624 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -2460,10 +2460,12 @@ ENTRY(aesni_cbc_dec) pxor IN3, STATE4 movaps IN4, IV #else - pxor (INP), STATE2 - pxor 0x10(INP), STATE3 pxor IN1, STATE4 movaps IN2, IV + movups (INP), IN1 + pxor IN1, STATE2 + movups 0x10(INP), IN2 + pxor IN2, STATE3 #endif movups STATE1, (OUTP) movups STATE2, 0x10(OUTP) -- cgit v0.10.2 From 5e626254206a709c6e937f3dda69bf26c7344f6f Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 29 May 2012 13:07:31 +0200 Subject: xen/setup: filter APERFMPERF cpuid feature out Xen PV kernels allow access to the APERF/MPERF registers to read the effective frequency. Access to the MSRs is however redirected to the currently scheduled physical CPU, making consecutive read and compares unreliable. In addition each rdmsr traps into the hypervisor. So to avoid bogus readouts and expensive traps, disable the kernel internal feature flag for APERF/MPERF if running under Xen. This will a) remove the aperfmperf flag from /proc/cpuinfo b) not mislead the power scheduler (arch/x86/kernel/cpu/sched.c) to use the feature to improve scheduling (by default disabled) c) not mislead the cpufreq driver to use the MSRs This does not cover userland programs which access the MSRs via the device file interface, but this will be addressed separately. Signed-off-by: Andre Przywara Cc: stable@vger.kernel.org # v3.0+ Signed-off-by: Konrad Rzeszutek Wilk diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index d1f9a04..272ebd0 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -208,6 +208,9 @@ static void __init xen_banner(void) xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); } +#define CPUID_THERM_POWER_LEAF 6 +#define APERFMPERF_PRESENT 0 + static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; @@ -241,6 +244,11 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, *dx = cpuid_leaf5_edx_val; return; + case CPUID_THERM_POWER_LEAF: + /* Disabling APERFMPERF for kernel usage */ + maskecx = ~(1 << APERFMPERF_PRESENT); + break; + case 0xb: /* Suppress extended topology stuff */ maskebx = 0; -- cgit v0.10.2 From b3b02ae5865c2dcd506322e0fc6def59a042e72f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 31 May 2012 15:26:38 -0400 Subject: NFSv4.1: Fix a request leak on the back channel If the call to svc_process_common() fails, then the request needs to be freed before we can exit bc_svc_process. Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 017c011..074df5a 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1377,7 +1377,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, sizeof(req->rq_snd_buf)); return bc_send(req); } else { - /* Nothing to do to drop request */ + /* drop request */ + xprt_free_bc_request(req); return 0; } } -- cgit v0.10.2 From bfaa25f33425db16a942b7c71e396a47581c646d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 23 May 2012 16:30:53 -0600 Subject: regmap: clean up debugfs if regmap_init fails If debugfs isn't cleaned up, stale files will be left in the filesystem which will cause an OOPS when accessed the first time, and hang the accessing application when accessed again, presumably due to some lock being left held. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 0bcda48..2aa076e 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -368,7 +368,7 @@ struct regmap *regmap_init(struct device *dev, ret = regcache_init(map, config); if (ret < 0) - goto err_free_workbuf; + goto err_debugfs; /* Add a devres resource for dev_get_regmap() */ m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); @@ -383,7 +383,8 @@ struct regmap *regmap_init(struct device *dev, err_cache: regcache_exit(map); -err_free_workbuf: +err_debugfs: + regmap_debugfs_exit(map); kfree(map->work_buf); err_map: kfree(map); -- cgit v0.10.2 From 5494a98f451d59f6c05f3f688510e0832445f661 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 31 May 2012 21:10:30 -0300 Subject: regmap: Fix the size calculation for map->format.buf_size The word to be transmitted/received via regmap is composed by the following parts: config->reg_bits config->val_bits config->pad_bits ,so the total size should be calculated by summing up the number of bits of each element and using a DIV_ROUND_UP to return the number of bytes. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 2aa076e..04b4802 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -246,11 +246,11 @@ struct regmap *regmap_init(struct device *dev, map->lock = regmap_lock_mutex; map->unlock = regmap_unlock_mutex; } - map->format.buf_size = (config->reg_bits + config->val_bits) / 8; map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); map->format.pad_bytes = config->pad_bits / 8; map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); - map->format.buf_size += map->format.pad_bytes; + map->format.buf_size = DIV_ROUND_UP(config->reg_bits + + config->val_bits + config->pad_bits, 8); map->reg_shift = config->pad_bits % 8; if (config->reg_stride) map->reg_stride = config->reg_stride; -- cgit v0.10.2 From 617caccebe451716df21c069b079d5936ed7b0f3 Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 23 May 2012 17:45:09 +0530 Subject: can: c_can: fix "BUG! echo_skb is occupied!" during transmit This patch fixes an issue with transmit routine, which causes "can_put_echo_skb: BUG! echo_skb is occupied!" message when using "cansequence -p" on D_CAN controller. In c_can driver, while transmitting packets tx_echo flag holds the no of can frames put for transmission into the hardware. As the comment above c_can_do_tx() indicates, if we find any packet which is not transmitted then we should stop looking for more. In the current implementation this is not taken care of causing the said message. Also, fix the condition used to find if the packet is transmitted or not. Current code skips the first tx message object and ends up checking one extra invalid object. While at it, fix the comment on top of c_can_do_tx() to use the terminology "packet" instead of "package" since it is more standard. Cc: stable@kernel.org # 2.6.39+ Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 536bda0..9ac28df 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -686,7 +686,7 @@ static int c_can_get_berr_counter(const struct net_device *dev, * * We iterate from priv->tx_echo to priv->tx_next and check if the * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted package, stop looking for more. + * If we discover a not yet transmitted packet, stop looking for more. */ static void c_can_do_tx(struct net_device *dev) { @@ -698,7 +698,7 @@ static void c_can_do_tx(struct net_device *dev) for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { msg_obj_no = get_tx_echo_msg_obj(priv); val = c_can_read_reg32(priv, &priv->regs->txrqst1); - if (!(val & (1 << msg_obj_no))) { + if (!(val & (1 << (msg_obj_no - 1)))) { can_get_echo_skb(dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); stats->tx_bytes += priv->read_reg(priv, @@ -706,6 +706,8 @@ static void c_can_do_tx(struct net_device *dev) & IF_MCONT_DLC_MASK; stats->tx_packets++; c_can_inval_msg_object(dev, 0, msg_obj_no); + } else { + break; } } -- cgit v0.10.2 From 148c87c89e1a8863d3d965179f3ab1a06490569e Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 23 May 2012 17:45:10 +0530 Subject: can: c_can: fix an interrupt thrash issue with c_can driver This patch fixes an interrupt thrash issue with c_can driver. In c_can_isr() function interrupts are disabled and enabled only in c_can_poll() function. c_can_isr() & c_can_poll() both read the irqstatus flag. However, irqstatus is always read as 0 in c_can_poll() because all C_CAN interrupts are disabled in c_can_isr(). This causes all interrupts to be re-enabled in c_can_poll() which in turn causes another interrupt since the event is not really handled. This keeps happening causing a flood of interrupts. To fix this, read the irqstatus register in isr and use the same cached value in the poll function. Cc: stable@kernel.org # 2.6.39+ Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 9ac28df..fa01621 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -952,7 +952,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + irqstatus = priv->irqstatus; if (!irqstatus) goto end; @@ -1030,12 +1030,11 @@ end: static irqreturn_t c_can_isr(int irq, void *dev_id) { - u16 irqstatus; struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); - if (!irqstatus) + priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + if (!priv->irqstatus) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 9b7fbef..5f32d34 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -76,6 +76,7 @@ struct c_can_priv { unsigned int tx_next; unsigned int tx_echo; void *priv; /* for board-specific data */ + u16 irqstatus; }; struct net_device *alloc_c_can_dev(void); -- cgit v0.10.2 From f461f27a4436dbe691908fe08b867ef888848cc3 Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 23 May 2012 17:45:11 +0530 Subject: can: c_can: fix race condition in c_can_open() Fix the issue of C_CAN interrupts getting disabled forever when canconfig utility is used multiple times. According to NAPI usage we disable all the hardware interrupts in ISR and re-enable them in poll(). Current implementation calls napi_enable() after hardware interrupts are enabled. If we get any interrupts between these two steps then we do not process those interrupts because napi is not enabled. Mostly these interrupts come because of STATUS is not 0x7 or ERROR interrupts. If napi_enable() happens before HW interrupts enabled then c_can_poll() function will be called eventual re-enabling. This patch moves the napi_enable() call before interrupts enabled. Cc: stable@kernel.org # 2.6.39+ Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index fa01621..8dc84d6 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -1064,10 +1064,11 @@ static int c_can_open(struct net_device *dev) goto exit_irq_fail; } + napi_enable(&priv->napi); + /* start the c_can controller */ c_can_start(dev); - napi_enable(&priv->napi); netif_start_queue(dev); return 0; -- cgit v0.10.2 From dc605dbdb8dd152448ccb8d4c4d5bd9439965a20 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 May 2012 13:25:55 -0700 Subject: can: cc770: Fix likely misuse of | for & Using | with a constant is always true. Likely this should have be &. Signed-off-by: Joe Perches Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index 53115ee..688371c 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -154,7 +154,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev, struct cc770_platform_data *pdata = pdev->dev.platform_data; priv->can.clock.freq = pdata->osc_freq; - if (priv->cpu_interface | CPUIF_DSC) + if (priv->cpu_interface & CPUIF_DSC) priv->can.clock.freq /= 2; priv->clkout = pdata->cor; priv->bus_config = pdata->bcr; -- cgit v0.10.2 From 1253585d7cb12a365e9effaf2f0c7991d2404996 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Mon, 21 May 2012 10:59:02 +0800 Subject: pinctrl: sirf: mark of_device_id match table as __devinitconst Signed-off-by: Barry Song Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index ba15b1a..e9f8e7d 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1184,7 +1184,7 @@ out_no_gpio_remap: return ret; } -static const struct of_device_id pinmux_ids[] = { +static const struct of_device_id pinmux_ids[] __devinitconst = { { .compatible = "sirf,prima2-gpio-pinmux" }, {} }; -- cgit v0.10.2 From bc66468cee4c23856b2e51d711e62e4ef773001a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 23 May 2012 00:20:17 +0200 Subject: pinctrl: fix a minor harmless typo The way the for_each_maps() macro is currently used, using "i" instead of "_i_" works and is harmless. Still, this is a bug, that can trigger any time, if the code around that macro changes. Better fix it now. Acked-by: Stephen Warren Signed-off-by: Guennadi Liakhovetski Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index c3b331b..0cc053a 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -61,7 +61,7 @@ static LIST_HEAD(pinctrl_maps); list_for_each_entry(_maps_node_, &pinctrl_maps, node) \ for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \ _i_ < _maps_node_->num_maps; \ - i++, _map_ = &_maps_node_->maps[_i_]) + _i_++, _map_ = &_maps_node_->maps[_i_]) /** * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support -- cgit v0.10.2 From 0e9a126e95748e8283488818d98ae5bcb7b84515 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 23 May 2012 16:45:09 +0300 Subject: OMAPDSS: fix build when DEBUG_FS or DSS_DEBUG_SUPPORT disabled If CONFIG_DEBUG_FS or CONFIG_OMAP2_DSS_DEBUG_SUPPORT is disabled, the build fails: drivers/video/omap2/dss/core.c:197:50: error: static declaration of 'dss_debugfs_create_file' follows non-static declaration drivers/video/omap2/dss/dss.h:166:5: note: previous declaration of 'dss_debugfs_create_file' was here This patch fixes the dummy dss_debugfs_create_file() so that the driver builds. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 72ded9c..5066eee 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -194,8 +194,7 @@ static inline int dss_initialize_debugfs(void) static inline void dss_uninitialize_debugfs(void) { } -static inline int dss_debugfs_create_file(const char *name, - void (*write)(struct seq_file *)) +int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) { return 0; } -- cgit v0.10.2 From d1700f9258552294300083eb62f83262f21ae1db Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 23 May 2012 16:56:09 +0300 Subject: OMAPDSS: Taal: fix compilation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a warning: drivers/video/omap2/displays/panel-taal.c: In function ‘taal_num_errors_show’: drivers/video/omap2/displays/panel-taal.c:529: warning: ‘errors’ may be used uninitialized in this function Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 2ce9992..901576e 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -526,7 +526,7 @@ static ssize_t taal_num_errors_show(struct device *dev, { struct omap_dss_device *dssdev = to_dss_device(dev); struct taal_data *td = dev_get_drvdata(&dssdev->dev); - u8 errors; + u8 errors = 0; int r; mutex_lock(&td->lock); -- cgit v0.10.2 From 5025ce070e2dff80bcf015a34a82edcf78229287 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 23 May 2012 17:02:26 +0300 Subject: OMAPDSS: fix bogus WARN_ON in dss_runtime_put() pm_runtime_put_sync() in dss_runtime_put() returns -EBUSY when any child of dss is still enabled. This happens, for example, when a display output is enabled and one dumps the clocks via debugfs. This causes dss_runtime_get & put to be called. While I couldn't find anything about this in the documentation and it wasn't immediately clear from runtime_pm code, it looks to me that pm_runtime_put_sync() returns -EBUSY to inform that things went fine, but the device could not be turned off as there are still child devices that are enabled. This is not a problem. This patch skips the WARN_ON if pm_runtime_put_sync() returns -EBUSY. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 6ea1ff1..7706323 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -731,7 +731,7 @@ static void dss_runtime_put(void) DSSDBG("dss_runtime_put\n"); r = pm_runtime_put_sync(&dss.pdev->dev); - WARN_ON(r < 0); + WARN_ON(r < 0 && r != -EBUSY); } /* DEBUGFS */ -- cgit v0.10.2 From c71c8fd4daa342ba714090586a55fc5db7eaa275 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 21 May 2012 20:55:40 +0800 Subject: regulator: palmas: Fix wrong kfree calls The devm_kzalloc function eliminates the need for manual resource releasing and simplify error handling. Resources allocated by devm_* are freed automatically on driver detach. Thus adding kfree calls here will introduce double free bug. The memory of desc array and the pointers to the rdev[] are allocated by devm_kzalloc call for struct palmas_pmic. struct palmas_pmic { struct palmas *palmas; struct device *dev; struct regulator_desc desc[PALMAS_NUM_REGS]; struct regulator_dev *rdev[PALMAS_NUM_REGS]; struct mutex mutex; int smps123; int smps457; int range[PALMAS_REG_SMPS10]; }; Which means we should not call kfree for pmic->rdev and pmic->desc. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index c4435f6..9b7ca90 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -775,9 +775,6 @@ static __devinit int palmas_probe(struct platform_device *pdev) err_unregister_regulator: while (--id >= 0) regulator_unregister(pmic->rdev[id]); - kfree(pmic->rdev); - kfree(pmic->desc); - kfree(pmic); return ret; } @@ -788,10 +785,6 @@ static int __devexit palmas_remove(struct platform_device *pdev) for (id = 0; id < PALMAS_NUM_REGS; id++) regulator_unregister(pmic->rdev[id]); - - kfree(pmic->rdev); - kfree(pmic->desc); - kfree(pmic); return 0; } -- cgit v0.10.2 From 0c09d3150902d8ca7e763d508ac1a93701b21321 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 May 2012 09:08:08 +0800 Subject: regulator: anatop: Use correct __devexit_p annotation __devexit functions are discarded when CONFIG_HOTPLUG is not set, so the symbol needs to be referenced carefully. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 3660bac..e82e7ea 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -224,7 +224,7 @@ static struct platform_driver anatop_regulator_driver = { .of_match_table = of_anatop_regulator_match_tbl, }, .probe = anatop_regulator_probe, - .remove = anatop_regulator_remove, + .remove = __devexit_p(anatop_regulator_remove), }; static int __init anatop_regulator_init(void) -- cgit v0.10.2 From 7d4be2f5ad223942577c2319153b86592f3da5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Sun, 3 Jun 2012 21:30:33 +0200 Subject: regulator: gpio-regulator: do not pass drvdata pointer as reference Commit c172708d38a4 (regulator: core: Use a struct to pass in regulator runtime configuration) added the drvdata pointer only per reference to the new config array in the gpio-regulator. Signed-off-by: Heiko Stuebner Acked-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 9997d7a..ebe2b5c 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -286,7 +286,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) cfg.dev = &pdev->dev; cfg.init_data = config->init_data; - cfg.driver_data = &drvdata; + cfg.driver_data = drvdata; drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { -- cgit v0.10.2 From 00926369b745fb0c1e5c27cec35f6adc9752f2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Sun, 3 Jun 2012 21:31:09 +0200 Subject: regulator: gpio-regulator: Fix finding of smallest value Commit 4dbd8f63f07a (regulator: gpio-regulator: Set the smallest voltage/current in the specified range) forgot to set the newly introduced best_val. Therefore it stayed always at INT_MAX thus breaking the setting of the voltage. Included is also an init value for target, as warnings about a possibly uninitialised target started appearing with this fix. Signed-off-by: Heiko Stuebner Acked-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index ebe2b5c..2c38bea 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -104,13 +104,15 @@ static int gpio_regulator_set_value(struct regulator_dev *dev, int min, int max) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); - int ptr, target, state, best_val = INT_MAX; + int ptr, target = 0, state, best_val = INT_MAX; for (ptr = 0; ptr < data->nr_states; ptr++) if (data->states[ptr].value < best_val && data->states[ptr].value >= min && - data->states[ptr].value <= max) + data->states[ptr].value <= max) { target = data->states[ptr].gpios; + best_val = data->states[ptr].value; + } if (best_val == INT_MAX) return -EINVAL; -- cgit v0.10.2 From b0e4d7bf8b5704904a5d138d81a8ec8b7145767f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Sun, 3 Jun 2012 21:32:05 +0200 Subject: regulator: gpio-regulator: populate selector from set_voltage This was missing until now and the underlying _regulator_do_set_voltage is using this value when calling list_voltage. Signed-off-by: Heiko Stuebner Acked-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 2c38bea..242851a 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -101,7 +101,7 @@ static int gpio_regulator_get_value(struct regulator_dev *dev) } static int gpio_regulator_set_value(struct regulator_dev *dev, - int min, int max) + int min, int max, unsigned *selector) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); int ptr, target = 0, state, best_val = INT_MAX; @@ -112,6 +112,8 @@ static int gpio_regulator_set_value(struct regulator_dev *dev, data->states[ptr].value <= max) { target = data->states[ptr].gpios; best_val = data->states[ptr].value; + if (selector) + *selector = ptr; } if (best_val == INT_MAX) @@ -130,7 +132,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV, unsigned *selector) { - return gpio_regulator_set_value(dev, min_uV, max_uV); + return gpio_regulator_set_value(dev, min_uV, max_uV, selector); } static int gpio_regulator_list_voltage(struct regulator_dev *dev, @@ -147,7 +149,7 @@ static int gpio_regulator_list_voltage(struct regulator_dev *dev, static int gpio_regulator_set_current_limit(struct regulator_dev *dev, int min_uA, int max_uA) { - return gpio_regulator_set_value(dev, min_uA, max_uA); + return gpio_regulator_set_value(dev, min_uA, max_uA, NULL); } static struct regulator_ops gpio_regulator_voltage_ops = { -- cgit v0.10.2 From d298caae9a920e1745599ddd4a19073d9a033df0 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 1 Jun 2012 18:03:00 +0100 Subject: ASoC: dapm: Fix connected widget capture path query. Make sure we check the correct path for capture. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 90ee77d..b47fe75 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -954,7 +954,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, if (stream == SNDRV_PCM_STREAM_PLAYBACK) paths = is_connected_output_ep(dai->playback_widget, list); else - paths = is_connected_input_ep(dai->playback_widget, list); + paths = is_connected_input_ep(dai->capture_widget, list); trace_snd_soc_dapm_connected(paths, stream); dapm_clear_walk(&card->dapm); -- cgit v0.10.2 From a1c85ec03738421668becb973f35fe6e1501c6e6 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Mon, 4 Jun 2012 09:42:54 +0800 Subject: ASoC: imx-audmux: add pinctrl support Signed-off-by: Richard Zhao Acked-by: Dong Aisheng Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index f237003..0803274 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "imx-audmux.h" @@ -249,6 +250,7 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); static int __devinit imx_audmux_probe(struct platform_device *pdev) { struct resource *res; + struct pinctrl *pinctrl; const struct of_device_id *of_id = of_match_device(imx_audmux_dt_ids, &pdev->dev); @@ -257,6 +259,12 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev) if (!audmux_base) return -EADDRNOTAVAIL; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(&pdev->dev, "setup pinctrl failed!"); + return PTR_ERR(pinctrl); + } + audmux_clk = clk_get(&pdev->dev, "audmux"); if (IS_ERR(audmux_clk)) { dev_dbg(&pdev->dev, "cannot get clock: %ld\n", -- cgit v0.10.2 From 2e063c305a3da896ec3db99e66891411d0e38820 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 4 Jun 2012 13:36:34 +0530 Subject: OMAPDSS: DSI: Fix bug when calculating LP command interleaving parameters In function dsi_compute_interleave_lp(), the escape clock/LP clock time period is calculated incorrectly. The escape clock/LP clock is calculated as: LP Clock(Hz) = DSI_FCLK(Hz) / lp_clk_div Since we are calculating the time period of LP clock, the LP clock divider should be multiplied with the time period of DSI_FCLK. Calculating incorrect value of txclkesc results in incorrect calculation of LP interleaving parameters, it also creates a possibility of a divide by zero error. Reported-by: Sureshkumar Manimuthu Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ec363d8..ca8382d 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3724,7 +3724,7 @@ static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, /* CLKIN4DDR = 16 * TXBYTECLKHS */ tlp_avail = thsbyte_clk * (blank - trans_lp); - ttxclkesc = tdsi_fclk / lp_clk_div; + ttxclkesc = tdsi_fclk * lp_clk_div; lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc - 26) / 16; -- cgit v0.10.2 From 4d5a0565cebf12c2ef854e4ac1961f13a710a950 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 30 Apr 2012 11:17:25 +0200 Subject: Btrfs: remove call to btrfs_header_nritems with no effect This is a leftover from cleanup patch 559af821. Before the cleanup, btrfs_header_nritems was called inside an if condition. As it has no side effects we need to preserve here, it should simply be dropped. Signed-off-by: Jan Schmidt diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index d7a96cf..836e4e0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1650,8 +1650,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, BTRFS_NODEPTRS_PER_BLOCK(root) / 4) return 0; - btrfs_header_nritems(mid); - left = read_node_slot(root, parent, pslot - 1); if (left) { btrfs_tree_lock(left); @@ -1681,7 +1679,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, wret = push_node_left(trans, root, left, mid, 1); if (wret < 0) ret = wret; - btrfs_header_nritems(mid); } /* -- cgit v0.10.2 From bec4596b4e6770c7037f21f6bd27567b152dc0d6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 4 Jun 2012 00:18:19 +0000 Subject: drop_monitor: dont sleep in atomic context drop_monitor calls several sleeping functions while in atomic context. BUG: sleeping function called from invalid context at mm/slub.c:943 in_atomic(): 1, irqs_disabled(): 0, pid: 2103, name: kworker/0:2 Pid: 2103, comm: kworker/0:2 Not tainted 3.5.0-rc1+ #55 Call Trace: [] __might_sleep+0xca/0xf0 [] kmem_cache_alloc_node+0x1b3/0x1c0 [] ? queue_delayed_work_on+0x11c/0x130 [] __alloc_skb+0x4b/0x230 [] ? reset_per_cpu_data+0x160/0x160 [drop_monitor] [] reset_per_cpu_data+0x2f/0x160 [drop_monitor] [] send_dm_alert+0x4b/0xb0 [drop_monitor] [] process_one_work+0x130/0x4c0 [] worker_thread+0x159/0x360 [] ? manage_workers.isra.27+0x240/0x240 [] kthread+0x93/0xa0 [] kernel_thread_helper+0x4/0x10 [] ? kthread_freezable_should_stop+0x80/0x80 [] ? gs_change+0xb/0xb Rework the logic to call the sleeping functions in right context. Use standard timer/workqueue api to let system chose any cpu to perform the allocation and netlink send. Also avoid a loop if reset_per_cpu_data() cannot allocate memory : use mod_timer() to wait 1/10 second before next try. Signed-off-by: Eric Dumazet Cc: Neil Horman Reviewed-by: Neil Horman Signed-off-by: David S. Miller diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index ea5fb9f..d23b668 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -36,9 +36,6 @@ #define TRACE_ON 1 #define TRACE_OFF 0 -static void send_dm_alert(struct work_struct *unused); - - /* * Globals, our netlink socket pointer * and the work handle that will send up @@ -48,11 +45,10 @@ static int trace_state = TRACE_OFF; static DEFINE_MUTEX(trace_state_mutex); struct per_cpu_dm_data { - struct work_struct dm_alert_work; - struct sk_buff __rcu *skb; - atomic_t dm_hit_count; - struct timer_list send_timer; - int cpu; + spinlock_t lock; + struct sk_buff *skb; + struct work_struct dm_alert_work; + struct timer_list send_timer; }; struct dm_hw_stat_delta { @@ -78,13 +74,13 @@ static int dm_delay = 1; static unsigned long dm_hw_check_delta = 2*HZ; static LIST_HEAD(hw_stats_list); -static void reset_per_cpu_data(struct per_cpu_dm_data *data) +static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; struct net_dm_alert_msg *msg; struct nlattr *nla; struct sk_buff *skb; - struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1); + unsigned long flags; al = sizeof(struct net_dm_alert_msg); al += dm_hit_limit * sizeof(struct net_dm_drop_point); @@ -99,65 +95,40 @@ static void reset_per_cpu_data(struct per_cpu_dm_data *data) sizeof(struct net_dm_alert_msg)); msg = nla_data(nla); memset(msg, 0, al); - } else - schedule_work_on(data->cpu, &data->dm_alert_work); - - /* - * Don't need to lock this, since we are guaranteed to only - * run this on a single cpu at a time. - * Note also that we only update data->skb if the old and new skb - * pointers don't match. This ensures that we don't continually call - * synchornize_rcu if we repeatedly fail to alloc a new netlink message. - */ - if (skb != oskb) { - rcu_assign_pointer(data->skb, skb); - - synchronize_rcu(); - - atomic_set(&data->dm_hit_count, dm_hit_limit); + } else { + mod_timer(&data->send_timer, jiffies + HZ / 10); } + spin_lock_irqsave(&data->lock, flags); + swap(data->skb, skb); + spin_unlock_irqrestore(&data->lock, flags); + + return skb; } -static void send_dm_alert(struct work_struct *unused) +static void send_dm_alert(struct work_struct *work) { struct sk_buff *skb; - struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); + struct per_cpu_dm_data *data; - WARN_ON_ONCE(data->cpu != smp_processor_id()); + data = container_of(work, struct per_cpu_dm_data, dm_alert_work); - /* - * Grab the skb we're about to send - */ - skb = rcu_dereference_protected(data->skb, 1); - - /* - * Replace it with a new one - */ - reset_per_cpu_data(data); + skb = reset_per_cpu_data(data); - /* - * Ship it! - */ if (skb) genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); - - put_cpu_var(dm_cpu_data); } /* * This is the timer function to delay the sending of an alert * in the event that more drops will arrive during the - * hysteresis period. Note that it operates under the timer interrupt - * so we don't need to disable preemption here + * hysteresis period. */ -static void sched_send_work(unsigned long unused) +static void sched_send_work(unsigned long _data) { - struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); - - schedule_work_on(smp_processor_id(), &data->dm_alert_work); + struct per_cpu_dm_data *data = (struct per_cpu_dm_data *)_data; - put_cpu_var(dm_cpu_data); + schedule_work(&data->dm_alert_work); } static void trace_drop_common(struct sk_buff *skb, void *location) @@ -167,33 +138,28 @@ static void trace_drop_common(struct sk_buff *skb, void *location) struct nlattr *nla; int i; struct sk_buff *dskb; - struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); - + struct per_cpu_dm_data *data; + unsigned long flags; - rcu_read_lock(); - dskb = rcu_dereference(data->skb); + local_irq_save(flags); + data = &__get_cpu_var(dm_cpu_data); + spin_lock(&data->lock); + dskb = data->skb; if (!dskb) goto out; - if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) { - /* - * we're already at zero, discard this hit - */ - goto out; - } - nlh = (struct nlmsghdr *)dskb->data; nla = genlmsg_data(nlmsg_data(nlh)); msg = nla_data(nla); for (i = 0; i < msg->entries; i++) { if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { msg->points[i].count++; - atomic_inc(&data->dm_hit_count); goto out; } } - + if (msg->entries == dm_hit_limit) + goto out; /* * We need to create a new entry */ @@ -205,13 +171,11 @@ static void trace_drop_common(struct sk_buff *skb, void *location) if (!timer_pending(&data->send_timer)) { data->send_timer.expires = jiffies + dm_delay * HZ; - add_timer_on(&data->send_timer, smp_processor_id()); + add_timer(&data->send_timer); } out: - rcu_read_unlock(); - put_cpu_var(dm_cpu_data); - return; + spin_unlock_irqrestore(&data->lock, flags); } static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location) @@ -418,11 +382,11 @@ static int __init init_net_drop_monitor(void) for_each_possible_cpu(cpu) { data = &per_cpu(dm_cpu_data, cpu); - data->cpu = cpu; INIT_WORK(&data->dm_alert_work, send_dm_alert); init_timer(&data->send_timer); - data->send_timer.data = cpu; + data->send_timer.data = (unsigned long)data; data->send_timer.function = sched_send_work; + spin_lock_init(&data->lock); reset_per_cpu_data(data); } -- cgit v0.10.2 From 9ec0db71af04f4560e27a3c2f5a0411ba3155198 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 4 Jun 2012 05:51:18 +0000 Subject: net: icplus: fix interrupt mask This patch fixes the interrupt mask for IC101 A/G devices and now enables the link/speed/duplex interrupts. This is done by setting the "INTR pin used" bit and cleaning all the other bits in the Register 17. Reported-by: Stuart Menefy Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index 5ac46f5..47f8e89 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -41,6 +41,8 @@ MODULE_LICENSE("GPL"); #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ +#define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */ +#define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED static int ip175c_config_init(struct phy_device *phydev) { @@ -136,6 +138,11 @@ static int ip1001_config_init(struct phy_device *phydev) if (c < 0) return c; + /* INTR pin used: speed/link/duplex will cause an interrupt */ + c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); + if (c < 0) + return c; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { /* Additional delay (2ns) used to adjust RX clock phase * at RGMII interface */ -- cgit v0.10.2 From dc5cd894cace7bda4a743487a9f87d59a3f0a095 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Mon, 4 Jun 2012 06:42:38 +0000 Subject: net/hyperv: Use wait_event on outstanding sends during device removal Change the busy-waiting/udelay to wait_event on outstanding sends. Signed-off-by: Haiyang Zhang Reviewed-by: K. Y. Srinivasan Signed-off-by: David S. Miller diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 4ffcd57..2857ab0 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -478,6 +478,7 @@ struct netvsc_device { u32 nvsp_version; atomic_t num_outstanding_sends; + wait_queue_head_t wait_drain; bool start_remove; bool destroy; /* diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 8b91947..0c56983 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -42,6 +42,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) if (!net_device) return NULL; + init_waitqueue_head(&net_device->wait_drain); net_device->start_remove = false; net_device->destroy = false; net_device->dev = device; @@ -387,12 +388,8 @@ int netvsc_device_remove(struct hv_device *device) spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* Wait for all send completions */ - while (atomic_read(&net_device->num_outstanding_sends)) { - dev_info(&device->device, - "waiting for %d requests to complete...\n", - atomic_read(&net_device->num_outstanding_sends)); - udelay(100); - } + wait_event(net_device->wait_drain, + atomic_read(&net_device->num_outstanding_sends) == 0); netvsc_disconnect_vsp(net_device); @@ -486,6 +483,9 @@ static void netvsc_send_completion(struct hv_device *device, num_outstanding_sends = atomic_dec_return(&net_device->num_outstanding_sends); + if (net_device->destroy && num_outstanding_sends == 0) + wake_up(&net_device->wait_drain); + if (netif_queue_stopped(ndev) && !net_device->start_remove && (hv_ringbuf_avail_percent(&device->channel->outbound) > RING_AVAIL_PERCENT_HIWATER || -- cgit v0.10.2 From 925e64c3c512e9f4452eaa7d52fd4c1518b8fb11 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 16 May 2012 15:27:20 +0200 Subject: mac80211: run scan after finish connection monitoring commit 133d40f9a22bdfd2617a446f1e3209537c5415ec Author: Stanislaw Gruszka Date: Wed Mar 28 16:01:19 2012 +0200 mac80211: do not scan and monitor connection in parallel add bug, which make possible to start a scan and never finish it, so make every new scanning request finish with -EBUSY error. This can happen on code paths where we finish connection monitoring and clear IEEE80211_STA_*_POLL flags, but do not check if scan was deferred. This patch fixes those code paths. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 04c3063..d94627c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1220,6 +1220,22 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, sdata->vif.bss_conf.qos = true; } +static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) +{ + lockdep_assert_held(&sdata->local->mtx); + + sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | + IEEE80211_STA_BEACON_POLL); + ieee80211_run_deferred_scan(sdata->local); +} + +static void ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) +{ + mutex_lock(&sdata->local->mtx); + __ieee80211_stop_poll(sdata); + mutex_unlock(&sdata->local->mtx); +} + static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, u16 capab, bool erp_valid, u8 erp) { @@ -1285,8 +1301,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; /* just to be sure */ - sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | - IEEE80211_STA_BEACON_POLL); + ieee80211_stop_poll(sdata); ieee80211_led_assoc(local, 1); @@ -1456,8 +1471,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) return; } - ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | - IEEE80211_STA_BEACON_POLL); + __ieee80211_stop_poll(sdata); mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); @@ -1477,7 +1491,6 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); out: - ieee80211_run_deferred_scan(local); mutex_unlock(&local->mtx); } @@ -2408,7 +2421,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n", sdata->name); #endif + mutex_lock(&local->mtx); ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; + ieee80211_run_deferred_scan(local); + mutex_unlock(&local->mtx); + mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); mutex_unlock(&local->iflist_mtx); @@ -2595,8 +2612,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[DEAUTH_DISASSOC_LEN]; - ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | - IEEE80211_STA_BEACON_POLL); + ieee80211_stop_poll(sdata); ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, false, frame_buf); @@ -2874,8 +2890,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) u32 flags; if (sdata->vif.type == NL80211_IFTYPE_STATION) { - sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | - IEEE80211_STA_CONNECTION_POLL); + __ieee80211_stop_poll(sdata); /* let's probe the connection once */ flags = sdata->local->hw.flags; @@ -2944,7 +2959,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) add_timer(&ifmgd->chswitch_timer); ieee80211_sta_reset_beacon_monitor(sdata); + + mutex_lock(&sdata->local->mtx); ieee80211_restart_sta_timer(sdata); + mutex_unlock(&sdata->local->mtx); } #endif -- cgit v0.10.2 From f0e3bd23418e1ec1aeac5fc36b74bf2f645b1244 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Tue, 29 May 2012 15:39:04 -0700 Subject: mwifiex: invalidate bss config before setting channel for uAP Mark bss_config parameters as invalid before setting AP channel. This prevents from setting invalid parameters while setting AP channel to FW. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 76dfbc4..e9482c9 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -416,6 +416,7 @@ int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) if (!bss_cfg) return -ENOMEM; + mwifiex_set_sys_config_invalid_data(bss_cfg); bss_cfg->band_cfg = BAND_CONFIG_MANUAL; bss_cfg->channel = channel; -- cgit v0.10.2 From 7a1c99343c5305c47b5e078d1af2144f9026df40 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Tue, 29 May 2012 15:39:05 -0700 Subject: mwifiex: support NL80211_HIDDEN_SSID_ZERO_LEN for uAP mwifiex uAP supports NL80211_HIDDEN_SSID_ZERO_LEN type of hidden SSID only. NL80211_HIDDEN_SSID_ZERO_CONTENTS is not supported. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 8767144..015fec3 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -948,6 +948,19 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, bss_cfg->ssid.ssid_len = params->ssid_len; } + switch (params->hidden_ssid) { + case NL80211_HIDDEN_SSID_NOT_IN_USE: + bss_cfg->bcast_ssid_ctl = 1; + break; + case NL80211_HIDDEN_SSID_ZERO_LEN: + bss_cfg->bcast_ssid_ctl = 0; + break; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + /* firmware doesn't support this type of hidden SSID */ + default: + return -EINVAL; + } + if (mwifiex_set_secure_params(priv, bss_cfg, params)) { kfree(bss_cfg); wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 9f674bb..561452a 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -122,6 +122,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) +#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) @@ -1209,6 +1210,11 @@ struct host_cmd_tlv_ssid { u8 ssid[0]; } __packed; +struct host_cmd_tlv_bcast_ssid { + struct host_cmd_tlv tlv; + u8 bcast_ctl; +} __packed; + struct host_cmd_tlv_beacon_period { struct host_cmd_tlv tlv; __le16 period; diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index e9482c9..8173ab6 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -132,6 +132,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) struct host_cmd_tlv_dtim_period *dtim_period; struct host_cmd_tlv_beacon_period *beacon_period; struct host_cmd_tlv_ssid *ssid; + struct host_cmd_tlv_bcast_ssid *bcast_ssid; struct host_cmd_tlv_channel_band *chan_band; struct host_cmd_tlv_frag_threshold *frag_threshold; struct host_cmd_tlv_rts_threshold *rts_threshold; @@ -153,6 +154,14 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) cmd_size += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; + + bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv; + bcast_ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID); + bcast_ssid->tlv.len = + cpu_to_le16(sizeof(bcast_ssid->bcast_ctl)); + bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl; + cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); + tlv += sizeof(struct host_cmd_tlv_bcast_ssid); } if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { chan_band = (struct host_cmd_tlv_channel_band *)tlv; -- cgit v0.10.2 From 28f333666ea766fdfb25de3783ff56cd2d1c51f0 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 29 May 2012 15:39:06 -0700 Subject: cfg80211: use sme_state in ibss start/join path CFG80211_DEV_WARN_ON() at "net/wireless/ibss.c line 63" is unnecessarily triggered even after successful connection, when cfg80211_ibss_joined() is called by driver inside .join_ibss handler. This patch fixes the problem by changing 'sme_state' in ibss path and having WARN_ON() check for 'sme_state' similar to infra association. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index d2a19b0..89baa33 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -42,6 +42,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); + wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_upload_connect_keys(wdev); nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, @@ -60,7 +61,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) struct cfg80211_event *ev; unsigned long flags; - CFG80211_DEV_WARN_ON(!wdev->ssid_len); + CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); ev = kzalloc(sizeof(*ev), gfp); if (!ev) @@ -115,9 +116,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, #ifdef CONFIG_CFG80211_WEXT wdev->wext.ibss.channel = params->channel; #endif + wdev->sme_state = CFG80211_SME_CONNECTING; err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); if (err) { wdev->connect_keys = NULL; + wdev->sme_state = CFG80211_SME_IDLE; return err; } @@ -169,6 +172,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) } wdev->current_bss = NULL; + wdev->sme_state = CFG80211_SME_IDLE; wdev->ssid_len = 0; #ifdef CONFIG_CFG80211_WEXT if (!nowext) -- cgit v0.10.2 From b8bacc187aa5b59af9b9fa19b3ce4df5ad1db112 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Wed, 30 May 2012 09:30:41 +0800 Subject: mac80211: Fix Unreachable Mesh Station Problem when joining to another MBSS Mesh station that joins an MBSS is reachable using mesh portal with 6 address frame by mesh stations from another MBSS if these two different MBSSes are bridged. However, if the mesh station later moves into the same MBSS of those mesh stations, it is unreachable by mesh stations in the MBSS due to the mpp_paths table is not deleted. A quick fix is to perform mesh_path_lookup, if it is available for the target destination, mpp_path_lookup is not performed. When the mesh station moves back to its original MBSS, the mesh_paths will be deleted once expired. So, it will be reachable using mpp_path_lookup again. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 847215b..e453212 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1737,7 +1737,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, __le16 fc; struct ieee80211_hdr hdr; struct ieee80211s_hdr mesh_hdr __maybe_unused; - struct mesh_path __maybe_unused *mppath = NULL; + struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL; const u8 *encaps_data; int encaps_len, skip_header_bytes; int nh_pos, h_pos; @@ -1803,8 +1803,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } rcu_read_lock(); - if (!is_multicast_ether_addr(skb->data)) - mppath = mpp_path_lookup(skb->data, sdata); + if (!is_multicast_ether_addr(skb->data)) { + mpath = mesh_path_lookup(skb->data, sdata); + if (!mpath) + mppath = mpp_path_lookup(skb->data, sdata); + } /* * Use address extension if it is a packet from -- cgit v0.10.2 From a5fdde28b4f5fb756032e7ad2c6fcdcffde20958 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 30 May 2012 10:36:12 +0200 Subject: iwlwifi: fix TX power antenna access Since my commit iwlwifi: use valid TX/RX antenna from hw_params the config values are pure overrides, not the real values for all hardware. Therefore, the EEPROM TX power reading code checks the wrong values, it should check the hw_params values. Cc: stable@kernel.org [3.4] Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 50c5891..b8e2b22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -568,28 +568,28 @@ static int iwl_find_otp_image(struct iwl_trans *trans, * iwl_get_max_txpower_avg - get the highest tx power from all chains. * find the highest tx power from all chains for the channel */ -static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, +static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element, s8 *max_txpower_in_half_dbm) { s8 max_txpower_avg = 0; /* (dBm) */ /* Take the highest tx power from any valid chains */ - if ((cfg->valid_tx_ant & ANT_A) && + if ((priv->hw_params.valid_tx_ant & ANT_A) && (enhanced_txpower[element].chain_a_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_a_max; - if ((cfg->valid_tx_ant & ANT_B) && + if ((priv->hw_params.valid_tx_ant & ANT_B) && (enhanced_txpower[element].chain_b_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_b_max; - if ((cfg->valid_tx_ant & ANT_C) && + if ((priv->hw_params.valid_tx_ant & ANT_C) && (enhanced_txpower[element].chain_c_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_c_max; - if (((cfg->valid_tx_ant == ANT_AB) | - (cfg->valid_tx_ant == ANT_BC) | - (cfg->valid_tx_ant == ANT_AC)) && + if (((priv->hw_params.valid_tx_ant == ANT_AB) | + (priv->hw_params.valid_tx_ant == ANT_BC) | + (priv->hw_params.valid_tx_ant == ANT_AC)) && (enhanced_txpower[element].mimo2_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo2_max; - if ((cfg->valid_tx_ant == ANT_ABC) && + if ((priv->hw_params.valid_tx_ant == ANT_ABC) && (enhanced_txpower[element].mimo3_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo3_max; @@ -691,7 +691,7 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) ((txp->delta_20_in_40 & 0xf0) >> 4), (txp->delta_20_in_40 & 0x0f)); - max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx, + max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, &max_txp_avg_halfdbm); /* -- cgit v0.10.2 From bd34ab62a3297bd7685da11b0cbe05ae4cd8b02c Mon Sep 17 00:00:00 2001 From: Meenakshi Venkataraman Date: Wed, 30 May 2012 11:39:33 +0200 Subject: mac80211: fix error in station state transitions during reconfig As part of hardware reconfig mac80211 tries to restore the station state to its values before the hardware reconfig, but it only goes to the last-state - 1. Fix this off-by-one error. Cc: stable@kernel.org [3.4] Signed-off-by: Meenakshi Venkataraman Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a44c680..8dd4712 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1271,7 +1271,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) enum ieee80211_sta_state state; for (state = IEEE80211_STA_NOTEXIST; - state < sta->sta_state - 1; state++) + state < sta->sta_state; state++) WARN_ON(drv_sta_state(local, sta->sdata, sta, state, state + 1)); } -- cgit v0.10.2 From 1ae2fc25a1289a84ca726541e3356ba5bcb7f7fe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 30 May 2012 14:59:36 +0200 Subject: mac80211_hwsim: advertise interface combinations Enforcing interface combinations broke uses of hwsim with multiple virtual interfaces. Advertise that all combinations are possible to fix this. Reported-by: Nirav Shah Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fb787df..4c9336c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1721,6 +1721,24 @@ static void hwsim_exit_netlink(void) "unregister family %i\n", ret); } +static const struct ieee80211_iface_limit hwsim_if_limits[] = { + { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) }, +}; + +static const struct ieee80211_iface_combination hwsim_if_comb = { + .limits = hwsim_if_limits, + .n_limits = ARRAY_SIZE(hwsim_if_limits), + .max_interfaces = 2048, + .num_different_channels = 1, +}; + static int __init init_mac80211_hwsim(void) { int i, err = 0; @@ -1782,6 +1800,9 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->n_addresses = 2; hw->wiphy->addresses = data->addresses; + hw->wiphy->iface_combinations = &hwsim_if_comb; + hw->wiphy->n_iface_combinations = 1; + if (fake_hw_scan) { hw->wiphy->max_scan_ssids = 255; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; -- cgit v0.10.2 From 71ecfa1893034eeb1c93e02e22ee2ad26d080858 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 May 2012 15:09:27 +0200 Subject: mac80211: clean up remain-on-channel on interface stop When any interface goes down, it could be the one that we were doing a remain-on-channel with. We therefore need to cancel the remain-on-channel and flush the related work structs so they don't run after the interface has been removed or even destroyed. It's also possible in this case that an off-channel SKB was never transmitted, so free it if this is the case. Note that this can also happen if the driver finishes the off-channel period without ever starting it. Cc: stable@kernel.org Reported-by: Nirav Shah Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d4c19a7..8664111 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -637,6 +637,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ieee80211_configure_filter(local); break; default: + mutex_lock(&local->mtx); + if (local->hw_roc_dev == sdata->dev && + local->hw_roc_channel) { + /* ignore return value since this is racy */ + drv_cancel_remain_on_channel(local); + ieee80211_queue_work(&local->hw, &local->hw_roc_done); + } + mutex_unlock(&local->mtx); + + flush_work(&local->hw_roc_start); + flush_work(&local->hw_roc_done); + flush_work(&sdata->work); /* * When we get here, the interface is marked down. diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index f054e94..935aa4b 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -234,6 +234,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work) return; } + /* was never transmitted */ + if (local->hw_roc_skb) { + u64 cookie; + + cookie = local->hw_roc_cookie ^ 2; + + cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, + local->hw_roc_skb->data, + local->hw_roc_skb->len, false, + GFP_KERNEL); + + kfree_skb(local->hw_roc_skb); + local->hw_roc_skb = NULL; + local->hw_roc_skb_for_status = NULL; + } + if (!local->hw_roc_for_tx) cfg80211_remain_on_channel_expired(local->hw_roc_dev, local->hw_roc_cookie, -- cgit v0.10.2 From d8c7aae64cd2db5eccc631c29fa978a24fb1feef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 May 2012 15:32:24 +0200 Subject: mac80211: add missing rcu_read_lock/unlock in agg-rx session timer Fixes a lockdep warning: =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- net/mac80211/agg-rx.c:148 invoked rcu_dereference_check() without protection! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 1 1 lock held by arecord/11226: #0: (&tid_agg_rx->session_timer){+.-...}, at: [] call_timer_fn+0x0/0x360 stack backtrace: Pid: 11226, comm: arecord Not tainted 3.1.0-kml #16 Call Trace: [] lockdep_rcu_dereference+0xa4/0xc0 [] sta_rx_agg_session_timer_expired+0xc9/0x110 [mac80211] [] ? ieee80211_process_addba_resp+0x220/0x220 [mac80211] [] call_timer_fn+0x8a/0x360 [] ? init_timer_deferrable_key+0x30/0x30 [] ? _raw_spin_unlock_irq+0x30/0x70 [] run_timer_softirq+0x139/0x310 [] ? put_lock_stats.isra.25+0xe/0x40 [] ? lock_release_holdtime.part.26+0xdc/0x160 [] ? ieee80211_process_addba_resp+0x220/0x220 [mac80211] [] __do_softirq+0xc8/0x3c0 [] ? tick_dev_program_event+0x48/0x110 [] ? tick_program_event+0x1f/0x30 [] ? putname+0x35/0x50 [] call_softirq+0x1c/0x30 [] do_softirq+0xa5/0xe0 [] irq_exit+0xae/0xe0 [] smp_apic_timer_interrupt+0x6b/0x98 [] apic_timer_interrupt+0x73/0x80 [] ? free_debug_processing+0x1a1/0x1d5 [] ? putname+0x35/0x50 [] __slab_free+0x31/0x2ca [] ? _raw_spin_unlock_irqrestore+0x4a/0x90 [] ? __debug_check_no_obj_freed+0x15f/0x210 [] ? lock_release_nested+0x84/0xc0 [] ? kmem_cache_free+0x105/0x250 [] ? putname+0x35/0x50 [] ? putname+0x35/0x50 [] kmem_cache_free+0x23f/0x250 [] putname+0x35/0x50 [] do_sys_open+0x16d/0x1d0 [] sys_open+0x20/0x30 [] system_call_fastpath+0x16/0x1b Reported-by: Johannes Berg Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 26ddb69..c649188 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -145,15 +145,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) struct tid_ampdu_rx *tid_rx; unsigned long timeout; + rcu_read_lock(); tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); - if (!tid_rx) + if (!tid_rx) { + rcu_read_unlock(); return; + } timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); if (time_is_after_jiffies(timeout)) { mod_timer(&tid_rx->session_timer, timeout); + rcu_read_unlock(); return; } + rcu_read_unlock(); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); -- cgit v0.10.2 From 5204267d2fd5e98fc52b44fec01ad10352642b78 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 May 2012 13:25:54 -0700 Subject: mac80211: Fix likely misuse of | for & Using | with a constant is always true. Likely this should have be &. cc: Ben Greear Signed-off-by: Joe Perches Signed-off-by: John W. Linville diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 495831e..e9cecca 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -533,16 +533,16 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, sinfo.filled = 0; sta_set_sinfo(sta, &sinfo); - if (sinfo.filled | STATION_INFO_TX_BITRATE) + if (sinfo.filled & STATION_INFO_TX_BITRATE) data[i] = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); i++; - if (sinfo.filled | STATION_INFO_RX_BITRATE) + if (sinfo.filled & STATION_INFO_RX_BITRATE) data[i] = 100000 * cfg80211_calculate_bitrate(&sinfo.rxrate); i++; - if (sinfo.filled | STATION_INFO_SIGNAL_AVG) + if (sinfo.filled & STATION_INFO_SIGNAL_AVG) data[i] = (u8)sinfo.signal_avg; i++; } else { -- cgit v0.10.2 From f304a993190965f48baa49792d5ab2849ae26bf9 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 May 2012 13:25:56 -0700 Subject: brcmfmac: Fix likely misuse of | for & Using | with a constant is always true. Likely this should have be &. Signed-off-by: Joe Perches Acked-by: Arend van Spriel Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index e2480d1..8e7e692 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -89,9 +89,9 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); - /* redirect, configure ane enable io for interrupt signal */ + /* redirect, configure and enable io for interrupt signal */ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; - if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) + if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH) data |= SDIO_SEPINT_ACT_HI; brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); -- cgit v0.10.2 From e5851dac2c95af7159716832300b9f50c62c648e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 1 Jun 2012 11:29:40 +0200 Subject: rt2x00: use atomic variable for seqno Remove spinlock as atomic_t can be used instead. Note we use only 16 lower bits, upper bits are changed but we impilcilty cast to u16. This fix possible deadlock on IBSS mode reproted by lockdep: ================================= [ INFO: inconsistent lock state ] 3.4.0-wl+ #4 Not tainted --------------------------------- inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage. kworker/u:2/30374 [HC0[0]:SC0[0]:HE1:SE1] takes: (&(&intf->seqlock)->rlock){+.?...}, at: [] rt2x00queue_create_tx_descriptor+0x380/0x490 [rt2x00lib] {IN-SOFTIRQ-W} state was registered at: [] __lock_acquire+0x47b/0x1050 [] lock_acquire+0x84/0xf0 [] _raw_spin_lock+0x33/0x40 [] rt2x00queue_create_tx_descriptor+0x380/0x490 [rt2x00lib] [] rt2x00queue_write_tx_frame+0x1a/0x300 [rt2x00lib] [] rt2x00mac_tx+0x7f/0x380 [rt2x00lib] [] __ieee80211_tx+0x1b3/0x300 [mac80211] [] ieee80211_tx+0x105/0x130 [mac80211] [] ieee80211_xmit+0xad/0x100 [mac80211] [] ieee80211_subif_start_xmit+0x2d9/0x930 [mac80211] [] dev_hard_start_xmit+0x307/0x660 [] sch_direct_xmit+0xa1/0x1e0 [] dev_queue_xmit+0x183/0x730 [] neigh_resolve_output+0xfa/0x1e0 [] ip_finish_output+0x24a/0x460 [] ip_output+0xb7/0x100 [] ip_local_out+0x20/0x60 [] igmpv3_sendpack+0x4f/0x60 [] igmp_ifc_timer_expire+0x29f/0x330 [] run_timer_softirq+0x15c/0x2f0 [] __do_softirq+0xae/0x1e0 irq event stamp: 18380437 hardirqs last enabled at (18380437): [] __slab_alloc.clone.3+0x67/0x5f0 hardirqs last disabled at (18380436): [] __slab_alloc.clone.3+0x33/0x5f0 softirqs last enabled at (18377616): [] __do_softirq+0x123/0x1e0 softirqs last disabled at (18377611): [] do_softirq+0x9d/0xe0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(&intf->seqlock)->rlock); lock(&(&intf->seqlock)->rlock); *** DEADLOCK *** 4 locks held by kworker/u:2/30374: #0: (wiphy_name(local->hw.wiphy)){++++.+}, at: [] process_one_work+0x109/0x3f0 #1: ((&sdata->work)){+.+.+.}, at: [] process_one_work+0x109/0x3f0 #2: (&ifibss->mtx){+.+.+.}, at: [] ieee80211_ibss_work+0x1b/0x470 [mac80211] #3: (&intf->beacon_skb_mutex){+.+...}, at: [] rt2x00queue_update_beacon+0x24/0x50 [rt2x00lib] stack backtrace: Pid: 30374, comm: kworker/u:2 Not tainted 3.4.0-wl+ #4 Call Trace: [] print_usage_bug+0x1f6/0x220 [] mark_lock+0x2c2/0x300 [] ? check_usage_forwards+0xc0/0xc0 [] __lock_acquire+0x4bc/0x1050 [] ? __kmalloc_track_caller+0x1c0/0x1d0 [] ? copy_skb_header+0x26/0x90 [] lock_acquire+0x84/0xf0 [] ? rt2x00queue_create_tx_descriptor+0x380/0x490 [rt2x00lib] [] _raw_spin_lock+0x33/0x40 [] ? rt2x00queue_create_tx_descriptor+0x380/0x490 [rt2x00lib] [] rt2x00queue_create_tx_descriptor+0x380/0x490 [rt2x00lib] [] rt2x00queue_update_beacon_locked+0x5f/0xb0 [rt2x00lib] [] rt2x00queue_update_beacon+0x2d/0x50 [rt2x00lib] [] rt2x00mac_bss_info_changed+0x1ca/0x200 [rt2x00lib] [] ? rt2x00mac_remove_interface+0x70/0x70 [rt2x00lib] [] ieee80211_bss_info_change_notify+0xe0/0x1d0 [mac80211] [] __ieee80211_sta_join_ibss+0x3b8/0x610 [mac80211] [] ? mark_held_locks+0x64/0xc0 [] ? virt_efi_query_capsule_caps+0x12/0x50 [] ieee80211_sta_join_ibss+0xf9/0x140 [mac80211] [] ieee80211_ibss_work+0x416/0x470 [mac80211] [] ? trace_hardirqs_on+0xb/0x10 [] ? skb_dequeue+0x4b/0x70 [] ieee80211_iface_work+0x13f/0x230 [mac80211] [] ? process_one_work+0x109/0x3f0 [] process_one_work+0x185/0x3f0 [] ? process_one_work+0x109/0x3f0 [] ? ieee80211_teardown_sdata+0xa0/0xa0 [mac80211] [] worker_thread+0x116/0x270 [] ? manage_workers+0x1e0/0x1e0 [] kthread+0x84/0x90 [] ? __init_kthread_worker+0x60/0x60 [] kernel_thread_helper+0x6/0x10 Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ca36ccc..8f75402 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -396,8 +396,7 @@ struct rt2x00_intf { * for hardware which doesn't support hardware * sequence counting. */ - spinlock_t seqlock; - u16 seqno; + atomic_t seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index b49773e..dd24b26 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -277,7 +277,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, else rt2x00dev->intf_sta_count++; - spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4c662ec..2fd8301 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -207,6 +207,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); + u16 seqno; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; @@ -238,15 +239,13 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ - spin_lock(&intf->seqlock); - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - intf->seqno += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(intf->seqno); - - spin_unlock(&intf->seqlock); + seqno = atomic_add_return(0x10, &intf->seqno); + else + seqno = atomic_read(&intf->seqno); + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seqno); } static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, -- cgit v0.10.2 From 69aaedd3cfd23b2c732e3cf1227370a35f5c89d4 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Fri, 1 Jun 2012 09:13:17 -0500 Subject: bcma: add ext PA workaround for BCM4331 and BCM43431 MacBook Pro models with BCM4331 wireless have been found to have the ext PA lines disabled after resuming from S3 without external power attach. This causes them to be unable to transmit. Add a workaround to ensure that the ext PA lines are enabled on BCM4331. Also extend all handling of ext PA line muxing to BCM43431 as is done in the Broadcom SDK. BugLink: http://bugs.launchpad.net/bugs/925577 Cc: Arend van Spriel Cc: Hauke Mehrtens Cc: stable@vger.kernel.org Signed-off-by: Seth Forshee Signed-off-by: John W. Linville diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index a058842..61ce405 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -139,7 +139,9 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ + case 43431: + /* Ext PA lines must be enabled for tx on BCM4331 */ + bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); break; case 43224: if (bus->chipinfo.rev == 0) { diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index c7f9335..f16f42d 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -579,13 +579,13 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - if (bus->chipinfo.id == 0x4331) + if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); pr_debug("SPROM offset 0x%x\n", offset); bcma_sprom_read(bus, offset, sprom); - if (bus->chipinfo.id == 0x4331) + if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); err = bcma_sprom_valid(sprom); -- cgit v0.10.2 From 794454ce72a298de6f4536ade597bdcc7dcde7c7 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 3 Jun 2012 23:32:32 +0300 Subject: mac80211: fix non RCU-safe sta_list manipulation sta_info_cleanup locks the sta_list using rcu_read_lock however the delete operation isn't rcu safe. A race between sta_info_cleanup timer being called and a STA being removed can occur which leads to a panic while traversing sta_list. Fix this by switching to the RCU-safe versions. Cc: stable@vger.kernel.org Reported-by: Eyal Shapira Signed-off-by: Arik Nemtsov Signed-off-by: John W. Linville diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f5b1638..de455f8 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -378,7 +378,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) /* make the station visible */ sta_info_hash_add(local, sta); - list_add(&sta->list, &local->sta_list); + list_add_rcu(&sta->list, &local->sta_list); set_sta_flag(sta, WLAN_STA_INSERTED); @@ -688,7 +688,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) if (ret) return ret; - list_del(&sta->list); + list_del_rcu(&sta->list); mutex_lock(&local->key_mtx); for (i = 0; i < NUM_DEFAULT_KEYS; i++) -- cgit v0.10.2 From fcb6ff5e2cb83e1de10631f6621f45ca3401bf61 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 4 Jun 2012 13:43:11 +0200 Subject: iwlwifi: disable WoWLAN if !CONFIG_PM_SLEEP If CONFIG_PM_SLEEP is disabled, then iwlwifi doesn't support suspend/resume handlers and thus mac80211 (correctly) refuses advertising WoWLAN. Disable WoWLAN in the driver in this case. Cc: stable@kernel.org Reported-by: Sebastian Kemper Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index ab2f4d7..5d158ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -199,6 +199,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; +#ifdef CONFIG_PM_SLEEP if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && priv->trans->ops->wowlan_suspend && device_can_wakeup(priv->trans->dev)) { @@ -217,6 +218,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->wiphy->wowlan.pattern_max_len = IWLAGN_WOWLAN_MAX_PATTERN_LEN; } +#endif if (iwlwifi_mod_params.power_save) hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; -- cgit v0.10.2 From ddcd0f41471a1e0394c8840a119ec3986a78462c Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 31 May 2012 22:53:39 -0300 Subject: Bluetooth: Fix checking the wrong flag when accepting a socket Most probably a typo, the check should have been for BT_SK_DEFER_SETUP instead of BT_DEFER_SETUP (which right now only represents a socket option). Signed-off-by: Vinicius Costa Gomes Acked-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 46e7f86..3e18af4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -210,7 +210,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) } if (sk->sk_state == BT_CONNECTED || !newsock || - test_bit(BT_DEFER_SETUP, &bt_sk(parent)->flags)) { + test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) { bt_accept_unlink(sk); if (newsock) sock_graft(sk, newsock); -- cgit v0.10.2 From 61663171bea0ccb499f0818234c5be7ea6c4c791 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 5 Jun 2012 18:10:10 +0800 Subject: regulator: max8649: fix missing regmap in rdev In probe(), rdev->regmap must be assigned. Signed-off-by: Haojian Zhuang Signed-off-by: Mark Brown diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 1f4bb80..9d540cd 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -259,6 +259,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, config.dev = &client->dev; config.init_data = pdata->regulator; config.driver_data = info; + config.regmap = info->regmap; info->regulator = regulator_register(&dcdc_desc, &config); if (IS_ERR(info->regulator)) { -- cgit v0.10.2 From c8fdc1b56611faa7b38eab6b99da5e20113661ff Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 12:25:19 +0100 Subject: ASoC: wm8994: Ensure all AIFnCLK events are run from the _late variants Ensure that all the actions get taken at appropriate times by calling the _PRE and _POST events for the aifNclk_ev functions explicitly. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 993639d..6d3a865 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1190,17 +1190,19 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: if (wm8994->aif1clk_enable) { - aif1clk_ev(w, kcontrol, event); + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, WM8994_AIF1CLK_ENA_MASK, WM8994_AIF1CLK_ENA); + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); wm8994->aif1clk_enable = 0; } if (wm8994->aif2clk_enable) { - aif2clk_ev(w, kcontrol, event); + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, WM8994_AIF2CLK_ENA_MASK, WM8994_AIF2CLK_ENA); + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); wm8994->aif2clk_enable = 0; } break; @@ -1221,15 +1223,17 @@ static int late_disable_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMD: if (wm8994->aif1clk_disable) { + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, WM8994_AIF1CLK_ENA_MASK, 0); - aif1clk_ev(w, kcontrol, event); + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); wm8994->aif1clk_disable = 0; } if (wm8994->aif2clk_disable) { + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, WM8994_AIF2CLK_ENA_MASK, 0); - aif2clk_ev(w, kcontrol, event); + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); wm8994->aif2clk_disable = 0; } break; -- cgit v0.10.2 From bfd37bb5f681961e255fd2f346c20fdae2ef3f27 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 5 Jun 2012 12:31:32 +0100 Subject: ASoC: wm8994: Apply volume updates with clocks enabled Volume updates may not be acted upon if there is no clock applied when the volume update is written. Ensure this doesn't happen by writing out registers with volume updates after we enable each of the clocks. There are more registers updated than before as previously we were relying on wm_hubs to set those for controls it manages. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6d3a865..aa8c98b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -46,6 +46,39 @@ #define WM8994_NUM_DRC 3 #define WM8994_NUM_EQ 3 +static struct { + unsigned int reg; + unsigned int mask; +} wm8994_vu_bits[] = { + { WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, + { WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, + { WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, + { WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, + { WM8994_SPEAKER_VOLUME_LEFT, WM8994_SPKOUT_VU }, + { WM8994_SPEAKER_VOLUME_RIGHT, WM8994_SPKOUT_VU }, + { WM8994_LEFT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, + { WM8994_RIGHT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, + { WM8994_LEFT_OPGA_VOLUME, WM8994_MIXOUT_VU }, + { WM8994_RIGHT_OPGA_VOLUME, WM8994_MIXOUT_VU }, + + { WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU }, + { WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU }, + { WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU }, + { WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU }, + { WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU }, + { WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU }, + { WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU }, + { WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU }, + { WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU }, + { WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, + { WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU }, + { WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, + { WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU }, + { WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU }, + { WM8994_DAC2_LEFT_VOLUME, WM8994_DAC2_VU }, + { WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU }, +}; + static int wm8994_drc_base[] = { WM8994_AIF1_DRC1_1, WM8994_AIF1_DRC2_1, @@ -989,6 +1022,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = w->codec; struct wm8994 *control = codec->control_data; int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; + int i; int dac; int adc; int val; @@ -1047,6 +1081,13 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF1DAC2L_ENA); break; + case SND_SOC_DAPM_POST_PMU: + for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) + snd_soc_write(codec, wm8994_vu_bits[i].reg, + snd_soc_read(codec, + wm8994_vu_bits[i].reg)); + break; + case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1072,6 +1113,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; + int i; int dac; int adc; int val; @@ -1122,6 +1164,13 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF2DACR_ENA); break; + case SND_SOC_DAPM_POST_PMU: + for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) + snd_soc_write(codec, wm8994_vu_bits[i].reg, + snd_soc_read(codec, + wm8994_vu_bits[i].reg)); + break; + case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1531,9 +1580,11 @@ SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), @@ -3883,39 +3934,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) pm_runtime_put(codec->dev); - /* Latch volume updates (right only; we always do left then right). */ - snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, - WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, - WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME, - WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); - snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, - WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); - snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME, - WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); - snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, - WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, - WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, - WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME, - WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, - WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME, - WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, - WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME, - WM8994_DAC1_VU, WM8994_DAC1_VU); - snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, - WM8994_DAC1_VU, WM8994_DAC1_VU); - snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME, - WM8994_DAC2_VU, WM8994_DAC2_VU); - snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, - WM8994_DAC2_VU, WM8994_DAC2_VU); + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) + snd_soc_update_bits(codec, wm8994_vu_bits[i].reg, + wm8994_vu_bits[i].mask, + wm8994_vu_bits[i].mask); /* Set the low bit of the 3D stereo depth so TLV matches */ snd_soc_update_bits(codec, WM8994_AIF1_DAC1_FILTERS_2, -- cgit v0.10.2 From 1549210fcc17e9ae20c09ac8cd4c48a8dfd431bd Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 5 Jun 2012 09:16:47 -0400 Subject: NFSv4: Fix an Oops in the open recovery code The open recovery code does not need to request a new value for the mdsthreshold, and so does not allocate a struct nfs4_threshold. The problem is that encode_getfattr_open() will still request an mdsthreshold, and so we end up Oopsing in decode_attr_mdsthreshold. This patch fixes encode_getfattr_open so that it doesn't request an mdsthreshold when the caller isn't asking for one. It also fixes decode_attr_mdsthreshold so that it errors if the server returns an mdsthreshold that we didn't ask for (instead of Oopsing). Signed-off-by: Trond Myklebust Cc: Andy Adamson diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c6827f93..cc5900a 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp) extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; -extern const u32 nfs4_fattr_bitmap[2]; +extern const u32 nfs4_fattr_bitmap[3]; extern const u32 nfs4_statfs_bitmap[2]; extern const u32 nfs4_pathconf_bitmap[2]; extern const u32 nfs4_fsinfo_bitmap[3]; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d48dbef..ad15155 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -116,7 +116,7 @@ static int nfs4_map_errors(int err) /* * This is our standard bitmap for GETATTR requests. */ -const u32 nfs4_fattr_bitmap[2] = { +const u32 nfs4_fattr_bitmap[3] = { FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE @@ -133,6 +133,24 @@ const u32 nfs4_fattr_bitmap[2] = { | FATTR4_WORD1_TIME_MODIFY }; +static const u32 nfs4_pnfs_open_bitmap[3] = { + FATTR4_WORD0_TYPE + | FATTR4_WORD0_CHANGE + | FATTR4_WORD0_SIZE + | FATTR4_WORD0_FSID + | FATTR4_WORD0_FILEID, + FATTR4_WORD1_MODE + | FATTR4_WORD1_NUMLINKS + | FATTR4_WORD1_OWNER + | FATTR4_WORD1_OWNER_GROUP + | FATTR4_WORD1_RAWDEV + | FATTR4_WORD1_SPACE_USED + | FATTR4_WORD1_TIME_ACCESS + | FATTR4_WORD1_TIME_METADATA + | FATTR4_WORD1_TIME_MODIFY, + FATTR4_WORD2_MDSTHRESHOLD +}; + const u32 nfs4_statfs_bitmap[2] = { FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE @@ -844,6 +862,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, p->o_arg.name = &dentry->d_name; p->o_arg.server = server; p->o_arg.bitmask = server->attr_bitmask; + p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; if (attrs != NULL && attrs->ia_valid != 0) { __be32 verf[2]; @@ -1820,6 +1839,7 @@ static int _nfs4_do_open(struct inode *dir, opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); if (!opendata->f_attr.mdsthreshold) goto err_opendata_put; + opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; } if (dentry->d_inode != NULL) opendata->state = nfs4_get_open_state(dentry->d_inode, sp); diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index ee4a74d..9ca1428 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c } static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, + const u32 *open_bitmap, struct compound_hdr *hdr) { encode_getattr_three(xdr, - bitmask[0] & nfs4_fattr_bitmap[0], - bitmask[1] & nfs4_fattr_bitmap[1], - bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD, + bitmask[0] & open_bitmap[0], + bitmask[1] & open_bitmap[1], + bitmask[2] & open_bitmap[2], hdr); } @@ -2221,7 +2222,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, encode_putfh(xdr, args->fh, &hdr); encode_open(xdr, args, &hdr); encode_getfh(xdr, &hdr); - encode_getfattr_open(xdr, args->bitmask, &hdr); + encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); encode_nops(&hdr); } @@ -4360,6 +4361,9 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) return -EIO; if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) { + /* Did the server return an unrequested attribute? */ + if (unlikely(res == NULL)) + return -EREMOTEIO; p = xdr_inline_decode(xdr, 4); if (unlikely(!p)) goto out_overflow; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index d1a7bf5..7519bae 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -348,6 +348,7 @@ struct nfs_openargs { const struct qstr * name; const struct nfs_server *server; /* Needed for ID mapping */ const u32 * bitmask; + const u32 * open_bitmap; __u32 claim; struct nfs4_sequence_args seq_args; }; -- cgit v0.10.2 From 029c53473727f21c1dd73237e8d630a6f007a2fe Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 5 Jun 2012 09:35:44 -0400 Subject: NFSv4: Fix up decode_attr_mdsthreshold Fix an incorrect use of 'likely()'. The FATTR4_WORD2_MDSTHRESHOLD bit is only expected in NFSv4.1 OPEN calls, and so is actually rather _unlikely_. decode_attr_mdsthreshold needs to clear FATTR4_WORD2_MDSTHRESHOLD from the attribute bitmap after it has decoded the data. Signed-off-by: Trond Myklebust Cc: Andy Adamson diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 9ca1428..18fae29 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -4360,7 +4360,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) return -EIO; - if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) { + if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) { /* Did the server return an unrequested attribute? */ if (unlikely(res == NULL)) return -EREMOTEIO; @@ -4376,6 +4376,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, __func__); status = decode_first_threshold_item4(xdr, res); + bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD; } return status; out_overflow: -- cgit v0.10.2 From 08106ac7c892cad769c5026cb9dd877a39aed603 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 5 Jun 2012 10:08:24 -0400 Subject: NFSv4.1: Convert a trivial printk into a dprintk There is no need to bug the user about the server returning an error on destroy_session. The error will be handled by the state manager, without any need for further input from anyone else. So convert that printk into a debugging dprintk. Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ad15155..7c218fd 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5766,8 +5766,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); if (status) - printk(KERN_WARNING - "NFS: Got error %d from the server on DESTROY_SESSION. " + dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " "Session has been destroyed regardless...\n", status); dprintk("<-- nfs4_proc_destroy_session\n"); -- cgit v0.10.2 From c3a21fc79b6bc097d8b0e47498903a649a111127 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Jun 2012 13:17:32 +0300 Subject: OMAPDSS: fix registration of DPI and SDI devices The omapdss arch initialization code registers all the output devices as omap_devices. However, DPI and SDI are not proper omap_devices, as they do not have any corresponding HWMOD. This leads to crashes or problems when the platform code tries to use omap_device functions for DPI and SDI devices. One such crash was reported by John Stultz : [ 18.756835] Unable to handle kernel NULL pointer dereference at virtual addr8 [ 18.765319] pgd = ea6b8000 [ 18.768188] [00000018] *pgd=aa942831, *pte=00000000, *ppte=00000000 [ 18.774749] Internal error: Oops: 17 [#1] SMP ARM [ 18.779663] Modules linked in: [ 18.782836] CPU: 0 Not tainted (3.5.0-rc1-dirty #456) [ 18.788482] PC is at _od_resume_noirq+0x1c/0x78 [ 18.793212] LR is at _od_resume_noirq+0x6c/0x78 [ 18.797943] pc : [] lr : [] psr: 20000113 [ 18.797943] sp : ec3abe80 ip : ec3abdb8 fp : 00000006 [ 18.809936] r10: ec1148b8 r9 : c08a48f0 r8 : c00307d0 [ 18.815368] r7 : 00000000 r6 : 00000000 r5 : ec114800 r4 : ec114808 [ 18.822174] r3 : 00000000 r2 : 00000000 r1 : ec154fe8 r0 : 00000006 [ 18.829010] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 18.836456] Control: 10c5387d Table: aa6b804a DAC: 00000015 [ 18.842437] Process sh (pid: 1139, stack limit = 0xec3aa2f0) [ 18.848358] Stack: (0xec3abe80 to 0xec3ac000) DPI and SDI can be plain platform_devices. This patch changes the registration from omap_device_register() to platform_device_add(). Signed-off-by: Tomi Valkeinen Reported-by: John Stultz Tested-by: Jean Pihet diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 54d49dd..5fb47a1 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -271,9 +271,9 @@ static struct platform_device *create_simple_dss_pdev(const char *pdev_name, goto err; } - r = omap_device_register(pdev); + r = platform_device_add(pdev); if (r) { - pr_err("Could not register omap_device for %s\n", pdev_name); + pr_err("Could not register platform_device for %s\n", pdev_name); goto err; } -- cgit v0.10.2 From bda197f5d71d56b95a84c0ccbcb8ce2691106cca Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 5 Jun 2012 10:22:14 -0400 Subject: NFSv4.1: Ensure we clear session state flags after a session creation Both nfs4_reset_session and nfs41_init_clientid need to clear all the session related state flags on success. Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index c679b9e..f38300e 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -244,6 +244,16 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) return nfs4_wait_on_slot_tbl(&ses->fc_slot_table); } +static void nfs41_finish_session_reset(struct nfs_client *clp) +{ + clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); + clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); + /* create_session negotiated new slot table */ + clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); + clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); + nfs41_setup_state_renewal(clp); +} + int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) { int status; @@ -259,8 +269,7 @@ do_confirm: status = nfs4_proc_create_session(clp, cred); if (status != 0) goto out; - clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); - nfs41_setup_state_renewal(clp); + nfs41_finish_session_reset(clp); nfs_mark_client_ready(clp, NFS_CS_READY); out: return status; @@ -1772,16 +1781,9 @@ static int nfs4_reset_session(struct nfs_client *clp) status = nfs4_handle_reclaim_lease_error(clp, status); goto out; } - clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); - /* create_session negotiated new slot table */ - clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); - clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); + nfs41_finish_session_reset(clp); dprintk("%s: session reset was successful for server %s!\n", __func__, clp->cl_hostname); - - /* Let the state manager reestablish state */ - if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) - nfs41_setup_state_renewal(clp); out: if (cred) put_rpccred(cred); -- cgit v0.10.2 From f69a23b795d6ee3673583146ed7efcbaaa5add18 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Jun 2012 19:56:06 +0200 Subject: iwlwifi: fix double free/complete in firmware loading Linus reported that due to mac80211 failing to register the device (due to WoWLAN) his machine crashed etc. as we double-freed the vmalloc() firmware area. His patch to fix it was very similar to this one but I noticed that there's another bug in the area: we complete the completion before starting, so since we're running in a work struct context stop() could be called while in the middle of start() which will almost certainly lead to issues. Make a modification similar to his to avoid the double- free but also move the completion to another spot so it is only done after start() either finished or failed so that stop() can have a consistent state. Reported-by: Linus Torvalds Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index d742900..fac67a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -861,13 +861,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); - complete(&drv->request_firmware_complete); drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw); if (!drv->op_mode) - goto out_free_fw; + goto out_unbind; + /* + * Complete the firmware request last so that + * a driver unbind (stop) doesn't run while we + * are doing the start() above. + */ + complete(&drv->request_firmware_complete); return; try_again: -- cgit v0.10.2 From 0e1fa7ef25004b9c1a14147bce61c15c2f1c6744 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Jun 2012 09:38:35 +0200 Subject: iwlwifi: unregister LEDs if mac80211 registration fails Otherwise the LEDs stick around and cause issues the next time around since they're still there but not really hooked up. Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 5d158ca..3ee23134 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -251,6 +251,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ret = ieee80211_register_hw(priv->hw); if (ret) { IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); + iwl_leds_exit(priv); return ret; } priv->mac80211_registered = 1; -- cgit v0.10.2 From 463454b5dbd8dbab6e2fc6c557329e5b811b9c32 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Jun 2012 12:16:50 +0200 Subject: cfg80211: fix interface combinations check If a given interface combination doesn't contain a required interface type then we missed checking that and erroneously allowed it even though iface type wasn't there at all. Add a check that makes sure that all interface types are accounted for. Cc: stable@kernel.org Reported-by: Mohammed Shafi Shajakhan Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/wireless/util.c b/net/wireless/util.c index 55d9946..8f2d68f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype) { struct wireless_dev *wdev_iter; + u32 used_iftypes = BIT(iftype); int num[NUM_NL80211_IFTYPES]; int total = 1; int i, j; @@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, num[wdev_iter->iftype]++; total++; + used_iftypes |= BIT(wdev_iter->iftype); } mutex_unlock(&rdev->devlist_mtx); @@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; struct ieee80211_iface_limit *limits; + u32 all_iftypes = 0; c = &rdev->wiphy.iface_combinations[i]; @@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(iftype)) continue; for (j = 0; j < c->n_limits; j++) { + all_iftypes |= limits[j].types; if (!(limits[j].types & BIT(iftype))) continue; if (limits[j].max < num[iftype]) @@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, limits[j].max -= num[iftype]; } } - /* yay, it fits */ + + /* + * Finally check that all iftypes that we're currently + * using are actually part of this combination. If they + * aren't then we can't use this combination and have + * to continue to the next. + */ + if ((all_iftypes & used_iftypes) != used_iftypes) + goto cont; + + /* + * This combination covered all interface types and + * supported the requested numbers, so we're good. + */ kfree(limits); return 0; cont: -- cgit v0.10.2 From cdf66442fab82916fe38f928b4f91815195a294c Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 5 Jun 2012 14:59:54 -0400 Subject: NFS4: Set parsed mount data version to 4 This patch only affects mounting through "-t nfs4" since it doesn't set up an nfs version to use in the mount data. The nfs client was trying to mount using NFS v0, causing either a BUG() or a protocol not supported message. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ff656c0..bdd6731 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2637,6 +2637,8 @@ static int nfs4_validate_mount_data(void *options, if (data == NULL) goto out_no_data; + args->version = 4; + switch (data->version) { case 1: if (data->host_addrlen > sizeof(args->nfs_server.address)) -- cgit v0.10.2 From 5c888aa43ee9872efe2a09e8c9f03db84f60dd28 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Tue, 29 May 2012 18:57:00 +0200 Subject: video: bfin_adv7393fb: Convert to kstrtouint_from_user This patch removes a call to the deprecated simple_strtoul function and simplifies the code by replacing two function calls with one call to kstrtouint_from_user. -Simplify the adv7393_write_proc function by replacing the simple_strtoul and copy_from_user calls with one call to kstrtouint_from_user. -Change the count parameter from unsigned long to size_t as this is the type that the kstrtouint_from_user function expects. (size_t is what will be passed to the adv7393_write_proc function by the proc write handler function proc_file_write anyway) Signed-off-by: Emil Goode Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c index 33ea874..9bdd4b0 100644 --- a/drivers/video/bfin_adv7393fb.c +++ b/drivers/video/bfin_adv7393fb.c @@ -353,18 +353,16 @@ adv7393_read_proc(char *page, char **start, off_t off, static int adv7393_write_proc(struct file *file, const char __user * buffer, - unsigned long count, void *data) + size_t count, void *data) { struct adv7393fb_device *fbdev = data; - char line[8]; unsigned int val; int ret; - ret = copy_from_user(line, buffer, count); + ret = kstrtouint_from_user(buffer, count, 0, &val); if (ret) return -EFAULT; - val = simple_strtoul(line, NULL, 0); adv7393_write(fbdev->client, val >> 8, val & 0xff); return count; -- cgit v0.10.2 From 9bce008bae8b57bc7b007bcc2071d1247a527120 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 5 Jun 2012 18:32:03 -0400 Subject: NFS: Fix a commit bug The new commit code fails to copy the verifier into the wb_verf field of _all_ the nfs_page structures; it only copies it into the first entry. The consequence is that most requests end up failing to match in nfs_commit_release. Fix is to copy the verifier into the req->wb_verf field in nfs_write_completion. Signed-off-by: Trond Myklebust Cc: Fred Isaman diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 23d170b..b5385a7 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -710,12 +710,12 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) bit = NFS_IOHDR_NEED_RESCHED; else if (dreq->flags == 0) { - memcpy(&dreq->verf, &req->wb_verf, + memcpy(&dreq->verf, hdr->verf, sizeof(dreq->verf)); bit = NFS_IOHDR_NEED_COMMIT; dreq->flags = NFS_ODIRECT_DO_COMMIT; } else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) { - if (memcmp(&dreq->verf, &req->wb_verf, sizeof(dreq->verf))) { + if (memcmp(&dreq->verf, hdr->verf, sizeof(dreq->verf))) { dreq->flags = NFS_ODIRECT_RESCHED_WRITES; bit = NFS_IOHDR_NEED_RESCHED; } else diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e6fe3d6..4d6861c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -80,6 +80,7 @@ struct nfs_write_header *nfs_writehdr_alloc(void) INIT_LIST_HEAD(&hdr->rpc_list); spin_lock_init(&hdr->lock); atomic_set(&hdr->refcnt, 0); + hdr->verf = &p->verf; } return p; } @@ -619,6 +620,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) goto next; } if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) { + memcpy(&req->wb_verf, hdr->verf, sizeof(req->wb_verf)); nfs_mark_request_commit(req, hdr->lseg, &cinfo); goto next; } @@ -1255,15 +1257,14 @@ static void nfs_writeback_release_common(void *calldata) struct nfs_write_data *data = calldata; struct nfs_pgio_header *hdr = data->header; int status = data->task.tk_status; - struct nfs_page *req = hdr->req; if ((status >= 0) && nfs_write_need_commit(data)) { spin_lock(&hdr->lock); if (test_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags)) ; /* Do nothing */ else if (!test_and_set_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) - memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); - else if (memcmp(&req->wb_verf, &data->verf, sizeof(req->wb_verf))) + memcpy(hdr->verf, &data->verf, sizeof(*hdr->verf)); + else if (memcmp(hdr->verf, &data->verf, sizeof(*hdr->verf))) set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags); spin_unlock(&hdr->lock); } diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 7519bae..8aadd90 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1237,6 +1237,7 @@ struct nfs_pgio_header { struct list_head rpc_list; atomic_t refcnt; struct nfs_page *req; + struct nfs_writeverf *verf; struct pnfs_layout_segment *lseg; loff_t io_start; const struct rpc_call_ops *mds_ops; @@ -1274,6 +1275,7 @@ struct nfs_write_data { struct nfs_write_header { struct nfs_pgio_header header; struct nfs_write_data rpc_data; + struct nfs_writeverf verf; }; struct nfs_mds_commit_info { -- cgit v0.10.2 From a2c658505bf5c75516ee0a79287223e86a2474af Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Tue, 17 Apr 2012 11:25:04 +0530 Subject: [SCSI] mpt2sas: Fix unsafe using smp_processor_id() in preemptible When CONFIG_DEBUG_PREEMPT is enabled, bug is observed in the smp_processor_id(). This is because smp_processor_id() is not called in preempt safe condition. To fix this issue, use raw_smp_processor_id instead of smp_processor_id. Signed-off-by: Nagalakshmi Nandigama CC: stable@vger.kernel.org Signed-off-by: James Bottomley diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 6102ef2..9d46fcb 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1792,7 +1792,7 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr, static inline u8 _base_get_msix_index(struct MPT2SAS_ADAPTER *ioc) { - return ioc->cpu_msix_table[smp_processor_id()]; + return ioc->cpu_msix_table[raw_smp_processor_id()]; } /** -- cgit v0.10.2 From 470a54207ccf7045a59df727573bd9d148988582 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Sat, 26 May 2012 06:08:48 +0000 Subject: e1000e: test for valid check_reset_block function pointer commit 44abd5c12767a8c567dc4e45fd9aec3b13ca85e0 introduced NULL pointer dereferences when attempting to access the check_reset_block function pointer on 8257x and 80003es2lan non-copper devices. This fix should be applied back through 3.4. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index d863075..905e214 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -258,7 +258,8 @@ static int e1000_set_settings(struct net_device *netdev, * When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ - if (hw->phy.ops.check_reset_block(hw)) { + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(hw)) { e_err("Cannot change link characteristics when SoL/IDER is active.\n"); return -EINVAL; } @@ -1615,7 +1616,8 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) * PHY loopback cannot be performed if SoL/IDER * sessions are active */ - if (hw->phy.ops.check_reset_block(hw)) { + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(hw)) { e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); *data = 0; goto out; diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index 026e8b3..a134399 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -709,7 +709,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) * In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ - if (hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return 0; /* diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index a4b0435..31d37a2 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -6237,7 +6237,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.phy.ms_type = e1000_ms_hw_default; } - if (hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) e_info("PHY reset is blocked due to SOL/IDER session.\n"); /* Set initial default active device features */ @@ -6404,7 +6404,7 @@ err_register: if (!(adapter->flags & FLAG_HAS_AMT)) e1000e_release_hw_control(adapter); err_eeprom: - if (!hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) e1000_phy_hw_reset(&adapter->hw); err_hw_init: kfree(adapter->tx_ring); diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 0334d01..b860d4f 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -2155,9 +2155,11 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) s32 ret_val; u32 ctrl; - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) - return 0; + if (phy->ops.check_reset_block) { + ret_val = phy->ops.check_reset_block(hw); + if (ret_val) + return 0; + } ret_val = phy->ops.acquire(hw); if (ret_val) -- cgit v0.10.2 From 146d4cc98d660cbdeae52ae35a4d038d0dab6da5 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 15 May 2012 05:59:26 +0000 Subject: ixgbe: fix_features rxvlan is independent of DCB and needs to be set DCB can be used independent of if RX VLAN stripping is enabled or disabled so remove erroneous check. Also enable or disable VLAN stripping when features are applied so hardware and feature flags are in sync. CC: Alexander Duyck Signed-off-by: John Fastabend Tested-by: Marcus Dennis Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index bf20457..b8b2087 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3607,10 +3607,6 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82598EB) netif_set_gso_max_size(adapter->netdev, 32768); - - /* Enable VLAN tag insert/strip */ - adapter->netdev->features |= NETIF_F_HW_VLAN_RX; - hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); #ifdef IXGBE_FCOE @@ -6701,11 +6697,6 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); -#ifdef CONFIG_DCB - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) - features &= ~NETIF_F_HW_VLAN_RX; -#endif - /* return error if RXHASH is being enabled when RSS is not supported */ if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) features &= ~NETIF_F_RXHASH; @@ -6718,7 +6709,6 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev, if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) features &= ~NETIF_F_LRO; - return features; } @@ -6766,6 +6756,11 @@ static int ixgbe_set_features(struct net_device *netdev, need_reset = true; } + if (features & NETIF_F_HW_VLAN_RX) + ixgbe_vlan_strip_enable(adapter); + else + ixgbe_vlan_strip_disable(adapter); + if (changed & NETIF_F_RXALL) need_reset = true; -- cgit v0.10.2 From 43e95f11ac0b06fec2c58431b092a60934d730e2 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 15 May 2012 06:12:17 +0000 Subject: ixgbe: IXGBE_RXD_STAT_VP set even with Rx stripping enabled The hardware bit IXGBE_RXD_STAT_VP appears to be set even when Rx stripping is disabled. This results in passing frames up the stack which do not have the 802.1Q tag stripped but have the tci bits set as if it was. Working around this with a check for the feature flag bit. I would welcome any better ideas or a pointer to exactly which bits in the hardware register need to be cleared to get the IXGBE_RXD_STAT_VP bit to be set per data sheet. Signed-off-by: John Fastabend Acked-by: Alexander Duyck Tested-by: Marcus Dennis Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index b8b2087..17ad6a3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1390,6 +1390,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb) { + struct net_device *dev = rx_ring->netdev; + ixgbe_update_rsc_stats(rx_ring, skb); ixgbe_rx_hash(rx_ring, rx_desc, skb); @@ -1401,14 +1403,15 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); #endif - if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { + if ((dev->features & NETIF_F_HW_VLAN_RX) && + ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); __vlan_hwaccel_put_tag(skb, vid); } skb_record_rx_queue(skb, rx_ring->queue_index); - skb->protocol = eth_type_trans(skb, rx_ring->netdev); + skb->protocol = eth_type_trans(skb, dev); } static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, -- cgit v0.10.2 From 8a173b1476d126674104c7c5c6cef0bcd824b001 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 29 May 2012 11:18:44 +0200 Subject: spinlock: Indicate that a lockup is only suspected On an over-committed KVM system we got a: "BUG: spinlock lockup on CPU#2, swapper/2/0" message on the heavily contended virtio blk spinlock. While we might want to reconsider the locking of virtio-blk (lock is held while switching to the host) this patch tries to make the message clearer: the lockup is only suspected. Signed-off-by: Christian Borntraeger Cc: Rusty Russell Cc: Michael S. Tsirkin Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1338283124-7063-1-git-send-email-borntraeger@de.ibm.com Signed-off-by: Ingo Molnar diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index d0ec4f3..e91fbc2 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -118,7 +118,7 @@ static void __spin_lock_debug(raw_spinlock_t *lock) /* lockup suspected: */ if (print_once) { print_once = 0; - spin_dump(lock, "lockup"); + spin_dump(lock, "lockup suspected"); #ifdef CONFIG_SMP trigger_all_cpu_backtrace(); #endif -- cgit v0.10.2 From d8ce7263e1bc3b6b2b906fec0c5037bc27d21d6a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 May 2012 23:30:08 +0200 Subject: m68k: Use generic strncpy_from_user(), strlen_user(), and strnlen_user() Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index cac5b6b..1471201 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -7,6 +7,8 @@ config M68K select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS select GENERIC_CPU_DEVICES + select GENERIC_STRNCPY_FROM_USER if MMU + select GENERIC_STRNLEN_USER if MMU select FPU if MMU select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index 1a922fa..eafa253 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -1,2 +1,4 @@ include include/asm-generic/Kbuild.asm header-y += cachectl.h + +generic-y += word-at-a-time.h diff --git a/arch/m68k/include/asm/uaccess_mm.h b/arch/m68k/include/asm/uaccess_mm.h index 9c80cd5..472c891 100644 --- a/arch/m68k/include/asm/uaccess_mm.h +++ b/arch/m68k/include/asm/uaccess_mm.h @@ -379,12 +379,15 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) #define copy_from_user(to, from, n) __copy_from_user(to, from, n) #define copy_to_user(to, from, n) __copy_to_user(to, from, n) -long strncpy_from_user(char *dst, const char __user *src, long count); -long strnlen_user(const char __user *src, long n); +#define user_addr_max() \ + (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) + +extern long strncpy_from_user(char *dst, const char __user *src, long count); +extern __must_check long strlen_user(const char __user *str); +extern __must_check long strnlen_user(const char __user *str, long n); + unsigned long __clear_user(void __user *to, unsigned long n); #define clear_user __clear_user -#define strlen_user(str) strnlen_user(str, 32767) - #endif /* _M68K_UACCESS_H */ diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c index 5664386..5e97f2e 100644 --- a/arch/m68k/lib/uaccess.c +++ b/arch/m68k/lib/uaccess.c @@ -104,80 +104,6 @@ unsigned long __generic_copy_to_user(void __user *to, const void *from, EXPORT_SYMBOL(__generic_copy_to_user); /* - * Copy a null terminated string from userspace. - */ -long strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res; - char c; - - if (count <= 0) - return count; - - asm volatile ("\n" - "1: "MOVES".b (%2)+,%4\n" - " move.b %4,(%1)+\n" - " jeq 2f\n" - " subq.l #1,%3\n" - " jne 1b\n" - "2: sub.l %3,%0\n" - "3:\n" - " .section .fixup,\"ax\"\n" - " .even\n" - "10: move.l %5,%0\n" - " jra 3b\n" - " .previous\n" - "\n" - " .section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,10b\n" - " .previous" - : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) - : "i" (-EFAULT), "0" (count)); - - return res; -} -EXPORT_SYMBOL(strncpy_from_user); - -/* - * Return the size of a string (including the ending 0) - * - * Return 0 on exception, a value greater than N if too long - */ -long strnlen_user(const char __user *src, long n) -{ - char c; - long res; - - asm volatile ("\n" - "1: subq.l #1,%1\n" - " jmi 3f\n" - "2: "MOVES".b (%0)+,%2\n" - " tst.b %2\n" - " jne 1b\n" - " jra 4f\n" - "\n" - "3: addq.l #1,%0\n" - "4: sub.l %4,%0\n" - "5:\n" - " .section .fixup,\"ax\"\n" - " .even\n" - "20: sub.l %0,%0\n" - " jra 5b\n" - " .previous\n" - "\n" - " .section __ex_table,\"a\"\n" - " .align 4\n" - " .long 2b,20b\n" - " .previous\n" - : "=&a" (res), "+d" (n), "=&d" (c) - : "0" (src), "r" (src)); - - return res; -} -EXPORT_SYMBOL(strnlen_user); - -/* * Zero Userspace */ -- cgit v0.10.2 From ff3dd78cb8055bcb3a10e526044d8b54a773c612 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 4 Jun 2012 19:22:55 +0000 Subject: stmmac: fix driver's doc when run kernel-doc script Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7096633..ea33eae 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -833,8 +833,9 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) /** * stmmac_selec_desc_mode - * @dev : device pointer - * Description: select the Enhanced/Alternate or Normal descriptors */ + * @priv : private structure + * Description: select the Enhanced/Alternate or Normal descriptors + */ static void stmmac_selec_desc_mode(struct stmmac_priv *priv) { if (priv->plat->enh_desc) { @@ -1861,6 +1862,8 @@ static int stmmac_hw_init(struct stmmac_priv *priv) /** * stmmac_dvr_probe * @device: device pointer + * @plat_dat: platform data pointer + * @addr: iobase memory address * Description: this is the main probe function used to * call the alloc_etherdev, allocate the priv structure. */ -- cgit v0.10.2 From 3d2377144ca66c98fa220bda5f945590cf5cfdc0 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 4 Jun 2012 19:22:56 +0000 Subject: stmmac: update driver's doc Fixed the driver's documentation that was obsolete and didn't report new platform fields (recently added). Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt index ab1e8d7..5cb9a19 100644 --- a/Documentation/networking/stmmac.txt +++ b/Documentation/networking/stmmac.txt @@ -10,8 +10,8 @@ Currently this network device driver is for all STM embedded MAC/GMAC (i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000 FF1152AMT0221 D1215994A VIRTEX FPGA board. -DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100 -Universal version 4.0 have been used for developing this driver. +DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether +MAC 10/100 Universal version 4.0 have been used for developing this driver. This driver supports both the platform bus and PCI. @@ -54,27 +54,27 @@ net_device structure enabling the scatter/gather feature. When one or more packets are received, an interrupt happens. The interrupts are not queued so the driver has to scan all the descriptors in the ring during the receive process. -This is based on NAPI so the interrupt handler signals only if there is work to be -done, and it exits. +This is based on NAPI so the interrupt handler signals only if there is work +to be done, and it exits. Then the poll method will be scheduled at some future point. The incoming packets are stored, by the DMA, in a list of pre-allocated socket buffers in order to avoid the memcpy (Zero-copy). 4.3) Timer-Driver Interrupt -Instead of having the device that asynchronously notifies the frame receptions, the -driver configures a timer to generate an interrupt at regular intervals. -Based on the granularity of the timer, the frames that are received by the device -will experience different levels of latency. Some NICs have dedicated timer -device to perform this task. STMMAC can use either the RTC device or the TMU -channel 2 on STLinux platforms. +Instead of having the device that asynchronously notifies the frame receptions, +the driver configures a timer to generate an interrupt at regular intervals. +Based on the granularity of the timer, the frames that are received by the +device will experience different levels of latency. Some NICs have dedicated +timer device to perform this task. STMMAC can use either the RTC device or the +TMU channel 2 on STLinux platforms. The timers frequency can be passed to the driver as parameter; when change it, take care of both hardware capability and network stability/performance impact. -Several performance tests on STM platforms showed this optimisation allows to spare -the CPU while having the maximum throughput. +Several performance tests on STM platforms showed this optimisation allows to +spare the CPU while having the maximum throughput. 4.4) WOL -Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC -core. +Wake up on Lan feature through Magic and Unicast frames are supported for the +GMAC core. 4.5) DMA descriptors Driver handles both normal and enhanced descriptors. The latter has been only @@ -106,7 +106,8 @@ Several driver's information can be passed through the platform These are included in the include/linux/stmmac.h header file and detailed below as well: - struct plat_stmmacenet_data { +struct plat_stmmacenet_data { + char *phy_bus_name; int bus_id; int phy_addr; int interface; @@ -124,19 +125,24 @@ and detailed below as well: void (*bus_setup)(void __iomem *ioaddr); int (*init)(struct platform_device *pdev); void (*exit)(struct platform_device *pdev); + void *custom_cfg; + void *custom_data; void *bsp_priv; }; Where: + o phy_bus_name: phy bus name to attach to the stmmac. o bus_id: bus identifier. o phy_addr: the physical address can be passed from the platform. If it is set to -1 the driver will automatically detect it at run-time by probing all the 32 addresses. o interface: PHY device's interface. o mdio_bus_data: specific platform fields for the MDIO bus. - o pbl: the Programmable Burst Length is maximum number of beats to + o dma_cfg: internal DMA parameters + o pbl: the Programmable Burst Length is maximum number of beats to be transferred in one DMA transaction. GMAC also enables the 4xPBL by default. + o fixed_burst/mixed_burst/burst_len o clk_csr: fixed CSR Clock range selection. o has_gmac: uses the GMAC core. o enh_desc: if sets the MAC will use the enhanced descriptor structure. @@ -160,8 +166,9 @@ Where: this is sometime necessary on some platforms (e.g. ST boxes) where the HW needs to have set some PIO lines or system cfg registers. - o custom_cfg: this is a custom configuration that can be passed while - initialising the resources. + o custom_cfg/custom_data: this is a custom configuration that can be passed + while initialising the resources. + o bsp_priv: another private poiter. For MDIO bus The we have: @@ -180,7 +187,6 @@ Where: o irqs: list of IRQs, one per PHY. o probed_phy_irq: if irqs is NULL, use this for probed PHY. - For DMA engine we have the following internal fields that should be tuned according to the HW capabilities. -- cgit v0.10.2 From ba27ec66ffeb78cbf9f85e168b32551a9aaf2a34 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 4 Jun 2012 19:22:57 +0000 Subject: stmmac: fix driver Kconfig when built as module This patches fixes the driver when built as dynamic module. In fact, the platform part cannot be built and the probe fails (thanks to Bob Liu that reported this bug). v2: as D. Miller suggested, it is not necessary to make the pci and the platform code mutually exclusive. Having both could also help, at built time ,to verify that all the code is validated and compiles fine. v3: removed wrong Reviewed-by from the patch Reported-by: Bob Liu cc: Rayagond Kokatanur Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 0364283..0076f77 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -13,9 +13,8 @@ config STMMAC_ETH if STMMAC_ETH config STMMAC_PLATFORM - tristate "STMMAC platform bus support" + bool "STMMAC Platform bus support" depends on STMMAC_ETH - default y ---help--- This selects the platform specific bus support for the stmmac device driver. This is the driver used @@ -26,7 +25,7 @@ config STMMAC_PLATFORM If unsure, say N. config STMMAC_PCI - tristate "STMMAC support on PCI bus (EXPERIMENTAL)" + bool "STMMAC PCI bus support (EXPERIMENTAL)" depends on STMMAC_ETH && PCI && EXPERIMENTAL ---help--- This is to select the Synopsys DWMAC available on PCI devices, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 6b5d060..6d07ba2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -95,7 +95,8 @@ extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); extern const struct stmmac_desc_ops enh_desc_ops; extern const struct stmmac_desc_ops ndesc_ops; - +extern struct pci_driver stmmac_pci_driver; +extern struct platform_driver stmmac_pltfr_driver; int stmmac_freeze(struct net_device *ndev); int stmmac_restore(struct net_device *ndev); int stmmac_resume(struct net_device *ndev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ea33eae..3638569 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef CONFIG_STMMAC_DEBUG_FS #include #include @@ -2093,6 +2094,30 @@ int stmmac_restore(struct net_device *ndev) } #endif /* CONFIG_PM */ +static int __init stmmac_init(void) +{ + int err = 0; + + err = platform_driver_register(&stmmac_pltfr_driver); + + if (!err) { + err = pci_register_driver(&stmmac_pci_driver); + if (err) + platform_driver_unregister(&stmmac_pltfr_driver); + } + + return err; +} + +static void __exit stmmac_exit(void) +{ + pci_unregister_driver(&stmmac_pci_driver); + platform_driver_unregister(&stmmac_pltfr_driver); +} + +module_init(stmmac_init); +module_exit(stmmac_exit); + #ifndef MODULE static int __init stmmac_cmdline_opt(char *str) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 58fab53..cf826e6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -179,7 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = { MODULE_DEVICE_TABLE(pci, stmmac_id_table); -static struct pci_driver stmmac_driver = { +struct pci_driver stmmac_pci_driver = { .name = STMMAC_RESOURCE_NAME, .id_table = stmmac_id_table, .probe = stmmac_pci_probe, @@ -190,33 +190,6 @@ static struct pci_driver stmmac_driver = { #endif }; -/** - * stmmac_init_module - Entry point for the driver - * Description: This function is the entry point for the driver. - */ -static int __init stmmac_init_module(void) -{ - int ret; - - ret = pci_register_driver(&stmmac_driver); - if (ret < 0) - pr_err("%s: ERROR: driver registration failed\n", __func__); - - return ret; -} - -/** - * stmmac_cleanup_module - Cleanup routine for the driver - * Description: This function is the cleanup routine for the driver. - */ -static void __exit stmmac_cleanup_module(void) -{ - pci_unregister_driver(&stmmac_driver); -} - -module_init(stmmac_init_module); -module_exit(stmmac_cleanup_module); - MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver"); MODULE_AUTHOR("Rayagond Kokatanur "); MODULE_AUTHOR("Giuseppe Cavallaro "); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 3dd8f08..680d2b8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -255,7 +255,7 @@ static const struct of_device_id stmmac_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, stmmac_dt_ids); -static struct platform_driver stmmac_driver = { +struct platform_driver stmmac_pltfr_driver = { .probe = stmmac_pltfr_probe, .remove = stmmac_pltfr_remove, .driver = { @@ -266,8 +266,6 @@ static struct platform_driver stmmac_driver = { }, }; -module_platform_driver(stmmac_driver); - MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); MODULE_AUTHOR("Giuseppe Cavallaro "); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 32a527add871a51b3c06177849d18bf71e33b320 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Tue, 5 Jun 2012 02:23:20 +0000 Subject: ide: icside.c: Fix compile with CONFIG_BLK_DEV_IDEDMA_ICS=n The icside driver can be configured without DMA support, but it doesn't compile then, because DMA operations are referenced. drivers/ide/icside.c:523: error: 'icside_v6_port_ops' undeclared drivers/ide/icside.c:522: error: 'icside_dma_init' undeclared Signed-off-by: Christian Dietrich Signed-off-by: David S. Miller diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 8716066..83e5100 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -375,8 +375,6 @@ static const struct ide_dma_ops icside_v6_dma_ops = { .dma_test_irq = icside_dma_test_irq, .dma_lost_irq = ide_dma_lost_irq, }; -#else -#define icside_v6_dma_ops NULL #endif static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) @@ -456,7 +454,6 @@ err_free: static const struct ide_port_info icside_v6_port_info __initdata = { .init_dma = icside_dma_off_init, .port_ops = &icside_v6_no_dma_port_ops, - .dma_ops = &icside_v6_dma_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2, .swdma_mask = ATA_SWDMA2, @@ -518,11 +515,13 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) ecard_set_drvdata(ec, state); +#ifdef CONFIG_BLK_DEV_IDEDMA_ICS if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { d.init_dma = icside_dma_init; d.port_ops = &icside_v6_port_ops; - } else - d.dma_ops = NULL; + d.dma_ops = &icside_v6_dma_ops; + } +#endif ret = ide_host_register(host, &d, hws); if (ret) -- cgit v0.10.2 From 027253c138a12b075e724f94b6cc43fd7071c14f Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Tue, 5 Jun 2012 02:28:59 +0000 Subject: ide: icside.c: fix printk format string compile warning Use correct format string parameter for the peak datarate, and prevent uninitialized use of cycle_time. Signed-off-by: Christian Dietrich Signed-off-by: David S. Miller diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 83e5100..bcb507b 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -236,7 +236,7 @@ static const struct ide_port_ops icside_v6_no_dma_port_ops = { */ static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) { - unsigned long cycle_time; + unsigned long cycle_time = 0; int use_dma_info = 0; const u8 xfer_mode = drive->dma_mode; @@ -271,9 +271,9 @@ static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) ide_set_drivedata(drive, (void *)cycle_time); - printk("%s: %s selected (peak %dMB/s)\n", drive->name, - ide_xfer_verbose(xfer_mode), - 2000 / (unsigned long)ide_get_drivedata(drive)); + printk(KERN_INFO "%s: %s selected (peak %luMB/s)\n", + drive->name, ide_xfer_verbose(xfer_mode), + 2000 / (cycle_time ? cycle_time : (unsigned long) -1)); } static const struct ide_port_ops icside_v6_port_ops = { -- cgit v0.10.2 From 9a43a02648e8414b2a757437820aa928208fc42f Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 6 Jun 2012 06:40:43 +0000 Subject: mv643xx_eth: Fix compile error for architectures without clk. Commit 452503ebc (ARM: Orion: Eth: Add clk/clkdev support.) broke the building of the driver on architectures which don't have clk support. In particular PPC32 Pegasos which uses this driver. Add #ifdef around the clk API usage. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 04d901d..f0f06b2 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -436,7 +436,9 @@ struct mv643xx_eth_private { /* * Hardware-specific parameters. */ +#if defined(CONFIG_HAVE_CLK) struct clk *clk; +#endif unsigned int t_clk; }; @@ -2895,17 +2897,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->dev = dev; /* - * Get the clk rate, if there is one, otherwise use the default. + * Start with a default rate, and if there is a clock, allow + * it to override the default. */ + mp->t_clk = 133000000; +#if defined(CONFIG_HAVE_CLK) mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0")); if (!IS_ERR(mp->clk)) { clk_prepare_enable(mp->clk); mp->t_clk = clk_get_rate(mp->clk); - } else { - mp->t_clk = 133000000; - printk(KERN_WARNING "Unable to get clock"); } - +#endif set_params(mp, pd); netif_set_real_num_tx_queues(dev, mp->txq_count); netif_set_real_num_rx_queues(dev, mp->rxq_count); @@ -2995,10 +2997,13 @@ static int mv643xx_eth_remove(struct platform_device *pdev) phy_detach(mp->phy); cancel_work_sync(&mp->tx_timeout_task); +#if defined(CONFIG_HAVE_CLK) if (!IS_ERR(mp->clk)) { clk_disable_unprepare(mp->clk); clk_put(mp->clk); } +#endif + free_netdev(mp->dev); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From dd03cff23d694cfb0fdae80cb618e7ced05ea696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 5 Jun 2012 21:18:10 +0000 Subject: net: sierra_net: device IDs for Aircard 320U++ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding device IDs for Aircard 320U and two other devices found in the out-of-tree version of this driver. Cc: linux@sierrawireless.com Cc: Autif Khan Cc: Tom Cassidy Cc: stable@vger.kernel.org Signed-off-by: Bjørn Mork Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 3faef56..d75d1f5 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -946,7 +946,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, } static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; -static const struct sierra_net_info_data sierra_net_info_data_68A3 = { +static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, .whitelist = { .infolen = ARRAY_SIZE(sierra_net_ifnum_list), @@ -954,7 +954,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = { } }; -static const struct driver_info sierra_net_info_68A3 = { +static const struct driver_info sierra_net_info_direct_ip = { .description = "Sierra Wireless USB-to-WWAN Modem", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .bind = sierra_net_bind, @@ -962,12 +962,18 @@ static const struct driver_info sierra_net_info_68A3 = { .status = sierra_net_status, .rx_fixup = sierra_net_rx_fixup, .tx_fixup = sierra_net_tx_fixup, - .data = (unsigned long)&sierra_net_info_data_68A3, + .data = (unsigned long)&sierra_net_info_data_direct_ip, }; static const struct usb_device_id products[] = { {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_68A3}, + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, {}, /* last item */ }; -- cgit v0.10.2 From 55432d2b543a4b6dfae54f5c432a566877a85d90 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 5 Jun 2012 03:00:18 +0000 Subject: inetpeer: fix a race in inetpeer_gc_worker() commit 5faa5df1fa2024 (inetpeer: Invalidate the inetpeer tree along with the routing cache) added a race : Before freeing an inetpeer, we must respect a RCU grace period, and make sure no user will attempt to increase refcnt. inetpeer_invalidate_tree() waits for a RCU grace period before inserting inetpeer tree into gc_list and waking the worker. At that time, no concurrent lookup can find a inetpeer in this tree. Signed-off-by: Eric Dumazet Cc: Steffen Klassert Acked-by: Steffen Klassert Signed-off-by: David S. Miller diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index b94765e..2040bff 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -40,7 +40,10 @@ struct inet_peer { u32 pmtu_orig; u32 pmtu_learned; struct inetpeer_addr_base redirect_learned; - struct list_head gc_list; + union { + struct list_head gc_list; + struct rcu_head gc_rcu; + }; /* * Once inet_peer is queued for deletion (refcnt == -1), following fields * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index d4d61b6..dfba343 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -560,6 +560,17 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout) } EXPORT_SYMBOL(inet_peer_xrlim_allow); +static void inetpeer_inval_rcu(struct rcu_head *head) +{ + struct inet_peer *p = container_of(head, struct inet_peer, gc_rcu); + + spin_lock_bh(&gc_lock); + list_add_tail(&p->gc_list, &gc_list); + spin_unlock_bh(&gc_lock); + + schedule_delayed_work(&gc_work, gc_delay); +} + void inetpeer_invalidate_tree(int family) { struct inet_peer *old, *new, *prev; @@ -576,10 +587,7 @@ void inetpeer_invalidate_tree(int family) prev = cmpxchg(&base->root, old, new); if (prev == old) { base->total = 0; - spin_lock(&gc_lock); - list_add_tail(&prev->gc_list, &gc_list); - spin_unlock(&gc_lock); - schedule_delayed_work(&gc_work, gc_delay); + call_rcu(&prev->gc_rcu, inetpeer_inval_rcu); } out: -- cgit v0.10.2 From f25efd851cc8c0f63d74334bc784a437f4df8ee4 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Wed, 6 Jun 2012 14:12:07 -0400 Subject: NFS: Map minor mismatch error to protocol not support error. Sservers that only have NFSv4.1 support the NFS4ERR_MINOR_VERS_MISMATCH error is return on v4.0 mounts. Mapping that error to EPROTONOSUPPORT will cause the mount to back off to v3 instead of failing. Signed-off-by: Steve Dickson Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7c218fd..bfc919f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -105,6 +105,8 @@ static int nfs4_map_errors(int err) return -EINVAL; case -NFS4ERR_SHARE_DENIED: return -EACCES; + case -NFS4ERR_MINOR_VERS_MISMATCH: + return -EPROTONOSUPPORT; default: dprintk("%s could not handle NFSv4 error %d\n", __func__, -err); -- cgit v0.10.2 From ea80dadec7a06889562b478cf0b87afbe62b7ac8 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 6 Jun 2012 14:54:13 +0900 Subject: [SCSI] Fix sd_probe_domain config problem With CONFIG_BLK_DEV_SD = n and CONFIG_PM = n, you get this compile failure: (.text+0x4f6c77): undefined reference to `scsi_sd_probe_domain' This was introduced by commit a7a20d103994fd760766e6c9d494daa569cbfe06 Author: Dan Williams Date: Thu Mar 22 17:05:11 2012 -0700 [SCSI] sd: limit the scope of the async probe domain And happens because scsi_sd_probe_domain is conditionally defined but unconditionally used. Fix this by making the symbol unconditionally defined. Reported-by: Randy Dunlap Cc: Dan Williams Tested-by: Randy Dunlap Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 61c82a3..bbbc9c9 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -90,11 +90,9 @@ unsigned int scsi_logging_level; EXPORT_SYMBOL(scsi_logging_level); #endif -#if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_BLK_DEV_SD) -/* sd and scsi_pm need to coordinate flushing async actions */ +/* sd, scsi core and power management need to coordinate flushing async actions */ LIST_HEAD(scsi_sd_probe_domain); EXPORT_SYMBOL(scsi_sd_probe_domain); -#endif /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. * You may not alter any existing entry (although adding new ones is -- cgit v0.10.2 From f2bf1f6f5f89d031245067512449fc889b2f4bb2 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 6 Jun 2012 19:50:40 -0400 Subject: tracing: Have tracing_off() actually turn tracing off A recent update to have tracing_on/off() only affect the ftrace ring buffers instead of all ring buffers had a cut and paste error. The tracing_off() did the exact same thing as tracing_on() and would not actually turn off tracing. Unfortunately, tracing_off() is more important to be working than tracing_on() as this is a key development tool, as it lets the developer turn off tracing as soon as a problem is discovered. It is also used by panic and oops code. This bug also breaks the 'echo func:traceoff > set_ftrace_filter' Cc: # 3.4 Signed-off-by: Steven Rostedt diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 68032c6..49249c2 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -371,7 +371,7 @@ EXPORT_SYMBOL_GPL(tracing_on); void tracing_off(void) { if (global_trace.buffer) - ring_buffer_record_on(global_trace.buffer); + ring_buffer_record_off(global_trace.buffer); /* * This flag is only looked at when buffers haven't been * allocated yet. We don't really care about the race -- cgit v0.10.2 From 8f5af6f1f2d09fe5eac86a5dc1731a5917c1503a Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 4 May 2012 08:31:53 -0700 Subject: rcu: RCU_FAST_NO_HZ detection of callback adoption In the present implementations of CPU hotplug, the outgoing CPU is guaranteed to run its stop-machine process on the way out, which will guarantee that RCU_FAST_NO_HZ forces the CPU out of dyntick-idle mode. However, new versions of CPU hotplug might not work this way. This commit therefore removes this design constraint by explicitly notifying CPUs when they adopt non-lazy RCU callbacks. Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested-by: Heiko Carstens Tested-by: Pascal Chapperon diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 0da7b88..3b0f133 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1397,6 +1397,8 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp) rdp->qlen_lazy += rsp->qlen_lazy; rdp->qlen += rsp->qlen; rdp->n_cbs_adopted += rsp->qlen; + if (rsp->qlen_lazy != rsp->qlen) + rcu_idle_count_callbacks_posted(); rsp->qlen_lazy = 0; rsp->qlen = 0; -- cgit v0.10.2 From fd4b352687fd8604d49c190c4c9ea9e369fd42d5 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 5 May 2012 19:10:35 -0700 Subject: rcu: Update RCU_FAST_NO_HZ tracing for lazy callbacks In the current code, a short dyntick-idle interval (where there is at least one non-lazy callback on the CPU) and a long dyntick-idle interval (where there are only lazy callbacks on the CPU) are traced identically, which can be less than helpful. This commit therefore emits different event traces in these two cases. Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested-by: Heiko Carstens Tested-by: Pascal Chapperon diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index 1480900..d274734 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -289,6 +289,7 @@ TRACE_EVENT(rcu_dyntick, * "In holdoff": Nothing to do, holding off after unsuccessful attempt. * "Begin holdoff": Attempt failed, don't retry until next jiffy. * "Dyntick with callbacks": Entering dyntick-idle despite callbacks. + * "Dyntick with lazy callbacks": Entering dyntick-idle w/lazy callbacks. * "More callbacks": Still more callbacks, try again to clear them out. * "Callbacks drained": All callbacks processed, off to dyntick idle! * "Timer": Timer fired to cause CPU to continue processing callbacks. diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 2411000..5449f02 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -2165,15 +2165,17 @@ static void rcu_prepare_for_idle(int cpu) !rcu_pending(cpu) && !local_softirq_pending()) { /* Can we go dyntick-idle despite still having callbacks? */ - trace_rcu_prep_idle("Dyntick with callbacks"); per_cpu(rcu_dyntick_drain, cpu) = 0; per_cpu(rcu_dyntick_holdoff, cpu) = jiffies; - if (rcu_cpu_has_nonlazy_callbacks(cpu)) + if (rcu_cpu_has_nonlazy_callbacks(cpu)) { + trace_rcu_prep_idle("Dyntick with callbacks"); per_cpu(rcu_idle_gp_timer_expires, cpu) = jiffies + RCU_IDLE_GP_DELAY; - else + } else { per_cpu(rcu_idle_gp_timer_expires, cpu) = jiffies + RCU_IDLE_LAZY_GP_DELAY; + trace_rcu_prep_idle("Dyntick with lazy callbacks"); + } tp = &per_cpu(rcu_idle_gp_timer, cpu); mod_timer_pinned(tp, per_cpu(rcu_idle_gp_timer_expires, cpu)); per_cpu(rcu_nonlazy_posted_snap, cpu) = -- cgit v0.10.2 From 5955f7eecd77d6b440db278b266cfecdb72ecd00 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 9 May 2012 12:07:05 -0700 Subject: rcu: Move RCU_FAST_NO_HZ per-CPU variables to rcu_dynticks structure The RCU_FAST_NO_HZ code relies on a number of per-CPU variables. This works, but is hidden from someone scanning the data structures in rcutree.h. This commit therefore converts these per-CPU variables to fields in the per-CPU rcu_dynticks structures. Suggested-by: Peter Zijlstra Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested-by: Heiko Carstens Tested-by: Pascal Chapperon diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 7f5d138..ea05649 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -84,6 +84,20 @@ struct rcu_dynticks { /* Process level is worth LLONG_MAX/2. */ int dynticks_nmi_nesting; /* Track NMI nesting level. */ atomic_t dynticks; /* Even value for idle, else odd. */ +#ifdef CONFIG_RCU_FAST_NO_HZ + int dyntick_drain; /* Prepare-for-idle state variable. */ + unsigned long dyntick_holdoff; + /* No retries for the jiffy of failure. */ + struct timer_list idle_gp_timer; + /* Wake up CPU sleeping with callbacks. */ + unsigned long idle_gp_timer_expires; + /* When to wake up CPU (for repost). */ + bool idle_first_pass; /* First pass of attempt to go idle? */ + unsigned long nonlazy_posted; + /* # times non-lazy CBs posted to CPU. */ + unsigned long nonlazy_posted_snap; + /* idle-period nonlazy_posted snapshot. */ +#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ }; /* RCU's kthread states for tracing. */ diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 5449f02..6bd9637 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1962,21 +1962,6 @@ static void rcu_idle_count_callbacks_posted(void) #define RCU_IDLE_GP_DELAY 6 /* Roughly one grace period. */ #define RCU_IDLE_LAZY_GP_DELAY (6 * HZ) /* Roughly six seconds. */ -/* Loop counter for rcu_prepare_for_idle(). */ -static DEFINE_PER_CPU(int, rcu_dyntick_drain); -/* If rcu_dyntick_holdoff==jiffies, don't try to enter dyntick-idle mode. */ -static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff); -/* Timer to awaken the CPU if it enters dyntick-idle mode with callbacks. */ -static DEFINE_PER_CPU(struct timer_list, rcu_idle_gp_timer); -/* Scheduled expiry time for rcu_idle_gp_timer to allow reposting. */ -static DEFINE_PER_CPU(unsigned long, rcu_idle_gp_timer_expires); -/* Enable special processing on first attempt to enter dyntick-idle mode. */ -static DEFINE_PER_CPU(bool, rcu_idle_first_pass); -/* Running count of non-lazy callbacks posted, never decremented. */ -static DEFINE_PER_CPU(unsigned long, rcu_nonlazy_posted); -/* Snapshot of rcu_nonlazy_posted to detect meaningful exits from idle. */ -static DEFINE_PER_CPU(unsigned long, rcu_nonlazy_posted_snap); - /* * Allow the CPU to enter dyntick-idle mode if either: (1) There are no * callbacks on this CPU, (2) this CPU has not yet attempted to enter @@ -1988,13 +1973,15 @@ static DEFINE_PER_CPU(unsigned long, rcu_nonlazy_posted_snap); */ int rcu_needs_cpu(int cpu) { + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + /* Flag a new idle sojourn to the idle-entry state machine. */ - per_cpu(rcu_idle_first_pass, cpu) = 1; + rdtp->idle_first_pass = 1; /* If no callbacks, RCU doesn't need the CPU. */ if (!rcu_cpu_has_callbacks(cpu)) return 0; /* Otherwise, RCU needs the CPU only if it recently tried and failed. */ - return per_cpu(rcu_dyntick_holdoff, cpu) == jiffies; + return rdtp->dyntick_holdoff == jiffies; } /* @@ -2075,21 +2062,24 @@ static void rcu_idle_gp_timer_func(unsigned long cpu_in) */ static void rcu_prepare_for_idle_init(int cpu) { - per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1; - setup_timer(&per_cpu(rcu_idle_gp_timer, cpu), - rcu_idle_gp_timer_func, cpu); - per_cpu(rcu_idle_gp_timer_expires, cpu) = jiffies - 1; - per_cpu(rcu_idle_first_pass, cpu) = 1; + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + + rdtp->dyntick_holdoff = jiffies - 1; + setup_timer(&rdtp->idle_gp_timer, rcu_idle_gp_timer_func, cpu); + rdtp->idle_gp_timer_expires = jiffies - 1; + rdtp->idle_first_pass = 1; } /* * Clean up for exit from idle. Because we are exiting from idle, there - * is no longer any point to rcu_idle_gp_timer, so cancel it. This will + * is no longer any point to ->idle_gp_timer, so cancel it. This will * do nothing if this timer is not active, so just cancel it unconditionally. */ static void rcu_cleanup_after_idle(int cpu) { - del_timer(&per_cpu(rcu_idle_gp_timer, cpu)); + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + + del_timer(&rdtp->idle_gp_timer); trace_rcu_prep_idle("Cleanup after idle"); } @@ -2108,42 +2098,41 @@ static void rcu_cleanup_after_idle(int cpu) * Because it is not legal to invoke rcu_process_callbacks() with irqs * disabled, we do one pass of force_quiescent_state(), then do a * invoke_rcu_core() to cause rcu_process_callbacks() to be invoked - * later. The per-cpu rcu_dyntick_drain variable controls the sequencing. + * later. The ->dyntick_drain field controls the sequencing. * * The caller must have disabled interrupts. */ static void rcu_prepare_for_idle(int cpu) { struct timer_list *tp; + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); /* * If this is an idle re-entry, for example, due to use of * RCU_NONIDLE() or the new idle-loop tracing API within the idle * loop, then don't take any state-machine actions, unless the * momentary exit from idle queued additional non-lazy callbacks. - * Instead, repost the rcu_idle_gp_timer if this CPU has callbacks + * Instead, repost the ->idle_gp_timer if this CPU has callbacks * pending. */ - if (!per_cpu(rcu_idle_first_pass, cpu) && - (per_cpu(rcu_nonlazy_posted, cpu) == - per_cpu(rcu_nonlazy_posted_snap, cpu))) { + if (!rdtp->idle_first_pass && + (rdtp->nonlazy_posted == rdtp->nonlazy_posted_snap)) { if (rcu_cpu_has_callbacks(cpu)) { - tp = &per_cpu(rcu_idle_gp_timer, cpu); - mod_timer_pinned(tp, per_cpu(rcu_idle_gp_timer_expires, cpu)); + tp = &rdtp->idle_gp_timer; + mod_timer_pinned(tp, rdtp->idle_gp_timer_expires); } return; } - per_cpu(rcu_idle_first_pass, cpu) = 0; - per_cpu(rcu_nonlazy_posted_snap, cpu) = - per_cpu(rcu_nonlazy_posted, cpu) - 1; + rdtp->idle_first_pass = 0; + rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted - 1; /* * If there are no callbacks on this CPU, enter dyntick-idle mode. * Also reset state to avoid prejudicing later attempts. */ if (!rcu_cpu_has_callbacks(cpu)) { - per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1; - per_cpu(rcu_dyntick_drain, cpu) = 0; + rdtp->dyntick_holdoff = jiffies - 1; + rdtp->dyntick_drain = 0; trace_rcu_prep_idle("No callbacks"); return; } @@ -2152,38 +2141,37 @@ static void rcu_prepare_for_idle(int cpu) * If in holdoff mode, just return. We will presumably have * refrained from disabling the scheduling-clock tick. */ - if (per_cpu(rcu_dyntick_holdoff, cpu) == jiffies) { + if (rdtp->dyntick_holdoff == jiffies) { trace_rcu_prep_idle("In holdoff"); return; } - /* Check and update the rcu_dyntick_drain sequencing. */ - if (per_cpu(rcu_dyntick_drain, cpu) <= 0) { + /* Check and update the ->dyntick_drain sequencing. */ + if (rdtp->dyntick_drain <= 0) { /* First time through, initialize the counter. */ - per_cpu(rcu_dyntick_drain, cpu) = RCU_IDLE_FLUSHES; - } else if (per_cpu(rcu_dyntick_drain, cpu) <= RCU_IDLE_OPT_FLUSHES && + rdtp->dyntick_drain = RCU_IDLE_FLUSHES; + } else if (rdtp->dyntick_drain <= RCU_IDLE_OPT_FLUSHES && !rcu_pending(cpu) && !local_softirq_pending()) { /* Can we go dyntick-idle despite still having callbacks? */ - per_cpu(rcu_dyntick_drain, cpu) = 0; - per_cpu(rcu_dyntick_holdoff, cpu) = jiffies; + rdtp->dyntick_drain = 0; + rdtp->dyntick_holdoff = jiffies; if (rcu_cpu_has_nonlazy_callbacks(cpu)) { trace_rcu_prep_idle("Dyntick with callbacks"); - per_cpu(rcu_idle_gp_timer_expires, cpu) = + rdtp->idle_gp_timer_expires = jiffies + RCU_IDLE_GP_DELAY; } else { - per_cpu(rcu_idle_gp_timer_expires, cpu) = + rdtp->idle_gp_timer_expires = jiffies + RCU_IDLE_LAZY_GP_DELAY; trace_rcu_prep_idle("Dyntick with lazy callbacks"); } - tp = &per_cpu(rcu_idle_gp_timer, cpu); - mod_timer_pinned(tp, per_cpu(rcu_idle_gp_timer_expires, cpu)); - per_cpu(rcu_nonlazy_posted_snap, cpu) = - per_cpu(rcu_nonlazy_posted, cpu); + tp = &rdtp->idle_gp_timer; + mod_timer_pinned(tp, rdtp->idle_gp_timer_expires); + rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted; return; /* Nothing more to do immediately. */ - } else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) { + } else if (--(rdtp->dyntick_drain) <= 0) { /* We have hit the limit, so time to give up. */ - per_cpu(rcu_dyntick_holdoff, cpu) = jiffies; + rdtp->dyntick_holdoff = jiffies; trace_rcu_prep_idle("Begin holdoff"); invoke_rcu_core(); /* Force the CPU out of dyntick-idle. */ return; @@ -2229,7 +2217,7 @@ static void rcu_prepare_for_idle(int cpu) */ static void rcu_idle_count_callbacks_posted(void) { - __this_cpu_add(rcu_nonlazy_posted, 1); + __this_cpu_add(rcu_dynticks.nonlazy_posted, 1); } #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ @@ -2240,11 +2228,12 @@ static void rcu_idle_count_callbacks_posted(void) static void print_cpu_stall_fast_no_hz(char *cp, int cpu) { - struct timer_list *tltp = &per_cpu(rcu_idle_gp_timer, cpu); + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + struct timer_list *tltp = &rdtp->idle_gp_timer; sprintf(cp, "drain=%d %c timer=%lu", - per_cpu(rcu_dyntick_drain, cpu), - per_cpu(rcu_dyntick_holdoff, cpu) == jiffies ? 'H' : '.', + rdtp->dyntick_drain, + rdtp->dyntick_holdoff == jiffies ? 'H' : '.', timer_pending(tltp) ? tltp->expires - jiffies : -1); } -- cgit v0.10.2 From aa9b16306e3243229580ff889cc59fd66bf77973 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 10 May 2012 16:41:44 -0700 Subject: rcu: Precompute RCU_FAST_NO_HZ timer offsets When a CPU is entering dyntick-idle mode, tick_nohz_stop_sched_tick() calls rcu_needs_cpu() see if RCU needs that CPU, and, if not, computes the next wakeup time based on the timer wheels. Only later, when actually entering the idle loop, rcu_prepare_for_idle() will be invoked. In some cases, rcu_prepare_for_idle() will post timers to wake the CPU back up. But all for naught: The next wakeup time for the CPU has already been computed, and posting a timer afterwards does not force that wakeup time to be recomputed. This means that rcu_prepare_for_idle()'s have no effect. This is not a problem on a busy system because something else will wake up the CPU soon enough. However, on lightly loaded systems, the CPU might stay asleep for a considerable length of time. If that CPU has a callback that the rest of the system is waiting on, the system might run very slowly or (in theory) even hang. This commit avoids this problem by having rcu_needs_cpu() give tick_nohz_stop_sched_tick() an estimate of when RCU will need the CPU to wake back up, which tick_nohz_stop_sched_tick() takes into account when programming the CPU's wakeup time. An alternative approach is for rcu_prepare_for_idle() to use hrtimers instead of normal timers, but timers are much more efficient than are hrtimers for frequently and repeatedly posting and cancelling a given timer, which is exactly what RCU_FAST_NO_HZ does. Reported-by: Pascal Chapperon Reported-by: Heiko Carstens Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested-by: Heiko Carstens Tested-by: Pascal Chapperon diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index adb5e5a..854dc4c 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -87,8 +87,9 @@ static inline void kfree_call_rcu(struct rcu_head *head, #ifdef CONFIG_TINY_RCU -static inline int rcu_needs_cpu(int cpu) +static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) { + *delta_jiffies = ULONG_MAX; return 0; } @@ -96,8 +97,9 @@ static inline int rcu_needs_cpu(int cpu) int rcu_preempt_needs_cpu(void); -static inline int rcu_needs_cpu(int cpu) +static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) { + *delta_jiffies = ULONG_MAX; return rcu_preempt_needs_cpu(); } diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 3c6083c..952b793 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -32,7 +32,7 @@ extern void rcu_init(void); extern void rcu_note_context_switch(int cpu); -extern int rcu_needs_cpu(int cpu); +extern int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); extern void rcu_cpu_stall_reset(void); /* diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 6bd9637..5271a02 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1886,8 +1886,9 @@ static void __cpuinit rcu_prepare_kthreads(int cpu) * Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs * any flavor of RCU. */ -int rcu_needs_cpu(int cpu) +int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) { + *delta_jiffies = ULONG_MAX; return rcu_cpu_has_callbacks(cpu); } @@ -1963,28 +1964,6 @@ static void rcu_idle_count_callbacks_posted(void) #define RCU_IDLE_LAZY_GP_DELAY (6 * HZ) /* Roughly six seconds. */ /* - * Allow the CPU to enter dyntick-idle mode if either: (1) There are no - * callbacks on this CPU, (2) this CPU has not yet attempted to enter - * dyntick-idle mode, or (3) this CPU is in the process of attempting to - * enter dyntick-idle mode. Otherwise, if we have recently tried and failed - * to enter dyntick-idle mode, we refuse to try to enter it. After all, - * it is better to incur scheduling-clock interrupts than to spin - * continuously for the same time duration! - */ -int rcu_needs_cpu(int cpu) -{ - struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); - - /* Flag a new idle sojourn to the idle-entry state machine. */ - rdtp->idle_first_pass = 1; - /* If no callbacks, RCU doesn't need the CPU. */ - if (!rcu_cpu_has_callbacks(cpu)) - return 0; - /* Otherwise, RCU needs the CPU only if it recently tried and failed. */ - return rdtp->dyntick_holdoff == jiffies; -} - -/* * Does the specified flavor of RCU have non-lazy callbacks pending on * the specified CPU? Both RCU flavor and CPU are specified by the * rcu_data structure. @@ -2027,6 +2006,47 @@ static bool rcu_cpu_has_nonlazy_callbacks(int cpu) } /* + * Allow the CPU to enter dyntick-idle mode if either: (1) There are no + * callbacks on this CPU, (2) this CPU has not yet attempted to enter + * dyntick-idle mode, or (3) this CPU is in the process of attempting to + * enter dyntick-idle mode. Otherwise, if we have recently tried and failed + * to enter dyntick-idle mode, we refuse to try to enter it. After all, + * it is better to incur scheduling-clock interrupts than to spin + * continuously for the same time duration! + * + * The delta_jiffies argument is used to store the time when RCU is + * going to need the CPU again if it still has callbacks. The reason + * for this is that rcu_prepare_for_idle() might need to post a timer, + * but if so, it will do so after tick_nohz_stop_sched_tick() has set + * the wakeup time for this CPU. This means that RCU's timer can be + * delayed until the wakeup time, which defeats the purpose of posting + * a timer. + */ +int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) +{ + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + + /* Flag a new idle sojourn to the idle-entry state machine. */ + rdtp->idle_first_pass = 1; + /* If no callbacks, RCU doesn't need the CPU. */ + if (!rcu_cpu_has_callbacks(cpu)) { + *delta_jiffies = ULONG_MAX; + return 0; + } + if (rdtp->dyntick_holdoff == jiffies) { + /* RCU recently tried and failed, so don't try again. */ + *delta_jiffies = 1; + return 1; + } + /* Set up for the possibility that RCU will post a timer. */ + if (rcu_cpu_has_nonlazy_callbacks(cpu)) + *delta_jiffies = RCU_IDLE_GP_DELAY; + else + *delta_jiffies = RCU_IDLE_LAZY_GP_DELAY; + return 0; +} + +/* * Handler for smp_call_function_single(). The only point of this * handler is to wake the CPU up, so the handler does only tracing. */ diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 6a3a5b9..52f5ebb 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -274,6 +274,7 @@ EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us); static void tick_nohz_stop_sched_tick(struct tick_sched *ts) { unsigned long seq, last_jiffies, next_jiffies, delta_jiffies; + unsigned long rcu_delta_jiffies; ktime_t last_update, expires, now; struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; u64 time_delta; @@ -322,7 +323,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) time_delta = timekeeping_max_deferment(); } while (read_seqretry(&xtime_lock, seq)); - if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || + if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) || arch_needs_cpu(cpu)) { next_jiffies = last_jiffies + 1; delta_jiffies = 1; @@ -330,6 +331,10 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) /* Get the next timer wheel timer */ next_jiffies = get_next_timer_interrupt(last_jiffies); delta_jiffies = next_jiffies - last_jiffies; + if (rcu_delta_jiffies < delta_jiffies) { + next_jiffies = last_jiffies + rcu_delta_jiffies; + delta_jiffies = rcu_delta_jiffies; + } } /* * Do not stop the tick, if we are only one off -- cgit v0.10.2 From d1992b169d31f339dc5ea4e9f312567c8cf322a3 Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Thu, 17 May 2012 22:35:46 +0000 Subject: netfilter: xt_HMARK: fix endianness and provide consistent hashing This patch addresses two issues: a) Fix usage of u32 and __be32 that causes endianess warnings via sparse. b) Ensure consistent hashing in a cluster that is composed of big and little endian systems. Thus, we obtain the same hash mark in an heterogeneous cluster. Reported-by: Dan Carpenter Signed-off-by: Hans Schillstrom Signed-off-by: Pablo Neira Ayuso diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h index abb1650..826fc58 100644 --- a/include/linux/netfilter/xt_HMARK.h +++ b/include/linux/netfilter/xt_HMARK.h @@ -27,7 +27,12 @@ union hmark_ports { __u16 src; __u16 dst; } p16; + struct { + __be16 src; + __be16 dst; + } b16; __u32 v32; + __be32 b32; }; struct xt_hmark_info { diff --git a/net/netfilter/xt_HMARK.c b/net/netfilter/xt_HMARK.c index 0a96a43..1686ca1 100644 --- a/net/netfilter/xt_HMARK.c +++ b/net/netfilter/xt_HMARK.c @@ -32,13 +32,13 @@ MODULE_ALIAS("ipt_HMARK"); MODULE_ALIAS("ip6t_HMARK"); struct hmark_tuple { - u32 src; - u32 dst; + __be32 src; + __be32 dst; union hmark_ports uports; - uint8_t proto; + u8 proto; }; -static inline u32 hmark_addr6_mask(const __u32 *addr32, const __u32 *mask) +static inline __be32 hmark_addr6_mask(const __be32 *addr32, const __be32 *mask) { return (addr32[0] & mask[0]) ^ (addr32[1] & mask[1]) ^ @@ -46,8 +46,8 @@ static inline u32 hmark_addr6_mask(const __u32 *addr32, const __u32 *mask) (addr32[3] & mask[3]); } -static inline u32 -hmark_addr_mask(int l3num, const __u32 *addr32, const __u32 *mask) +static inline __be32 +hmark_addr_mask(int l3num, const __be32 *addr32, const __be32 *mask) { switch (l3num) { case AF_INET: @@ -58,6 +58,22 @@ hmark_addr_mask(int l3num, const __u32 *addr32, const __u32 *mask) return 0; } +static inline void hmark_swap_ports(union hmark_ports *uports, + const struct xt_hmark_info *info) +{ + union hmark_ports hp; + u16 src, dst; + + hp.b32 = (uports->b32 & info->port_mask.b32) | info->port_set.b32; + src = ntohs(hp.b16.src); + dst = ntohs(hp.b16.dst); + + if (dst > src) + uports->v32 = (dst << 16) | src; + else + uports->v32 = (src << 16) | dst; +} + static int hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, const struct xt_hmark_info *info) @@ -74,22 +90,19 @@ hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, otuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; rtuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; - t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.all, - info->src_mask.all); - t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.all, - info->dst_mask.all); + t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.ip6, + info->src_mask.ip6); + t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.ip6, + info->dst_mask.ip6); if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) return 0; t->proto = nf_ct_protonum(ct); if (t->proto != IPPROTO_ICMP) { - t->uports.p16.src = otuple->src.u.all; - t->uports.p16.dst = rtuple->src.u.all; - t->uports.v32 = (t->uports.v32 & info->port_mask.v32) | - info->port_set.v32; - if (t->uports.p16.dst < t->uports.p16.src) - swap(t->uports.p16.dst, t->uports.p16.src); + t->uports.b16.src = otuple->src.u.all; + t->uports.b16.dst = rtuple->src.u.all; + hmark_swap_ports(&t->uports, info); } return 0; @@ -98,15 +111,19 @@ hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, #endif } +/* This hash function is endian independent, to ensure consistent hashing if + * the cluster is composed of big and little endian systems. */ static inline u32 hmark_hash(struct hmark_tuple *t, const struct xt_hmark_info *info) { u32 hash; + u32 src = ntohl(t->src); + u32 dst = ntohl(t->dst); - if (t->dst < t->src) - swap(t->src, t->dst); + if (dst < src) + swap(src, dst); - hash = jhash_3words(t->src, t->dst, t->uports.v32, info->hashrnd); + hash = jhash_3words(src, dst, t->uports.v32, info->hashrnd); hash = hash ^ (t->proto & info->proto_mask); return (((u64)hash * info->hmodulus) >> 32) + info->hoffset; @@ -126,11 +143,7 @@ hmark_set_tuple_ports(const struct sk_buff *skb, unsigned int nhoff, if (skb_copy_bits(skb, nhoff, &t->uports, sizeof(t->uports)) < 0) return; - t->uports.v32 = (t->uports.v32 & info->port_mask.v32) | - info->port_set.v32; - - if (t->uports.p16.dst < t->uports.p16.src) - swap(t->uports.p16.dst, t->uports.p16.src); + hmark_swap_ports(&t->uports, info); } #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) @@ -178,8 +191,8 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t, return -1; } noicmp: - t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.all); - t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.all); + t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.ip6); + t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.ip6); if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) return 0; @@ -255,11 +268,8 @@ hmark_pkt_set_htuple_ipv4(const struct sk_buff *skb, struct hmark_tuple *t, } } - t->src = (__force u32) ip->saddr; - t->dst = (__force u32) ip->daddr; - - t->src &= info->src_mask.ip; - t->dst &= info->dst_mask.ip; + t->src = ip->saddr & info->src_mask.ip; + t->dst = ip->daddr & info->dst_mask.ip; if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) return 0; -- cgit v0.10.2 From d109e9af61a6d2fdf33dc615ab8b724a8e75a8a4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 4 Jun 2012 13:31:04 +0200 Subject: netfilter: nf_ct_h323: fix bug in rtcp natting The nat_rtp_rtcp hook takes two separate parameters port and rtp_port. port is expected to be the real h245 address (found inside the packet). rtp_port is the even number closest to port (RTP ports are even and RTCP ports are odd). However currently, both port and rtp_port are having same value (both are rounded to nearest even numbers). This works well in case of openlogicalchannel with media (RTP/even) port. But in case of openlogicalchannel for media control (RTCP/odd) port, h245 address in the packet is wrongly modified to have an even port. I am attaching a pcap demonstrating the problem, for any further analysis. This behavior was introduced around v2.6.19 while rewriting the helper. Signed-off-by: Jagdish Motwani Signed-off-by: Sanket Shah Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 46d69d7..31f50bc 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -270,9 +270,8 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, return 0; /* RTP port is even */ - port &= htons(~1); - rtp_port = port; - rtcp_port = htons(ntohs(port) + 1); + rtp_port = port & ~htons(1); + rtcp_port = port | htons(1); /* Create expect for RTP */ if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL) -- cgit v0.10.2 From f07936f2c446bd5310e669c8e6eab3f812ea665a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 7 Jun 2012 10:21:03 -0400 Subject: NFS: Remove incorrect BUG_ON in nfs_found_client It is perfectly valid for nfs_get_client() to return a nfs_client that is in the process of setting up the NFSv4.1 session. Signed-off-by: Trond Myklebust diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 7d10875..17ba6b9 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -544,8 +544,6 @@ nfs_found_client(const struct nfs_client_initdata *cl_init, smp_rmb(); - BUG_ON(clp->cl_cons_state != NFS_CS_READY); - dprintk("<-- %s found nfs_client %p for %s\n", __func__, clp, cl_init->hostname ?: ""); return clp; -- cgit v0.10.2 From fb47ddc9d5ded3d202335ea29743b9242d54eb5a Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Thu, 7 Jun 2012 11:42:12 -0400 Subject: NFS4: Fix open bug when pnfs module blacklisted Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 29fd23c..64f90d8 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -365,7 +365,7 @@ static inline bool pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, struct nfs_server *nfss) { - return (dst && src && src->bm != 0 && + return (dst && src && src->bm != 0 && nfss->pnfs_curr_ld && nfss->pnfs_curr_ld->id == src->l_type); } -- cgit v0.10.2 From 02c67525cf325131aa06c6b0c6fd457bd57161e3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 7 Jun 2012 13:45:53 -0400 Subject: NFSv4.1: Convert another trivial printk into a dprintk Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index bfc919f..5881f2c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5297,7 +5297,7 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); if (status) - pr_warn("NFS: Got error %d from the server %s on " + dprintk("NFS: Got error %d from the server %s on " "DESTROY_CLIENTID.", status, clp->cl_hostname); return status; } -- cgit v0.10.2 From a06998b88b1651c5f71c0e35f528bf2057188ead Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 7 Jun 2012 00:07:20 +0000 Subject: net: l2tp_eth: fix kernel panic on rmmod l2tp_eth We must prevent module unloading if some devices are still attached to l2tp_eth driver. Signed-off-by: Eric Dumazet Reported-by: Denys Fedoryshchenko Tested-by: Denys Fedoryshchenko Cc: James Chapman Signed-off-by: David S. Miller diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 443591d..185f12f 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -162,6 +162,7 @@ static void l2tp_eth_delete(struct l2tp_session *session) if (dev) { unregister_netdev(dev); spriv->dev = NULL; + module_put(THIS_MODULE); } } } @@ -249,6 +250,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p if (rc < 0) goto out_del_dev; + __module_get(THIS_MODULE); /* Must be done after register_netdev() */ strlcpy(session->ifname, dev->name, IFNAMSIZ); -- cgit v0.10.2 From 4bd6683bd400c8b1d2ad544bb155d86a5d10f91c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 7 Jun 2012 04:58:35 +0000 Subject: net: neighbour: fix neigh_dump_info() Denys found out "ip neigh" output was truncated to about 54 neighbours. Signed-off-by: Eric Dumazet Reported-by: Denys Fedoryshchenko Signed-off-by: David S. Miller diff --git a/net/core/neighbour.c b/net/core/neighbour.c index eb09f8b..d81d026 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2219,9 +2219,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, rcu_read_lock_bh(); nht = rcu_dereference_bh(tbl->nht); - for (h = 0; h < (1 << nht->hash_shift); h++) { - if (h < s_h) - continue; + for (h = s_h; h < (1 << nht->hash_shift); h++) { if (h > s_h) s_idx = 0; for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; @@ -2260,9 +2258,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, read_lock_bh(&tbl->lock); - for (h = 0; h <= PNEIGH_HASHMASK; h++) { - if (h < s_h) - continue; + for (h = s_h; h <= PNEIGH_HASHMASK; h++) { if (h > s_h) s_idx = 0; for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { @@ -2297,7 +2293,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) struct neigh_table *tbl; int t, family, s_t; int proxy = 0; - int err = 0; + int err; read_lock(&neigh_tbl_lock); family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; @@ -2311,7 +2307,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) s_t = cb->args[0]; - for (tbl = neigh_tables, t = 0; tbl && (err >= 0); + for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) { if (t < s_t || (family && tbl->family != family)) continue; @@ -2322,6 +2318,8 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) err = pneigh_dump_table(tbl, skb, cb); else err = neigh_dump_table(tbl, skb, cb); + if (err < 0) + break; } read_unlock(&neigh_tbl_lock); -- cgit v0.10.2 From 8bd74516b1bd9308c17f67583134d93f777203ca Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 7 Jun 2012 06:51:04 +0000 Subject: ipv6: fib: Restore NTF_ROUTER exception in fib6_age() Commit 5339ab8b1dd82 (ipv6: fib: Convert fib6_age() to dst_neigh_lookup().) seems to have mistakenly inverted the exception for cached NTF_ROUTER routes. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 0c220a4..74c21b9 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1561,7 +1561,7 @@ static int fib6_age(struct rt6_info *rt, void *arg) neigh_flags = neigh->flags; neigh_release(neigh); } - if (neigh_flags & NTF_ROUTER) { + if (!(neigh_flags & NTF_ROUTER)) { RT6_TRACE("purging route %p via non-router but gateway\n", rt); return -1; -- cgit v0.10.2 From 5ff0feac88ced864f44adb145142269196fa79d9 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 6 Jun 2012 10:01:30 +0000 Subject: sky2: fix checksum bit management on some chips The newer flavors of Yukon II use a different method for receive checksum offload. This is indicated in the driver by the SKY2_HW_NEW_LE flag. On these newer chips, the BMU_ENA_RX_CHKSUM should not be set. The driver would get incorrectly toggle the bit, enabling the old checksum logic on these chips and cause a BUG_ON() assertion. If receive checksum was toggled via ethtool. Reported-by: Kirill Smelkov Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index cace36f..28a5445 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4381,10 +4381,12 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features) struct sky2_port *sky2 = netdev_priv(dev); netdev_features_t changed = dev->features ^ features; - if (changed & NETIF_F_RXCSUM) { - bool on = features & NETIF_F_RXCSUM; - sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), - on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + if ((changed & NETIF_F_RXCSUM) && + !(sky2->hw->flags & SKY2_HW_NEW_LE)) { + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + (features & NETIF_F_RXCSUM) + ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } if (changed & NETIF_F_RXHASH) -- cgit v0.10.2 From 278f015e9b67566991d4e831fe38e0ebbeef245e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 6 Jun 2012 08:45:59 +0000 Subject: appletalk: Remove out of date message in printk I accidentally triggered this printk, which amused me for a few moments. Given we're post 2.2, we could just -EACCES, but does anyone even care about Appletalk now ? I figure it's better to leave sleeping dogs lie, and just update the message. Signed-off-by: Dave Jones Signed-off-by: David S. Miller diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 0301b32..8685296 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1208,9 +1208,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, if (addr->sat_addr.s_node == ATADDR_BCAST && !sock_flag(sk, SOCK_BROADCAST)) { #if 1 - printk(KERN_WARNING "%s is broken and did not set " - "SO_BROADCAST. It will break when 2.2 is " - "released.\n", + pr_warn("atalk_connect: %s is broken and did not set SO_BROADCAST.\n", current->comm); #else return -EACCES; -- cgit v0.10.2 From 2d8dbb04c63e5369988f008bc4df3359c01d8812 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Tue, 5 Jun 2012 03:41:42 +0000 Subject: snmp: fix OutOctets counter to include forwarded datagrams RFC 4293 defines ipIfStatsOutOctets (similar definition for ipSystemStatsOutOctets): The total number of octets in IP datagrams delivered to the lower layers for transmission. Octets from datagrams counted in ipIfStatsOutTransmits MUST be counted here. And ipIfStatsOutTransmits: The total number of IP datagrams that this entity supplied to the lower layers for transmission. This includes datagrams generated locally and those forwarded by this entity. Therefore, IPSTATS_MIB_OUTOCTETS must be incremented when incrementing IPSTATS_MIB_OUTFORWDATAGRAMS. IP_UPD_PO_STATS is not used since ipIfStatsOutRequests must not include forwarded datagrams: The total number of IP datagrams that local IP user-protocols (including ICMP) supplied to IP in requests for transmission. Note that this counter does not include any datagrams counted in ipIfStatsOutForwDatagrams. Signed-off-by: Vincent Bernat Signed-off-by: David S. Miller diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index e5c44fc..ab09b12 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -44,6 +44,7 @@ static int ip_forward_finish(struct sk_buff *skb) struct ip_options *opt = &(IPCB(skb)->opt); IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen)) ip_forward_options(skb); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index a9e519a..c94bbc6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1574,6 +1574,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) struct ip_options *opt = &(IPCB(skb)->opt); IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen)) ip_forward_options(skb); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 17b8c67..decc21d1 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -526,6 +526,7 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index b15dc08..461e47c 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1886,6 +1886,8 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb) { IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP6_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_OUTOCTETS, skb->len); return dst_output(skb); } -- cgit v0.10.2 From 752a6a5f84bfed18d0709383913d9d9d21b61c77 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 10:00:12 +0100 Subject: regmap: Export regmap_reinit_cache() It's supposed to be there for drivers. Signed-off-by: Mark Brown diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 04b4802..c89aa01 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -472,6 +472,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) return ret; } +EXPORT_SYMBOL_GPL(regmap_reinit_cache); /** * regmap_exit(): Free a previously allocated register map -- cgit v0.10.2 From 35ea0655a1bcdb1dcb1c1d0c4b6b391ade9c6d01 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 5 Jun 2012 19:26:59 +0100 Subject: ASoC: dpcm: Fix dpcm_get_be() to check that DAI is BE Make sure that the dpcm_get_be() only returns BE DAI links. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index bedd171..48fd15b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -794,6 +794,9 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, for (i = 0; i < card->num_links; i++) { be = &card->rtd[i]; + if (!be->dai_link->no_pcm) + continue; + if (be->cpu_dai->playback_widget == widget || be->codec_dai->playback_widget == widget) return be; @@ -803,6 +806,9 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, for (i = 0; i < card->num_links; i++) { be = &card->rtd[i]; + if (!be->dai_link->no_pcm) + continue; + if (be->cpu_dai->capture_widget == widget || be->codec_dai->capture_widget == widget) return be; -- cgit v0.10.2 From 90c6ce0d5482ee52b0a427115e185d488783164b Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 5 Jun 2012 19:27:15 +0100 Subject: ASoC: dapm: Fix input list to use source widgets We should only add source widgets to the input list. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b47fe75..89eae93 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -913,7 +913,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, /* do we need to add this widget to the list ? */ if (list) { int err; - err = dapm_list_add_widget(list, path->sink); + err = dapm_list_add_widget(list, path->source); if (err < 0) { dev_err(widget->dapm->dev, "could not add widget %s\n", widget->name); -- cgit v0.10.2 From 3ff1ec27e9f567824e73316025a9025528494506 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 8 Jun 2012 06:53:48 +0800 Subject: ASoC: wm2000: Always use a 4s timeout for the firmware Rather than having varying timeouts depending on the transition always use a 4s timeout. This provides better diagnostics for clocking errors and ensures compatibility with current calibration firmwares. Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a75c376..0418fa1 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -99,8 +99,9 @@ static void wm2000_reset(struct wm2000_priv *wm2000) } static int wm2000_poll_bit(struct i2c_client *i2c, - unsigned int reg, u8 mask, int timeout) + unsigned int reg, u8 mask) { + int timeout = 4000; int val; val = wm2000_read(i2c, reg); @@ -119,7 +120,7 @@ static int wm2000_poll_bit(struct i2c_client *i2c, static int wm2000_power_up(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int ret, timeout; + int ret; BUG_ON(wm2000->anc_mode != ANC_OFF); @@ -140,13 +141,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) /* Wait for ANC engine to become ready */ if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE, 1)) { + WM2000_ANC_ENG_IDLE)) { dev_err(&i2c->dev, "ANC engine failed to reset\n"); return -ETIMEDOUT; } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_BOOT_COMPLETE, 1)) { + WM2000_STATUS_BOOT_COMPLETE)) { dev_err(&i2c->dev, "ANC engine failed to initialise\n"); return -ETIMEDOUT; } @@ -173,16 +174,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) dev_dbg(&i2c->dev, "Download complete\n"); if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); + wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 248 / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_MOUSE_ENABLE | WM2000_MODE_THERMAL_ENABLE); } else { - timeout = 10; - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_MOUSE_ENABLE | WM2000_MODE_THERMAL_ENABLE); @@ -201,9 +199,8 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE, timeout)) { - dev_err(&i2c->dev, "Timed out waiting for device after %dms\n", - timeout * 10); + WM2000_STATUS_MOUSE_ACTIVE)) { + dev_err(&i2c->dev, "Timed out waiting for device\n"); return -ETIMEDOUT; } @@ -218,28 +215,25 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) static int wm2000_power_down(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int timeout; if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); + wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 248 / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_POWER_DOWN); } else { - timeout = 10; wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_POWER_DOWN); } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_POWER_DOWN_COMPLETE, timeout)) { + WM2000_STATUS_POWER_DOWN_COMPLETE)) { dev_err(&i2c->dev, "Timeout waiting for ANC power down\n"); return -ETIMEDOUT; } if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE, 1)) { + WM2000_ANC_ENG_IDLE)) { dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); return -ETIMEDOUT; } @@ -268,13 +262,13 @@ static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue) } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_ANC_DISABLED, 10)) { + WM2000_STATUS_ANC_DISABLED)) { dev_err(&i2c->dev, "Timeout waiting for ANC disable\n"); return -ETIMEDOUT; } if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE, 1)) { + WM2000_ANC_ENG_IDLE)) { dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); return -ETIMEDOUT; } @@ -311,7 +305,7 @@ static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue) wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE, 10)) { + WM2000_STATUS_MOUSE_ACTIVE)) { dev_err(&i2c->dev, "Timed out waiting for MOUSE\n"); return -ETIMEDOUT; } @@ -325,38 +319,32 @@ static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue) static int wm2000_enter_standby(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int timeout; BUG_ON(wm2000->anc_mode != ANC_ACTIVE); if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); + wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 248 / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_STANDBY_ENTRY); } else { - timeout = 10; - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_STANDBY_ENTRY); } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_ANC_DISABLED, timeout)) { + WM2000_STATUS_ANC_DISABLED)) { dev_err(&i2c->dev, "Timed out waiting for ANC disable after 1ms\n"); return -ETIMEDOUT; } - if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE, - 1)) { + if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE)) { dev_err(&i2c->dev, - "Timed out waiting for standby after %dms\n", - timeout * 10); + "Timed out waiting for standby\n"); return -ETIMEDOUT; } @@ -374,23 +362,19 @@ static int wm2000_enter_standby(struct i2c_client *i2c, int analogue) static int wm2000_exit_standby(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int timeout; BUG_ON(wm2000->anc_mode != ANC_STANDBY); wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); + wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 248 / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_MOUSE_ENABLE); } else { - timeout = 10; - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_MOUSE_ENABLE); @@ -400,9 +384,8 @@ static int wm2000_exit_standby(struct i2c_client *i2c, int analogue) wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE, timeout)) { - dev_err(&i2c->dev, "Timed out waiting for MOUSE after %dms\n", - timeout * 10); + WM2000_STATUS_MOUSE_ACTIVE)) { + dev_err(&i2c->dev, "Timed out waiting for MOUSE\n"); return -ETIMEDOUT; } -- cgit v0.10.2 From 0bdc81e4e944781a2bcc971f9e3cf24ac7030939 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 7 Jun 2012 09:52:12 +0800 Subject: regulator: core: Properly handle the case min_uV < rdev->desc->min_uV in map_voltage_linear Properly handle the case if the specified min_uV is less than the voltage given by the lowest selector. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7584a74..09a737c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2050,6 +2050,9 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, return -EINVAL; } + if (min_uV < rdev->desc->min_uV) + min_uV = rdev->desc->min_uV; + ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); if (ret < 0) return ret; -- cgit v0.10.2 From 69c5b7530651c8e375d2fbecd157a9a9a20c4cc9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 7 Jun 2012 17:58:31 -0600 Subject: ASoC: tegra: add MODULE_DEVICE_TABLE to tegra30_ahub This allows the module to automatically load when instantiated from device tree. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 57cd419..f43edb3 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -629,3 +629,4 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra30 AHUB driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); -- cgit v0.10.2 From 33d5e332b9c5ce0bf3bfd44ca2127d1773b3f2ad Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Thu, 7 Jun 2012 19:25:07 +0000 Subject: stmmac: fix driver built w/ w/o both pci and platf modules The commit ba27ec66ffeb78cbf fixes the Kconfig of the driver when built as module allowing to select/unselect the PCI and Platform modules that are not anymore mutually exclusive. This patch fixes and guarantees that the driver builds on all the platforms w/ w/o PCI and when select/unselect the two stmmac supports. In case of there are some problems on both the configuration and the pci/pltf registration the module_init will fail. v2: set the CONFIG_STMMAC_PLATFORM enabled by default. I've just noticed that this can actually help on some configurations that don't enable any STMMAC options by default (e.g. SPEAr). v3: change printk level when do not register the driver. Reported-by: Fengguang Wu Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 0076f77..9f44827 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -15,6 +15,7 @@ if STMMAC_ETH config STMMAC_PLATFORM bool "STMMAC Platform bus support" depends on STMMAC_ETH + default y ---help--- This selects the platform specific bus support for the stmmac device driver. This is the driver used diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 6d07ba2..94b21b4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "common.h" #ifdef CONFIG_STMMAC_TIMER #include "stmmac_timer.h" @@ -95,8 +96,6 @@ extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); extern const struct stmmac_desc_ops enh_desc_ops; extern const struct stmmac_desc_ops ndesc_ops; -extern struct pci_driver stmmac_pci_driver; -extern struct platform_driver stmmac_pltfr_driver; int stmmac_freeze(struct net_device *ndev); int stmmac_restore(struct net_device *ndev); int stmmac_resume(struct net_device *ndev); @@ -144,3 +143,60 @@ static inline int stmmac_clk_get(struct stmmac_priv *priv) return 0; } #endif /* CONFIG_HAVE_CLK */ + + +#ifdef CONFIG_STMMAC_PLATFORM +extern struct platform_driver stmmac_pltfr_driver; +static inline int stmmac_register_platform(void) +{ + int err; + + err = platform_driver_register(&stmmac_pltfr_driver); + if (err) + pr_err("stmmac: failed to register the platform driver\n"); + + return err; +} +static inline void stmmac_unregister_platform(void) +{ + platform_driver_register(&stmmac_pltfr_driver); +} +#else +static inline int stmmac_register_platform(void) +{ + pr_debug("stmmac: do not register the platf driver\n"); + + return -EINVAL; +} +static inline void stmmac_unregister_platform(void) +{ +} +#endif /* CONFIG_STMMAC_PLATFORM */ + +#ifdef CONFIG_STMMAC_PCI +extern struct pci_driver stmmac_pci_driver; +static inline int stmmac_register_pci(void) +{ + int err; + + err = pci_register_driver(&stmmac_pci_driver); + if (err) + pr_err("stmmac: failed to register the PCI driver\n"); + + return err; +} +static inline void stmmac_unregister_pci(void) +{ + pci_unregister_driver(&stmmac_pci_driver); +} +#else +static inline int stmmac_register_pci(void) +{ + pr_debug("stmmac: do not register the PCI driver\n"); + + return -EINVAL; +} +static inline void stmmac_unregister_pci(void) +{ +} +#endif /* CONFIG_STMMAC_PCI */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3638569..51b3b68 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -42,7 +42,6 @@ #include #include #include -#include #ifdef CONFIG_STMMAC_DEBUG_FS #include #include @@ -2094,25 +2093,29 @@ int stmmac_restore(struct net_device *ndev) } #endif /* CONFIG_PM */ +/* Driver can be configured w/ and w/ both PCI and Platf drivers + * depending on the configuration selected. + */ static int __init stmmac_init(void) { - int err = 0; + int err_plt = 0; + int err_pci = 0; - err = platform_driver_register(&stmmac_pltfr_driver); + err_plt = stmmac_register_platform(); + err_pci = stmmac_register_pci(); - if (!err) { - err = pci_register_driver(&stmmac_pci_driver); - if (err) - platform_driver_unregister(&stmmac_pltfr_driver); + if ((err_pci) && (err_plt)) { + pr_err("stmmac: driver registration failed\n"); + return -EINVAL; } - return err; + return 0; } static void __exit stmmac_exit(void) { - pci_unregister_driver(&stmmac_pci_driver); - platform_driver_unregister(&stmmac_pltfr_driver); + stmmac_unregister_platform(); + stmmac_unregister_pci(); } module_init(stmmac_init); -- cgit v0.10.2 From 8260ef075bd9848ce6a8004ec73b7454d410cc15 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Jun 2012 09:01:37 +0200 Subject: ALSA: usb-audio: Fix substream assignments In 3.5 kernel, the endpoint is assigned dynamically for the substreams, but the PCM assignment still checks the presence of the endpoint pointer. This ended up in duplicated PCM substream creations at probing time, resulting in kernel warnings like: WARNING: at fs/proc/generic.c:586 proc_register+0x169/0x1a6() Pid: 1152, comm: modprobe Not tainted 3.5.0-rc1-00110-g71fae7e #2 Call Trace: [] warn_slowpath_common+0x83/0x9c [] warn_slowpath_fmt+0x46/0x48 [] ? add_preempt_count+0x39/0x3b [] proc_register+0x169/0x1a6 [] create_proc_entry+0x74/0x8c [] snd_info_register+0x3e/0xc3 [snd] [] snd_pcm_new_stream+0xb1/0x404 [snd_pcm] [] snd_usb_add_audio_stream+0xd2/0x230 [snd_usb_audio] [] ? snd_usb_parse_audio_format+0x252/0x34f [snd_usb_audio] [] ? kmem_cache_alloc_trace+0xab/0xbb [] snd_usb_parse_audio_interface+0x4ac/0x567 [snd_usb_audio] [] snd_usb_create_stream+0xe9/0x125 [snd_usb_audio] [] usb_audio_probe+0x62a/0x72c [snd_usb_audio] ..... This patch fixes the regression by checking the fixed endpoint number for each substream instead of the endpoint pointer. Reported-and-tested-by: Jamie Heilman Signed-off-by: Takashi Iwai diff --git a/sound/usb/card.h b/sound/usb/card.h index 0d37238..2b9ffff 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -119,6 +119,7 @@ struct snd_usb_substream { unsigned long unlink_mask; /* bitmask of unlinked urbs */ /* data and sync endpoints for this stream */ + unsigned int ep_num; /* the endpoint number */ struct snd_usb_endpoint *data_endpoint; struct snd_usb_endpoint *sync_endpoint; unsigned long flags; diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 6b7d7a2..083ed81 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -97,6 +97,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->formats |= fp->formats; subs->num_formats++; subs->fmt_type = fp->fmt_type; + subs->ep_num = fp->endpoint; } /* @@ -119,9 +120,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, if (as->fmt_type != fp->fmt_type) continue; subs = &as->substream[stream]; - if (!subs->data_endpoint) - continue; - if (subs->data_endpoint->ep_num == fp->endpoint) { + if (subs->ep_num == fp->endpoint) { list_add_tail(&fp->list, &subs->fmt_list); subs->num_formats++; subs->formats |= fp->formats; @@ -134,7 +133,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, if (as->fmt_type != fp->fmt_type) continue; subs = &as->substream[stream]; - if (subs->data_endpoint) + if (subs->ep_num) continue; err = snd_pcm_new_stream(as->pcm, stream, 1); if (err < 0) -- cgit v0.10.2 From 6a2b28ef036ab5c66fdc606fe97d9e5cb34ea409 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 8 Jun 2012 00:28:16 -0700 Subject: Revert "niu: Add support for byte queue limits." This reverts commit efa230f2c68abab817f13473077f8d0cc74f43f3. BQL doesn't work with how this driver currently only takes TX interrupts every 1/4 of the TX ring. That behavior needs to be fixed, but that's a larger non-trivial task and for now we have to revert BQL support as this makes the device currently completely unusable. Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 703c8cc..8c726b7 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -3598,7 +3598,6 @@ static int release_tx_packet(struct niu *np, struct tx_ring_info *rp, int idx) static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) { struct netdev_queue *txq; - unsigned int tx_bytes; u16 pkt_cnt, tmp; int cons, index; u64 cs; @@ -3621,18 +3620,12 @@ static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) netif_printk(np, tx_done, KERN_DEBUG, np->dev, "%s() pkt_cnt[%u] cons[%d]\n", __func__, pkt_cnt, cons); - tx_bytes = 0; - tmp = pkt_cnt; - while (tmp--) { - tx_bytes += rp->tx_buffs[cons].skb->len; + while (pkt_cnt--) cons = release_tx_packet(np, rp, cons); - } rp->cons = cons; smp_mb(); - netdev_tx_completed_queue(txq, pkt_cnt, tx_bytes); - out: if (unlikely(netif_tx_queue_stopped(txq) && (niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp)))) { @@ -4333,7 +4326,6 @@ static void niu_free_channels(struct niu *np) struct tx_ring_info *rp = &np->tx_rings[i]; niu_free_tx_ring_info(np, rp); - netdev_tx_reset_queue(netdev_get_tx_queue(np->dev, i)); } kfree(np->tx_rings); np->tx_rings = NULL; @@ -6739,8 +6731,6 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, prod = NEXT_TX(rp, prod); } - netdev_tx_sent_queue(txq, skb->len); - if (prod < rp->prod) rp->wrap_bit ^= TX_RING_KICK_WRAP; rp->prod = prod; -- cgit v0.10.2 From c8e9cf7bb240049117d2fa64d1540476c289396d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 7 Jun 2012 12:15:15 +0200 Subject: vga_switcheroo: Add a helper function to get the client state Add vga_switcheroo_get_client_state() to get the current state of the client. This is necessary to determine the proper initial state of audio clients in HD-audio driver. Acked-by: Dave Airlie Signed-off-by: Takashi Iwai diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 38f9534..eb4f64f 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -190,6 +190,19 @@ find_active_client(struct list_head *head) return NULL; } +int vga_switcheroo_get_client_state(struct pci_dev *pdev) +{ + struct vga_switcheroo_client *client; + + client = find_client_from_pci(&vgasr_priv.clients, pdev); + if (!client) + return VGA_SWITCHEROO_NOT_FOUND; + if (!vgasr_priv.active) + return VGA_SWITCHEROO_INIT; + return client->pwr_state; +} +EXPORT_SYMBOL(vga_switcheroo_get_client_state); + void vga_switcheroo_unregister_client(struct pci_dev *pdev) { struct vga_switcheroo_client *client; diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index b455c7c..b176342 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -12,6 +12,9 @@ enum vga_switcheroo_state { VGA_SWITCHEROO_OFF, VGA_SWITCHEROO_ON, + /* below are referred only from vga_switcheroo_get_client_state() */ + VGA_SWITCHEROO_INIT, + VGA_SWITCHEROO_NOT_FOUND, }; enum vga_switcheroo_client_id { @@ -50,6 +53,8 @@ void vga_switcheroo_unregister_handler(void); int vga_switcheroo_process_delayed_switch(void); +int vga_switcheroo_get_client_state(struct pci_dev *dev); + #else static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} @@ -62,5 +67,7 @@ static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, int id, bool active) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } +static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_CLIENT_ON; } + #endif -- cgit v0.10.2 From 12b78a7f671aa91fd41899615bf6d171c925c3d7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 7 Jun 2012 12:15:16 +0200 Subject: ALSA: hda - Fix uninitialized HDMI controllers with VGA-switcheroo When VGA-switcheroo is built in but unused on systems with multiple graphics cards, the initializations of non-default graphics cards are skipped and never enabled (because the switcheroo is activated only when the controller supports). The current behavior is for avoiding the system lockup by accessing the disabled GPU, but due to the recent change in VGA-switcheroo, it determines the state simply by checking with the default VGA device. This is the culprit. Now with the new vga_switcheroo_get_client_state(), we can know the initial state of the bound GPU, thus can determine the initial audio client state more correctly. Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2b6392b..5f0375f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2670,7 +2670,7 @@ static bool __devinit check_hdmi_disabled(struct pci_dev *pci) struct pci_dev *p = get_bound_vga(pci); if (p) { - if (vga_default_device() && p != vga_default_device()) + if (vga_switcheroo_get_client_state(p) == VGA_SWITCHEROO_OFF) vga_inactive = true; pci_dev_put(p); } -- cgit v0.10.2 From eab309494ae2b9e15f85520f00de3893162c2e43 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 24 May 2012 00:45:21 -0700 Subject: memblock: Document memblock_is_region_{memory,reserved}() At first glance one would think that memblock_is_region_memory() and memblock_is_region_reserved() would be implemented in the same way. Unfortunately they aren't and the former returns whether the region specified is a subset of a memory bank while the latter returns whether the region specified intersects with reserved memory. Document the two functions so that users aren't tempted to make the implementation the same between them and to clarify the purpose of the functions. Signed-off-by: Stephen Boyd Cc: Tejun Heo Link: http://lkml.kernel.org/r/1337845521-32755-1-git-send-email-sboyd@codeaurora.org Signed-off-by: Ingo Molnar diff --git a/mm/memblock.c b/mm/memblock.c index 952123e..32a0a5e 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -867,6 +867,16 @@ int __init_memblock memblock_is_memory(phys_addr_t addr) return memblock_search(&memblock.memory, addr) != -1; } +/** + * memblock_is_region_memory - check if a region is a subset of memory + * @base: base of region to check + * @size: size of region to check + * + * Check if the region [@base, @base+@size) is a subset of a memory block. + * + * RETURNS: + * 0 if false, non-zero if true + */ int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size) { int idx = memblock_search(&memblock.memory, base); @@ -879,6 +889,16 @@ int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size memblock.memory.regions[idx].size) >= end; } +/** + * memblock_is_region_reserved - check if a region intersects reserved memory + * @base: base of region to check + * @size: size of region to check + * + * Check if the region [@base, @base+@size) intersects a reserved memory block. + * + * RETURNS: + * 0 if false, non-zero if true + */ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size) { memblock_cap_size(base, &size); -- cgit v0.10.2 From 505cff00de9c303b95c204eb4544066e3e707911 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Jun 2012 12:49:17 +0200 Subject: vga_switcheroo: Fix error without CONFIG_VGA_SWITCHEROO Fix a typo that is built only when CONFIG_VGA_SWITCHEROO=n. Signed-off-by: Takashi Iwai diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index b176342..60da41f 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -67,7 +67,7 @@ static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, int id, bool active) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } -static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_CLIENT_ON; } +static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } #endif -- cgit v0.10.2 From 8393ec4a13889339bacfb8b038fb13716eef7a2b Mon Sep 17 00:00:00 2001 From: Steven Newbury Date: Fri, 8 Jun 2012 13:06:29 +0200 Subject: ALSA: hda - HDMI Audio init all connectors when VGA-switcheroo is off When VGA_SWITCHEROO support is enabled hda_intel initialises the HDMI audio device on the current VGA device. When it's not enabled it only initialises the HDMI device on the default VGA adaptor, this means secondary cards get no audio support which is very unhelpful for multi-seat! With this patch, when SUPPORT_VGA_SWITCHEROO is disabled hda_intel initialises all HDMI audio devices, not just the default VGA. [minor optimizations by tiwai] Signed-off-by: Steven Newbury Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5f0375f..e172c5d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2484,9 +2484,9 @@ static void azx_notifier_unregister(struct azx *chip) static int DELAYED_INIT_MARK azx_first_init(struct azx *chip); static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip); +#ifdef SUPPORT_VGA_SWITCHEROO static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci); -#ifdef SUPPORT_VGA_SWITCHEROO static void azx_vs_set_state(struct pci_dev *pci, enum vga_switcheroo_state state) { @@ -2578,6 +2578,7 @@ static int __devinit register_vga_switcheroo(struct azx *chip) #else #define init_vga_switcheroo(chip) /* NOP */ #define register_vga_switcheroo(chip) 0 +#define check_hdmi_disabled(pci) false #endif /* SUPPORT_VGA_SWITCHER */ /* @@ -2638,6 +2639,7 @@ static int azx_dev_free(struct snd_device *device) return azx_free(device->device_data); } +#ifdef SUPPORT_VGA_SWITCHEROO /* * Check of disabled HDMI controller by vga-switcheroo */ @@ -2676,6 +2678,7 @@ static bool __devinit check_hdmi_disabled(struct pci_dev *pci) } return vga_inactive; } +#endif /* SUPPORT_VGA_SWITCHEROO */ /* * white/black-listing for position_fix -- cgit v0.10.2 From 2d0dbc6ae8a5194aaecb9cfffb9053f38fce8b86 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 8 Jun 2012 10:58:09 -0400 Subject: NFSv4: Fix unnecessary delegation returns in nfs4_do_open While nfs4_do_open() expects the fmode argument to be restricted to combinations of FMODE_READ and FMODE_WRITE, both nfs4_atomic_open() and nfs4_proc_create will pass the nfs_open_context->mode, which contains the full fmode_t. This patch ensures that nfs4_do_open strips the other fmode_t bits, fixing a problem in which the nfs4_do_open call would result in an unnecessary delegation return. Reported-by: Fred Isaman Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5881f2c..f23977e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1902,6 +1902,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct nfs4_state *res; int status; + fmode &= FMODE_READ|FMODE_WRITE; do { status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, &res, ctx_th); -- cgit v0.10.2 From aac495a8002bbf20e879572c6cf0789ab2ffb32b Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Mon, 14 May 2012 19:06:19 -0400 Subject: net/wireless: ipw2100: Fix WARN_ON occurring in wiphy_register called by ipw2100_pci_init_one The problem was found by Larry Finger: http://marc.info/?l=linux-wireless&m=133702401700614&w=2 The problem is identical to the one for ipw2200 which is already fixed: http://marc.info/?l=linux-wireless&m=133457257407196&w=2 [ 17.766431] ------------[ cut here ]------------ [ 17.766467] WARNING: at net/wireless/core.c:562 wiphy_register+0x34c/0x3c0 [cfg80211]() [ 17.766471] Hardware name: Latitude D600 [ 17.766474] Modules linked in: ipw2100(+) libipw pcmcia cfg80211 ppdev parport_pc yenta_socket sr_mod pcmcia_rsrc parport iTCO_wdt cdrom sg rfkill pcmcia_ core lib80211 tg3 video button battery ac iTCO_vendor_support joydev shpchp pcspkr pciehp pci_hotplug autofs4 radeon ttm drm_kms_helper uhci_hcd ehci_hcd rtc _cmos thermal drm hwmon i2c_algo_bit i2c_core processor usbcore usb_common ata_generic ata_piix ahci libahci libata [ 17.766525] Pid: 474, comm: modprobe Not tainted 3.4.0-rc7-wl+ #6 [ 17.766528] Call Trace: [ 17.766541] [] ? printk+0x28/0x2a [ 17.766552] [] warn_slowpath_common+0x6d/0xa0 [ 17.766563] [] ? wiphy_register+0x34c/0x3c0 [cfg80211] [ 17.766573] [] ? wiphy_register+0x34c/0x3c0 [cfg80211] [ 17.766578] [] warn_slowpath_null+0x1d/0x20 [ 17.766588] [] wiphy_register+0x34c/0x3c0 [cfg80211] [ 17.766605] [] ipw2100_wdev_init+0x196/0x1c0 [ipw2100] [ 17.766616] [] ipw2100_pci_init_one+0x2b2/0x694 [ipw2100] [ 17.766632] [] local_pci_probe+0x42/0xb0 [ 17.766637] [] pci_device_probe+0x60/0x90 [ 17.766645] [] ? sysfs_create_link+0x12/0x20 [ 17.766654] [] really_probe+0x56/0x2e0 [ 17.766659] [] ? create_dir+0x5d/0xa0 [ 17.766667] [] ? pm_runtime_barrier+0x3b/0xa0 [ 17.766672] [] driver_probe_device+0x44/0xa0 [ 17.766677] [] ? pci_match_device+0x97/0xa0 [ 17.766681] [] __driver_attach+0x89/0x90 [ 17.766686] [] ? driver_probe_device+0xa0/0xa0 [ 17.766691] [] bus_for_each_dev+0x3a/0x70 [ 17.766695] [] driver_attach+0x1c/0x30 [ 17.766699] [] ? driver_probe_device+0xa0/0xa0 [ 17.766704] [] bus_add_driver+0x187/0x280 [ 17.766710] [] ? kset_find_obj+0x2d/0x60 [ 17.766715] [] ? pci_device_probe+0x90/0x90 [ 17.766719] [] ? pci_device_probe+0x90/0x90 [ 17.766724] [] driver_register+0x65/0x110 [ 17.766729] [] __pci_register_driver+0x3d/0xa0 [ 17.766738] [] ipw2100_init+0x5c/0x1000 [ipw2100] [ 17.766743] [] do_one_initcall+0x2f/0x170 [ 17.766749] [] ? 0xe09f6fff [ 17.766757] [] sys_init_module+0xa8/0x210 [ 17.766766] [] syscall_call+0x7/0xb [ 17.766769] ---[ end trace 559898c6bb0d1c75 ]--- [ 17.767093] ipw2100: probe of 0000:02:03.0 failed with error -5 This warning appears only if we apply Ben Hutchings' fix http://marc.info/?l=linux-wireless&m=132720204412667&w=2 for the bug reported by Cesare Leonardi http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=656813 with cfg80211 warning during device registration ("cfg80211: failed to add phy80211 symlink to netdev!"). We separate device bring up and registration with network stack to avoid the problem. Signed-off-by: Stanislav Yakovlev Tested-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 9cfae0c..95aa8e1 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1903,14 +1903,6 @@ static void ipw2100_down(struct ipw2100_priv *priv) netif_stop_queue(priv->net_dev); } -/* Called by register_netdev() */ -static int ipw2100_net_init(struct net_device *dev) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - - return ipw2100_up(priv, 1); -} - static int ipw2100_wdev_init(struct net_device *dev) { struct ipw2100_priv *priv = libipw_priv(dev); @@ -6087,7 +6079,6 @@ static const struct net_device_ops ipw2100_netdev_ops = { .ndo_stop = ipw2100_close, .ndo_start_xmit = libipw_xmit, .ndo_change_mtu = libipw_change_mtu, - .ndo_init = ipw2100_net_init, .ndo_tx_timeout = ipw2100_tx_timeout, .ndo_set_mac_address = ipw2100_set_address, .ndo_validate_addr = eth_validate_addr, @@ -6329,6 +6320,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2100 Network Connection\n"); + err = ipw2100_up(priv, 1); + if (err) + goto fail; + err = ipw2100_wdev_init(dev); if (err) goto fail; @@ -6338,12 +6333,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, * network device we would call ipw2100_up. This introduced a race * condition with newer hotplug configurations (network was coming * up and making calls before the device was initialized). - * - * If we called ipw2100_up before we registered the device, then the - * device name wasn't registered. So, we instead use the net_dev->init - * member to call a function that then just turns and calls ipw2100_up. - * net_dev->init is called after name allocation but before the - * notifier chain is called */ + */ err = register_netdev(dev); if (err) { printk(KERN_WARNING DRV_NAME -- cgit v0.10.2 From 0fde0a8cfd0ede7f310d6a681c8e5a7cb3e32406 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 16 May 2012 11:06:21 +0200 Subject: rtl8187: ->brightness_set can not sleep Fix: BUG: sleeping function called from invalid context at kernel/workqueue.c:2547 in_atomic(): 1, irqs_disabled(): 0, pid: 629, name: wpa_supplicant 2 locks held by wpa_supplicant/629: #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x14/0x20 #1: (&trigger->leddev_list_lock){.+.?..}, at: [] led_trigger_event+0x21/0x80 Pid: 629, comm: wpa_supplicant Not tainted 3.3.0-0.rc3.git5.1.fc17.i686 Call Trace: [] __might_sleep+0x126/0x1d0 [] wait_on_work+0x2c/0x1d0 [] __cancel_work_timer+0x6a/0x120 [] cancel_delayed_work_sync+0x10/0x20 [] rtl8187_led_brightness_set+0x82/0xf0 [rtl8187] [] led_trigger_event+0x5c/0x80 [] ieee80211_led_radio+0x1d/0x40 [mac80211] [] ieee80211_stop_device+0x13/0x230 [mac80211] Removing _sync is ok, because if led_on work is currently running it will be finished before led_off work start to perform, since they are always queued on the same mac80211 local->workqueue. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=795176 Signed-off-by: Stanislaw Gruszka Acked-by: Larry Finger Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c index 2e0de2f..c2d5b49 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c @@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, radio_on = true; } else if (radio_on) { radio_on = false; - cancel_delayed_work_sync(&priv->led_on); + cancel_delayed_work(&priv->led_on); ieee80211_queue_delayed_work(hw, &priv->led_off, 0); } } else if (radio_on) { -- cgit v0.10.2 From 06cf5c4c5bea549235da1aace86b90d4ad0084f8 Mon Sep 17 00:00:00 2001 From: Qasim Javed Date: Tue, 5 Jun 2012 01:25:44 -0500 Subject: mac80211_hwsim: Set IEEE80211_STAT_ACK flag when userspace indicates that the frame has been acknowledged. The station fail average is not updated correctly since the IEEE80211_STAT_ACK flag is not set when using wmediumd with mac80211_hwsim. Set this flag when wmediumd indicates that the frame was successfully transmitted (eventually). Signed-off-by: Qasim Javed Signed-off-by: Javier Cardona Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 4c9336c..a0b7cfd 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1555,6 +1555,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, hdr = (struct ieee80211_hdr *) skb->data; mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); } + txi->flags |= IEEE80211_TX_STAT_ACK; } ieee80211_tx_status_irqsafe(data2->hw, skb); return 0; -- cgit v0.10.2 From ce466579b1c92fce78bf5f74a3707f46e228d949 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Jun 2012 15:42:55 +0200 Subject: wireless: add my new trees to MAINTAINERS Add my new trees to the MAINTAINERS file for the components that I maintain in the new trees. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 55f0fda..03660de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1800,6 +1800,9 @@ F: include/linux/cfag12864b.h CFG80211 and NL80211 M: Johannes Berg L: linux-wireless@vger.kernel.org +W: http://wireless.kernel.org/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: include/linux/nl80211.h F: include/net/cfg80211.h @@ -4340,7 +4343,8 @@ MAC80211 M: Johannes Berg L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: Documentation/networking/mac80211-injection.txt F: include/net/mac80211.h @@ -4351,7 +4355,8 @@ M: Stefano Brivio M: Mattias Nissler L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID -T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: net/mac80211/rc80211_pid* @@ -5695,6 +5700,9 @@ F: include/linux/remoteproc.h RFKILL M: Johannes Berg L: linux-wireless@vger.kernel.org +W: http://wireless.kernel.org/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: Documentation/rfkill.txt F: net/rfkill/ -- cgit v0.10.2 From d2c8b15d0cb486f4938ba7f2af349d9d1220cb10 Mon Sep 17 00:00:00 2001 From: Meenakshi Venkataraman Date: Tue, 5 Jun 2012 20:24:37 +0200 Subject: iwlwifi: use correct supported firmware for 6035 and 6000g2 My patch iwlwifi: use correct released ucode version did not correctly report supported firmware for the 6035 device. This patch fixes it. The minimum supported firmware version for 6035 is v6. Also correct the minimum supported firmware version for the 6000g2 series of devices. Cc: stable@kernel.org Signed-off-by: Meenakshi Venkataraman Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 19f7ee8..e5e8ada 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -35,17 +35,20 @@ #define IWL6000_UCODE_API_MAX 6 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 6 +#define IWL6035_UCODE_API_MAX 6 /* Oldest version we won't warn about */ #define IWL6000_UCODE_API_OK 4 #define IWL6000G2_UCODE_API_OK 5 #define IWL6050_UCODE_API_OK 5 #define IWL6000G2B_UCODE_API_OK 6 +#define IWL6035_UCODE_API_OK 6 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 -#define IWL6000G2_UCODE_API_MIN 4 +#define IWL6000G2_UCODE_API_MIN 5 +#define IWL6035_UCODE_API_MIN 6 /* EEPROM versions */ #define EEPROM_6000_TX_POWER_VERSION (4) @@ -227,9 +230,25 @@ const struct iwl_cfg iwl6030_2bg_cfg = { IWL_DEVICE_6030, }; +#define IWL_DEVICE_6035 \ + .fw_name_pre = IWL6030_FW_PRE, \ + .ucode_api_max = IWL6035_UCODE_API_MAX, \ + .ucode_api_ok = IWL6035_UCODE_API_OK, \ + .ucode_api_min = IWL6035_UCODE_API_MIN, \ + .device_family = IWL_DEVICE_FAMILY_6030, \ + .max_inst_size = IWL60_RTC_INST_SIZE, \ + .max_data_size = IWL60_RTC_DATA_SIZE, \ + .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ + .base_params = &iwl6000_g2_base_params, \ + .bt_params = &iwl6000_bt_params, \ + .need_temp_offset_calib = true, \ + .led_mode = IWL_LED_RF_STATE, \ + .adv_pm = true + const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", - IWL_DEVICE_6030, + IWL_DEVICE_6035, .ht_params = &iwl6000_ht_params, }; -- cgit v0.10.2 From e64add27e1b4874f589e550b4e0ca6715070373f Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Tue, 5 Jun 2012 20:39:32 +0200 Subject: b43: do not call ieee80211_unregister_hw if we are not registred this patch fixes kernel Oops on "rmmod b43" if firmware was not loaded: BUG: unable to handle kernel NULL pointer dereference at 0000000000000088 IP: [] drain_workqueue+0x25/0x142 PGD 153ac6067 PUD 153b82067 PMD 0 Oops: 0000 [#1] SMP Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 67c13af..c06b6cb 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -877,6 +877,10 @@ struct b43_wl { * from the mac80211 subsystem. */ u16 mac80211_initially_registered_queues; + /* Set this if we call ieee80211_register_hw() and check if we call + * ieee80211_unregister_hw(). */ + bool hw_registred; + /* We can only have one operating interface (802.11 core) * at a time. General information about this interface follows. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5a39b22..acd03a4 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2437,6 +2437,7 @@ start_ieee80211: err = ieee80211_register_hw(wl->hw); if (err) goto err_one_core_detach; + wl->hw_registred = true; b43_leds_register(wl->current_dev); goto out; @@ -5299,6 +5300,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; wl->mac80211_initially_registered_queues = hw->queues; + wl->hw_registred = false; hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) @@ -5370,12 +5372,15 @@ static void b43_bcma_remove(struct bcma_device *core) * as the ieee80211 unreg will destroy the workqueue. */ cancel_work_sync(&wldev->restart_work); - /* Restore the queues count before unregistering, because firmware detect - * might have modified it. Restoring is important, so the networking - * stack can properly free resources. */ - wl->hw->queues = wl->mac80211_initially_registered_queues; - b43_leds_stop(wldev); - ieee80211_unregister_hw(wl->hw); + B43_WARN_ON(!wl); + if (wl->current_dev == wldev && wl->hw_registred) { + /* Restore the queues count before unregistering, because firmware detect + * might have modified it. Restoring is important, so the networking + * stack can properly free resources. */ + wl->hw->queues = wl->mac80211_initially_registered_queues; + b43_leds_stop(wldev); + ieee80211_unregister_hw(wl->hw); + } b43_one_core_detach(wldev->dev); @@ -5446,7 +5451,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); - if (wl->current_dev == wldev) { + if (wl->current_dev == wldev && wl->hw_registred) { /* Restore the queues count before unregistering, because firmware detect * might have modified it. Restoring is important, so the networking * stack can properly free resources. */ -- cgit v0.10.2 From e7027075d0d8fe2d1bf7b0db24623328d2601d3c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 5 Jun 2012 20:58:20 +0200 Subject: bcma: fix null pointer in bcma_core_pci_irq_ctl pc could be null if hosttype != BCMA_HOSTTYPE_PCI. If we are on a device without a pci core this function is called with pc = null by b43 and brcmsmac. If the host type is PCI we have a pci core as well and pc can not be null. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 9a96f14..c32ebd5 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -232,17 +232,19 @@ void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, bool enable) { - struct pci_dev *pdev = pc->core->bus->host_pci; + struct pci_dev *pdev; u32 coremask, tmp; int err = 0; - if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { + if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) { /* This bcma device is not on a PCI host-bus. So the IRQs are * not routed through the PCI core. * So we must not enable routing through the PCI core. */ goto out; } + pdev = pc->core->bus->host_pci; + err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); if (err) goto out; -- cgit v0.10.2 From d6ee27eb13beab94056e0de52d81220058ca2297 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 6 Jun 2012 09:13:36 +0200 Subject: iwlwifi: don't mess up the SCD when removing a key When we remove a key, we put a key index which was supposed to tell the fw that we are actually removing the key. But instead the fw took that index as a valid index and messed up the SRAM of the device. This memory corruption on the device mangled the data of the SCD. The impact on the user is that SCD queue 2 got stuck after having removed keys. The message is the log that was printed is: Queue 2 stuck for 10000ms This doesn't seem to fix the higher queues that get stuck from time to time. Cc: stable@vger.kernel.org [2.6.27+] Reviewed-by: Meenakshi Venkataraman Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index aea07aa..eb6a8ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1267,7 +1267,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, key_flags |= STA_KEY_MULTICAST_MSK; sta_cmd.key.key_flags = key_flags; - sta_cmd.key.key_offset = WEP_INVALID_OFFSET; + sta_cmd.key.key_offset = keyconf->hw_key_idx; sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; sta_cmd.mode = STA_CONTROL_MODIFY_MSK; -- cgit v0.10.2 From d012d04e4d6312ea157b6cf19e9689af934f5aa7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 6 Jun 2012 13:55:02 +0200 Subject: iwlwifi: disable the buggy chain extension feature in HW This feature has been reported to be buggy and enabled by default. We therefore need to disable it manually. Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 3b106929..dfd5466 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -224,6 +224,7 @@ #define SCD_TXFACT (SCD_BASE + 0x10) #define SCD_ACTIVE (SCD_BASE + 0x14) #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) +#define SCD_CHAINEXT_EN (SCD_BASE + 0x244) #define SCD_AGGR_SEL (SCD_BASE + 0x248) #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ec6fb39..79c6b91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1058,6 +1058,11 @@ static void iwl_tx_start(struct iwl_trans *trans) iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, trans_pcie->scd_bc_tbls.dma >> 10); + /* The chain extension of the SCD doesn't work well. This feature is + * enabled by default by the HW, so we need to disable it manually. + */ + iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); + /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), -- cgit v0.10.2 From 58d1eab7ef1d7ff8e448699dfd1a21b7f3303296 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 6 Jun 2012 23:02:55 +0200 Subject: NFC: Fix possible NULL ptr deref when getting the name of a socket llcp_sock_getname() might get called before the LLCP socket was created. This condition isn't checked, and llcp_sock_getname will simply deref a NULL ptr in that case. This exists starting with d646960 ("NFC: Initial LLCP support"). Signed-off-by: Sasha Levin Signed-off-by: John W. Linville diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 3f339b1..17a707d 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -292,6 +292,9 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, pr_debug("%p\n", sk); + if (llcp_sock == NULL) + return -EBADFD; + addr->sa_family = AF_NFC; *len = sizeof(struct sockaddr_nfc_llcp); -- cgit v0.10.2 From 6aee4ca3d2217d3f76469e5ed576d62695f0912a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 7 Jun 2012 14:47:21 +0200 Subject: mac80211: add back channel change flag commit 24398e39c8ee4a9d9123eed322b859ece4d16cac Author: Johannes Berg Date: Wed Mar 28 10:58:36 2012 +0200 mac80211: set HT channel before association removed IEEE80211_CONF_CHANGE_CHANNEL argument from ieee80211_hw_config, which is required by iwl4965 driver, otherwise that driver does not configure channel properly and is not able to associate. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d94627c..91d84cc 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3124,7 +3124,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, } local->oper_channel = cbss->channel; - ieee80211_hw_config(local, 0); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); if (!have_sta) { u32 rates = 0, basic_rates = 0; -- cgit v0.10.2 From 4399a4df98a63e30fd16e9d0cecc46ea92269e8f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 8 Jun 2012 06:25:00 +0000 Subject: l2tp: fix a race in l2tp_ip_sendmsg() Commit 081b1b1bb27f (l2tp: fix l2tp_ip_sendmsg() route handling) added a race, in case IP route cache is disabled. In this case, we should not do the dst_release(&rt->dst), since it'll free the dst immediately, instead of waiting a RCU grace period. Signed-off-by: Eric Dumazet Cc: James Chapman Cc: Denys Fedoryshchenko Signed-off-by: David S. Miller diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 70614e7..61d8b75 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -464,10 +464,12 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m sk->sk_bound_dev_if); if (IS_ERR(rt)) goto no_route; - if (connected) + if (connected) { sk_setup_caps(sk, &rt->dst); - else - dst_release(&rt->dst); /* safe since we hold rcu_read_lock */ + } else { + skb_dst_set(skb, &rt->dst); + goto xmit; + } } /* We dont need to clone dst here, it is guaranteed to not disappear. @@ -475,6 +477,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m */ skb_dst_set_noref(skb, &rt->dst); +xmit: /* Queue the packet to IP for output */ rc = ip_queue_xmit(skb, &inet->cork.fl); rcu_read_unlock(); -- cgit v0.10.2 From cd8f76c0a0c6fce0b2cf23c9bd0123f91453f46d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 7 Jun 2012 22:59:59 +0000 Subject: be2net: fix a race in be_xmit() As soon as hardware is notified of a transmit, we no longer can assume skb can be dereferenced, as TX completion might have freed the packet. Signed-off-by: Eric Dumazet Cc: Sathya Perla Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 08efd30..fdb50ce 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -736,6 +736,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); if (copied) { + int gso_segs = skb_shinfo(skb)->gso_segs; + /* record the sent skb in the sent_skb table */ BUG_ON(txo->sent_skb_list[start]); txo->sent_skb_list[start] = skb; @@ -753,8 +755,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(txo, wrb_cnt, copied, - skb_shinfo(skb)->gso_segs, stopped); + be_tx_stats_update(txo, wrb_cnt, copied, gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); -- cgit v0.10.2 From ead188f9f930fb5d7f0c49315a7fce3d8bd16b7e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 8 Jun 2012 17:07:36 +0200 Subject: writeback: Fix lock imbalance in writeback_sb_inodes() Fix bug introduced by 169ebd90. We have to have wb_list_lock locked when restarting writeback loop after having waited for inode writeback. Bug description by Ted Tso: I can reproduce this fairly easily by using ext4 w/o a journal, running under KVM with 1024megs memory, with fsstress (xfstests #13): [ 45.153294] ===================================== [ 45.154784] [ BUG: bad unlock balance detected! ] [ 45.155591] 3.5.0-rc1-00002-gb22b1f1 #124 Not tainted [ 45.155591] ------------------------------------- [ 45.155591] flush-254:16/2499 is trying to release lock (&(&wb->list_lock)->rlock) at: [ 45.155591] [] writeback_sb_inodes+0x160/0x327 [ 45.155591] but there are no more locks to release! Reported-by: Theodore Ts'o Tested-by: Theodore Ts'o Signed-off-by: Jan Kara Signed-off-by: Fengguang Wu diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 8d2fb8c..41a3ccf 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -664,6 +664,7 @@ static long writeback_sb_inodes(struct super_block *sb, /* Wait for I_SYNC. This function drops i_lock... */ inode_sleep_on_writeback(inode); /* Inode may be gone, start again */ + spin_lock(&wb->list_lock); continue; } inode->i_state |= I_SYNC; -- cgit v0.10.2 From c6c4b97c6b7003e8082dd43db224c1d1f7a24aa2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 8 Jun 2012 14:01:44 +0000 Subject: net/core: fix kernel-doc warnings Fix kernel-doc warnings in net/core: Warning(net/core/skbuff.c:3368): No description found for parameter 'delta_truesize' Warning(net/core/filter.c:628): No description found for parameter 'pfp' Warning(net/core/filter.c:628): Excess function parameter 'sk' description in 'sk_unattached_filter_create' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/net/core/filter.c b/net/core/filter.c index a3eddb5..d4ce2dc 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -616,9 +616,9 @@ static int __sk_prepare_filter(struct sk_filter *fp) /** * sk_unattached_filter_create - create an unattached filter * @fprog: the filter program - * @sk: the socket to use + * @pfp: the unattached filter that is created * - * Create a filter independent ofr any socket. We first run some + * Create a filter independent of any socket. We first run some * sanity checks on it to make sure it does not explode on us later. * If an error occurs or there is insufficient memory for the filter * a negative errno code is returned. On success the return is zero. diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 016694d..d78671e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3361,7 +3361,7 @@ EXPORT_SYMBOL(kfree_skb_partial); * @to: prior buffer * @from: buffer to add * @fragstolen: pointer to boolean - * + * @delta_truesize: how much more was allocated than was requested */ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, bool *fragstolen, int *delta_truesize) -- cgit v0.10.2 From f41ef2e7dc4515777810016612316c38f84275e7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 8 Jun 2012 14:07:19 +0000 Subject: netdev: fix drivers/net/phy/ kernel-doc warnings Fix kernel-doc warnings in drivers/net/phy: Warning(drivers/net/phy/mdio_bus.c:109): No description found for parameter 'mdio_bus_np' Warning(drivers/net/phy/mdio_bus.c:109): Excess function parameter 'mdio_np' description in 'of_mdio_find_bus' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 683ef1c..5061608 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -96,7 +96,7 @@ static int of_mdio_bus_match(struct device *dev, void *mdio_bus_np) } /** * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. - * @mdio_np: Pointer to the mii_bus. + * @mdio_bus_np: Pointer to the mii_bus. * * Returns a pointer to the mii_bus, or NULL if none found. * -- cgit v0.10.2 From c91c3faea500da34d42a14735f1f67bb137b6413 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 9 Jun 2012 08:46:42 +0200 Subject: vga_switcheroo: Enable/disable audio clients at the right time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The audio clients have to be disabled before disabling the VGA and switching. Similarly, enabling the audio client should be done at last. Otherwise the audio-side operation stalls, eventually leading to Oops or lockups. Tested-by: Jörg-Volker Peetz Acked-by: Dave Airlie Signed-off-by: Takashi Iwai diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index eb4f64f..5b3c7d1 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -304,8 +304,6 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) vga_switchon(new_client); vga_set_default_device(new_client->pdev); - set_audio_state(new_client->id, VGA_SWITCHEROO_ON); - return 0; } @@ -321,6 +319,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) active->active = false; + set_audio_state(active->id, VGA_SWITCHEROO_OFF); + if (new_client->fb_info) { struct fb_event event; event.info = new_client->fb_info; @@ -334,11 +334,11 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) if (new_client->ops->reprobe) new_client->ops->reprobe(new_client->pdev); - set_audio_state(active->id, VGA_SWITCHEROO_OFF); - if (active->pwr_state == VGA_SWITCHEROO_ON) vga_switchoff(active); + set_audio_state(new_client->id, VGA_SWITCHEROO_ON); + new_client->active = true; return 0; } @@ -384,8 +384,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, /* pwr off the device not in use */ if (strncmp(usercmd, "OFF", 3) == 0) { list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->active) + if (client->active || client_is_audio(client)) continue; + set_audio_state(client->id, VGA_SWITCHEROO_OFF); if (client->pwr_state == VGA_SWITCHEROO_ON) vga_switchoff(client); } @@ -394,10 +395,11 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, /* pwr on the device not in use */ if (strncmp(usercmd, "ON", 2) == 0) { list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->active) + if (client->active || client_is_audio(client)) continue; if (client->pwr_state == VGA_SWITCHEROO_OFF) vga_switchon(client); + set_audio_state(client->id, VGA_SWITCHEROO_ON); } goto out; } -- cgit v0.10.2 From 6f32d03bc63ab27f5e21d40c4ec81e18d991f424 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 May 2012 15:02:57 -0600 Subject: drivers/video: use correct __devexit_p annotation __devexit functions are discarded when CONFIG_HOTPLUG is not set, so the symbol needs to be referenced carefully. Signed-off-by: Arnd Bergmann Signed-off-by: Mathieu Poirier Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c index 377dde3..c95b417 100644 --- a/drivers/video/broadsheetfb.c +++ b/drivers/video/broadsheetfb.c @@ -1211,7 +1211,7 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev) static struct platform_driver broadsheetfb_driver = { .probe = broadsheetfb_probe, - .remove = broadsheetfb_remove, + .remove = __devexit_p(broadsheetfb_remove), .driver = { .owner = THIS_MODULE, .name = "broadsheetfb", diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index ab0a8e5..85e4f44 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -1045,7 +1045,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev) static struct platform_driver mbxfb_driver = { .probe = mbxfb_probe, - .remove = mbxfb_remove, + .remove = __devexit_p(mbxfb_remove), .suspend = mbxfb_suspend, .resume = mbxfb_resume, .driver = { -- cgit v0.10.2 From ff9440465c82099ba3365930a97f90b3acfcc980 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 May 2012 15:02:58 -0600 Subject: video/ili9320: do not mark exported functions __devexit No symbol can be exported when the section is discarded - the only solution I could think of is not to mark symbols as __devexit when they are exported. Signed-off-by: Arnd Bergmann Signed-off-by: Mathieu Poirier Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c index 5118a9f..b67485a 100644 --- a/drivers/video/backlight/ili9320.c +++ b/drivers/video/backlight/ili9320.c @@ -267,7 +267,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi, EXPORT_SYMBOL_GPL(ili9320_probe_spi); -int __devexit ili9320_remove(struct ili9320 *ili) +int ili9320_remove(struct ili9320 *ili) { ili9320_power(ili, FB_BLANK_POWERDOWN); -- cgit v0.10.2 From d399099cbba92b247ac323a99ac4c5fa5b0ca68d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 May 2012 15:02:59 -0600 Subject: video/console: automatically select a font The frame buffer console needs at least one font to be built into the kernel, so add the necessary Kconfig magic to guarantee that one of the available font is always on. If a user accidentally disables all fonts manually, the 8x16 font will be selected anyway. Signed-off-by: Arnd Bergmann Signed-off-by: Mathieu Poirier Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index c2d11fe..e2c96d0 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -224,5 +224,19 @@ config FONT_10x18 big letters. It fits between the sun 12x22 and the normal 8x16 font. If other fonts are too big or too small for you, say Y, otherwise say N. +config FONT_AUTOSELECT + def_bool y + depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE || STI_CONSOLE || USB_SISUSBVGA_CON + depends on !FONT_8x8 + depends on !FONT_6x11 + depends on !FONT_7x14 + depends on !FONT_PEARL_8x8 + depends on !FONT_ACORN_8x8 + depends on !FONT_MINI_4x6 + depends on !FONT_SUN8x16 + depends on !FONT_SUN12x22 + depends on !FONT_10x18 + select FONT_8x16 + endmenu -- cgit v0.10.2 From f5c3ac242d05c07f646824aba25a541af7464c82 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 May 2012 15:03:00 -0600 Subject: drivers/savagefb: use mdelay instead of udelay Long delays need to use mdelay on architectures such as ARM that cannot compute long timeouts in udelay. Signed-off-by: Arnd Bergmann Signed-off-by: Mathieu Poirier Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index cee7803..f3d3b9c 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1351,7 +1351,7 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r /* following part not present in X11 driver */ cr67 = vga_in8(0x3d5, par) & 0xf; vga_out8(0x3d5, 0x50 | cr67, par); - udelay(10000); + mdelay(10); vga_out8(0x3d4, 0x67, par); /* end of part */ vga_out8(0x3d5, reg->CR67 & ~0x0c, par); @@ -1904,11 +1904,11 @@ static int savage_init_hw(struct savagefb_par *par) vga_out8(0x3d4, 0x66, par); cr66 = vga_in8(0x3d5, par); vga_out8(0x3d5, cr66 | 0x02, par); - udelay(10000); + mdelay(10); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66 & ~0x02, par); /* clear reset flag */ - udelay(10000); + mdelay(10); /* @@ -1918,11 +1918,11 @@ static int savage_init_hw(struct savagefb_par *par) vga_out8(0x3d4, 0x3f, par); cr3f = vga_in8(0x3d5, par); vga_out8(0x3d5, cr3f | 0x08, par); - udelay(10000); + mdelay(10); vga_out8(0x3d4, 0x3f, par); vga_out8(0x3d5, cr3f & ~0x08, par); /* clear reset flags */ - udelay(10000); + mdelay(10); /* Savage ramdac speeds */ par->numClocks = 4; -- cgit v0.10.2 From 5fc05780b84d5227e6c15986f1bde488e52752bd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 May 2012 15:03:01 -0600 Subject: drivers/tosa: driver needs I2C and SPI to compile This driver requires both SPI and I2C to build. Signed-off-by: Arnd Bergmann Signed-off-by: Mathieu Poirier Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index af16884..d7487d2 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -88,7 +88,7 @@ config LCD_PLATFORM config LCD_TOSA tristate "Sharp SL-6000 LCD Driver" - depends on SPI && MACH_TOSA + depends on I2C && SPI && MACH_TOSA help If you have an Sharp SL-6000 Zaurus say Y to enable a driver for its LCD. -- cgit v0.10.2 From 906369e43c29001c39c7dfed8a01b9dff24ace75 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Fri, 8 Jun 2012 16:48:33 -0400 Subject: NFS: fix directio refcount bug on commit This reverts a hunk from commit 04277086577 "NFS: Clean up - Simplify reference counting in fs/nfs/direct.c" The cleanups in that patch affect the write path, but by the time processing hits commit the removed reference has been added back by nfs_scan_commit_list(). Without this reversion, any page that is sent to commit holds on to an unbalanced reference that is never freed. The immediate effect is an imbalance over the wire between OPENs and CLOSEs. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index b5385a7..0509989 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -517,9 +517,9 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data) nfs_list_remove_request(req); if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) { /* Note the rewrite will go through mds */ - kref_get(&req->wb_kref); nfs_mark_request_commit(req, NULL, &cinfo); - } + } else + nfs_release_request(req); nfs_unlock_and_release_request(req); } -- cgit v0.10.2 From c5afc8da5b881633717bfc0510792428aa01fa3f Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Fri, 8 Jun 2012 11:32:56 -0400 Subject: NFS: Use the NFS_DEFAULT_VERSION for v2 and v3 mounts Older versions of nfs utils don't always pass a "vers=" mount option for NFS. This chould lead to attempts at using NFS v0 due to a zeroed out nfs_parsed_mount_data struct. I solve this by setting the default NFS version to NFS_DEFAULT_VERSION in the v2 and v3 cases (v4 has already been taken care of by a similar patch). Reported-by: Joerg Roedel Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust diff --git a/fs/nfs/super.c b/fs/nfs/super.c index bdd6731..906f09c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options, if (data == NULL) goto out_no_data; + args->version = NFS_DEFAULT_VERSION; switch (data->version) { case 1: data->namlen = 0; -- cgit v0.10.2 From 9271b0b4b2044c6db06051fe60bc58cdd4f17c7c Mon Sep 17 00:00:00 2001 From: Martin Pelikan Date: Sat, 9 Jun 2012 21:22:11 +0200 Subject: x86, um: Correct syscall table type attributes breaking gcc 4.8 The latest GCC 4.8 does some more checking on type attributes that break the build for ARCH=um -> fill them in. Specifically, the "asmlinkage" attributes is now tested for consistency. Signed-off-by: Martin Pelikan Link: http://lkml.kernel.org/r/1339269731-10772-1-git-send-email-pelikan@storkhole.cz Acked-by: Richard Weinberger Signed-off-by: H. Peter Anvin diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 416bd40..68d1dc9 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c @@ -39,9 +39,9 @@ #undef __SYSCALL_I386 #define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym, -typedef void (*sys_call_ptr_t)(void); +typedef asmlinkage void (*sys_call_ptr_t)(void); -extern void sys_ni_syscall(void); +extern asmlinkage void sys_ni_syscall(void); const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { /* -- cgit v0.10.2 From 8876d6b5f81f4e242a6660da22bbd92f17a8d058 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Sat, 9 Jun 2012 07:53:03 -0700 Subject: net: Make linux/tcp.h C++ friendly (trivial) I originally sent this patch to , but Jiri Kosina did not feel that this is fully appropriate for the trivial tree. Using linux/tcp.h from C++ results in: cat t.cc #include int main() { } g++ -c t.cc In file included from t.cc:1: /usr/include/linux/tcp.h:72: error: '__u32 __fswab32(__u32)' cannot appear in a constant-expression /usr/include/linux/tcp.h:72: error: a function call cannot appear in a constant-expression ... Attached trivial patch fixes this problem. Tested: - the t.cc above compiles with g++ and - the following program generates the same output before/after the patch: #include #include int main () { #define P(a) printf("%s: %08x\n", #a, (int)a) P(TCP_FLAG_CWR); P(TCP_FLAG_ECE); P(TCP_FLAG_URG); P(TCP_FLAG_ACK); P(TCP_FLAG_PSH); P(TCP_FLAG_RST); P(TCP_FLAG_SYN); P(TCP_FLAG_FIN); P(TCP_RESERVED_BITS); P(TCP_DATA_OFFSET); #undef P return 0; } Signed-off-by: Paul Pluzhnikov Signed-off-by: David S. Miller diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 4c5b632..5f359db 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -69,16 +69,16 @@ union tcp_word_hdr { #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) enum { - TCP_FLAG_CWR = __cpu_to_be32(0x00800000), - TCP_FLAG_ECE = __cpu_to_be32(0x00400000), - TCP_FLAG_URG = __cpu_to_be32(0x00200000), - TCP_FLAG_ACK = __cpu_to_be32(0x00100000), - TCP_FLAG_PSH = __cpu_to_be32(0x00080000), - TCP_FLAG_RST = __cpu_to_be32(0x00040000), - TCP_FLAG_SYN = __cpu_to_be32(0x00020000), - TCP_FLAG_FIN = __cpu_to_be32(0x00010000), - TCP_RESERVED_BITS = __cpu_to_be32(0x0F000000), - TCP_DATA_OFFSET = __cpu_to_be32(0xF0000000) + TCP_FLAG_CWR = __constant_cpu_to_be32(0x00800000), + TCP_FLAG_ECE = __constant_cpu_to_be32(0x00400000), + TCP_FLAG_URG = __constant_cpu_to_be32(0x00200000), + TCP_FLAG_ACK = __constant_cpu_to_be32(0x00100000), + TCP_FLAG_PSH = __constant_cpu_to_be32(0x00080000), + TCP_FLAG_RST = __constant_cpu_to_be32(0x00040000), + TCP_FLAG_SYN = __constant_cpu_to_be32(0x00020000), + TCP_FLAG_FIN = __constant_cpu_to_be32(0x00010000), + TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0F000000), + TCP_DATA_OFFSET = __constant_cpu_to_be32(0xF0000000) }; /* -- cgit v0.10.2 From d26098759cf6d32148649c165f87a7590bc25b89 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sat, 9 Jun 2012 10:57:41 -0400 Subject: drm/radeon: fix tiling and command stream checking on evergreen v3 Fix regresson since the introduction of command stream checking on evergreen (thread referenced below). Issue is cause by ddx allocating bo with formula width*height*bpp while programming the GPU command stream with ALIGN(height, 8). In some case (where page alignment does not hide the extra size bo should be according to height alignment) the kernel will reject the command stream. This patch reprogram the command stream to slice - 1 (slice is a derivative value from height) which avoid rejecting the command stream while keeping the value of command stream checking from a security point of view. This patch also fix wrong computation of layer size for 2D tiled surface. Which should fix issue when 2D color tiling is enabled. This dump the radeon KMS_DRIVER_MINOR so userspace can know if they are on a fixed kernel or not. https://lkml.org/lkml/2012/6/3/80 https://bugs.freedesktop.org/show_bug.cgi?id=50892 https://bugs.freedesktop.org/show_bug.cgi?id=50857 !!! STABLE need a custom version of this patch for 3.4 !!! v2: actually bump the minor version and add comment about stable v3: do compute the height the ddx was trying to use [airlied: drop left over debug] Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 4e7dd2b..c1655412 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -52,6 +52,7 @@ struct evergreen_cs_track { u32 cb_color_view[12]; u32 cb_color_pitch[12]; u32 cb_color_slice[12]; + u32 cb_color_slice_idx[12]; u32 cb_color_attrib[12]; u32 cb_color_cmask_slice[8];/* unused */ u32 cb_color_fmask_slice[8];/* unused */ @@ -127,12 +128,14 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->cb_color_info[i] = 0; track->cb_color_view[i] = 0xFFFFFFFF; track->cb_color_pitch[i] = 0; - track->cb_color_slice[i] = 0; + track->cb_color_slice[i] = 0xfffffff; + track->cb_color_slice_idx[i] = 0; } track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; + track->db_depth_slice = 0xffffffff; track->db_depth_view = 0xFFFFC000; track->db_depth_size = 0xFFFFFFFF; track->db_depth_control = 0xFFFFFFFF; @@ -250,10 +253,9 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, { struct evergreen_cs_track *track = p->track; unsigned palign, halign, tileb, slice_pt; + unsigned mtile_pr, mtile_ps, mtileb; tileb = 64 * surf->bpe * surf->nsamples; - palign = track->group_size / (8 * surf->bpe * surf->nsamples); - palign = MAX(8, palign); slice_pt = 1; if (tileb > surf->tsplit) { slice_pt = tileb / surf->tsplit; @@ -262,7 +264,10 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, /* macro tile width & height */ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; - surf->layer_size = surf->nbx * surf->nby * surf->bpe * slice_pt; + mtileb = (palign / 8) * (halign / 8) * tileb;; + mtile_pr = surf->nbx / palign; + mtile_ps = (mtile_pr * surf->nby) / halign; + surf->layer_size = mtile_ps * mtileb * slice_pt; surf->base_align = (palign / 8) * (halign / 8) * tileb; surf->palign = palign; surf->halign = halign; @@ -434,6 +439,39 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i offset += surf.layer_size * mslice; if (offset > radeon_bo_size(track->cb_color_bo[id])) { + /* old ddx are broken they allocate bo with w*h*bpp but + * program slice with ALIGN(h, 8), catch this and patch + * command stream. + */ + if (!surf.mode) { + volatile u32 *ib = p->ib.ptr; + unsigned long tmp, nby, bsize, size, min = 0; + + /* find the height the ddx wants */ + if (surf.nby > 8) { + min = surf.nby - 8; + } + bsize = radeon_bo_size(track->cb_color_bo[id]); + tmp = track->cb_color_bo_offset[id] << 8; + for (nby = surf.nby; nby > min; nby--) { + size = nby * surf.nbx * surf.bpe * surf.nsamples; + if ((tmp + size * mslice) <= bsize) { + break; + } + } + if (nby > min) { + surf.nby = nby; + slice = ((nby * surf.nbx) / 64) - 1; + if (!evergreen_surface_check(p, &surf, "cb")) { + /* check if this one works */ + tmp += surf.layer_size * mslice; + if (tmp <= bsize) { + ib[track->cb_color_slice_idx[id]] = slice; + goto old_ddx_ok; + } + } + } + } dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " "offset %d, max layer %d, bo size %ld, slice %d)\n", __func__, __LINE__, id, surf.layer_size, @@ -446,6 +484,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i surf.tsplit, surf.mtilea); return -EINVAL; } +old_ddx_ok: return 0; } @@ -1532,6 +1571,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR7_SLICE: tmp = (reg - CB_COLOR0_SLICE) / 0x3c; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR8_SLICE: @@ -1540,6 +1580,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR11_SLICE: tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR0_ATTRIB: diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index f0bb2b5..03e5f5d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -57,9 +57,10 @@ * 2.13.0 - virtual memory support, streamout * 2.14.0 - add evergreen tiling informations * 2.15.0 - add max_pipes query + * 2.16.0 - fix evergreen 2D tiled surface calculation */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 15 +#define KMS_DRIVER_MINOR 16 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); -- cgit v0.10.2 From 7dbb491878a2c51d372a8890fa45a8ff80358af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Sat, 9 Jun 2012 10:53:16 +0000 Subject: r8169: avoid NAPI scheduling delay. While reworking the r8169 driver a few months ago to perform the smallest amount of work in the irq handler, I took care of avoiding any irq mask register operation in the slow work dedicated user context thread. The slow work thread scheduled an extra round of NAPI work which would ultimately set the irq mask register as required, thus keeping such irq mask operations in the NAPI handler. It would eventually race with the irq handler and delay NAPI execution for - assuming no further irq - a whole ksoftirqd period. Mildly a problem for rare link changes or corner case PCI events. The race was always lost after the last bh disabling lock had been removed from the work thread and people started wondering where those pesky "NOHZ: local_softirq_pending 08" messages came from. Actually the irq mask register _can_ be set up directly in the slow work thread. Signed-off-by: Francois Romieu Reported-by: Dave Jones Tested-by: Marc Dionne Cc: Thomas Gleixner Cc: Hayes Wang Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 9757ce3..7260aa7 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5889,11 +5889,7 @@ static void rtl_slow_event_work(struct rtl8169_private *tp) if (status & LinkChg) __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - napi_disable(&tp->napi); - rtl_irq_disable(tp); - - napi_enable(&tp->napi); - napi_schedule(&tp->napi); + rtl_irq_enable_all(tp); } static void rtl_task(struct work_struct *work) -- cgit v0.10.2 From 83a27052c3376793bc879e00e6e6805d6fb7aab9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 5 Jun 2012 22:35:24 +0000 Subject: virtio-net: fix a race on 32bit arches commit 3fa2a1df909 (virtio-net: per cpu 64 bit stats (v2)) added a race on 32bit arches. We must use separate syncp for rx and tx path as they can be run at the same time on different cpus. Thus one sequence increment can be lost and readers spin forever. Signed-off-by: Eric Dumazet Cc: Stephen Hemminger Cc: Michael S. Tsirkin Cc: Jason Wang Acked-by: Rusty Russell Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 5214b1e..f18149a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -42,7 +42,8 @@ module_param(gso, bool, 0444); #define VIRTNET_DRIVER_VERSION "1.0.0" struct virtnet_stats { - struct u64_stats_sync syncp; + struct u64_stats_sync tx_syncp; + struct u64_stats_sync rx_syncp; u64 tx_bytes; u64 tx_packets; @@ -300,10 +301,10 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len) hdr = skb_vnet_hdr(skb); - u64_stats_update_begin(&stats->syncp); + u64_stats_update_begin(&stats->rx_syncp); stats->rx_bytes += skb->len; stats->rx_packets++; - u64_stats_update_end(&stats->syncp); + u64_stats_update_end(&stats->rx_syncp); if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { pr_debug("Needs csum!\n"); @@ -565,10 +566,10 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) { pr_debug("Sent skb %p\n", skb); - u64_stats_update_begin(&stats->syncp); + u64_stats_update_begin(&stats->tx_syncp); stats->tx_bytes += skb->len; stats->tx_packets++; - u64_stats_update_end(&stats->syncp); + u64_stats_update_end(&stats->tx_syncp); tot_sgs += skb_vnet_hdr(skb)->num_sg; dev_kfree_skb_any(skb); @@ -703,12 +704,16 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev, u64 tpackets, tbytes, rpackets, rbytes; do { - start = u64_stats_fetch_begin(&stats->syncp); + start = u64_stats_fetch_begin(&stats->tx_syncp); tpackets = stats->tx_packets; tbytes = stats->tx_bytes; + } while (u64_stats_fetch_retry(&stats->tx_syncp, start)); + + do { + start = u64_stats_fetch_begin(&stats->rx_syncp); rpackets = stats->rx_packets; rbytes = stats->rx_bytes; - } while (u64_stats_fetch_retry(&stats->syncp, start)); + } while (u64_stats_fetch_retry(&stats->rx_syncp, start)); tot->rx_packets += rpackets; tot->tx_packets += tpackets; -- cgit v0.10.2 From 3777808873b0c49c5cf27e44c948dfb02675d578 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 11 Jun 2012 14:29:58 +0900 Subject: bug.h: need linux/kernel.h for TAINT_WARN. asm-generic/bug.h uses taint flags that are only defined in linux/kernel.h, resulting in build failures on platforms that don't include linux/kernel.h some other way: arch/sh/include/asm/thread_info.h:172:2: error: 'TAINT_WARN' undeclared (first use in this function) Caused by commit edd63a2763bd ("set_restore_sigmask() is never called without SIGPENDING (and never should be)"). Reported-by: Stephen Rothwell Cc: Al Viro Signed-off-by: Paul Mundt diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 2520a6e..9f02005 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -2,6 +2,7 @@ #define _ASM_GENERIC_BUG_H #include +#include #ifdef CONFIG_BUG -- cgit v0.10.2 From 7d0c399fe94d4fe572eadc7405654a282e5df63d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 25 May 2012 13:36:43 +0900 Subject: clocksource: sh_cmt: Convert timer lock to raw spinlock. Signed-off-by: Paul Mundt diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 32fe9ef..98b06ba 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -48,13 +48,13 @@ struct sh_cmt_priv { unsigned long next_match_value; unsigned long max_match_value; unsigned long rate; - spinlock_t lock; + raw_spinlock_t lock; struct clock_event_device ced; struct clocksource cs; unsigned long total_cycles; }; -static DEFINE_SPINLOCK(sh_cmt_lock); +static DEFINE_RAW_SPINLOCK(sh_cmt_lock); #define CMSTR -1 /* shared register */ #define CMCSR 0 /* channel register */ @@ -139,7 +139,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - spin_lock_irqsave(&sh_cmt_lock, flags); + raw_spin_lock_irqsave(&sh_cmt_lock, flags); value = sh_cmt_read(p, CMSTR); if (start) @@ -148,7 +148,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_cmt_write(p, CMSTR, value); - spin_unlock_irqrestore(&sh_cmt_lock, flags); + raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); } static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) @@ -328,9 +328,9 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) { unsigned long flags; - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); __sh_cmt_set_next(p, delta); - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); } static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) @@ -385,7 +385,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) int ret = 0; unsigned long flags; - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) ret = sh_cmt_enable(p, &p->rate); @@ -398,7 +398,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) __sh_cmt_set_next(p, p->max_match_value); out: - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); return ret; } @@ -408,7 +408,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) unsigned long flags; unsigned long f; - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); p->flags &= ~flag; @@ -420,7 +420,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) __sh_cmt_set_next(p, p->max_match_value); - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); } static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs) @@ -435,13 +435,13 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs) unsigned long value; int has_wrapped; - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); value = p->total_cycles; raw = sh_cmt_get_counter(p, &has_wrapped); if (unlikely(has_wrapped)) raw += p->match_value + 1; - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); return value + raw; } @@ -591,7 +591,7 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name, p->max_match_value = (1 << p->width) - 1; p->match_value = p->max_match_value; - spin_lock_init(&p->lock); + raw_spin_lock_init(&p->lock); if (clockevent_rating) sh_cmt_register_clockevent(p, name, clockevent_rating); -- cgit v0.10.2 From 50393a92c89c603e2d043c9f0212d3bd66701c86 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 25 May 2012 13:38:54 +0900 Subject: clocksource: sh_mtu2: Convert timer lock to raw spinlock. Signed-off-by: Paul Mundt diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index a2172f6..d9b76ca 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -43,7 +43,7 @@ struct sh_mtu2_priv { struct clock_event_device ced; }; -static DEFINE_SPINLOCK(sh_mtu2_lock); +static DEFINE_RAW_SPINLOCK(sh_mtu2_lock); #define TSTR -1 /* shared register */ #define TCR 0 /* channel register */ @@ -107,7 +107,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - spin_lock_irqsave(&sh_mtu2_lock, flags); + raw_spin_lock_irqsave(&sh_mtu2_lock, flags); value = sh_mtu2_read(p, TSTR); if (start) @@ -116,7 +116,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_mtu2_write(p, TSTR, value); - spin_unlock_irqrestore(&sh_mtu2_lock, flags); + raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags); } static int sh_mtu2_enable(struct sh_mtu2_priv *p) -- cgit v0.10.2 From c2225a57e596a308424e59abc7e864f866fe4493 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 25 May 2012 13:39:09 +0900 Subject: clocksource: sh_tmu: Convert timer lock to raw spinlock. Signed-off-by: Paul Mundt diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 97f54b6..852b3f1 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -45,7 +45,7 @@ struct sh_tmu_priv { struct clocksource cs; }; -static DEFINE_SPINLOCK(sh_tmu_lock); +static DEFINE_RAW_SPINLOCK(sh_tmu_lock); #define TSTR -1 /* shared register */ #define TCOR 0 /* channel register */ @@ -95,7 +95,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - spin_lock_irqsave(&sh_tmu_lock, flags); + raw_spin_lock_irqsave(&sh_tmu_lock, flags); value = sh_tmu_read(p, TSTR); if (start) @@ -104,7 +104,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_tmu_write(p, TSTR, value); - spin_unlock_irqrestore(&sh_tmu_lock, flags); + raw_spin_unlock_irqrestore(&sh_tmu_lock, flags); } static int sh_tmu_enable(struct sh_tmu_priv *p) -- cgit v0.10.2 From c5d21c4b2a7765ab0600c8426374b50eb9f4a36f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sun, 10 Jun 2012 20:05:24 +0000 Subject: net: Reorder initialization in ip_route_output to fix gcc warning If I build with W=1, for every file that includes , I get the warning include/net/route.h: In function 'ip_route_output': include/net/route.h:135:3: warning: initialized field overwritten [-Woverride-init] include/net/route.h:135:3: warning: (near initialization for 'fl4') [-Woverride-init] (This is with "gcc (Debian 4.6.3-1) 4.6.3") A fix seems pretty trivial: move the initialization of .flowi4_tos earlier. As far as I can tell, this has no effect on code generation. Signed-off-by: Roland Dreier Signed-off-by: David S. Miller diff --git a/include/net/route.h b/include/net/route.h index ed2b78e..9870546 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -130,9 +130,9 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, { struct flowi4 fl4 = { .flowi4_oif = oif, + .flowi4_tos = tos, .daddr = daddr, .saddr = saddr, - .flowi4_tos = tos, }; return ip_route_output_key(net, &fl4); } -- cgit v0.10.2 From 3977407e83129f53e43d3ac44be8702f59fa3f77 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 11 Jun 2012 17:10:16 +0900 Subject: clocksource: sh_tmu: Use clockevents_config_and_register(). This switches over to the now exported clockevents_config() and clockevents_config_and_register() helpers. This knocks off a long-standing TMU TODO item. Signed-off-by: Paul Mundt diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 852b3f1..c1b51d4 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -245,12 +245,7 @@ static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic) sh_tmu_enable(p); - /* TODO: calculate good shift from rate and counter bit width */ - - ced->shift = 32; - ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); - ced->max_delta_ns = clockevent_delta2ns(0xffffffff, ced); - ced->min_delta_ns = 5000; + clockevents_config(ced, p->rate); if (periodic) { p->periodic = (p->rate + HZ/2) / HZ; @@ -323,7 +318,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->set_mode = sh_tmu_clock_event_mode; dev_info(&p->pdev->dev, "used for clock events\n"); - clockevents_register_device(ced); + + clockevents_config_and_register(ced, 1, 0x300, 0xffffffff); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { -- cgit v0.10.2 From 16b0dc29c1af9df341428f4c49ada4f626258082 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 10 Jun 2012 21:11:57 +0000 Subject: dummy: fix rcu_sched self-detected stalls Trying to "modprobe dummy numdummies=30000" triggers : INFO: rcu_sched self-detected stall on CPU { 8} (t=60000 jiffies) After this splat, RTNL is locked and reboot is needed. We must call cond_resched() to avoid this, even holding RTNL. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 442d91a..bab0158 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -187,8 +187,10 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); - for (i = 0; i < numdummies && !err; i++) + for (i = 0; i < numdummies && !err; i++) { err = dummy_init_one(); + cond_resched(); + } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); rtnl_unlock(); -- cgit v0.10.2 From 9efc31b81d740487fd204fade0913ffa8cc97fc3 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Sun, 10 Jun 2012 10:50:52 +0800 Subject: x86/mm: Fix some kernel-doc warnings Fix kernel-doc warnings in arch/x86/mm/ioremap.c and arch/x86/mm/pageattr.c, just like this one: Warning(arch/x86/mm/ioremap.c:204): No description found for parameter 'phys_addr' Warning(arch/x86/mm/ioremap.c:204): Excess function parameter 'offset' description in 'ioremap_nocache' Signed-off-by: Wanpeng Li Cc: Gavin Shan Cc: Wanpeng Li Link: http://lkml.kernel.org/r/1339296652-2935-1-git-send-email-liwp.linux@gmail.com Signed-off-by: Ingo Molnar diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index be1ef57..78fe3f1 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -180,7 +180,7 @@ err_free_memtype: /** * ioremap_nocache - map bus memory into CPU space - * @offset: bus address of the memory + * @phys_addr: bus address of the memory * @size: size of the resource to map * * ioremap_nocache performs a platform specific sequence of operations to @@ -217,7 +217,7 @@ EXPORT_SYMBOL(ioremap_nocache); /** * ioremap_wc - map memory into CPU space write combined - * @offset: bus address of the memory + * @phys_addr: bus address of the memory * @size: size of the resource to map * * This version of ioremap ensures that the memory is marked write combining. diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index e1ebde3..a718e0d 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -122,7 +122,7 @@ within(unsigned long addr, unsigned long start, unsigned long end) /** * clflush_cache_range - flush a cache range with clflush - * @addr: virtual start address + * @vaddr: virtual start address * @size: number of bytes to flush * * clflush is an unordered instruction which needs fencing with mfence -- cgit v0.10.2 From e53f517ff236a0ec5413ff3935c53406b69bc1e2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 6 Jun 2012 08:03:35 +0200 Subject: ARM: dma-mapping: Add missing static storage class specifier Fixes the following sparse warnings: arch/arm/mm/dma-mapping.c:231:15: warning: symbol 'consistent_base' was not declared. Should it be static? arch/arm/mm/dma-mapping.c:326:8: warning: symbol 'coherent_pool_size' was not declared. Should it be static? Signed-off-by: Sachin Kamat Signed-off-by: Marek Szyprowski diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 106c4c0..d766e42 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -228,7 +228,7 @@ static pte_t **consistent_pte; #define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M -unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; +static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; void __init init_consistent_dma_size(unsigned long size) { @@ -321,7 +321,7 @@ static struct arm_vmregion_head coherent_head = { .vm_list = LIST_HEAD_INIT(coherent_head.vm_list), }; -size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8; +static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8; static int __init early_coherent_pool(char *p) { -- cgit v0.10.2 From 4986e5c7cd91817d0f58dd15073c9080d47980cf Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 6 Jun 2012 12:05:01 +0200 Subject: ARM: mm: fix type of the arm_dma_limit global variable arm_dma_limit stores physical address of maximal address accessible by DMA, so the phys_addr_t type makes much more sense for it instead of u32. This patch fixes the following build warning: arch/arm/mm/init.c:380: warning: comparison of distinct pointer types lacks a cast Reported-by: Russell King Signed-off-by: Marek Szyprowski diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index c21d06c..f54d592 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -212,7 +212,7 @@ EXPORT_SYMBOL(arm_dma_zone_size); * allocations. This must be the smallest DMA mask in the system, * so a successful GFP_DMA allocation will always satisfy this. */ -u32 arm_dma_limit; +phys_addr_t arm_dma_limit; static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole, unsigned long dma_size) diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 93dc0c1..c471436 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -62,7 +62,7 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page #endif #ifdef CONFIG_ZONE_DMA -extern u32 arm_dma_limit; +extern phys_addr_t arm_dma_limit; #else #define arm_dma_limit ((u32)~0) #endif -- cgit v0.10.2 From f2a8ecaf6d7259cc70fb5898823eab9a2dd86570 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Jun 2012 15:51:54 +0200 Subject: ALSA: hda - Fix detection of Creative SoundCore3D controllers The PCI ID entries of Creative SoundCore3D HD-audio controllers should be before the wildcard for vendor = Creative. Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e172c5d..0276382 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3354,6 +3354,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, /* Creative X-Fi (CA0110-IBG) */ + /* CTHDA chips */ + { PCI_DEVICE(0x1102, 0x0010), + .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, + { PCI_DEVICE(0x1102, 0x0012), + .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, #if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE) /* the following entry conflicts with snd-ctxfi driver, * as ctxfi driver mutates from HD-audio to native mode with @@ -3370,11 +3375,6 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #endif - /* CTHDA chips */ - { PCI_DEVICE(0x1102, 0x0010), - .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, - { PCI_DEVICE(0x1102, 0x0012), - .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, /* Vortex86MX */ { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, /* VMware HDAudio */ -- cgit v0.10.2 From e30478598a8476d02e3b00caa89ce1a3b1dad54b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 10 Jun 2012 23:24:00 +0000 Subject: lpc_eth: add missing ndo_change_mtu() lpc_eth does a copy of transmitted skbs to DMA area, without checking skb lengths, so can trigger buffer overflows : memcpy(pldat->tx_buff_v + txidx * ENET_MAXF_SIZE, skb->data, len); One way to get bigger skbs is to allow MTU changes above the 1500 limit. Calling eth_change_mtu() in ndo_change_mtu() makes sure this cannot happen. Signed-off-by: Eric Dumazet Cc: Roland Stigge Cc: Kevin Wells Acked-by: Roland Stigge Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 8d2666f..10febdc 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1320,6 +1320,7 @@ static const struct net_device_ops lpc_netdev_ops = { .ndo_set_rx_mode = lpc_eth_set_multicast_list, .ndo_do_ioctl = lpc_eth_ioctl, .ndo_set_mac_address = lpc_set_mac_address, + .ndo_change_mtu = eth_change_mtu, }; static int lpc_eth_drv_probe(struct platform_device *pdev) -- cgit v0.10.2 From 3f16da51b0e533871d22a29682f3c3969d4f7e22 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 11 Jun 2012 07:21:36 +0000 Subject: lpc_eth: fix tx completion __lpc_handle_xmit() has two bugs : 1) It can leak skbs in case TXSTATUS_ERROR is set 2) It can wake up txqueue while no slot was freed. Signed-off-by: Eric Dumazet Reported-by: Roland Stigge Tested-by: Roland Stigge Cc: Kevin Wells Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 10febdc..083d671 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -946,16 +946,16 @@ static void __lpc_handle_xmit(struct net_device *ndev) /* Update stats */ ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; - - /* Free buffer */ - dev_kfree_skb_irq(skb); } + dev_kfree_skb_irq(skb); txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); } - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); + if (pldat->num_used_tx_buffs <= ENET_TX_DESC/2) { + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); + } } static int __lpc_handle_recv(struct net_device *ndev, int budget) -- cgit v0.10.2 From 64f9a83665e4f168ff50ce1db9eb175f954048fa Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Thu, 31 May 2012 17:45:00 +0100 Subject: NFSv2: EOF incorrectly set on short read In cases where the server returns fewer bytes then those requested, we can incorrectly set the eof flag for the file. Fixing this allows the request to be retried with updated offset and count arguments. Signed-off-by: Sachin Prabhu Signed-off-by: Trond Myklebust diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index a706b6b..617c741 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -651,7 +651,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) /* Emulate the eof flag, which isn't normally needed in NFSv2 * as it is guaranteed to always return the file attributes */ - if (data->args.offset + data->args.count >= data->res.fattr->size) + if (data->args.offset + data->res.count >= data->res.fattr->size) data->res.eof = 1; } return 0; -- cgit v0.10.2 From 2669940db8d02147181e338bb6db98394569f31a Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 30 May 2012 16:12:24 -0400 Subject: NFSv4 do not send an empty SETATTR compound Commit 536e43d12b9517bbbf6114cd1a12be27857a4d7a ATTR_OPEN check can result in an ia_valid with only ATTR_FILE set, and no NFS_VALID_ATTRS attributes to request from the server. Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f23977e..15fc7e4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2549,6 +2549,14 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, nfs_fattr_init(fattr); + /* Deal with open(O_TRUNC) */ + if (sattr->ia_valid & ATTR_OPEN) + sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); + + /* Optimization: if the end result is no change, don't RPC */ + if ((sattr->ia_valid & ~(ATTR_FILE)) == 0) + return 0; + /* Search for an existing open(O_WRITE) file */ if (sattr->ia_valid & ATTR_FILE) { struct nfs_open_context *ctx; @@ -2560,10 +2568,6 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } } - /* Deal with open(O_TRUNC) */ - if (sattr->ia_valid & ATTR_OPEN) - sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); - status = nfs4_do_setattr(inode, cred, fattr, sattr, state); if (status == 0) nfs_setattr_update_inode(inode, sattr); -- cgit v0.10.2 From 92123e068efa310b09e9943ac1cfd10ff6b6d2e4 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 11 Jun 2012 10:03:42 -0400 Subject: rpc_pipefs: allow rpc_purge_list to take a NULL waitq pointer In the event that we don't have a dentry for a rpc_pipefs pipe, we still need to allow the queue_timeout job to clean out the queue. There's just no waitq to wake up in that event. Cc: stable@kernel.org Reported-by: Hans de Bruin Reported-by: Joerg Platte Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 0404047..21fde99 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -71,7 +71,9 @@ static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, msg->errno = err; destroy_msg(msg); } while (!list_empty(head)); - wake_up(waitq); + + if (waitq) + wake_up(waitq); } static void @@ -91,11 +93,9 @@ rpc_timeout_upcall_queue(struct work_struct *work) } dentry = dget(pipe->dentry); spin_unlock(&pipe->lock); - if (dentry) { - rpc_purge_list(&RPC_I(dentry->d_inode)->waitq, - &free_list, destroy_msg, -ETIMEDOUT); - dput(dentry); - } + rpc_purge_list(dentry ? &RPC_I(dentry->d_inode)->waitq : NULL, + &free_list, destroy_msg, -ETIMEDOUT); + dput(dentry); } ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, -- cgit v0.10.2 From 883ffd6e64114495f68652721065149a2bbd9de6 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 7 Jun 2012 23:21:05 +0000 Subject: net: stmmac: Fix clock en-/disable calls clk_{un}prepare is mandatory for platforms using common clock framework. Since these drivers are used by SPEAr platform, which supports common clock framework, add clk_{un}prepare() support for them. Otherwise the clocks are not correctly en-/disabled and ethernet support doesn't work. Signed-off-by: Stefan Roese Cc: Viresh Kumar Cc: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 94b21b4..dc20c56 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -109,7 +109,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, static inline int stmmac_clk_enable(struct stmmac_priv *priv) { if (!IS_ERR(priv->stmmac_clk)) - return clk_enable(priv->stmmac_clk); + return clk_prepare_enable(priv->stmmac_clk); return 0; } @@ -119,7 +119,7 @@ static inline void stmmac_clk_disable(struct stmmac_priv *priv) if (IS_ERR(priv->stmmac_clk)) return; - clk_disable(priv->stmmac_clk); + clk_disable_unprepare(priv->stmmac_clk); } static inline int stmmac_clk_get(struct stmmac_priv *priv) { -- cgit v0.10.2 From b7abee6ef888117f92db370620ebf116a38e3f4d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 7 Jun 2012 12:56:54 +0000 Subject: tg3: Apply short DMA frag workaround to 5906 5906 devices also need the short DMA fragment workaround. This patch makes the necessary change. Signed-off-by: Matt Carlson Tested-by: Christian Kujau Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index edeeb51..e47ff8b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14275,7 +14275,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (tg3_flag(tp, 5755_PLUS)) + if (tg3_flag(tp, 5755_PLUS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tg3_flag_set(tp, SHORT_DMA_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) -- cgit v0.10.2 From e3d62d7e8e05a6a4b08f4672385ae58fc0f132c4 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 7 Jun 2012 10:45:02 +0000 Subject: tilegx network driver: initial support This change adds support for the tilegx network driver based on the GXIO IORPC support in the tilegx software stack, using the on-chip mPIPE packet processing engine. Signed-off-by: Chris Metcalf Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig index 2d9218f..098b1c4 100644 --- a/drivers/net/ethernet/tile/Kconfig +++ b/drivers/net/ethernet/tile/Kconfig @@ -7,6 +7,8 @@ config TILE_NET depends on TILE default y select CRC32 + select TILE_GXIO_MPIPE if TILEGX + select HIGH_RES_TIMERS if TILEGX ---help--- This is a standard Linux network device driver for the on-chip Tilera Gigabit Ethernet and XAUI interfaces. diff --git a/drivers/net/ethernet/tile/Makefile b/drivers/net/ethernet/tile/Makefile index f634f14..0ef9eef 100644 --- a/drivers/net/ethernet/tile/Makefile +++ b/drivers/net/ethernet/tile/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_TILE_NET) += tile_net.o ifdef CONFIG_TILEGX -tile_net-objs := tilegx.o mpipe.o iorpc_mpipe.o dma_queue.o +tile_net-y := tilegx.o else -tile_net-objs := tilepro.o +tile_net-y := tilepro.o endif diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c new file mode 100644 index 0000000..83b4b38 --- /dev/null +++ b/drivers/net/ethernet/tile/tilegx.c @@ -0,0 +1,1898 @@ +/* + * Copyright 2012 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include /* printk() */ +#include /* kmalloc() */ +#include /* error codes */ +#include /* size_t */ +#include +#include +#include +#include /* struct device, and other headers */ +#include /* eth_type_trans */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Default transmit lockup timeout period, in jiffies. */ +#define TILE_NET_TIMEOUT (5 * HZ) + +/* The maximum number of distinct channels (idesc.channel is 5 bits). */ +#define TILE_NET_CHANNELS 32 + +/* Maximum number of idescs to handle per "poll". */ +#define TILE_NET_BATCH 128 + +/* Maximum number of packets to handle per "poll". */ +#define TILE_NET_WEIGHT 64 + +/* Number of entries in each iqueue. */ +#define IQUEUE_ENTRIES 512 + +/* Number of entries in each equeue. */ +#define EQUEUE_ENTRIES 2048 + +/* Total header bytes per equeue slot. Must be big enough for 2 bytes + * of NET_IP_ALIGN alignment, plus 14 bytes (?) of L2 header, plus up to + * 60 bytes of actual TCP header. We round up to align to cache lines. + */ +#define HEADER_BYTES 128 + +/* Maximum completions per cpu per device (must be a power of two). + * ISSUE: What is the right number here? If this is too small, then + * egress might block waiting for free space in a completions array. + * ISSUE: At the least, allocate these only for initialized echannels. + */ +#define TILE_NET_MAX_COMPS 64 + +#define MAX_FRAGS (MAX_SKB_FRAGS + 1) + +/* Size of completions data to allocate. + * ISSUE: Probably more than needed since we don't use all the channels. + */ +#define COMPS_SIZE (TILE_NET_CHANNELS * sizeof(struct tile_net_comps)) + +/* Size of NotifRing data to allocate. */ +#define NOTIF_RING_SIZE (IQUEUE_ENTRIES * sizeof(gxio_mpipe_idesc_t)) + +/* Timeout to wake the per-device TX timer after we stop the queue. + * We don't want the timeout too short (adds overhead, and might end + * up causing stop/wake/stop/wake cycles) or too long (affects performance). + * For the 10 Gb NIC, 30 usec means roughly 30+ 1500-byte packets. + */ +#define TX_TIMER_DELAY_USEC 30 + +/* Timeout to wake the per-cpu egress timer to free completions. */ +#define EGRESS_TIMER_DELAY_USEC 1000 + +MODULE_AUTHOR("Tilera Corporation"); +MODULE_LICENSE("GPL"); + +/* A "packet fragment" (a chunk of memory). */ +struct frag { + void *buf; + size_t length; +}; + +/* A single completion. */ +struct tile_net_comp { + /* The "complete_count" when the completion will be complete. */ + s64 when; + /* The buffer to be freed when the completion is complete. */ + struct sk_buff *skb; +}; + +/* The completions for a given cpu and echannel. */ +struct tile_net_comps { + /* The completions. */ + struct tile_net_comp comp_queue[TILE_NET_MAX_COMPS]; + /* The number of completions used. */ + unsigned long comp_next; + /* The number of completions freed. */ + unsigned long comp_last; +}; + +/* The transmit wake timer for a given cpu and echannel. */ +struct tile_net_tx_wake { + struct hrtimer timer; + struct net_device *dev; +}; + +/* Info for a specific cpu. */ +struct tile_net_info { + /* The NAPI struct. */ + struct napi_struct napi; + /* Packet queue. */ + gxio_mpipe_iqueue_t iqueue; + /* Our cpu. */ + int my_cpu; + /* True if iqueue is valid. */ + bool has_iqueue; + /* NAPI flags. */ + bool napi_added; + bool napi_enabled; + /* Number of small sk_buffs which must still be provided. */ + unsigned int num_needed_small_buffers; + /* Number of large sk_buffs which must still be provided. */ + unsigned int num_needed_large_buffers; + /* A timer for handling egress completions. */ + struct hrtimer egress_timer; + /* True if "egress_timer" is scheduled. */ + bool egress_timer_scheduled; + /* Comps for each egress channel. */ + struct tile_net_comps *comps_for_echannel[TILE_NET_CHANNELS]; + /* Transmit wake timer for each egress channel. */ + struct tile_net_tx_wake tx_wake[TILE_NET_CHANNELS]; +}; + +/* Info for egress on a particular egress channel. */ +struct tile_net_egress { + /* The "equeue". */ + gxio_mpipe_equeue_t *equeue; + /* The headers for TSO. */ + unsigned char *headers; +}; + +/* Info for a specific device. */ +struct tile_net_priv { + /* Our network device. */ + struct net_device *dev; + /* The primary link. */ + gxio_mpipe_link_t link; + /* The primary channel, if open, else -1. */ + int channel; + /* The "loopify" egress link, if needed. */ + gxio_mpipe_link_t loopify_link; + /* The "loopify" egress channel, if open, else -1. */ + int loopify_channel; + /* The egress channel (channel or loopify_channel). */ + int echannel; + /* Total stats. */ + struct net_device_stats stats; +}; + +/* Egress info, indexed by "priv->echannel" (lazily created as needed). */ +static struct tile_net_egress egress_for_echannel[TILE_NET_CHANNELS]; + +/* Devices currently associated with each channel. + * NOTE: The array entry can become NULL after ifconfig down, but + * we do not free the underlying net_device structures, so it is + * safe to use a pointer after reading it from this array. + */ +static struct net_device *tile_net_devs_for_channel[TILE_NET_CHANNELS]; + +/* A mutex for "tile_net_devs_for_channel". */ +static DEFINE_MUTEX(tile_net_devs_for_channel_mutex); + +/* The per-cpu info. */ +static DEFINE_PER_CPU(struct tile_net_info, per_cpu_info); + +/* The "context" for all devices. */ +static gxio_mpipe_context_t context; + +/* Buffer sizes and mpipe enum codes for buffer stacks. + * See arch/tile/include/gxio/mpipe.h for the set of possible values. + */ +#define BUFFER_SIZE_SMALL_ENUM GXIO_MPIPE_BUFFER_SIZE_128 +#define BUFFER_SIZE_SMALL 128 +#define BUFFER_SIZE_LARGE_ENUM GXIO_MPIPE_BUFFER_SIZE_1664 +#define BUFFER_SIZE_LARGE 1664 + +/* The small/large "buffer stacks". */ +static int small_buffer_stack = -1; +static int large_buffer_stack = -1; + +/* Amount of memory allocated for each buffer stack. */ +static size_t buffer_stack_size; + +/* The actual memory allocated for the buffer stacks. */ +static void *small_buffer_stack_va; +static void *large_buffer_stack_va; + +/* The buckets. */ +static int first_bucket = -1; +static int num_buckets = 1; + +/* The ingress irq. */ +static int ingress_irq = -1; + +/* Text value of tile_net.cpus if passed as a module parameter. */ +static char *network_cpus_string; + +/* The actual cpus in "network_cpus". */ +static struct cpumask network_cpus_map; + +/* If "loopify=LINK" was specified, this is "LINK". */ +static char *loopify_link_name; + +/* If "tile_net.custom" was specified, this is non-NULL. */ +static char *custom_str; + +/* The "tile_net.cpus" argument specifies the cpus that are dedicated + * to handle ingress packets. + * + * The parameter should be in the form "tile_net.cpus=m-n[,x-y]", where + * m, n, x, y are integer numbers that represent the cpus that can be + * neither a dedicated cpu nor a dataplane cpu. + */ +static bool network_cpus_init(void) +{ + char buf[1024]; + int rc; + + if (network_cpus_string == NULL) + return false; + + rc = cpulist_parse_crop(network_cpus_string, &network_cpus_map); + if (rc != 0) { + pr_warn("tile_net.cpus=%s: malformed cpu list\n", + network_cpus_string); + return false; + } + + /* Remove dedicated cpus. */ + cpumask_and(&network_cpus_map, &network_cpus_map, cpu_possible_mask); + + if (cpumask_empty(&network_cpus_map)) { + pr_warn("Ignoring empty tile_net.cpus='%s'.\n", + network_cpus_string); + return false; + } + + cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map); + pr_info("Linux network CPUs: %s\n", buf); + return true; +} + +module_param_named(cpus, network_cpus_string, charp, 0444); +MODULE_PARM_DESC(cpus, "cpulist of cores that handle network interrupts"); + +/* The "tile_net.loopify=LINK" argument causes the named device to + * actually use "loop0" for ingress, and "loop1" for egress. This + * allows an app to sit between the actual link and linux, passing + * (some) packets along to linux, and forwarding (some) packets sent + * out by linux. + */ +module_param_named(loopify, loopify_link_name, charp, 0444); +MODULE_PARM_DESC(loopify, "name the device to use loop0/1 for ingress/egress"); + +/* The "tile_net.custom" argument causes us to ignore the "conventional" + * classifier metadata, in particular, the "l2_offset". + */ +module_param_named(custom, custom_str, charp, 0444); +MODULE_PARM_DESC(custom, "indicates a (heavily) customized classifier"); + +/* Atomically update a statistics field. + * Note that on TILE-Gx, this operation is fire-and-forget on the + * issuing core (single-cycle dispatch) and takes only a few cycles + * longer than a regular store when the request reaches the home cache. + * No expensive bus management overhead is required. + */ +static void tile_net_stats_add(unsigned long value, unsigned long *field) +{ + BUILD_BUG_ON(sizeof(atomic_long_t) != sizeof(unsigned long)); + atomic_long_add(value, (atomic_long_t *)field); +} + +/* Allocate and push a buffer. */ +static bool tile_net_provide_buffer(bool small) +{ + int stack = small ? small_buffer_stack : large_buffer_stack; + const unsigned long buffer_alignment = 128; + struct sk_buff *skb; + int len; + + len = sizeof(struct sk_buff **) + buffer_alignment; + len += (small ? BUFFER_SIZE_SMALL : BUFFER_SIZE_LARGE); + skb = dev_alloc_skb(len); + if (skb == NULL) + return false; + + /* Make room for a back-pointer to 'skb' and guarantee alignment. */ + skb_reserve(skb, sizeof(struct sk_buff **)); + skb_reserve(skb, -(long)skb->data & (buffer_alignment - 1)); + + /* Save a back-pointer to 'skb'. */ + *(struct sk_buff **)(skb->data - sizeof(struct sk_buff **)) = skb; + + /* Make sure "skb" and the back-pointer have been flushed. */ + wmb(); + + gxio_mpipe_push_buffer(&context, stack, + (void *)va_to_tile_io_addr(skb->data)); + + return true; +} + +/* Convert a raw mpipe buffer to its matching skb pointer. */ +static struct sk_buff *mpipe_buf_to_skb(void *va) +{ + /* Acquire the associated "skb". */ + struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); + struct sk_buff *skb = *skb_ptr; + + /* Paranoia. */ + if (skb->data != va) { + /* Panic here since there's a reasonable chance + * that corrupt buffers means generic memory + * corruption, with unpredictable system effects. + */ + panic("Corrupt linux buffer! va=%p, skb=%p, skb->data=%p", + va, skb, skb->data); + } + + return skb; +} + +static void tile_net_pop_all_buffers(int stack) +{ + for (;;) { + tile_io_addr_t addr = + (tile_io_addr_t)gxio_mpipe_pop_buffer(&context, stack); + if (addr == 0) + break; + dev_kfree_skb_irq(mpipe_buf_to_skb(tile_io_addr_to_va(addr))); + } +} + +/* Provide linux buffers to mPIPE. */ +static void tile_net_provide_needed_buffers(void) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + + while (info->num_needed_small_buffers != 0) { + if (!tile_net_provide_buffer(true)) + goto oops; + info->num_needed_small_buffers--; + } + + while (info->num_needed_large_buffers != 0) { + if (!tile_net_provide_buffer(false)) + goto oops; + info->num_needed_large_buffers--; + } + + return; + +oops: + /* Add a description to the page allocation failure dump. */ + pr_notice("Tile %d still needs some buffers\n", info->my_cpu); +} + +static inline bool filter_packet(struct net_device *dev, void *buf) +{ + /* Filter packets received before we're up. */ + if (dev == NULL || !(dev->flags & IFF_UP)) + return true; + + /* Filter out packets that aren't for us. */ + if (!(dev->flags & IFF_PROMISC) && + !is_multicast_ether_addr(buf) && + compare_ether_addr(dev->dev_addr, buf) != 0) + return true; + + return false; +} + +static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb, + gxio_mpipe_idesc_t *idesc, unsigned long len) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + struct tile_net_priv *priv = netdev_priv(dev); + + /* Encode the actual packet length. */ + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, dev); + + /* Acknowledge "good" hardware checksums. */ + if (idesc->cs && idesc->csum_seed_val == 0xFFFF) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + netif_receive_skb(skb); + + /* Update stats. */ + tile_net_stats_add(1, &priv->stats.rx_packets); + tile_net_stats_add(len, &priv->stats.rx_bytes); + + /* Need a new buffer. */ + if (idesc->size == BUFFER_SIZE_SMALL_ENUM) + info->num_needed_small_buffers++; + else + info->num_needed_large_buffers++; +} + +/* Handle a packet. Return true if "processed", false if "filtered". */ +static bool tile_net_handle_packet(gxio_mpipe_idesc_t *idesc) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + struct net_device *dev = tile_net_devs_for_channel[idesc->channel]; + uint8_t l2_offset; + void *va; + void *buf; + unsigned long len; + bool filter; + + /* Drop packets for which no buffer was available. + * NOTE: This happens under heavy load. + */ + if (idesc->be) { + struct tile_net_priv *priv = netdev_priv(dev); + tile_net_stats_add(1, &priv->stats.rx_dropped); + gxio_mpipe_iqueue_consume(&info->iqueue, idesc); + if (net_ratelimit()) + pr_info("Dropping packet (insufficient buffers).\n"); + return false; + } + + /* Get the "l2_offset", if allowed. */ + l2_offset = custom_str ? 0 : gxio_mpipe_idesc_get_l2_offset(idesc); + + /* Get the raw buffer VA (includes "headroom"). */ + va = tile_io_addr_to_va((unsigned long)(long)idesc->va); + + /* Get the actual packet start/length. */ + buf = va + l2_offset; + len = idesc->l2_size - l2_offset; + + /* Point "va" at the raw buffer. */ + va -= NET_IP_ALIGN; + + filter = filter_packet(dev, buf); + if (filter) { + gxio_mpipe_iqueue_drop(&info->iqueue, idesc); + } else { + struct sk_buff *skb = mpipe_buf_to_skb(va); + + /* Skip headroom, and any custom header. */ + skb_reserve(skb, NET_IP_ALIGN + l2_offset); + + tile_net_receive_skb(dev, skb, idesc, len); + } + + gxio_mpipe_iqueue_consume(&info->iqueue, idesc); + return !filter; +} + +/* Handle some packets for the current CPU. + * + * This function handles up to TILE_NET_BATCH idescs per call. + * + * ISSUE: Since we do not provide new buffers until this function is + * complete, we must initially provide enough buffers for each network + * cpu to fill its iqueue and also its batched idescs. + * + * ISSUE: The "rotting packet" race condition occurs if a packet + * arrives after the queue appears to be empty, and before the + * hypervisor interrupt is re-enabled. + */ +static int tile_net_poll(struct napi_struct *napi, int budget) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + unsigned int work = 0; + gxio_mpipe_idesc_t *idesc; + int i, n; + + /* Process packets. */ + while ((n = gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc)) > 0) { + for (i = 0; i < n; i++) { + if (i == TILE_NET_BATCH) + goto done; + if (tile_net_handle_packet(idesc + i)) { + if (++work >= budget) + goto done; + } + } + } + + /* There are no packets left. */ + napi_complete(&info->napi); + + /* Re-enable hypervisor interrupts. */ + gxio_mpipe_enable_notif_ring_interrupt(&context, info->iqueue.ring); + + /* HACK: Avoid the "rotting packet" problem. */ + if (gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc) > 0) + napi_schedule(&info->napi); + + /* ISSUE: Handle completions? */ + +done: + tile_net_provide_needed_buffers(); + + return work; +} + +/* Handle an ingress interrupt on the current cpu. */ +static irqreturn_t tile_net_handle_ingress_irq(int irq, void *unused) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + napi_schedule(&info->napi); + return IRQ_HANDLED; +} + +/* Free some completions. This must be called with interrupts blocked. */ +static int tile_net_free_comps(gxio_mpipe_equeue_t *equeue, + struct tile_net_comps *comps, + int limit, bool force_update) +{ + int n = 0; + while (comps->comp_last < comps->comp_next) { + unsigned int cid = comps->comp_last % TILE_NET_MAX_COMPS; + struct tile_net_comp *comp = &comps->comp_queue[cid]; + if (!gxio_mpipe_equeue_is_complete(equeue, comp->when, + force_update || n == 0)) + break; + dev_kfree_skb_irq(comp->skb); + comps->comp_last++; + if (++n == limit) + break; + } + return n; +} + +/* Add a completion. This must be called with interrupts blocked. + * tile_net_equeue_try_reserve() will have ensured a free completion entry. + */ +static void add_comp(gxio_mpipe_equeue_t *equeue, + struct tile_net_comps *comps, + uint64_t when, struct sk_buff *skb) +{ + int cid = comps->comp_next % TILE_NET_MAX_COMPS; + comps->comp_queue[cid].when = when; + comps->comp_queue[cid].skb = skb; + comps->comp_next++; +} + +static void tile_net_schedule_tx_wake_timer(struct net_device *dev) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + struct tile_net_priv *priv = netdev_priv(dev); + + hrtimer_start(&info->tx_wake[priv->echannel].timer, + ktime_set(0, TX_TIMER_DELAY_USEC * 1000UL), + HRTIMER_MODE_REL_PINNED); +} + +static enum hrtimer_restart tile_net_handle_tx_wake_timer(struct hrtimer *t) +{ + struct tile_net_tx_wake *tx_wake = + container_of(t, struct tile_net_tx_wake, timer); + netif_wake_subqueue(tx_wake->dev, smp_processor_id()); + return HRTIMER_NORESTART; +} + +/* Make sure the egress timer is scheduled. */ +static void tile_net_schedule_egress_timer(void) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + + if (!info->egress_timer_scheduled) { + hrtimer_start(&info->egress_timer, + ktime_set(0, EGRESS_TIMER_DELAY_USEC * 1000UL), + HRTIMER_MODE_REL_PINNED); + info->egress_timer_scheduled = true; + } +} + +/* The "function" for "info->egress_timer". + * + * This timer will reschedule itself as long as there are any pending + * completions expected for this tile. + */ +static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + unsigned long irqflags; + bool pending = false; + int i; + + local_irq_save(irqflags); + + /* The timer is no longer scheduled. */ + info->egress_timer_scheduled = false; + + /* Free all possible comps for this tile. */ + for (i = 0; i < TILE_NET_CHANNELS; i++) { + struct tile_net_egress *egress = &egress_for_echannel[i]; + struct tile_net_comps *comps = info->comps_for_echannel[i]; + if (comps->comp_last >= comps->comp_next) + continue; + tile_net_free_comps(egress->equeue, comps, -1, true); + pending = pending || (comps->comp_last < comps->comp_next); + } + + /* Reschedule timer if needed. */ + if (pending) + tile_net_schedule_egress_timer(); + + local_irq_restore(irqflags); + + return HRTIMER_NORESTART; +} + +/* Helper function for "tile_net_update()". + * "dev" (i.e. arg) is the device being brought up or down, + * or NULL if all devices are now down. + */ +static void tile_net_update_cpu(void *arg) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + struct net_device *dev = arg; + + if (!info->has_iqueue) + return; + + if (dev != NULL) { + if (!info->napi_added) { + netif_napi_add(dev, &info->napi, + tile_net_poll, TILE_NET_WEIGHT); + info->napi_added = true; + } + if (!info->napi_enabled) { + napi_enable(&info->napi); + info->napi_enabled = true; + } + enable_percpu_irq(ingress_irq, 0); + } else { + disable_percpu_irq(ingress_irq); + if (info->napi_enabled) { + napi_disable(&info->napi); + info->napi_enabled = false; + } + /* FIXME: Drain the iqueue. */ + } +} + +/* Helper function for tile_net_open() and tile_net_stop(). + * Always called under tile_net_devs_for_channel_mutex. + */ +static int tile_net_update(struct net_device *dev) +{ + static gxio_mpipe_rules_t rules; /* too big to fit on the stack */ + bool saw_channel = false; + int channel; + int rc; + int cpu; + + gxio_mpipe_rules_init(&rules, &context); + + for (channel = 0; channel < TILE_NET_CHANNELS; channel++) { + if (tile_net_devs_for_channel[channel] == NULL) + continue; + if (!saw_channel) { + saw_channel = true; + gxio_mpipe_rules_begin(&rules, first_bucket, + num_buckets, NULL); + gxio_mpipe_rules_set_headroom(&rules, NET_IP_ALIGN); + } + gxio_mpipe_rules_add_channel(&rules, channel); + } + + /* NOTE: This can fail if there is no classifier. + * ISSUE: Can anything else cause it to fail? + */ + rc = gxio_mpipe_rules_commit(&rules); + if (rc != 0) { + netdev_warn(dev, "gxio_mpipe_rules_commit failed: %d\n", rc); + return -EIO; + } + + /* Update all cpus, sequentially (to protect "netif_napi_add()"). */ + for_each_online_cpu(cpu) + smp_call_function_single(cpu, tile_net_update_cpu, + (saw_channel ? dev : NULL), 1); + + /* HACK: Allow packets to flow in the simulator. */ + if (saw_channel) + sim_enable_mpipe_links(0, -1); + + return 0; +} + +/* Allocate and initialize mpipe buffer stacks, and register them in + * the mPIPE TLBs, for both small and large packet sizes. + * This routine supports tile_net_init_mpipe(), below. + */ +static int init_buffer_stacks(struct net_device *dev, int num_buffers) +{ + pte_t hash_pte = pte_set_home((pte_t) { 0 }, PAGE_HOME_HASH); + int rc; + + /* Compute stack bytes; we round up to 64KB and then use + * alloc_pages() so we get the required 64KB alignment as well. + */ + buffer_stack_size = + ALIGN(gxio_mpipe_calc_buffer_stack_bytes(num_buffers), + 64 * 1024); + + /* Allocate two buffer stack indices. */ + rc = gxio_mpipe_alloc_buffer_stacks(&context, 2, 0, 0); + if (rc < 0) { + netdev_err(dev, "gxio_mpipe_alloc_buffer_stacks failed: %d\n", + rc); + return rc; + } + small_buffer_stack = rc; + large_buffer_stack = rc + 1; + + /* Allocate the small memory stack. */ + small_buffer_stack_va = + alloc_pages_exact(buffer_stack_size, GFP_KERNEL); + if (small_buffer_stack_va == NULL) { + netdev_err(dev, + "Could not alloc %zd bytes for buffer stacks\n", + buffer_stack_size); + return -ENOMEM; + } + rc = gxio_mpipe_init_buffer_stack(&context, small_buffer_stack, + BUFFER_SIZE_SMALL_ENUM, + small_buffer_stack_va, + buffer_stack_size, 0); + if (rc != 0) { + netdev_err(dev, "gxio_mpipe_init_buffer_stack: %d\n", rc); + return rc; + } + rc = gxio_mpipe_register_client_memory(&context, small_buffer_stack, + hash_pte, 0); + if (rc != 0) { + netdev_err(dev, + "gxio_mpipe_register_buffer_memory failed: %d\n", + rc); + return rc; + } + + /* Allocate the large buffer stack. */ + large_buffer_stack_va = + alloc_pages_exact(buffer_stack_size, GFP_KERNEL); + if (large_buffer_stack_va == NULL) { + netdev_err(dev, + "Could not alloc %zd bytes for buffer stacks\n", + buffer_stack_size); + return -ENOMEM; + } + rc = gxio_mpipe_init_buffer_stack(&context, large_buffer_stack, + BUFFER_SIZE_LARGE_ENUM, + large_buffer_stack_va, + buffer_stack_size, 0); + if (rc != 0) { + netdev_err(dev, "gxio_mpipe_init_buffer_stack failed: %d\n", + rc); + return rc; + } + rc = gxio_mpipe_register_client_memory(&context, large_buffer_stack, + hash_pte, 0); + if (rc != 0) { + netdev_err(dev, + "gxio_mpipe_register_buffer_memory failed: %d\n", + rc); + return rc; + } + + return 0; +} + +/* Allocate per-cpu resources (memory for completions and idescs). + * This routine supports tile_net_init_mpipe(), below. + */ +static int alloc_percpu_mpipe_resources(struct net_device *dev, + int cpu, int ring) +{ + struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); + int order, i, rc; + struct page *page; + void *addr; + + /* Allocate the "comps". */ + order = get_order(COMPS_SIZE); + page = homecache_alloc_pages(GFP_KERNEL, order, cpu); + if (page == NULL) { + netdev_err(dev, "Failed to alloc %zd bytes comps memory\n", + COMPS_SIZE); + return -ENOMEM; + } + addr = pfn_to_kaddr(page_to_pfn(page)); + memset(addr, 0, COMPS_SIZE); + for (i = 0; i < TILE_NET_CHANNELS; i++) + info->comps_for_echannel[i] = + addr + i * sizeof(struct tile_net_comps); + + /* If this is a network cpu, create an iqueue. */ + if (cpu_isset(cpu, network_cpus_map)) { + order = get_order(NOTIF_RING_SIZE); + page = homecache_alloc_pages(GFP_KERNEL, order, cpu); + if (page == NULL) { + netdev_err(dev, + "Failed to alloc %zd bytes iqueue memory\n", + NOTIF_RING_SIZE); + return -ENOMEM; + } + addr = pfn_to_kaddr(page_to_pfn(page)); + rc = gxio_mpipe_iqueue_init(&info->iqueue, &context, ring++, + addr, NOTIF_RING_SIZE, 0); + if (rc < 0) { + netdev_err(dev, + "gxio_mpipe_iqueue_init failed: %d\n", rc); + return rc; + } + info->has_iqueue = true; + } + + return ring; +} + +/* Initialize NotifGroup and buckets. + * This routine supports tile_net_init_mpipe(), below. + */ +static int init_notif_group_and_buckets(struct net_device *dev, + int ring, int network_cpus_count) +{ + int group, rc; + + /* Allocate one NotifGroup. */ + rc = gxio_mpipe_alloc_notif_groups(&context, 1, 0, 0); + if (rc < 0) { + netdev_err(dev, "gxio_mpipe_alloc_notif_groups failed: %d\n", + rc); + return rc; + } + group = rc; + + /* Initialize global num_buckets value. */ + if (network_cpus_count > 4) + num_buckets = 256; + else if (network_cpus_count > 1) + num_buckets = 16; + + /* Allocate some buckets, and set global first_bucket value. */ + rc = gxio_mpipe_alloc_buckets(&context, num_buckets, 0, 0); + if (rc < 0) { + netdev_err(dev, "gxio_mpipe_alloc_buckets failed: %d\n", rc); + return rc; + } + first_bucket = rc; + + /* Init group and buckets. */ + rc = gxio_mpipe_init_notif_group_and_buckets( + &context, group, ring, network_cpus_count, + first_bucket, num_buckets, + GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY); + if (rc != 0) { + netdev_err( + dev, + "gxio_mpipe_init_notif_group_and_buckets failed: %d\n", + rc); + return rc; + } + + return 0; +} + +/* Create an irq and register it, then activate the irq and request + * interrupts on all cores. Note that "ingress_irq" being initialized + * is how we know not to call tile_net_init_mpipe() again. + * This routine supports tile_net_init_mpipe(), below. + */ +static int tile_net_setup_interrupts(struct net_device *dev) +{ + int cpu, rc; + + rc = create_irq(); + if (rc < 0) { + netdev_err(dev, "create_irq failed: %d\n", rc); + return rc; + } + ingress_irq = rc; + tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU); + rc = request_irq(ingress_irq, tile_net_handle_ingress_irq, + 0, NULL, NULL); + if (rc != 0) { + netdev_err(dev, "request_irq failed: %d\n", rc); + destroy_irq(ingress_irq); + ingress_irq = -1; + return rc; + } + + for_each_online_cpu(cpu) { + struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); + if (info->has_iqueue) { + gxio_mpipe_request_notif_ring_interrupt( + &context, cpu_x(cpu), cpu_y(cpu), + 1, ingress_irq, info->iqueue.ring); + } + } + + return 0; +} + +/* Undo any state set up partially by a failed call to tile_net_init_mpipe. */ +static void tile_net_init_mpipe_fail(void) +{ + int cpu; + + /* Do cleanups that require the mpipe context first. */ + if (small_buffer_stack >= 0) + tile_net_pop_all_buffers(small_buffer_stack); + if (large_buffer_stack >= 0) + tile_net_pop_all_buffers(large_buffer_stack); + + /* Destroy mpipe context so the hardware no longer owns any memory. */ + gxio_mpipe_destroy(&context); + + for_each_online_cpu(cpu) { + struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); + free_pages((unsigned long)(info->comps_for_echannel[0]), + get_order(COMPS_SIZE)); + info->comps_for_echannel[0] = NULL; + free_pages((unsigned long)(info->iqueue.idescs), + get_order(NOTIF_RING_SIZE)); + info->iqueue.idescs = NULL; + } + + if (small_buffer_stack_va) + free_pages_exact(small_buffer_stack_va, buffer_stack_size); + if (large_buffer_stack_va) + free_pages_exact(large_buffer_stack_va, buffer_stack_size); + + small_buffer_stack_va = NULL; + large_buffer_stack_va = NULL; + large_buffer_stack = -1; + small_buffer_stack = -1; + first_bucket = -1; +} + +/* The first time any tilegx network device is opened, we initialize + * the global mpipe state. If this step fails, we fail to open the + * device, but if it succeeds, we never need to do it again, and since + * tile_net can't be unloaded, we never undo it. + * + * Note that some resources in this path (buffer stack indices, + * bindings from init_buffer_stack, etc.) are hypervisor resources + * that are freed implicitly by gxio_mpipe_destroy(). + */ +static int tile_net_init_mpipe(struct net_device *dev) +{ + int i, num_buffers, rc; + int cpu; + int first_ring, ring; + int network_cpus_count = cpus_weight(network_cpus_map); + + if (!hash_default) { + netdev_err(dev, "Networking requires hash_default!\n"); + return -EIO; + } + + rc = gxio_mpipe_init(&context, 0); + if (rc != 0) { + netdev_err(dev, "gxio_mpipe_init failed: %d\n", rc); + return -EIO; + } + + /* Set up the buffer stacks. */ + num_buffers = + network_cpus_count * (IQUEUE_ENTRIES + TILE_NET_BATCH); + rc = init_buffer_stacks(dev, num_buffers); + if (rc != 0) + goto fail; + + /* Provide initial buffers. */ + rc = -ENOMEM; + for (i = 0; i < num_buffers; i++) { + if (!tile_net_provide_buffer(true)) { + netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); + goto fail; + } + } + for (i = 0; i < num_buffers; i++) { + if (!tile_net_provide_buffer(false)) { + netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); + goto fail; + } + } + + /* Allocate one NotifRing for each network cpu. */ + rc = gxio_mpipe_alloc_notif_rings(&context, network_cpus_count, 0, 0); + if (rc < 0) { + netdev_err(dev, "gxio_mpipe_alloc_notif_rings failed %d\n", + rc); + goto fail; + } + + /* Init NotifRings per-cpu. */ + first_ring = rc; + ring = first_ring; + for_each_online_cpu(cpu) { + rc = alloc_percpu_mpipe_resources(dev, cpu, ring); + if (rc < 0) + goto fail; + ring = rc; + } + + /* Initialize NotifGroup and buckets. */ + rc = init_notif_group_and_buckets(dev, first_ring, network_cpus_count); + if (rc != 0) + goto fail; + + /* Create and enable interrupts. */ + rc = tile_net_setup_interrupts(dev); + if (rc != 0) + goto fail; + + return 0; + +fail: + tile_net_init_mpipe_fail(); + return rc; +} + +/* Create persistent egress info for a given egress channel. + * Note that this may be shared between, say, "gbe0" and "xgbe0". + * ISSUE: Defer header allocation until TSO is actually needed? + */ +static int tile_net_init_egress(struct net_device *dev, int echannel) +{ + struct page *headers_page, *edescs_page, *equeue_page; + gxio_mpipe_edesc_t *edescs; + gxio_mpipe_equeue_t *equeue; + unsigned char *headers; + int headers_order, edescs_order, equeue_order; + size_t edescs_size; + int edma; + int rc = -ENOMEM; + + /* Only initialize once. */ + if (egress_for_echannel[echannel].equeue != NULL) + return 0; + + /* Allocate memory for the "headers". */ + headers_order = get_order(EQUEUE_ENTRIES * HEADER_BYTES); + headers_page = alloc_pages(GFP_KERNEL, headers_order); + if (headers_page == NULL) { + netdev_warn(dev, + "Could not alloc %zd bytes for TSO headers.\n", + PAGE_SIZE << headers_order); + goto fail; + } + headers = pfn_to_kaddr(page_to_pfn(headers_page)); + + /* Allocate memory for the "edescs". */ + edescs_size = EQUEUE_ENTRIES * sizeof(*edescs); + edescs_order = get_order(edescs_size); + edescs_page = alloc_pages(GFP_KERNEL, edescs_order); + if (edescs_page == NULL) { + netdev_warn(dev, + "Could not alloc %zd bytes for eDMA ring.\n", + edescs_size); + goto fail_headers; + } + edescs = pfn_to_kaddr(page_to_pfn(edescs_page)); + + /* Allocate memory for the "equeue". */ + equeue_order = get_order(sizeof(*equeue)); + equeue_page = alloc_pages(GFP_KERNEL, equeue_order); + if (equeue_page == NULL) { + netdev_warn(dev, + "Could not alloc %zd bytes for equeue info.\n", + PAGE_SIZE << equeue_order); + goto fail_edescs; + } + equeue = pfn_to_kaddr(page_to_pfn(equeue_page)); + + /* Allocate an edma ring. Note that in practice this can't + * fail, which is good, because we will leak an edma ring if so. + */ + rc = gxio_mpipe_alloc_edma_rings(&context, 1, 0, 0); + if (rc < 0) { + netdev_warn(dev, "gxio_mpipe_alloc_edma_rings failed: %d\n", + rc); + goto fail_equeue; + } + edma = rc; + + /* Initialize the equeue. */ + rc = gxio_mpipe_equeue_init(equeue, &context, edma, echannel, + edescs, edescs_size, 0); + if (rc != 0) { + netdev_err(dev, "gxio_mpipe_equeue_init failed: %d\n", rc); + goto fail_equeue; + } + + /* Done. */ + egress_for_echannel[echannel].equeue = equeue; + egress_for_echannel[echannel].headers = headers; + return 0; + +fail_equeue: + __free_pages(equeue_page, equeue_order); + +fail_edescs: + __free_pages(edescs_page, edescs_order); + +fail_headers: + __free_pages(headers_page, headers_order); + +fail: + return rc; +} + +/* Return channel number for a newly-opened link. */ +static int tile_net_link_open(struct net_device *dev, gxio_mpipe_link_t *link, + const char *link_name) +{ + int rc = gxio_mpipe_link_open(link, &context, link_name, 0); + if (rc < 0) { + netdev_err(dev, "Failed to open '%s'\n", link_name); + return rc; + } + rc = gxio_mpipe_link_channel(link); + if (rc < 0 || rc >= TILE_NET_CHANNELS) { + netdev_err(dev, "gxio_mpipe_link_channel bad value: %d\n", rc); + gxio_mpipe_link_close(link); + return -EINVAL; + } + return rc; +} + +/* Help the kernel activate the given network interface. */ +static int tile_net_open(struct net_device *dev) +{ + struct tile_net_priv *priv = netdev_priv(dev); + int cpu, rc; + + mutex_lock(&tile_net_devs_for_channel_mutex); + + /* Do one-time initialization the first time any device is opened. */ + if (ingress_irq < 0) { + rc = tile_net_init_mpipe(dev); + if (rc != 0) + goto fail; + } + + /* Determine if this is the "loopify" device. */ + if (unlikely((loopify_link_name != NULL) && + !strcmp(dev->name, loopify_link_name))) { + rc = tile_net_link_open(dev, &priv->link, "loop0"); + if (rc < 0) + goto fail; + priv->channel = rc; + rc = tile_net_link_open(dev, &priv->loopify_link, "loop1"); + if (rc < 0) + goto fail; + priv->loopify_channel = rc; + priv->echannel = rc; + } else { + rc = tile_net_link_open(dev, &priv->link, dev->name); + if (rc < 0) + goto fail; + priv->channel = rc; + priv->echannel = rc; + } + + /* Initialize egress info (if needed). Once ever, per echannel. */ + rc = tile_net_init_egress(dev, priv->echannel); + if (rc != 0) + goto fail; + + tile_net_devs_for_channel[priv->channel] = dev; + + rc = tile_net_update(dev); + if (rc != 0) + goto fail; + + mutex_unlock(&tile_net_devs_for_channel_mutex); + + /* Initialize the transmit wake timer for this device for each cpu. */ + for_each_online_cpu(cpu) { + struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); + struct tile_net_tx_wake *tx_wake = + &info->tx_wake[priv->echannel]; + + hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + tx_wake->timer.function = tile_net_handle_tx_wake_timer; + tx_wake->dev = dev; + } + + for_each_online_cpu(cpu) + netif_start_subqueue(dev, cpu); + netif_carrier_on(dev); + return 0; + +fail: + if (priv->loopify_channel >= 0) { + if (gxio_mpipe_link_close(&priv->loopify_link) != 0) + netdev_warn(dev, "Failed to close loopify link!\n"); + priv->loopify_channel = -1; + } + if (priv->channel >= 0) { + if (gxio_mpipe_link_close(&priv->link) != 0) + netdev_warn(dev, "Failed to close link!\n"); + priv->channel = -1; + } + priv->echannel = -1; + tile_net_devs_for_channel[priv->channel] = NULL; + mutex_unlock(&tile_net_devs_for_channel_mutex); + + /* Don't return raw gxio error codes to generic Linux. */ + return (rc > -512) ? rc : -EIO; +} + +/* Help the kernel deactivate the given network interface. */ +static int tile_net_stop(struct net_device *dev) +{ + struct tile_net_priv *priv = netdev_priv(dev); + int cpu; + + for_each_online_cpu(cpu) { + struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); + struct tile_net_tx_wake *tx_wake = + &info->tx_wake[priv->echannel]; + + hrtimer_cancel(&tx_wake->timer); + netif_stop_subqueue(dev, cpu); + } + + mutex_lock(&tile_net_devs_for_channel_mutex); + tile_net_devs_for_channel[priv->channel] = NULL; + (void)tile_net_update(dev); + if (priv->loopify_channel >= 0) { + if (gxio_mpipe_link_close(&priv->loopify_link) != 0) + netdev_warn(dev, "Failed to close loopify link!\n"); + priv->loopify_channel = -1; + } + if (priv->channel >= 0) { + if (gxio_mpipe_link_close(&priv->link) != 0) + netdev_warn(dev, "Failed to close link!\n"); + priv->channel = -1; + } + priv->echannel = -1; + mutex_unlock(&tile_net_devs_for_channel_mutex); + + return 0; +} + +/* Determine the VA for a fragment. */ +static inline void *tile_net_frag_buf(skb_frag_t *f) +{ + unsigned long pfn = page_to_pfn(skb_frag_page(f)); + return pfn_to_kaddr(pfn) + f->page_offset; +} + +/* Acquire a completion entry and an egress slot, or if we can't, + * stop the queue and schedule the tx_wake timer. + */ +static s64 tile_net_equeue_try_reserve(struct net_device *dev, + struct tile_net_comps *comps, + gxio_mpipe_equeue_t *equeue, + int num_edescs) +{ + /* Try to acquire a completion entry. */ + if (comps->comp_next - comps->comp_last < TILE_NET_MAX_COMPS - 1 || + tile_net_free_comps(equeue, comps, 32, false) != 0) { + + /* Try to acquire an egress slot. */ + s64 slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); + if (slot >= 0) + return slot; + + /* Freeing some completions gives the equeue time to drain. */ + tile_net_free_comps(equeue, comps, TILE_NET_MAX_COMPS, false); + + slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); + if (slot >= 0) + return slot; + } + + /* Still nothing; give up and stop the queue for a short while. */ + netif_stop_subqueue(dev, smp_processor_id()); + tile_net_schedule_tx_wake_timer(dev); + return -1; +} + +/* Determine how many edesc's are needed for TSO. + * + * Sometimes, if "sendfile()" requires copying, we will be called with + * "data" containing the header and payload, with "frags" being empty. + * Sometimes, for example when using NFS over TCP, a single segment can + * span 3 fragments. This requires special care. + */ +static int tso_count_edescs(struct sk_buff *skb) +{ + struct skb_shared_info *sh = skb_shinfo(skb); + unsigned int data_len = skb->data_len; + unsigned int p_len = sh->gso_size; + long f_id = -1; /* id of the current fragment */ + long f_size = -1; /* size of the current fragment */ + long f_used = -1; /* bytes used from the current fragment */ + long n; /* size of the current piece of payload */ + int num_edescs = 0; + int segment; + + for (segment = 0; segment < sh->gso_segs; segment++) { + + unsigned int p_used = 0; + + /* One edesc for header and for each piece of the payload. */ + for (num_edescs++; p_used < p_len; num_edescs++) { + + /* Advance as needed. */ + while (f_used >= f_size) { + f_id++; + f_size = sh->frags[f_id].size; + f_used = 0; + } + + /* Use bytes from the current fragment. */ + n = p_len - p_used; + if (n > f_size - f_used) + n = f_size - f_used; + f_used += n; + p_used += n; + } + + /* The last segment may be less than gso_size. */ + data_len -= p_len; + if (data_len < p_len) + p_len = data_len; + } + + return num_edescs; +} + +/* Prepare modified copies of the skbuff headers. + * FIXME: add support for IPv6. + */ +static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, + s64 slot) +{ + struct skb_shared_info *sh = skb_shinfo(skb); + struct iphdr *ih; + struct tcphdr *th; + unsigned int data_len = skb->data_len; + unsigned char *data = skb->data; + unsigned int ih_off, th_off, sh_len, p_len; + unsigned int isum_seed, tsum_seed, id, seq; + long f_id = -1; /* id of the current fragment */ + long f_size = -1; /* size of the current fragment */ + long f_used = -1; /* bytes used from the current fragment */ + long n; /* size of the current piece of payload */ + int segment; + + /* Locate original headers and compute various lengths. */ + ih = ip_hdr(skb); + th = tcp_hdr(skb); + ih_off = skb_network_offset(skb); + th_off = skb_transport_offset(skb); + sh_len = th_off + tcp_hdrlen(skb); + p_len = sh->gso_size; + + /* Set up seed values for IP and TCP csum and initialize id and seq. */ + isum_seed = ((0xFFFF - ih->check) + + (0xFFFF - ih->tot_len) + + (0xFFFF - ih->id)); + tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); + id = ntohs(ih->id); + seq = ntohl(th->seq); + + /* Prepare all the headers. */ + for (segment = 0; segment < sh->gso_segs; segment++) { + unsigned char *buf; + unsigned int p_used = 0; + + /* Copy to the header memory for this segment. */ + buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + + NET_IP_ALIGN; + memcpy(buf, data, sh_len); + + /* Update copied ip header. */ + ih = (struct iphdr *)(buf + ih_off); + ih->tot_len = htons(sh_len + p_len - ih_off); + ih->id = htons(id); + ih->check = csum_long(isum_seed + ih->tot_len + + ih->id) ^ 0xffff; + + /* Update copied tcp header. */ + th = (struct tcphdr *)(buf + th_off); + th->seq = htonl(seq); + th->check = csum_long(tsum_seed + htons(sh_len + p_len)); + if (segment != sh->gso_segs - 1) { + th->fin = 0; + th->psh = 0; + } + + /* Skip past the header. */ + slot++; + + /* Skip past the payload. */ + while (p_used < p_len) { + + /* Advance as needed. */ + while (f_used >= f_size) { + f_id++; + f_size = sh->frags[f_id].size; + f_used = 0; + } + + /* Use bytes from the current fragment. */ + n = p_len - p_used; + if (n > f_size - f_used) + n = f_size - f_used; + f_used += n; + p_used += n; + + slot++; + } + + id++; + seq += p_len; + + /* The last segment may be less than gso_size. */ + data_len -= p_len; + if (data_len < p_len) + p_len = data_len; + } + + /* Flush the headers so they are ready for hardware DMA. */ + wmb(); +} + +/* Pass all the data to mpipe for egress. */ +static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, + struct sk_buff *skb, unsigned char *headers, s64 slot) +{ + struct tile_net_priv *priv = netdev_priv(dev); + struct skb_shared_info *sh = skb_shinfo(skb); + unsigned int data_len = skb->data_len; + unsigned int p_len = sh->gso_size; + gxio_mpipe_edesc_t edesc_head = { { 0 } }; + gxio_mpipe_edesc_t edesc_body = { { 0 } }; + long f_id = -1; /* id of the current fragment */ + long f_size = -1; /* size of the current fragment */ + long f_used = -1; /* bytes used from the current fragment */ + long n; /* size of the current piece of payload */ + unsigned long tx_packets = 0, tx_bytes = 0; + unsigned int csum_start, sh_len; + int segment; + + /* Prepare to egress the headers: set up header edesc. */ + csum_start = skb_checksum_start_offset(skb); + sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + edesc_head.csum = 1; + edesc_head.csum_start = csum_start; + edesc_head.csum_dest = csum_start + skb->csum_offset; + edesc_head.xfer_size = sh_len; + + /* This is only used to specify the TLB. */ + edesc_head.stack_idx = large_buffer_stack; + edesc_body.stack_idx = large_buffer_stack; + + /* Egress all the edescs. */ + for (segment = 0; segment < sh->gso_segs; segment++) { + void *va; + unsigned char *buf; + unsigned int p_used = 0; + + /* Egress the header. */ + buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + + NET_IP_ALIGN; + edesc_head.va = va_to_tile_io_addr(buf); + gxio_mpipe_equeue_put_at(equeue, edesc_head, slot); + slot++; + + /* Egress the payload. */ + while (p_used < p_len) { + + /* Advance as needed. */ + while (f_used >= f_size) { + f_id++; + f_size = sh->frags[f_id].size; + f_used = 0; + } + + va = tile_net_frag_buf(&sh->frags[f_id]) + f_used; + + /* Use bytes from the current fragment. */ + n = p_len - p_used; + if (n > f_size - f_used) + n = f_size - f_used; + f_used += n; + p_used += n; + + /* Egress a piece of the payload. */ + edesc_body.va = va_to_tile_io_addr(va); + edesc_body.xfer_size = n; + edesc_body.bound = !(p_used < p_len); + gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); + slot++; + } + + tx_packets++; + tx_bytes += sh_len + p_len; + + /* The last segment may be less than gso_size. */ + data_len -= p_len; + if (data_len < p_len) + p_len = data_len; + } + + /* Update stats. */ + tile_net_stats_add(tx_packets, &priv->stats.tx_packets); + tile_net_stats_add(tx_bytes, &priv->stats.tx_bytes); +} + +/* Do "TSO" handling for egress. + * + * Normally drivers set NETIF_F_TSO only to support hardware TSO; + * otherwise the stack uses scatter-gather to implement GSO in software. + * On our testing, enabling GSO support (via NETIF_F_SG) drops network + * performance down to around 7.5 Gbps on the 10G interfaces, although + * also dropping cpu utilization way down, to under 8%. But + * implementing "TSO" in the driver brings performance back up to line + * rate, while dropping cpu usage even further, to less than 4%. In + * practice, profiling of GSO shows that skb_segment() is what causes + * the performance overheads; we benefit in the driver from using + * preallocated memory to duplicate the TCP/IP headers. + */ +static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + struct tile_net_priv *priv = netdev_priv(dev); + int channel = priv->echannel; + struct tile_net_egress *egress = &egress_for_echannel[channel]; + struct tile_net_comps *comps = info->comps_for_echannel[channel]; + gxio_mpipe_equeue_t *equeue = egress->equeue; + unsigned long irqflags; + int num_edescs; + s64 slot; + + /* Determine how many mpipe edesc's are needed. */ + num_edescs = tso_count_edescs(skb); + + local_irq_save(irqflags); + + /* Try to acquire a completion entry and an egress slot. */ + slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); + if (slot < 0) { + local_irq_restore(irqflags); + return NETDEV_TX_BUSY; + } + + /* Set up copies of header data properly. */ + tso_headers_prepare(skb, egress->headers, slot); + + /* Actually pass the data to the network hardware. */ + tso_egress(dev, equeue, skb, egress->headers, slot); + + /* Add a completion record. */ + add_comp(equeue, comps, slot + num_edescs - 1, skb); + + local_irq_restore(irqflags); + + /* Make sure the egress timer is scheduled. */ + tile_net_schedule_egress_timer(); + + return NETDEV_TX_OK; +} + +/* Analyze the body and frags for a transmit request. */ +static unsigned int tile_net_tx_frags(struct frag *frags, + struct sk_buff *skb, + void *b_data, unsigned int b_len) +{ + unsigned int i, n = 0; + + struct skb_shared_info *sh = skb_shinfo(skb); + + if (b_len != 0) { + frags[n].buf = b_data; + frags[n++].length = b_len; + } + + for (i = 0; i < sh->nr_frags; i++) { + skb_frag_t *f = &sh->frags[i]; + frags[n].buf = tile_net_frag_buf(f); + frags[n++].length = skb_frag_size(f); + } + + return n; +} + +/* Help the kernel transmit a packet. */ +static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + struct tile_net_priv *priv = netdev_priv(dev); + struct tile_net_egress *egress = &egress_for_echannel[priv->echannel]; + gxio_mpipe_equeue_t *equeue = egress->equeue; + struct tile_net_comps *comps = + info->comps_for_echannel[priv->echannel]; + unsigned int len = skb->len; + unsigned char *data = skb->data; + unsigned int num_edescs; + struct frag frags[MAX_FRAGS]; + gxio_mpipe_edesc_t edescs[MAX_FRAGS]; + unsigned long irqflags; + gxio_mpipe_edesc_t edesc = { { 0 } }; + unsigned int i; + s64 slot; + + if (skb_is_gso(skb)) + return tile_net_tx_tso(skb, dev); + + num_edescs = tile_net_tx_frags(frags, skb, data, skb_headlen(skb)); + + /* This is only used to specify the TLB. */ + edesc.stack_idx = large_buffer_stack; + + /* Prepare the edescs. */ + for (i = 0; i < num_edescs; i++) { + edesc.xfer_size = frags[i].length; + edesc.va = va_to_tile_io_addr(frags[i].buf); + edescs[i] = edesc; + } + + /* Mark the final edesc. */ + edescs[num_edescs - 1].bound = 1; + + /* Add checksum info to the initial edesc, if needed. */ + if (skb->ip_summed == CHECKSUM_PARTIAL) { + unsigned int csum_start = skb_checksum_start_offset(skb); + edescs[0].csum = 1; + edescs[0].csum_start = csum_start; + edescs[0].csum_dest = csum_start + skb->csum_offset; + } + + local_irq_save(irqflags); + + /* Try to acquire a completion entry and an egress slot. */ + slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); + if (slot < 0) { + local_irq_restore(irqflags); + return NETDEV_TX_BUSY; + } + + for (i = 0; i < num_edescs; i++) + gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++); + + /* Add a completion record. */ + add_comp(equeue, comps, slot - 1, skb); + + /* NOTE: Use ETH_ZLEN for short packets (e.g. 42 < 60). */ + tile_net_stats_add(1, &priv->stats.tx_packets); + tile_net_stats_add(max_t(unsigned int, len, ETH_ZLEN), + &priv->stats.tx_bytes); + + local_irq_restore(irqflags); + + /* Make sure the egress timer is scheduled. */ + tile_net_schedule_egress_timer(); + + return NETDEV_TX_OK; +} + +/* Return subqueue id on this core (one per core). */ +static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + return smp_processor_id(); +} + +/* Deal with a transmit timeout. */ +static void tile_net_tx_timeout(struct net_device *dev) +{ + int cpu; + + for_each_online_cpu(cpu) + netif_wake_subqueue(dev, cpu); +} + +/* Ioctl commands. */ +static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + return -EOPNOTSUPP; +} + +/* Get system network statistics for device. */ +static struct net_device_stats *tile_net_get_stats(struct net_device *dev) +{ + struct tile_net_priv *priv = netdev_priv(dev); + return &priv->stats; +} + +/* Change the MTU. */ +static int tile_net_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > 1500)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +/* Change the Ethernet address of the NIC. + * + * The hypervisor driver does not support changing MAC address. However, + * the hardware does not do anything with the MAC address, so the address + * which gets used on outgoing packets, and which is accepted on incoming + * packets, is completely up to us. + * + * Returns 0 on success, negative on failure. + */ +static int tile_net_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void tile_net_netpoll(struct net_device *dev) +{ + disable_percpu_irq(ingress_irq); + tile_net_handle_ingress_irq(ingress_irq, NULL); + enable_percpu_irq(ingress_irq, 0); +} +#endif + +static const struct net_device_ops tile_net_ops = { + .ndo_open = tile_net_open, + .ndo_stop = tile_net_stop, + .ndo_start_xmit = tile_net_tx, + .ndo_select_queue = tile_net_select_queue, + .ndo_do_ioctl = tile_net_ioctl, + .ndo_get_stats = tile_net_get_stats, + .ndo_change_mtu = tile_net_change_mtu, + .ndo_tx_timeout = tile_net_tx_timeout, + .ndo_set_mac_address = tile_net_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tile_net_netpoll, +#endif +}; + +/* The setup function. + * + * This uses ether_setup() to assign various fields in dev, including + * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields. + */ +static void tile_net_setup(struct net_device *dev) +{ + ether_setup(dev); + dev->netdev_ops = &tile_net_ops; + dev->watchdog_timeo = TILE_NET_TIMEOUT; + dev->features |= NETIF_F_LLTX; + dev->features |= NETIF_F_HW_CSUM; + dev->features |= NETIF_F_SG; + dev->features |= NETIF_F_TSO; + dev->mtu = 1500; +} + +/* Allocate the device structure, register the device, and obtain the + * MAC address from the hypervisor. + */ +static void tile_net_dev_init(const char *name, const uint8_t *mac) +{ + int ret; + int i; + int nz_addr = 0; + struct net_device *dev; + struct tile_net_priv *priv; + + /* HACK: Ignore "loop" links. */ + if (strncmp(name, "loop", 4) == 0) + return; + + /* Allocate the device structure. Normally, "name" is a + * template, instantiated by register_netdev(), but not for us. + */ + dev = alloc_netdev_mqs(sizeof(*priv), name, tile_net_setup, + NR_CPUS, 1); + if (!dev) { + pr_err("alloc_netdev_mqs(%s) failed\n", name); + return; + } + + /* Initialize "priv". */ + priv = netdev_priv(dev); + memset(priv, 0, sizeof(*priv)); + priv->dev = dev; + priv->channel = -1; + priv->loopify_channel = -1; + priv->echannel = -1; + + /* Get the MAC address and set it in the device struct; this must + * be done before the device is opened. If the MAC is all zeroes, + * we use a random address, since we're probably on the simulator. + */ + for (i = 0; i < 6; i++) + nz_addr |= mac[i]; + + if (nz_addr) { + memcpy(dev->dev_addr, mac, 6); + dev->addr_len = 6; + } else { + random_ether_addr(dev->dev_addr); + } + + /* Register the network device. */ + ret = register_netdev(dev); + if (ret) { + netdev_err(dev, "register_netdev failed %d\n", ret); + free_netdev(dev); + return; + } +} + +/* Per-cpu module initialization. */ +static void tile_net_init_module_percpu(void *unused) +{ + struct tile_net_info *info = &__get_cpu_var(per_cpu_info); + int my_cpu = smp_processor_id(); + + info->has_iqueue = false; + + info->my_cpu = my_cpu; + + /* Initialize the egress timer. */ + hrtimer_init(&info->egress_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + info->egress_timer.function = tile_net_handle_egress_timer; +} + +/* Module initialization. */ +static int __init tile_net_init_module(void) +{ + int i; + char name[GXIO_MPIPE_LINK_NAME_LEN]; + uint8_t mac[6]; + + pr_info("Tilera Network Driver\n"); + + mutex_init(&tile_net_devs_for_channel_mutex); + + /* Initialize each CPU. */ + on_each_cpu(tile_net_init_module_percpu, NULL, 1); + + /* Find out what devices we have, and initialize them. */ + for (i = 0; gxio_mpipe_link_enumerate_mac(i, name, mac) >= 0; i++) + tile_net_dev_init(name, mac); + + if (!network_cpus_init()) + network_cpus_map = *cpu_online_mask; + + return 0; +} + +module_init(tile_net_init_module); -- cgit v0.10.2 From 8a51178ed64dca418478996697611ef087fa22df Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sat, 9 Jun 2012 22:51:47 +0000 Subject: sparc: remove two unused headers Nothing includes these two headers. None of the macros they define are used anywhere in the tree. This was also the case in v2.6.12-rc2 and, presumably, every release in between. These two headers can safely be removed. Signed-off-by: Paul Bolle Signed-off-by: David S. Miller diff --git a/arch/sparc/include/asm/cmt.h b/arch/sparc/include/asm/cmt.h deleted file mode 100644 index 870db59..0000000 --- a/arch/sparc/include/asm/cmt.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _SPARC64_CMT_H -#define _SPARC64_CMT_H - -/* cmt.h: Chip Multi-Threading register definitions - * - * Copyright (C) 2004 David S. Miller (davem@redhat.com) - */ - -/* ASI_CORE_ID - private */ -#define LP_ID 0x0000000000000010UL -#define LP_ID_MAX 0x00000000003f0000UL -#define LP_ID_ID 0x000000000000003fUL - -/* ASI_INTR_ID - private */ -#define LP_INTR_ID 0x0000000000000000UL -#define LP_INTR_ID_ID 0x00000000000003ffUL - -/* ASI_CESR_ID - private */ -#define CESR_ID 0x0000000000000040UL -#define CESR_ID_ID 0x00000000000000ffUL - -/* ASI_CORE_AVAILABLE - shared */ -#define LP_AVAIL 0x0000000000000000UL -#define LP_AVAIL_1 0x0000000000000002UL -#define LP_AVAIL_0 0x0000000000000001UL - -/* ASI_CORE_ENABLE_STATUS - shared */ -#define LP_ENAB_STAT 0x0000000000000010UL -#define LP_ENAB_STAT_1 0x0000000000000002UL -#define LP_ENAB_STAT_0 0x0000000000000001UL - -/* ASI_CORE_ENABLE - shared */ -#define LP_ENAB 0x0000000000000020UL -#define LP_ENAB_1 0x0000000000000002UL -#define LP_ENAB_0 0x0000000000000001UL - -/* ASI_CORE_RUNNING - shared */ -#define LP_RUNNING_RW 0x0000000000000050UL -#define LP_RUNNING_W1S 0x0000000000000060UL -#define LP_RUNNING_W1C 0x0000000000000068UL -#define LP_RUNNING_1 0x0000000000000002UL -#define LP_RUNNING_0 0x0000000000000001UL - -/* ASI_CORE_RUNNING_STAT - shared */ -#define LP_RUN_STAT 0x0000000000000058UL -#define LP_RUN_STAT_1 0x0000000000000002UL -#define LP_RUN_STAT_0 0x0000000000000001UL - -/* ASI_XIR_STEERING - shared */ -#define LP_XIR_STEER 0x0000000000000030UL -#define LP_XIR_STEER_1 0x0000000000000002UL -#define LP_XIR_STEER_0 0x0000000000000001UL - -/* ASI_CMT_ERROR_STEERING - shared */ -#define CMT_ER_STEER 0x0000000000000040UL -#define CMT_ER_STEER_1 0x0000000000000002UL -#define CMT_ER_STEER_0 0x0000000000000001UL - -#endif /* _SPARC64_CMT_H */ diff --git a/arch/sparc/include/asm/mpmbox.h b/arch/sparc/include/asm/mpmbox.h deleted file mode 100644 index f842303..0000000 --- a/arch/sparc/include/asm/mpmbox.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * mpmbox.h: Interface and defines for the OpenProm mailbox - * facilities for MP machines under Linux. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _SPARC_MPMBOX_H -#define _SPARC_MPMBOX_H - -/* The prom allocates, for each CPU on the machine an unsigned - * byte in physical ram. You probe the device tree prom nodes - * for these values. The purpose of this byte is to be able to - * pass messages from one cpu to another. - */ - -/* These are the main message types we have to look for in our - * Cpu mailboxes, based upon these values we decide what course - * of action to take. - */ - -/* The CPU is executing code in the kernel. */ -#define MAILBOX_ISRUNNING 0xf0 - -/* Another CPU called romvec->pv_exit(), you should call - * prom_stopcpu() when you see this in your mailbox. - */ -#define MAILBOX_EXIT 0xfb - -/* Another CPU called romvec->pv_enter(), you should call - * prom_cpuidle() when this is seen. - */ -#define MAILBOX_GOSPIN 0xfc - -/* Another CPU has hit a breakpoint either into kadb or the prom - * itself. Just like MAILBOX_GOSPIN, you should call prom_cpuidle() - * at this point. - */ -#define MAILBOX_BPT_SPIN 0xfd - -/* Oh geese, some other nitwit got a damn watchdog reset. The party's - * over so go call prom_stopcpu(). - */ -#define MAILBOX_WDOG_STOP 0xfe - -#ifndef __ASSEMBLY__ - -/* Handy macro's to determine a cpu's state. */ - -/* Is the cpu still in Power On Self Test? */ -#define MBOX_POST_P(letter) ((letter) >= 0x00 && (letter) <= 0x7f) - -/* Is the cpu at the 'ok' prompt of the PROM? */ -#define MBOX_PROMPROMPT_P(letter) ((letter) >= 0x80 && (letter) <= 0x8f) - -/* Is the cpu spinning in the PROM? */ -#define MBOX_PROMSPIN_P(letter) ((letter) >= 0x90 && (letter) <= 0xef) - -/* Sanity check... This is junk mail, throw it out. */ -#define MBOX_BOGON_P(letter) ((letter) >= 0xf1 && (letter) <= 0xfa) - -/* Is the cpu actively running an application/kernel-code? */ -#define MBOX_RUNNING_P(letter) ((letter) == MAILBOX_ISRUNNING) - -#endif /* !(__ASSEMBLY__) */ - -#endif /* !(_SPARC_MPMBOX_H) */ -- cgit v0.10.2 From f75b0d07da12e67559d51071391feaf0c265d292 Mon Sep 17 00:00:00 2001 From: Steven King Date: Sat, 5 May 2012 13:40:44 -0700 Subject: m68knommu: m528x qspi definition fix The consolidation of the qspi code missed a definition for 528x. Signed-off-by: Steven King Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h index d63b99f..497c31c 100644 --- a/arch/m68k/include/asm/m528xsim.h +++ b/arch/m68k/include/asm/m528xsim.h @@ -86,7 +86,7 @@ /* * QSPI module. */ -#define MCFQSPI_IOBASE (MCF_IPSBAR + 0x340) +#define MCFQSPI_BASE (MCF_IPSBAR + 0x340) #define MCFQSPI_SIZE 0x40 #define MCFQSPI_CS0 147 -- cgit v0.10.2 From b13b3f51ff7bec19ac1ba66e3623bfaa484af124 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 23 May 2012 11:32:45 +1000 Subject: m68k: fix inclusion of arch_gettimeoffset for non-MMU 68k classic CPU types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building for non-MMU based classic 68k CPU types (like the 68328 for example) you get a compilation error: CC arch/m68k/kernel/time.o arch/m68k/kernel/time.c:91:5: error: redefinition of ‘arch_gettimeoffset’ include/linux/time.h:145:19: note: previous definition of ‘arch_gettimeoffset’ was here The arch_gettimeoffset() code is included when building for these CPU types, but it shouldn't be. Those machine types do not have CONFIG_ARCH_USES_GETTIMEOFFSET set. The fix is simply to conditionally include the arch_gettimeoffset() code on that same config setting that specifies its use or not. Signed-off-by: Greg Ungerer Acked-by: Geert Uytterhoeven diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index d7deb7f..707f057 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -85,7 +85,7 @@ void __init time_init(void) mach_sched_init(timer_interrupt); } -#ifdef CONFIG_M68KCLASSIC +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET u32 arch_gettimeoffset(void) { @@ -108,4 +108,4 @@ static int __init rtc_init(void) module_init(rtc_init); -#endif /* CONFIG_M68KCLASSIC */ +#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ -- cgit v0.10.2 From dc5588ae3c597006095926c25634408257457a8f Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 23 May 2012 13:27:18 +1000 Subject: m68knommu: fix 68328 local setting of timer interrupt handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compiling for 68328 based targets fails with: arch/m68k/platform/68328/timers.c: In function ‘hw_tick’: arch/m68k/platform/68328/timers.c:65:2: error: implicit declaration of function ‘arch_timer_interrupt’ arch/m68k/platform/68328/timers.c: At top level: arch/m68k/platform/68328/timers.c:102:6: error: conflicting types for ‘hw_timer_init’ arch/m68k/include/asm/machdep.h:36:13: note: previous declaration of ‘hw_timer_init’ was here Changes made to hw_timer_init() didn't get updated in the 68328 timer code. So process and call the "handler" arg that is now passed into that hw_timer_init() function. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/platform/68328/timers.c b/arch/m68k/platform/68328/timers.c index c801c17..f4dc9b2 100644 --- a/arch/m68k/platform/68328/timers.c +++ b/arch/m68k/platform/68328/timers.c @@ -53,6 +53,7 @@ #endif static u32 m68328_tick_cnt; +static irq_handler_t timer_interrupt; /***************************************************************************/ @@ -62,7 +63,7 @@ static irqreturn_t hw_tick(int irq, void *dummy) TSTAT &= 0; m68328_tick_cnt += TICKS_PER_JIFFY; - return arch_timer_interrupt(irq, dummy); + return timer_interrupt(irq, dummy); } /***************************************************************************/ @@ -99,7 +100,7 @@ static struct clocksource m68328_clk = { /***************************************************************************/ -void hw_timer_init(void) +void hw_timer_init(irq_handler_t handler) { /* disable timer 1 */ TCTL = 0; @@ -115,6 +116,7 @@ void hw_timer_init(void) /* Enable timer 1 */ TCTL |= TCTL_TEN; clocksource_register_hz(&m68328_clk, TICKS_PER_JIFFY*HZ); + timer_interrupt = handler; } /***************************************************************************/ -- cgit v0.10.2 From 1b461d7631f17804257ab1734bd95c05ab655f8b Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 23 May 2012 13:32:55 +1000 Subject: m68knommu: fix 68360 local setting of timer interrupt handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compiling for 68360 based targets fails with: arch/m68k/platform/68360/config.c: In function ‘hw_tick’: arch/m68k/platform/68360/config.c:55:2: error: implicit declaration of function ‘arch_timer_interrupt’ arch/m68k/platform/68360/config.c: At top level: arch/m68k/platform/68360/config.c:64:6: error: conflicting types for ‘hw_timer_init’ arch/m68k/include/asm/machdep.h:36:13: note: previous declaration of ‘hw_timer_init’ was here Changes made to hw_timer_init() didn't get updated in the 68328 timer code. So process and call the "handler" arg that is now passed into that hw_timer_init() function. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/platform/68360/config.c b/arch/m68k/platform/68360/config.c index 255fc03..9877cef 100644 --- a/arch/m68k/platform/68360/config.c +++ b/arch/m68k/platform/68360/config.c @@ -35,6 +35,7 @@ extern void m360_cpm_reset(void); #define OSCILLATOR (unsigned long int)33000000 #endif +static irq_handler_t timer_interrupt; unsigned long int system_clock; extern QUICC *pquicc; @@ -52,7 +53,7 @@ static irqreturn_t hw_tick(int irq, void *dummy) pquicc->timer_ter1 = 0x0002; /* clear timer event */ - return arch_timer_interrupt(irq, dummy); + return timer_interrupt(irq, dummy); } static struct irqaction m68360_timer_irq = { @@ -61,7 +62,7 @@ static struct irqaction m68360_timer_irq = { .handler = hw_tick, }; -void hw_timer_init(void) +void hw_timer_init(irq_handler_t handler) { unsigned char prescaler; unsigned short tgcr_save; @@ -94,6 +95,8 @@ void hw_timer_init(void) pquicc->timer_ter1 = 0x0003; /* clear timer events */ + timer_interrupt = handler; + /* enable timer 1 interrupt in CIMR */ setup_irq(CPMVEC_TIMER1, &m68360_timer_irq); -- cgit v0.10.2 From 70c778f7a1075cf688ef50ca52c464e7ea60b506 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 23 May 2012 13:43:52 +1000 Subject: m68k: make syscall_trace_enter/leave exist for non-MMU classic m68k types The assembler entry code calls directly to the syscall_trace_enter() and syscall_trace_leave() functions. But currently they are conditionaly compiled out for the non-MMU classic m68k CPU types (so 68328 for example), resulting in a link error: LD vmlinux arch/m68k/platform/68328/built-in.o: In function `do_trace': (.text+0x1c): undefined reference to `syscall_trace_enter' arch/m68k/platform/68328/built-in.o: In function `do_trace': (.text+0x4c): undefined reference to `syscall_trace_leave' Change the conditional check that includes these functions to be true for the !defined(CONFIG_MMU) case as well. Signed-off-by: Greg Ungerer Acked-by: Geert Uytterhoeven diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 8b4a222..1bc10e6 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -286,7 +286,7 @@ asmlinkage void syscall_trace(void) } } -#ifdef CONFIG_COLDFIRE +#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) asmlinkage int syscall_trace_enter(void) { int ret = 0; -- cgit v0.10.2 From e32025a56403df4386cd61a741c0a36afe79ae8a Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 11 Jun 2012 23:18:33 -0300 Subject: x86: kvmclock: remove check_and_clear_guest_paused warning CPU offline path calls the hrtimer interrupt handler with interrupts disabled, without touching preempt_count, triggering this warning. Remove the warning since it is supposed to be used from hrtimer interrupt context only. Signed-off-by: Marcelo Tosatti diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 086eb58..f1b42b3 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -120,11 +120,6 @@ bool kvm_check_and_clear_guest_paused(void) bool ret = false; struct pvclock_vcpu_time_info *src; - /* - * per_cpu() is safe here because this function is only called from - * timer functions where preemption is already disabled. - */ - WARN_ON(!in_atomic()); src = &__get_cpu_var(hv_clock); if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) { __this_cpu_and(hv_clock.flags, ~PVCLOCK_GUEST_STOPPED); -- cgit v0.10.2 From 3fbd8716da4c69ddbb76c022f3f4a0d50723c68f Mon Sep 17 00:00:00 2001 From: Rafal Prylowski Date: Mon, 28 May 2012 23:35:54 +0800 Subject: leds: don't disable blinking when writing the same value to delay_on or delay_off Function led_set_software_blink() assumes that blink timer is still running, but commit 488bc35bf40df89d37486c1826b178a2fba36ce7 introduced disabling of blink timer before each call to led_set_software_blink(). Correct led_software_blink(): 1) remove protection against reprogramming blink timer to the same values, because it only disables blinking now, 2) remove unnecessary call to led_stop_software_blink(). Signed-off-by: Rafal Prylowski Cc: Richard Purdie Signed-off-by: Bryan Wu diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index d686004..d65353d 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -44,13 +44,6 @@ static void led_set_software_blink(struct led_classdev *led_cdev, if (!led_cdev->blink_brightness) led_cdev->blink_brightness = led_cdev->max_brightness; - if (led_get_trigger_data(led_cdev) && - delay_on == led_cdev->blink_delay_on && - delay_off == led_cdev->blink_delay_off) - return; - - led_stop_software_blink(led_cdev); - led_cdev->blink_delay_on = delay_on; led_cdev->blink_delay_off = delay_off; -- cgit v0.10.2 From 9cd5ec5e5447f99ffb33ce39c1fcd0e3306e11d1 Mon Sep 17 00:00:00 2001 From: Jeffrin Jose Date: Sun, 3 Jun 2012 20:11:52 +0800 Subject: leds: fixed a coding style issue. Fixed a coding style issue relating to trailing white space error found by checkpatch.pl tool in drivers/leds/led-class.c Signed-off-by: Jeffrin Jose Signed-off-by: Bryan Wu diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 8ee92c8..e663e6f 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev) led_cdev->brightness = led_cdev->brightness_get(led_cdev); } -static ssize_t led_brightness_show(struct device *dev, +static ssize_t led_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); -- cgit v0.10.2 From 9473c4c16700ec965904f23234fd0f8677ce6231 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 9 Jun 2012 07:41:42 +0800 Subject: leds: Make LEDS_ASIC3 and LEDS_RENESAS_TPU depend on LEDS_CLASS=y Otherwise, I got below build error when CONFIG_LEDS_CLASS=m. LD init/built-in.o drivers/built-in.o: In function `asic3_led_probe': clkdev.c:(.devinit.text+0x4680): undefined reference to `led_classdev_register' drivers/built-in.o: In function `r_tpu_probe': clkdev.c:(.devinit.text+0x4838): undefined reference to `led_classdev_register' drivers/built-in.o: In function `asic3_led_remove': clkdev.c:(.devexit.text+0x564): undefined reference to `led_classdev_unregister' drivers/built-in.o: In function `r_tpu_remove': clkdev.c:(.devexit.text+0x5a0): undefined reference to `led_classdev_unregister' make: *** [vmlinux] Error 1 Signed-off-by: Axel Lin Signed-off-by: Bryan Wu diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 04cb8c8..12b2b55 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -379,7 +379,7 @@ config LEDS_NETXBIG config LEDS_ASIC3 bool "LED support for the HTC ASIC3" - depends on LEDS_CLASS + depends on LEDS_CLASS=y depends on MFD_ASIC3 default y help @@ -390,7 +390,7 @@ config LEDS_ASIC3 config LEDS_RENESAS_TPU bool "LED support for Renesas TPU" - depends on LEDS_CLASS && HAVE_CLK && GENERIC_GPIO + depends on LEDS_CLASS=y && HAVE_CLK && GENERIC_GPIO help This option enables build of the LED TPU platform driver, suitable to drive any TPU channel on newer Renesas SoCs. -- cgit v0.10.2 From b84297197ce60bb5da14cbd5516cf5130b0cd380 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 11 Jun 2012 16:46:55 -0700 Subject: exofs: fix sparse non-ANSI function warning Fix sparse non-ANSI function warning: fs/exofs/sys.c:112:28: warning: non-ANSI function declaration of function 'exofs_sysfs_dbg_print' Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds diff --git a/fs/exofs/sys.c b/fs/exofs/sys.c index e32bc91..5a7b691 100644 --- a/fs/exofs/sys.c +++ b/fs/exofs/sys.c @@ -109,7 +109,7 @@ static struct kobj_type odev_ktype = { static struct kobj_type uuid_ktype = { }; -void exofs_sysfs_dbg_print() +void exofs_sysfs_dbg_print(void) { #ifdef CONFIG_EXOFS_DEBUG struct kobject *k_name, *k_tmp; -- cgit v0.10.2 From efec381ced2c0416c3765abce076896cf464dc0c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 6 Jun 2012 22:50:41 +0200 Subject: pinctrl: nomadik: add clk_prepare() call We now strictly require clk_prepare() calls to be issued before any clk_enable() calls. Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index b26395d..ba7122f 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1246,6 +1246,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) ret = PTR_ERR(clk); goto out_unmap; } + clk_prepare(clk); nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); if (!nmk_chip) { -- cgit v0.10.2 From e85bbc19d5a9ad2b48bf8f2fd3277d6fe58f23ce Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 12 Jun 2012 12:43:06 +0200 Subject: pinctrl: nomadik: fix up typo Commit a60b57eddaa8af6c02cf7bbeb58ebf82881f08ac "drivers/gpio: gpio-nomadik: Add support for irqdomains" changed GPIO offset calculations to have this form: (gpio % NMK_GPIO_PER_CHIP) except in this one place for setting sleep mode, where the conversion was all wrong, and instead mod:ing the GPIO with the IRQ base which does not make any sense. So fix this up so we can use sleepmode. Reviewed-by: Lee Jones Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index ba7122f..e8937e7 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -673,7 +673,7 @@ static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, * wakeup is anyhow controlled by the RIMSC and FIMSC registers. */ if (nmk_chip->sleepmode && on) { - __nmk_gpio_set_slpm(nmk_chip, gpio % nmk_chip->chip.base, + __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, NMK_GPIO_SLPM_WAKEUP_ENABLE); } -- cgit v0.10.2 From 3a86a5f8abb33956446ae31b1e9c149d7b2d1d21 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 9 Jun 2012 00:52:11 +0530 Subject: pinctrl: pinctrl-imx: free allocated pinctrl_map structure only once and use kernel facilities for IMX_PMX_DUMP a) as we allocate the pinctrl_map structure at imx_dt_node_to_map at line 167, anyway if its an element, or a num_elements * (sizeof(type)) elements allocated to one single pointer must be freed only once. CASE. A) as new_map is not moved and allocated like, for (i = 0; i < MAX_ELEMS; i++) { new_map[i] = kmalloc(numelems * size, GFP_KERNEL); } its freed as for (i = 0; i < MAX_ELEMS; i++) { kfree(new_map[i]); } CASE. B) and its allocated like new_map = kmalloc(numelems * size, GFP_KERNEL); it just needs kfree not as case A's. b) use KERN_DEBUG facility for the IMX_PMX_DUMP macro. Signed-off-by: Devendra Naga Acked-by: Dong Aisheng Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index f6e7c67..09f3a30 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c @@ -27,16 +27,16 @@ #include "core.h" #include "pinctrl-imx.h" -#define IMX_PMX_DUMP(info, p, m, c, n) \ -{ \ - int i, j; \ - printk("Format: Pin Mux Config\n"); \ - for (i = 0; i < n; i++) { \ - j = p[i]; \ - printk("%s %d 0x%lx\n", \ - info->pins[j].name, \ - m[i], c[i]); \ - } \ +#define IMX_PMX_DUMP(info, p, m, c, n) \ +{ \ + int i, j; \ + printk(KERN_DEBUG "Format: Pin Mux Config\n"); \ + for (i = 0; i < n; i++) { \ + j = p[i]; \ + printk(KERN_DEBUG "%s %d 0x%lx\n", \ + info->pins[j].name, \ + m[i], c[i]); \ + } \ } /* The bits in CONFIG cell defined in binding doc*/ @@ -201,10 +201,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, static void imx_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { - int i; - - for (i = 0; i < num_maps; i++) - kfree(map); + kfree(map); } static struct pinctrl_ops imx_pctrl_ops = { @@ -475,9 +472,8 @@ static int __devinit imx_pinctrl_parse_groups(struct device_node *np, grp->configs[j] = config & ~IMX_PAD_SION; } -#ifdef DEBUG IMX_PMX_DUMP(info, grp->pins, grp->mux_mode, grp->configs, grp->npins); -#endif + return 0; } -- cgit v0.10.2 From c71157c54a4f86e4f355dc6952268e8536013502 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Thu, 7 Jun 2012 22:19:26 +0530 Subject: pinctrl: pinctrl-imx: free if of_get_parent fails to get the parent node of_get_parent can return null if no parent node found, so the allocated new_map should be freed. Signed-off-by: Devendra Naga Acked-by: Dong Aisheng Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index 09f3a30..542b01b 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c @@ -173,8 +173,10 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, /* create mux map */ parent = of_get_parent(np); - if (!parent) + if (!parent) { + kfree(new_map); return -EINVAL; + } new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; new_map[0].data.mux.function = parent->name; new_map[0].data.mux.group = np->name; -- cgit v0.10.2 From 67695f2eae210b0631fb92cf5649d0454953e230 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 8 Jun 2012 21:33:12 +0800 Subject: pinctrl: pinctrl-imx: fix incorrect debug message of maps After create config map, the new_map pointer becomes point to PIN_MAP_TYPE_CONFIGS_PIN map rather than PIN_MAP_TYPE_MUX_GROUP map any more. Thus using new_map pointer to display the MUX_GROUP info is not correct. Using map pointer instead to show the correct MUX_GROUP map info. Original the debug message is: imx6q-pinctrl 20e0000.iomuxc: maps: function Yp group MX6Q_PAD_SD3_CMD num 12 After fix it is: imx6q-pinctrl 20e0000.iomuxc: maps: function usdhc3 group usdhc3grp-1 num 11 Reported-by: Richard Zhao Signed-off-by: Dong Aisheng Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index 542b01b..dd6d93a 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c @@ -195,7 +195,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, } dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", - new_map->data.mux.function, new_map->data.mux.group, map_num); + (*map)->data.mux.function, (*map)->data.mux.group, map_num); return 0; } -- cgit v0.10.2 From 0439f31c35d1da0b28988b308ea455e38e6a350d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 12 Jun 2012 10:37:08 +0300 Subject: NFSv4.1: integer overflow in decode_cb_sequence_args() This seems like it could overflow on 32 bits. Use kmalloc_array() which has overflow protection built in. Signed-off-by: Dan Carpenter Signed-off-by: Trond Myklebust diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 95bfc24..27c2969 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -455,9 +455,9 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp, args->csa_nrclists = ntohl(*p++); args->csa_rclists = NULL; if (args->csa_nrclists) { - args->csa_rclists = kmalloc(args->csa_nrclists * - sizeof(*args->csa_rclists), - GFP_KERNEL); + args->csa_rclists = kmalloc_array(args->csa_nrclists, + sizeof(*args->csa_rclists), + GFP_KERNEL); if (unlikely(args->csa_rclists == NULL)) goto out; -- cgit v0.10.2 From e216c8c771c9a77f14d7e8b4131846b038f6c145 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 12 Jun 2012 10:37:39 +0300 Subject: NFS: add an endian notation for sparse This is supposed to be a __be32 value. Sparse complains a lot: fs/nfs/callback_xdr.c:699:30: warning: incorrect type in initializer (different base types) fs/nfs/callback_xdr.c:699:30: expected unsigned int [unsigned] status fs/nfs/callback_xdr.c:699:30: got restricted __be32 const [usertype] csr_status fs/nfs/callback_xdr.c:715:9: warning: cast to restricted __be32 fs/nfs/callback_xdr.c:716:16: warning: incorrect type in return expression (different base types) fs/nfs/callback_xdr.c:716:16: expected restricted __be32 fs/nfs/callback_xdr.c:716:16: got unsigned int [unsigned] status Signed-off-by: Dan Carpenter Signed-off-by: Trond Myklebust diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 27c2969..e64b01d 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -696,7 +696,7 @@ static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp, const struct cb_sequenceres *res) { __be32 *p; - unsigned status = res->csr_status; + __be32 status = res->csr_status; if (unlikely(status != 0)) goto out; -- cgit v0.10.2 From 0bf7481852c8ece4888c299ba0259b789c3dbde3 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 9 Jun 2012 17:31:23 +0530 Subject: pinctrl: pinctrl-mxs: Take care of frees if the kzalloc fails if there is no purecfg , the group pointer is allocated using kzalloc and if it fails to allocate, we wont free the new_map, if config is true, we call kmemdup and if it fails to do so we wont free the allocated group if there is no purecfg. fix this by doing the frees of new_map pointer and group pointers. Acked-by: Dong Aisheng Signed-off-by: Devendra Naga Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c index 556e45a..9d46303 100644 --- a/drivers/pinctrl/pinctrl-mxs.c +++ b/drivers/pinctrl/pinctrl-mxs.c @@ -107,8 +107,10 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, /* Compose group name */ group = kzalloc(length, GFP_KERNEL); - if (!group) - return -ENOMEM; + if (!group) { + ret = -ENOMEM; + goto free; + } snprintf(group, length, "%s.%d", np->name, reg); new_map[i].data.mux.group = group; i++; @@ -118,7 +120,7 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL); if (!pconfig) { ret = -ENOMEM; - goto free; + goto free_group; } new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; @@ -133,6 +135,9 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, return 0; +free_group: + if (!purecfg) + free(group); free: kfree(new_map); return ret; -- cgit v0.10.2 From 149ff9e1f240e7b57a02e0be5f74f21d0307d1d3 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sat, 9 Jun 2012 17:32:31 +0530 Subject: pinctrl: pinctrl-mxs: set platform driver data to NULL at errpath and at unregister clear the platform data pointer when mxs_pinctrl_probe_dt fails, and also before the unregistering with pinctrl subsystem. Signed-off-by: Devendra Naga Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c index 9d46303..afb50ee 100644 --- a/drivers/pinctrl/pinctrl-mxs.c +++ b/drivers/pinctrl/pinctrl-mxs.c @@ -516,6 +516,7 @@ int __devinit mxs_pinctrl_probe(struct platform_device *pdev, return 0; err: + platform_set_drvdata(pdev, NULL); iounmap(d->base); return ret; } @@ -525,6 +526,7 @@ int __devexit mxs_pinctrl_remove(struct platform_device *pdev) { struct mxs_pinctrl_data *d = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); pinctrl_unregister(d->pctl); iounmap(d->base); -- cgit v0.10.2 From fe4561680519019cc15d660862dce513ded2f3a7 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 12 Jun 2012 11:27:01 -0300 Subject: drm: increase DRM_OBJECT_MAX_PROPERTY to 24 Before Kernel 3.5, no one was checking for the return value of drm_connector_attach_property, so we never noticed that we were unable to create some properties. Commit "drm: WARN() when drm_connector_attach_property fails" added a WARN when we fail to create a property, and the transition from "connector properties" to "object properties" changed the warning message a little bit. On i915 machines with many TV connectors we hit the maximum number of properties (since each TV connector uses a lot of properties), so we get a few backtraces in our logs. This commit increases the maximum number of properties to 24 hoping we'll have enough room for everybody. Chris suggested that we convert this code to "lists", but I believe this conversion can come after we make sure people's dmesgs are not spammed by our driver. Signed-off-by: Paulo Zanoni Reported-by: Dave Jones Tested-by: Daniel Vetter Signed-off-by: Dave Airlie diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 73e4560..bac55c2 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -54,7 +54,7 @@ struct drm_mode_object { struct drm_object_properties *properties; }; -#define DRM_OBJECT_MAX_PROPERTY 16 +#define DRM_OBJECT_MAX_PROPERTY 24 struct drm_object_properties { int count; uint32_t ids[DRM_OBJECT_MAX_PROPERTY]; -- cgit v0.10.2 From a393c730ab69617c3291a3b0b2a228c9be2fc28c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 12 Jun 2012 13:28:42 +0200 Subject: drm/ttm: Fix buffer object metadata accounting regression v2 A regression was introduced in the 3.3 rc series, commit "drm/ttm: simplify memory accounting for ttm user v2", causing the metadata of buffer objects created using the ttm_bo_create() function to be accounted twice. That causes massive leaks with the vmwgfx driver running for example SpecViewperf Catia-03 test 2, eventually killing the app. Furthermore, the same commit introduces a regression where metadata accounting is leaked if a buffer object is initialized with an illegal size. This is also fixed with this commit. v2: Fixed an error path and removed an unused variable. Signed-off-by: Thomas Hellstrom Reviewed-by: Konrad Rzeszutek Wilk Cc: Jerome Glisse Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index b67cfca..36f4b28 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1204,6 +1204,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, (*destroy)(bo); else kfree(bo); + ttm_mem_global_free(mem_glob, acc_size); return -EINVAL; } bo->destroy = destroy; @@ -1307,22 +1308,14 @@ int ttm_bo_create(struct ttm_bo_device *bdev, struct ttm_buffer_object **p_bo) { struct ttm_buffer_object *bo; - struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; size_t acc_size; int ret; - acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); - if (unlikely(ret != 0)) - return ret; - bo = kzalloc(sizeof(*bo), GFP_KERNEL); - - if (unlikely(bo == NULL)) { - ttm_mem_global_free(mem_glob, acc_size); + if (unlikely(bo == NULL)) return -ENOMEM; - } + acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, buffer_start, interruptible, persistent_swap_storage, acc_size, NULL, NULL); -- cgit v0.10.2 From 6b18f79399f25a0f8e2b915b2dcb8bf5c7aa470d Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 12 Jun 2012 16:16:17 +0530 Subject: ALSA: compress_core: don't wake up on pause during pause the core should maintain the status-quo on the device and pointers and not wake up. If app needs it should call DROP explcitly. Signed-off-by: Namarta Kohli Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index a68aed7..375f7a0 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -502,10 +502,8 @@ static int snd_compr_pause(struct snd_compr_stream *stream) if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) return -EPERM; retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) { + if (!retval) stream->runtime->state = SNDRV_PCM_STATE_PAUSED; - wake_up(&stream->runtime->sleep); - } return retval; } -- cgit v0.10.2 From 8b21460ac6c0c88a0fec1cc70906c8e25c5aaa54 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 12 Jun 2012 16:16:18 +0530 Subject: ALSA: compress_core: cleanup pointers on stop as the start can be called after stop again, we need to reset state Signed-off-by: Namarta Kohli Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 375f7a0..ec2118d 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -542,6 +542,10 @@ static int snd_compr_stop(struct snd_compr_stream *stream) if (!retval) { stream->runtime->state = SNDRV_PCM_STATE_SETUP; wake_up(&stream->runtime->sleep); + stream->runtime->hw_pointer = 0; + stream->runtime->app_pointer = 0; + stream->runtime->total_bytes_available = 0; + stream->runtime->total_bytes_transferred = 0; } return retval; } -- cgit v0.10.2 From edfe3bfc1b779ddda9bcff523eb022dda37b93c8 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 12 Jun 2012 13:15:12 +0200 Subject: ALSA: HDA: Pin fixup for Zotac Z68 motherboard Pin 0x1b was connected to the front panel connector, which according to the HDA standard should contain a mic and a headphone. In this case, the headphone was listed as "line out" by BIOS. Cc: stable@kernel.org BugLink: https://bugs.launchpad.net/bugs/993162 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 224410e..b896681 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6439,6 +6439,7 @@ enum { ALC662_FIXUP_ASUS_MODE7, ALC662_FIXUP_ASUS_MODE8, ALC662_FIXUP_NO_JACK_DETECT, + ALC662_FIXUP_ZOTAC_Z68, }; static const struct alc_fixup alc662_fixups[] = { @@ -6588,6 +6589,13 @@ static const struct alc_fixup alc662_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc_fixup_no_jack_detect, }, + [ALC662_FIXUP_ZOTAC_Z68] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1b, 0x02214020 }, /* Front HP */ + { } + } + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -6601,6 +6609,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68), SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), #if 0 -- cgit v0.10.2 From 8a93664df90db983cfede122f9b4ddb3a8284e52 Mon Sep 17 00:00:00 2001 From: Weiping Pan Date: Sun, 10 Jun 2012 23:00:20 +0000 Subject: bonding:record primary when modify it via sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we modify primary via sysfs and it is not a valid slave, we should record it for future use, and this behavior is the same with bond_check_params(). Signed-off-by: Weiping Pan Acked-by: Nicolas de Pesloüan Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index aef42f0..485bedb 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1082,8 +1082,12 @@ static ssize_t bonding_store_primary(struct device *d, } } - pr_info("%s: Unable to set %.*s as primary slave.\n", - bond->dev->name, (int)strlen(buf) - 1, buf); + strncpy(bond->params.primary, ifname, IFNAMSIZ); + bond->params.primary[IFNAMSIZ - 1] = 0; + + pr_info("%s: Recording %s as primary, " + "but it has not been enslaved to %s yet.\n", + bond->dev->name, ifname, bond->dev->name); out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); -- cgit v0.10.2 From 5ee31c6898ea5537fcea160999d60dc63bc0c305 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Jun 2012 06:03:51 +0000 Subject: bonding: Fix corrupted queue_mapping In the transmit path of the bonding driver, skb->cb is used to stash the skb->queue_mapping so that the bonding device can set its own queue mapping. This value becomes corrupted since the skb->cb is also used in __dev_xmit_skb. When transmitting through bonding driver, bond_select_queue is called from dev_queue_xmit. In bond_select_queue the original skb->queue_mapping is copied into skb->cb (via bond_queue_mapping) and skb->queue_mapping is overwritten with the bond driver queue. Subsequently in dev_queue_xmit, __dev_xmit_skb is called which writes the packet length into skb->cb, thereby overwriting the stashed queue mappping. In bond_dev_queue_xmit (called from hard_start_xmit), the queue mapping for the skb is set to the stashed value which is now the skb length and hence is an invalid queue for the slave device. If we want to save skb->queue_mapping into skb->cb[], best place is to add a field in struct qdisc_skb_cb, to make sure it wont conflict with other layers (eg : Qdiscc, Infiniband...) This patchs also makes sure (struct qdisc_skb_cb)->data is aligned on 8 bytes : netem qdisc for example assumes it can store an u64 in it, without misalignment penalty. Note : we only have 20 bytes left in (struct qdisc_skb_cb)->data[]. The largest user is CHOKe and it fills it. Based on a previous patch from Tom Herbert. Signed-off-by: Eric Dumazet Reported-by: Tom Herbert Cc: John Fastabend Cc: Roland Dreier Acked-by: Neil Horman Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2ee8cf9..b9c2ae6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -76,6 +76,7 @@ #include #include #include +#include #include "bonding.h" #include "bond_3ad.h" #include "bond_alb.h" @@ -381,8 +382,6 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } -#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) - /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -395,7 +394,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { skb->dev = slave_dev; - skb->queue_mapping = bond_queue_mapping(skb); + BUILD_BUG_ON(sizeof(skb->queue_mapping) != + sizeof(qdisc_skb_cb(skb)->bond_queue_mapping)); + skb->queue_mapping = qdisc_skb_cb(skb)->bond_queue_mapping; if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); @@ -4171,7 +4172,7 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) /* * Save the original txq to restore before passing to the driver */ - bond_queue_mapping(skb) = skb->queue_mapping; + qdisc_skb_cb(skb)->bond_queue_mapping = skb->queue_mapping; if (unlikely(txq >= dev->real_num_tx_queues)) { do { diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 55ce96b..9d7d54a 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -220,13 +220,16 @@ struct tcf_proto { struct qdisc_skb_cb { unsigned int pkt_len; - unsigned char data[24]; + u16 bond_queue_mapping; + u16 _pad; + unsigned char data[20]; }; static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) { struct qdisc_skb_cb *qcb; - BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz); + + BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz); BUILD_BUG_ON(sizeof(qcb->data) < sz); } -- cgit v0.10.2 From e58c5de8f59d124907c993ea3126c69493b7eec7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 12 Jun 2012 10:17:25 -0400 Subject: drivers/ide/ide-cs.c: adjust suspicious bit operation IO_DATA_PATH_WIDTH_8 is 0, so a bit-and with it is always false. The value IO_DATA_PATH_WIDTH covers the bits of the IO_DATA_PATH constants, so first pick those bits and then make the test using !=. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Signed-off-by: Julia Lawall Signed-off-by: David S. Miller diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 28e344e..f1e922e 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c @@ -167,7 +167,8 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data) { int *is_kme = priv_data; - if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { + if ((pdev->resource[0]->flags & IO_DATA_PATH_WIDTH) + != IO_DATA_PATH_WIDTH_8) { pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; } -- cgit v0.10.2 From 6dae14216c85eea13db7b12c469475c5d30e5499 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Jun 2012 00:28:23 +0200 Subject: serial: sh-sci: Fix probe error paths When probing fails, the driver must not try to cleanup resources that have not been initialized. Fix this. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4604153..27df2ad 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2179,6 +2179,16 @@ static int __devinit sci_init_single(struct platform_device *dev, return 0; } +static void sci_cleanup_single(struct sci_port *port) +{ + sci_free_gpios(port); + + clk_put(port->iclk); + clk_put(port->fclk); + + pm_runtime_disable(port->port.dev); +} + #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE static void serial_console_putchar(struct uart_port *port, int ch) { @@ -2360,14 +2370,10 @@ static int sci_remove(struct platform_device *dev) cpufreq_unregister_notifier(&port->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - sci_free_gpios(port); - uart_remove_one_port(&sci_uart_driver, &port->port); - clk_put(port->iclk); - clk_put(port->fclk); + sci_cleanup_single(port); - pm_runtime_disable(&dev->dev); return 0; } @@ -2392,7 +2398,13 @@ static int __devinit sci_probe_single(struct platform_device *dev, if (ret) return ret; - return uart_add_one_port(&sci_uart_driver, &sciport->port); + ret = uart_add_one_port(&sci_uart_driver, &sciport->port); + if (ret) { + sci_cleanup_single(sciport); + return ret; + } + + return 0; } static int __devinit sci_probe(struct platform_device *dev) @@ -2413,24 +2425,22 @@ static int __devinit sci_probe(struct platform_device *dev) ret = sci_probe_single(dev, dev->id, p, sp); if (ret) - goto err_unreg; + return ret; sp->freq_transition.notifier_call = sci_notifier; ret = cpufreq_register_notifier(&sp->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - if (unlikely(ret < 0)) - goto err_unreg; + if (unlikely(ret < 0)) { + sci_cleanup_single(sp); + return ret; + } #ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); #endif return 0; - -err_unreg: - sci_remove(dev); - return ret; } static int sci_suspend(struct device *dev) -- cgit v0.10.2 From b6c5ef6f6d3e46d6200b141c30ac000a11b851df Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Jun 2012 00:28:24 +0200 Subject: serial: sh-sci: Make probe fail for ports that exceed the maximum count The driver supports a maximum number of ports configurable at compile time. Make sure the probe() method fails when registering a port that exceeds the maximum instead of returning success without registering the port. This fixes a crash at system suspend time, when the driver tried to suspend a non-registered port using the UART core. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 27df2ad..1bd9163 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2391,7 +2391,7 @@ static int __devinit sci_probe_single(struct platform_device *dev, index+1, SCI_NPORTS); dev_notice(&dev->dev, "Consider bumping " "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); - return 0; + return -EINVAL; } ret = sci_init_single(dev, sciport, index, p); -- cgit v0.10.2 From 74ca4313bdd0423a7917bbe74be3f27da8a39fe1 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Fri, 8 Jun 2012 22:49:17 +0200 Subject: sh: Kill off last dead UBC header Commit 7025bec9125b0a02edcaf22c2dce753bf2c95480 ("sh: Kill off dead UBC headers.") skipped arch/sh/include/cpu-sh2a/cpu/ubc.h. Since nothing is using that header either, kill it off too. Signed-off-by: Paul Bolle Signed-off-by: Paul Mundt diff --git a/arch/sh/include/cpu-sh2a/cpu/ubc.h b/arch/sh/include/cpu-sh2a/cpu/ubc.h deleted file mode 100644 index 1192e1c..0000000 --- a/arch/sh/include/cpu-sh2a/cpu/ubc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SH-2A UBC definitions - * - * Copyright (C) 2008 Kieran Bingham - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef __ASM_CPU_SH2A_UBC_H -#define __ASM_CPU_SH2A_UBC_H - -#define UBC_BARA 0xfffc0400 -#define UBC_BAMRA 0xfffc0404 -#define UBC_BBRA 0xfffc04a0 /* 16 bit access */ -#define UBC_BDRA 0xfffc0408 -#define UBC_BDMRA 0xfffc040c - -#define UBC_BARB 0xfffc0410 -#define UBC_BAMRB 0xfffc0414 -#define UBC_BBRB 0xfffc04b0 /* 16 bit access */ -#define UBC_BDRB 0xfffc0418 -#define UBC_BDMRB 0xfffc041c - -#define UBC_BRCR 0xfffc04c0 - -#endif /* __ASM_CPU_SH2A_UBC_H */ -- cgit v0.10.2 From 0e100e11bd73be4e28e457cf5ad49a6892d5d1fe Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 25 May 2012 13:02:48 +0900 Subject: sh: switch to generic strncpy_from_user(). This kills off the special sh32/64 versions and adopts the generic version. It should be possible to optimize this for SH-4A unaligned loads, but this is a corner case that can be supported incrementally. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 99bcd0e..cbffc26 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -32,6 +32,7 @@ config SUPERH select GENERIC_SMP_IDLE_THREAD select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST + select GENERIC_STRNCPY_FROM_USER help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h index 050f221..3df7eee 100644 --- a/arch/sh/include/asm/uaccess.h +++ b/arch/sh/include/asm/uaccess.h @@ -25,6 +25,8 @@ (__chk_user_ptr(addr), \ __access_ok((unsigned long __force)(addr), (size))) +#define user_addr_max() (current_thread_info()->addr_limit.seg) + /* * Uh, these should become the main single-value transfer routines ... * They automatically use the right size if we just have the right @@ -100,6 +102,8 @@ struct __large_struct { unsigned long buf[100]; }; # include "uaccess_64.h" #endif +extern long strncpy_from_user(char *dest, const char __user *src, long count); + /* Generic arbitrary sized copy. */ /* Return the number of bytes NOT copied */ __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); @@ -137,37 +141,6 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size); __cl_size; \ }) -/** - * strncpy_from_user: - Copy a NUL terminated string from userspace. - * @dst: Destination address, in kernel space. This buffer must be at - * least @count bytes long. - * @src: Source address, in user space. - * @count: Maximum number of bytes to copy, including the trailing NUL. - * - * Copies a NUL-terminated string from userspace to kernel space. - * - * On success, returns the length of the string (not including the trailing - * NUL). - * - * If access to userspace fails, returns -EFAULT (some data may have been - * copied). - * - * If @count is smaller than the length of the string, copies @count bytes - * and returns @count. - */ -#define strncpy_from_user(dest,src,count) \ -({ \ - unsigned long __sfu_src = (unsigned long)(src); \ - int __sfu_count = (int)(count); \ - long __sfu_res = -EFAULT; \ - \ - if (__access_ok(__sfu_src, __sfu_count)) \ - __sfu_res = __strncpy_from_user((unsigned long)(dest), \ - __sfu_src, __sfu_count); \ - \ - __sfu_res; \ -}) - static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { diff --git a/arch/sh/include/asm/uaccess_32.h b/arch/sh/include/asm/uaccess_32.h index ae0d24f..ef44d05 100644 --- a/arch/sh/include/asm/uaccess_32.h +++ b/arch/sh/include/asm/uaccess_32.h @@ -170,45 +170,6 @@ __asm__ __volatile__( \ extern void __put_user_unknown(void); -static inline int -__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) -{ - __kernel_size_t res; - unsigned long __dummy, _d, _s, _c; - - __asm__ __volatile__( - "9:\n" - "mov.b @%2+, %1\n\t" - "cmp/eq #0, %1\n\t" - "bt/s 2f\n" - "1:\n" - "mov.b %1, @%3\n\t" - "dt %4\n\t" - "bf/s 9b\n\t" - " add #1, %3\n\t" - "2:\n\t" - "sub %4, %0\n" - "3:\n" - ".section .fixup,\"ax\"\n" - "4:\n\t" - "mov.l 5f, %1\n\t" - "jmp @%1\n\t" - " mov %9, %0\n\t" - ".balign 4\n" - "5: .long 3b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .balign 4\n" - " .long 9b,4b\n" - ".previous" - : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c) - : "0" (__count), "2" (__src), "3" (__dest), "4" (__count), - "i" (-EFAULT) - : "memory", "t"); - - return res; -} - /* * Return the size of a string (including the ending 0 even when we have * exceeded the maximum string length). diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h index 56fd20b..0042c90 100644 --- a/arch/sh/include/asm/uaccess_64.h +++ b/arch/sh/include/asm/uaccess_64.h @@ -85,7 +85,5 @@ extern long __put_user_asm_q(void *, long); extern void __put_user_unknown(void); extern long __strnlen_user(const char *__s, long __n); -extern int __strncpy_from_user(unsigned long __dest, - unsigned long __user __src, int __count); #endif /* __ASM_SH_UACCESS_64_H */ diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index ff1f0e6..b7b3f63 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -1569,46 +1569,6 @@ ___clear_user_exit: #endif /* CONFIG_MMU */ /* - * int __strncpy_from_user(unsigned long __dest, unsigned long __src, - * int __count) - * - * Inputs: - * (r2) target address - * (r3) source address - * (r4) maximum size in bytes - * - * Ouputs: - * (*r2) copied data - * (r2) -EFAULT (in case of faulting) - * copied data (otherwise) - */ - .global __strncpy_from_user -__strncpy_from_user: - pta ___strncpy_from_user1, tr0 - pta ___strncpy_from_user_done, tr1 - or r4, ZERO, r5 /* r5 = original count */ - beq/u r4, r63, tr1 /* early exit if r4==0 */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - -___strncpy_from_user1: - ld.b r3, 0, r7 /* Fault address: only in reading */ - st.b r2, 0, r7 - addi r2, 1, r2 - addi r3, 1, r3 - beq/u ZERO, r7, tr1 - addi r4, -1, r4 /* return real number of copied bytes */ - bne/l ZERO, r4, tr0 - -___strncpy_from_user_done: - sub r5, r4, r6 /* If done, return copied */ - -___strncpy_from_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* * extern long __strnlen_user(const char *__s, long __n) * * Inputs: @@ -1982,7 +1942,6 @@ asm_uaccess_start: .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit #endif - .long ___strncpy_from_user1, ___strncpy_from_user_exit .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit .long ___get_user_asm_w1, ___get_user_asm_w_exit diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index 45afa5c..3a3ba60 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -33,7 +33,6 @@ EXPORT_SYMBOL(__get_user_asm_w); EXPORT_SYMBOL(__get_user_asm_l); EXPORT_SYMBOL(__get_user_asm_q); EXPORT_SYMBOL(__strnlen_user); -EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); -- cgit v0.10.2 From cba8df4be3bdf10c86a26c458c5fc2ca978eeb2c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 4 Jun 2012 15:46:05 +0900 Subject: sh: use the new generic strnlen_user() function This discards both the _32 and _64 versions in favour of the consolidated generic one. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index cbffc26..31d9db7 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -33,6 +33,7 @@ config SUPERH select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h index 3df7eee..8698a80 100644 --- a/arch/sh/include/asm/uaccess.h +++ b/arch/sh/include/asm/uaccess.h @@ -104,6 +104,9 @@ struct __large_struct { unsigned long buf[100]; }; extern long strncpy_from_user(char *dest, const char __user *src, long count); +extern __must_check long strlen_user(const char __user *str); +extern __must_check long strnlen_user(const char __user *str, long n); + /* Generic arbitrary sized copy. */ /* Return the number of bytes NOT copied */ __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); @@ -165,43 +168,6 @@ copy_to_user(void __user *to, const void *from, unsigned long n) return __copy_size; } -/** - * strnlen_user: - Get the size of a string in user space. - * @s: The string to measure. - * @n: The maximum valid length - * - * Context: User context only. This function may sleep. - * - * Get the size of a NUL-terminated string in user space. - * - * Returns the size of the string INCLUDING the terminating NUL. - * On exception, returns 0. - * If the string is too long, returns a value greater than @n. - */ -static inline long strnlen_user(const char __user *s, long n) -{ - if (!__addr_ok(s)) - return 0; - else - return __strnlen_user(s, n); -} - -/** - * strlen_user: - Get the size of a string in user space. - * @str: The string to measure. - * - * Context: User context only. This function may sleep. - * - * Get the size of a NUL-terminated string in user space. - * - * Returns the size of the string INCLUDING the terminating NUL. - * On exception, returns 0. - * - * If there is a limit on the length of a valid string, you may wish to - * consider using strnlen_user() instead. - */ -#define strlen_user(str) strnlen_user(str, ~0UL >> 1) - /* * The exception table consists of pairs of addresses: the first is the * address of an instruction that is allowed to fault, and the second is diff --git a/arch/sh/include/asm/uaccess_32.h b/arch/sh/include/asm/uaccess_32.h index ef44d05..c0de7ee 100644 --- a/arch/sh/include/asm/uaccess_32.h +++ b/arch/sh/include/asm/uaccess_32.h @@ -170,40 +170,4 @@ __asm__ __volatile__( \ extern void __put_user_unknown(void); -/* - * Return the size of a string (including the ending 0 even when we have - * exceeded the maximum string length). - */ -static inline long __strnlen_user(const char __user *__s, long __n) -{ - unsigned long res; - unsigned long __dummy; - - __asm__ __volatile__( - "1:\t" - "mov.b @(%0,%3), %1\n\t" - "cmp/eq %4, %0\n\t" - "bt/s 2f\n\t" - " add #1, %0\n\t" - "tst %1, %1\n\t" - "bf 1b\n\t" - "2:\n" - ".section .fixup,\"ax\"\n" - "3:\n\t" - "mov.l 4f, %1\n\t" - "jmp @%1\n\t" - " mov #0, %0\n" - ".balign 4\n" - "4: .long 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .balign 4\n" - " .long 1b,3b\n" - ".previous" - : "=z" (res), "=&r" (__dummy) - : "0" (0), "r" (__s), "r" (__n) - : "t"); - return res; -} - #endif /* __ASM_SH_UACCESS_32_H */ diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h index 0042c90..2e07e0f 100644 --- a/arch/sh/include/asm/uaccess_64.h +++ b/arch/sh/include/asm/uaccess_64.h @@ -84,6 +84,4 @@ extern long __put_user_asm_l(void *, long); extern long __put_user_asm_q(void *, long); extern void __put_user_unknown(void); -extern long __strnlen_user(const char *__s, long __n); - #endif /* __ASM_SH_UACCESS_64_H */ diff --git a/arch/sh/include/asm/word-at-a-time.h b/arch/sh/include/asm/word-at-a-time.h new file mode 100644 index 0000000..6e38953 --- /dev/null +++ b/arch/sh/include/asm/word-at-a-time.h @@ -0,0 +1,53 @@ +#ifndef __ASM_SH_WORD_AT_A_TIME_H +#define __ASM_SH_WORD_AT_A_TIME_H + +#ifdef CONFIG_CPU_BIG_ENDIAN +# include +#else +/* + * Little-endian version cribbed from x86. + */ +struct word_at_a_time { + const unsigned long one_bits, high_bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } + +/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ +static inline long count_masked_bytes(long mask) +{ + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + long a = (0x0ff0001+mask) >> 23; + /* Fix the 1 for 00 case */ + return a & mask; +} + +/* Return nonzero if it has a zero */ +static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) +{ + unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; + *bits = mask; + return mask; +} + +static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) +{ + return bits; +} + +static inline unsigned long create_zero_mask(unsigned long bits) +{ + bits = (bits - 1) & ~bits; + return bits >> 7; +} + +/* The mask we created is directly usable as a bytemask */ +#define zero_bytemask(mask) (mask) + +static inline unsigned long find_zero(unsigned long mask) +{ + return count_masked_bytes(mask); +} +#endif + +#endif diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index b7b3f63..b7cf6a5 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -1569,46 +1569,6 @@ ___clear_user_exit: #endif /* CONFIG_MMU */ /* - * extern long __strnlen_user(const char *__s, long __n) - * - * Inputs: - * (r2) source address - * (r3) source size in bytes - * - * Ouputs: - * (r2) -EFAULT (in case of faulting) - * string length (otherwise) - */ - .global __strnlen_user -__strnlen_user: - pta ___strnlen_user_set_reply, tr0 - pta ___strnlen_user1, tr1 - or ZERO, ZERO, r5 /* r5 = counter */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - beq r3, ZERO, tr0 - -___strnlen_user1: - ldx.b r2, r5, r7 /* Fault address: only in reading */ - addi r3, -1, r3 /* No real fixup */ - addi r5, 1, r5 - beq r3, ZERO, tr0 - bne r7, ZERO, tr1 -! The line below used to be active. This meant led to a junk byte lying between each pair -! of entries in the argv & envp structures in memory. Whilst the program saw the right data -! via the argv and envp arguments to main, it meant the 'flat' representation visible through -! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. -! addi r5, 1, r5 /* Include '\0' */ - -___strnlen_user_set_reply: - or r5, ZERO, r6 /* If done, return counter */ - -___strnlen_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* * extern long __get_user_asm_?(void *val, long addr) * * Inputs: @@ -1942,7 +1902,6 @@ asm_uaccess_start: .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit #endif - .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit .long ___get_user_asm_w1, ___get_user_asm_w_exit .long ___get_user_asm_l1, ___get_user_asm_l_exit diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index 3a3ba60..26a0774 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -32,7 +32,6 @@ EXPORT_SYMBOL(__get_user_asm_b); EXPORT_SYMBOL(__get_user_asm_w); EXPORT_SYMBOL(__get_user_asm_l); EXPORT_SYMBOL(__get_user_asm_q); -EXPORT_SYMBOL(__strnlen_user); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); -- cgit v0.10.2 From 4149268e7816d719b0fde8e89aaa6db8c168fc43 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 18 May 2012 13:57:19 -0700 Subject: target: Add TFO->put_session() caller for HW fabric session shutdown This patch adds an optional target_core_fabric_ops->put_session() caller within the existing target_put_session() code path. This is required by tcm_qla2xxx code in order to invoke it's own fabric specific session shutdown handler using se_session->sess_kref. Signed-off-by: Joern Engel Cc: Roland Dreier Cc: Arun Easi Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index b05fdc0..634d0f3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -315,7 +315,7 @@ void transport_register_session( } EXPORT_SYMBOL(transport_register_session); -static void target_release_session(struct kref *kref) +void target_release_session(struct kref *kref) { struct se_session *se_sess = container_of(kref, struct se_session, sess_kref); @@ -332,6 +332,12 @@ EXPORT_SYMBOL(target_get_session); void target_put_session(struct se_session *se_sess) { + struct se_portal_group *tpg = se_sess->se_tpg; + + if (tpg->se_tpg_tfo->put_session != NULL) { + tpg->se_tpg_tfo->put_session(se_sess); + return; + } kref_put(&se_sess->sess_kref, target_release_session); } EXPORT_SYMBOL(target_put_session); diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 1169599..c78a233 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -47,6 +47,7 @@ struct target_core_fabric_ops { */ int (*check_stop_free)(struct se_cmd *); void (*release_cmd)(struct se_cmd *); + void (*put_session)(struct se_session *); /* * Called with spin_lock_bh(struct se_portal_group->session_lock held. */ -- cgit v0.10.2 From 8e780be960c3e7000a94652bc56efeb3c932ee24 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 13 Jun 2012 11:36:36 +0900 Subject: sh: Fix up link time defsym warnings. sh-linux-gnu-ld:--defsym 'jiffies=jiffies_64': ignoring invalid character `'' in expression For some reason ld has recently started complaining about the quotes, so just get rid of them, we don't need them for anything anyways. Signed-off-by: Paul Mundt diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 46edf07..dbf887e 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -114,11 +114,11 @@ endif ifdef CONFIG_CPU_LITTLE_ENDIAN ld-bfd := elf32-$(UTS_MACHINE)-linux -LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' --oformat $(ld-bfd) +LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld-bfd) LDFLAGS += -EL else ld-bfd := elf32-$(UTS_MACHINE)big-linux -LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' --oformat $(ld-bfd) +LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld-bfd) LDFLAGS += -EB endif -- cgit v0.10.2 From aaf68b753313f1e67fd2e8996e32ab2813f441fa Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 18 May 2012 13:58:23 -0700 Subject: tcm_qla2xxx: Convert to TFO->put_session() usage This patch converts tcm_qla2xxx code to use an internal kref_put() for se_session->sess_kref in order to ensure that qla_hw_data->hardware_lock can be held while calling qlt_unreg_sess() for the final put. Signed-off-by: Joern Engel Cc: Roland Dreier Cc: Arun Easi Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 436598f..3cee5b6 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -844,9 +844,28 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) se_nacl, nacl->nport_wwnn, nacl->nport_id); } +static void tcm_qla2xxx_release_session(struct kref *kref) +{ + struct se_session *se_sess = container_of(kref, + struct se_session, sess_kref); + + qlt_unreg_sess(se_sess->fabric_sess_ptr); +} + +static void tcm_qla2xxx_put_session(struct se_session *se_sess) +{ + struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; + struct qla_hw_data *ha = sess->vha->hw; + unsigned long flags; + + spin_lock_irqsave(&ha->hardware_lock, flags); + kref_put(&se_sess->sess_kref, tcm_qla2xxx_release_session); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) { - target_put_session(sess->se_sess); + tcm_qla2xxx_put_session(sess->se_sess); } static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) @@ -1731,6 +1750,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = { .new_cmd_map = NULL, .check_stop_free = tcm_qla2xxx_check_stop_free, .release_cmd = tcm_qla2xxx_release_cmd, + .put_session = tcm_qla2xxx_put_session, .shutdown_session = tcm_qla2xxx_shutdown_session, .close_session = tcm_qla2xxx_close_session, .sess_get_index = tcm_qla2xxx_sess_get_index, @@ -1779,6 +1799,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, .release_cmd = tcm_qla2xxx_release_cmd, + .put_session = tcm_qla2xxx_put_session, .shutdown_session = tcm_qla2xxx_shutdown_session, .close_session = tcm_qla2xxx_close_session, .sess_get_index = tcm_qla2xxx_sess_get_index, -- cgit v0.10.2 From d14a5fdc26986f7bac8376a339f336be18ba2a90 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 12 May 2012 22:39:07 +0200 Subject: sh: Setup CROSS_COMPILE at the top CROSS_COMPILE must be setup before using e.g. cc-option (and a few other as-*, cc-*, ld-* macros), else they will check against the wrong compiler when cross-compiling, and may invoke the cross compiler with wrong or suboptimal compiler options. Signed-off-by: Geert Uytterhoeven Cc: Paul Mundt Cc: linux-sh@vger.kernel.org Signed-off-by: Paul Mundt diff --git a/arch/sh/Makefile b/arch/sh/Makefile index dbf887e..aed701c 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -9,6 +9,12 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # +ifneq ($(SUBARCH),$(ARCH)) + ifeq ($(CROSS_COMPILE),) + CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-) + endif +endif + isa-y := any isa-$(CONFIG_SH_DSP) := sh isa-$(CONFIG_CPU_SH2) := sh2 @@ -106,12 +112,6 @@ LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \ KBUILD_DEFCONFIG := cayman_defconfig endif -ifneq ($(SUBARCH),$(ARCH)) - ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-) - endif -endif - ifdef CONFIG_CPU_LITTLE_ENDIAN ld-bfd := elf32-$(UTS_MACHINE)-linux LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld-bfd) -- cgit v0.10.2 From 1318002aebadf18217ad3de677b6c96b8140dcff Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 13 Jun 2012 11:59:47 +0900 Subject: sh: Kill off additional asm-generic wrappers. A few wrappers were overlooked in the initial conversion, take care of them now. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 09d1e60..7b673dd 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -3,6 +3,7 @@ include include/asm-generic/Kbuild.asm generic-y += bitsperlong.h generic-y += cputime.h generic-y += current.h +generic-y += delay.h generic-y += div64.h generic-y += emergency-restart.h generic-y += errno.h @@ -10,7 +11,9 @@ generic-y += fcntl.h generic-y += ioctl.h generic-y += ipcbuf.h generic-y += irq_regs.h +generic-y += kvm_para.h generic-y += local.h +generic-y += local64.h generic-y += param.h generic-y += parport.h generic-y += percpu.h @@ -18,10 +21,12 @@ generic-y += poll.h generic-y += mman.h generic-y += msgbuf.h generic-y += resource.h +generic-y += scatterlist.h generic-y += sembuf.h generic-y += serial.h generic-y += shmbuf.h generic-y += siginfo.h +generic-y += sizes.h generic-y += socket.h generic-y += statfs.h generic-y += termbits.h diff --git a/arch/sh/include/asm/delay.h b/arch/sh/include/asm/delay.h deleted file mode 100644 index 9670e12..0000000 --- a/arch/sh/include/asm/delay.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/kvm_para.h b/arch/sh/include/asm/kvm_para.h deleted file mode 100644 index 14fab8f..0000000 --- a/arch/sh/include/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/local64.h b/arch/sh/include/asm/local64.h deleted file mode 100644 index 36c93b5..0000000 --- a/arch/sh/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/sh/include/asm/scatterlist.h b/arch/sh/include/asm/scatterlist.h deleted file mode 100644 index 98dfc35..0000000 --- a/arch/sh/include/asm/scatterlist.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH_SCATTERLIST_H -#define __ASM_SH_SCATTERLIST_H - -#include - -#endif /* __ASM_SH_SCATTERLIST_H */ diff --git a/arch/sh/include/asm/sizes.h b/arch/sh/include/asm/sizes.h deleted file mode 100644 index dd248c2..0000000 --- a/arch/sh/include/asm/sizes.h +++ /dev/null @@ -1 +0,0 @@ -#include -- cgit v0.10.2 From f2d5d9b90b095ab0e8097b2b0793f4a56ed98147 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 18 May 2012 15:37:53 -0700 Subject: tcm_qla2xxx: Clear session s_id + loop_id earlier during shutdown This patch adds a new tcm_qla2xxx_clear_sess_lookup() call to clear session specific s_id + loop_id entries used for se_node_acl pointer lookup ahead of releasing se_session within the process context workqueue callback in tcm_qla2xxx_free_session(). It makes the call in existing tcm_qla2xxx_clear_nacl_from_fcport_map() code invoked from qlt_unreg_sess() in interrupt context w/ hardware_lock held, ahead of the process context callback into qlt_free_session_done() -> tcm_qla2xxx_free_session(). We are doing this to address a race between incoming ATIO or TMR packets using stale se_node_acl pointer once session shutdown has been invoked via qlt_unreg_sess() in qla_target.c LLD code, and when the entire tcm_qla2xxx endpoint has not been forced into shutdown w/ echo 0 > ../$QLA2XXX_PORT/enable Cc: Joern Engel Cc: Roland Dreier Cc: Arun Easi Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 3cee5b6..a641c97 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -821,6 +821,8 @@ static int tcm_qla2xxx_setup_nacl_from_rport( return 0; } +static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, + struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *); /* * Expected to be called with struct qla_hw_data->hardware_lock held */ @@ -842,6 +844,16 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) pr_debug("Removed from fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%06x\n", se_nacl, nacl->nport_wwnn, nacl->nport_id); + /* + * Now clear the se_nacl and session pointers from our HW lport lookup + * table mapping for this initiator's fabric S_ID and LOOP_ID entries. + * + * This is done ahead of callbacks into tcm_qla2xxx_free_session() -> + * target_wait_for_sess_cmds() before the session waits for outstanding + * I/O to complete, to avoid a race between session shutdown execution + * and incoming ATIOs or TMRs picking up a stale se_node_act reference. + */ + tcm_qla2xxx_clear_sess_lookup(lport, nacl, sess); } static void tcm_qla2xxx_release_session(struct kref *kref) @@ -1409,6 +1421,25 @@ static void tcm_qla2xxx_set_sess_by_loop_id( nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname); } +/* + * Should always be called with qla_hw_data->hardware_lock held. + */ +static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport, + struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess) +{ + struct se_session *se_sess = sess->se_sess; + unsigned char be_sid[3]; + + be_sid[0] = sess->s_id.b.domain; + be_sid[1] = sess->s_id.b.area; + be_sid[2] = sess->s_id.b.al_pa; + + tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess, + sess, be_sid); + tcm_qla2xxx_set_sess_by_loop_id(lport, NULL, nacl, se_sess, + sess, sess->loop_id); +} + static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) { struct qla_tgt *tgt = sess->tgt; @@ -1417,8 +1448,6 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) struct se_node_acl *se_nacl; struct tcm_qla2xxx_lport *lport; struct tcm_qla2xxx_nacl *nacl; - unsigned char be_sid[3]; - unsigned long flags; BUG_ON(in_interrupt()); @@ -1438,21 +1467,6 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) return; } target_wait_for_sess_cmds(se_sess, 0); - /* - * And now clear the se_nacl and session pointers from our HW lport - * mappings for fabric S_ID and LOOP_ID. - */ - memset(&be_sid, 0, 3); - be_sid[0] = sess->s_id.b.domain; - be_sid[1] = sess->s_id.b.area; - be_sid[2] = sess->s_id.b.al_pa; - - spin_lock_irqsave(&ha->hardware_lock, flags); - tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess, - sess, be_sid); - tcm_qla2xxx_set_sess_by_loop_id(lport, NULL, nacl, se_sess, - sess, sess->loop_id); - spin_unlock_irqrestore(&ha->hardware_lock, flags); transport_deregister_session_configfs(sess->se_sess); transport_deregister_session(sess->se_sess); -- cgit v0.10.2 From 59e4f541baf728dbb426949bfa9f6862387ffd0e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 4 Jun 2012 23:24:51 -0700 Subject: target: Return error to initiator if SET TARGET PORT GROUPS emulation fails The error paths in target_emulate_set_target_port_groups() are all essentially "rc = -EINVAL; goto out;" but the code at "out:" ignores rc and always returns success. This means that even if eg explicit ALUA is turned off, the initiator will always see a good SCSI status for SET TARGET PORT GROUPS. Fix this by returning rc as is intended. It appears this bug was added by the following patch: commit 05d1c7c0d0db4cc25548d9aadebb416888a82327 Author: Andy Grover Date: Wed Jul 20 19:13:28 2011 +0000 target: Make all control CDBs scatter-gather Signed-off-by: Roland Dreier Cc: Andy Grover Cc: Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index e624b83..9179997 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -374,8 +374,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) out: transport_kunmap_data_sg(cmd); - target_complete_cmd(cmd, GOOD); - return 0; + if (!rc) + target_complete_cmd(cmd, GOOD); + return rc; } static inline int core_alua_state_nonoptimized( -- cgit v0.10.2 From 3578ddba1ae93263d373e7bc85fd38d1f0368b78 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 4 Jun 2012 23:37:34 -0700 Subject: tcm_qla2xxx: Don't insert nacls without sessions into the btree When we create an explicit node ACL in tcm_qla2xxx_make_nodeacl(), there is a call to tcm_qla2xxx_setup_nacl_from_rport(), which puts the node ACL into the lport_fcport_map even though there is no session yet for the initiator. Since the only time we remove entries from this map is when we free a session, this means that if we later delete this node ACL without the initiator ever creating a session, we'll leave the nacl pointer in the btree pointing at freed memory. This is especially bad if that initiator later does send us a command that would cause us to create a dynamic ACL and session: we'll find the stale freed nacl pointer in the btree and end up with use-after-free. We could add more code to clear the btree entry when deleting the explicit nacl, but the original insertion is pointless: without a session attached, we'll just have to update the entry when a session appears anyway. So we can just delete tcm_qla2xxx_setup_nacl_from_rport() and the code that calls it. Signed-off-by: Roland Dreier Cc: Chad Dupuis Cc: Giridhar Malavali Cc: Arun Easi Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index a641c97..acc3b11 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -762,65 +762,6 @@ static u16 tcm_qla2xxx_set_fabric_sense_len(struct se_cmd *se_cmd, struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs; struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs; -static int tcm_qla2xxx_setup_nacl_from_rport( - struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct tcm_qla2xxx_lport *lport, - struct tcm_qla2xxx_nacl *nacl, - u64 rport_wwnn) -{ - struct scsi_qla_host *vha = lport->qla_vha; - struct Scsi_Host *sh = vha->host; - struct fc_host_attrs *fc_host = shost_to_fc_host(sh); - struct fc_rport *rport; - unsigned long flags; - void *node; - int rc; - - /* - * Scan the existing rports, and create a session for the - * explict NodeACL is an matching rport->node_name already - * exists. - */ - spin_lock_irqsave(sh->host_lock, flags); - list_for_each_entry(rport, &fc_host->rports, peers) { - if (rport_wwnn != rport->node_name) - continue; - - pr_debug("Located existing rport_wwpn and rport->node_name: 0x%016LX, port_id: 0x%04x\n", - rport->node_name, rport->port_id); - nacl->nport_id = rport->port_id; - - spin_unlock_irqrestore(sh->host_lock, flags); - - spin_lock_irqsave(&vha->hw->hardware_lock, flags); - node = btree_lookup32(&lport->lport_fcport_map, rport->port_id); - if (node) { - rc = btree_update32(&lport->lport_fcport_map, - rport->port_id, se_nacl); - } else { - rc = btree_insert32(&lport->lport_fcport_map, - rport->port_id, se_nacl, - GFP_ATOMIC); - } - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); - - if (rc) { - pr_err("Unable to insert se_nacl into fcport_map"); - WARN_ON(rc > 0); - return rc; - } - - pr_debug("Inserted into fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%08x\n", - se_nacl, rport_wwnn, nacl->nport_id); - - return 1; - } - spin_unlock_irqrestore(sh->host_lock, flags); - - return 0; -} - static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *); /* @@ -890,14 +831,10 @@ static struct se_node_acl *tcm_qla2xxx_make_nodeacl( struct config_group *group, const char *name) { - struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; - struct tcm_qla2xxx_lport *lport = container_of(se_wwn, - struct tcm_qla2xxx_lport, lport_wwn); struct se_node_acl *se_nacl, *se_nacl_new; struct tcm_qla2xxx_nacl *nacl; u64 wwnn; u32 qla2xxx_nexus_depth; - int rc; if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) return ERR_PTR(-EINVAL); @@ -924,16 +861,6 @@ static struct se_node_acl *tcm_qla2xxx_make_nodeacl( nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); nacl->nport_wwnn = wwnn; tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); - /* - * Setup a se_nacl handle based on an a matching struct fc_rport setup - * via drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() - */ - rc = tcm_qla2xxx_setup_nacl_from_rport(se_tpg, se_nacl, lport, - nacl, wwnn); - if (rc < 0) { - tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new); - return ERR_PTR(rc); - } return se_nacl; } -- cgit v0.10.2 From 092e1dc3f227ebef9ad45c26ef05c283ca4495a5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 11 Jun 2012 18:23:15 -0700 Subject: qla2xxx: Don't crash if we can't find cmd for failed CTIO In qlt_do_ctio_completion(), there's no point in calling qlt_term_ctio_exchange() with a NULL cmd -- all that it does is crash in a NULL pointer dereference, since it does qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); and dereferencing &cmd->atio is a bad idea if cmd itself is NULL. If we really need to do this, we could take the values from the failed CTIO we're processing, but it's not clear if it's worth the replumbing to do that. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 04f80eb..c263f90 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2477,11 +2477,9 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, } cmd = qlt_ctio_to_cmd(vha, handle, ctio); - if (cmd == NULL) { - if (status != CTIO_SUCCESS) - qlt_term_ctio_exchange(vha, ctio, NULL, status); + if (cmd == NULL) return; - } + se_cmd = &cmd->se_cmd; tfo = se_cmd->se_tfo; -- cgit v0.10.2 From fae9eaf81323eda64f28b9f4f4aeffb807e5b5f4 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 11 Jun 2012 18:23:16 -0700 Subject: qla2xxx: Don't leak commands we give up on in qlt_do_work() If we go to the "out_term:" exit path in qlt_do_work(), we call qlt_send_term_exchange() with a NULL cmd, which means that it can't possibly free the cmd for us. Add an explicit call to free the command memory, so we don't leak the allocation. This will also fix warnings about "BUG qla_tgt_cmd_cachep: Objects remaining on kmem_cache_close" from slub when unloading the qla2xxx target module. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index c263f90..e912920 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2725,10 +2725,12 @@ static void qlt_do_work(struct work_struct *work) out_term: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf020, "Terminating work cmd %p", cmd); /* - * cmd has not sent to target yet, so pass NULL as the second argument + * cmd has not sent to target yet, so pass NULL as the second + * argument to qlt_send_term_exchange() and free the memory here. */ spin_lock_irqsave(&ha->hardware_lock, flags); qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); + kmem_cache_free(qla_tgt_cmd_cachep, cmd); spin_unlock_irqrestore(&ha->hardware_lock, flags); if (sess) ha->tgt.tgt_ops->put_sess(sess); -- cgit v0.10.2 From 9389c3c943da7e5f903eebf79d596601537afe01 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 11 Jun 2012 18:31:30 -0700 Subject: tcm_qla2xxx: tcm_qla2xxx_handle_tmr() can be static Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index acc3b11..2f12c09 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -652,8 +652,8 @@ static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd) /* * Called from qla_target.c:qlt_issue_task_mgmt() */ -int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, uint32_t lun, - uint8_t tmr_func, uint32_t tag) +static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, uint32_t lun, + uint8_t tmr_func, uint32_t tag) { struct qla_tgt_sess *sess = mcmd->sess; struct se_cmd *se_cmd = &mcmd->se_cmd; -- cgit v0.10.2 From d4f75b567bb63b51e5ecd42af1e82d5aed5100dd Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 11 Jun 2012 18:31:31 -0700 Subject: tcm_qla2xxx: Handle malformed wwn strings properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we make a variable an unsigned int and then expect it to be < 0 on a bad character, we're going to have a bad time. Fix the tcm_qla2xxx code to actually notice if hex_to_bin() returns a negative variable. This was detected by the compiler warning: scsi/qla2xxx/tcm_qla2xxx.c: In function ‘tcm_qla2xxx_npiv_extract_wwn’: scsi/qla2xxx/tcm_qla2xxx.c:148:3: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 2f12c09..6e64314 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -137,13 +137,15 @@ static char *tcm_qla2xxx_get_fabric_name(void) */ static int tcm_qla2xxx_npiv_extract_wwn(const char *ns, u64 *nm) { - unsigned int i, j, value; + unsigned int i, j; u8 wwn[8]; memset(wwn, 0, sizeof(wwn)); /* Validate and store the new name */ for (i = 0, j = 0; i < 16; i++) { + int value; + value = hex_to_bin(*ns++); if (value >= 0) j = (j << 4) | value; -- cgit v0.10.2 From 5134de2815ac723ecfba4a1c7b2a90fa4d8dcfd9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 3 Jun 2012 22:27:01 +0530 Subject: qla2xxx: Remove version.h header file inclusion version.h header file is no longer required for qla_target code. Signed-off-by: Sachin Kamat Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index e912920..6986552 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 9ec19bc..9f9ef16 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -919,7 +919,6 @@ struct qla_tgt_srr_ctio { #define QLA_TGT_XMIT_STATUS 2 #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) -#include extern struct qla_tgt_data qla_target; /* -- cgit v0.10.2 From fdb1117325ad719dc39e81209bc622d511db70e0 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 13 Jun 2012 14:04:58 +0200 Subject: ARM: dma-mapping: fix debug messages in dmabounce code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the usage of uninitialized variables in dmabounce code intoduced by commit a227fb92 ('ARM: dma-mapping: remove offset parameter to prepare for generic dma_ops'): arch/arm/common/dmabounce.c: In function ‘dmabounce_sync_for_device’: arch/arm/common/dmabounce.c:409: warning: ‘off’ may be used uninitialized in this function arch/arm/common/dmabounce.c:407: note: ‘off’ was declared here arch/arm/common/dmabounce.c: In function ‘dmabounce_sync_for_cpu’: arch/arm/common/dmabounce.c:369: warning: ‘off’ may be used uninitialized in this function arch/arm/common/dmabounce.c:367: note: ‘off’ was declared here Signed-off-by: Marek Szyprowski diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 9d7eb53..aa07f59 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -366,8 +366,8 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, struct safe_buffer *buf; unsigned long off; - dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n", - __func__, addr, off, sz, dir); + dev_dbg(dev, "%s(dma=%#x,sz=%zx,dir=%x)\n", + __func__, addr, sz, dir); buf = find_safe_buffer_dev(dev, addr, __func__); if (!buf) @@ -377,8 +377,8 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, BUG_ON(buf->direction != dir); - dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n", - __func__, buf->ptr, virt_to_dma(dev, buf->ptr), + dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n", + __func__, buf->ptr, virt_to_dma(dev, buf->ptr), off, buf->safe, buf->safe_dma_addr); DO_STATS(dev->archdata.dmabounce->bounce_count++); @@ -406,8 +406,8 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr, struct safe_buffer *buf; unsigned long off; - dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n", - __func__, addr, off, sz, dir); + dev_dbg(dev, "%s(dma=%#x,sz=%zx,dir=%x)\n", + __func__, addr, sz, dir); buf = find_safe_buffer_dev(dev, addr, __func__); if (!buf) @@ -417,8 +417,8 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr, BUG_ON(buf->direction != dir); - dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n", - __func__, buf->ptr, virt_to_dma(dev, buf->ptr), + dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n", + __func__, buf->ptr, virt_to_dma(dev, buf->ptr), off, buf->safe, buf->safe_dma_addr); DO_STATS(dev->archdata.dmabounce->bounce_count++); -- cgit v0.10.2 From 161270fc1f9ddfc17154e0d49291472a9cdef7db Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 6 Jun 2012 17:31:26 +0200 Subject: x86/smp: Fix topology checks on AMD MCM CPUs The warning below triggers on AMD MCM packages because physical package IDs on the cores of a _physical_ socket are the same. I.e., this field says which CPUs belong to the same physical package. However, the same two CPUs belong to two different internal, i.e. "logical" nodes in the same physical socket which is reflected in the CPU-to-node map on x86 with NUMA. Which makes this check wrong on the above topologies so circumvent it. [ 0.444413] Booting Node 0, Processors #1 #2 #3 #4 #5 Ok. [ 0.461388] ------------[ cut here ]------------ [ 0.465997] WARNING: at arch/x86/kernel/smpboot.c:310 topology_sane.clone.1+0x6e/0x81() [ 0.473960] Hardware name: Dinar [ 0.477170] sched: CPU #6's mc-sibling CPU #0 is not on the same node! [node: 1 != 0]. Ignoring dependency. [ 0.486860] Booting Node 1, Processors #6 [ 0.491104] Modules linked in: [ 0.494141] Pid: 0, comm: swapper/6 Not tainted 3.4.0+ #1 [ 0.499510] Call Trace: [ 0.501946] [] ? topology_sane.clone.1+0x6e/0x81 [ 0.508185] [] warn_slowpath_common+0x85/0x9d [ 0.514163] [] warn_slowpath_fmt+0x46/0x48 [ 0.519881] [] topology_sane.clone.1+0x6e/0x81 [ 0.525943] [] set_cpu_sibling_map+0x251/0x371 [ 0.532004] [] start_secondary+0x19a/0x218 [ 0.537729] ---[ end trace 4eaa2a86a8e2da22 ]--- [ 0.628197] #7 #8 #9 #10 #11 Ok. [ 0.807108] Booting Node 3, Processors #12 #13 #14 #15 #16 #17 Ok. [ 0.897587] Booting Node 2, Processors #18 #19 #20 #21 #22 #23 Ok. [ 0.917443] Brought up 24 CPUs We ran a topology sanity check test we have here on it and it all looks ok... hopefully :). Signed-off-by: Borislav Petkov Cc: Andreas Herrmann Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120529135442.GE29157@aftab.osrc.amd.com Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fd019d7..c3a6bac 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -349,9 +349,12 @@ static bool __cpuinit match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) { - if (c->phys_proc_id == o->phys_proc_id) - return topology_sane(c, o, "mc"); + if (c->phys_proc_id == o->phys_proc_id) { + if (cpu_has(c, X86_FEATURE_AMD_DCM)) + return true; + return topology_sane(c, o, "mc"); + } return false; } -- cgit v0.10.2 From 25f42985825dd93f0593efe454e54c2aa13f7830 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 11 Jun 2012 15:44:26 +0200 Subject: perf/x86: Fix broken LBR fixup code I noticed that the LBR fixups were not working anymore on programs where they used to. I tracked this down to a recent change to copy_from_user_nmi(): db0dc75d640 ("perf/x86: Check user address explicitly in copy_from_user_nmi()") This commit added a call to __range_not_ok() to the copy_from_user_nmi() routine. The problem is that the logic of the test must be reversed. __range_not_ok() returns 0 if the range is VALID. We want to return early from copy_from_user_nmi() if the range is NOT valid. Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra Acked-by: Arun Sharma Link: http://lkml.kernel.org/r/20120611134426.GA7542@quad Signed-off-by: Ingo Molnar diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index 677b1ed..4f74d94 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -22,7 +22,7 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) void *map; int ret; - if (__range_not_ok(from, n, TASK_SIZE) == 0) + if (__range_not_ok(from, n, TASK_SIZE)) return len; do { -- cgit v0.10.2 From 2e8b2b29d1f904353c3e54b342ccb8c66390dab8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Jun 2012 16:47:32 +0200 Subject: ALSA: hda - Don't forget to call init verbs added by fixup list During the split to the auto-parser helper functions, the actual call of init verbs was lost. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43366 Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 3acb582..172370b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -4061,7 +4061,7 @@ static void cx_auto_init_digital(struct hda_codec *codec) static int cx_auto_init(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; - /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ + snd_hda_gen_apply_verbs(codec); cx_auto_init_output(codec); cx_auto_init_input(codec); cx_auto_init_digital(codec); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b896681..f8f4906 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1896,6 +1896,7 @@ static int alc_init(struct hda_codec *codec) alc_fix_pll(codec); alc_auto_init_amp(codec, spec->init_amp); + snd_hda_gen_apply_verbs(codec); alc_init_special_input_src(codec); alc_auto_init_std(codec); -- cgit v0.10.2 From ecd57ae28eb34e2b34fac1c5b74bb876efa665c0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 11 Jun 2012 11:26:41 +0900 Subject: video: s3c-fb: clear SHADOWCON register when clearing hardware window registers All bits of SHADOWCON register should be cleared when clearing hardware window registers; however, some bits of SHADOWCON register are not cleared previously. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 5f9d8e690..b5c2939 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -1348,8 +1348,14 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) writel(0, regs + VIDOSD_A(win, sfb->variant)); writel(0, regs + VIDOSD_B(win, sfb->variant)); writel(0, regs + VIDOSD_C(win, sfb->variant)); - reg = readl(regs + SHADOWCON); - writel(reg & ~SHADOWCON_WINx_PROTECT(win), regs + SHADOWCON); + + if (sfb->variant.has_shadowcon) { + reg = readl(sfb->regs + SHADOWCON); + reg &= ~(SHADOWCON_WINx_PROTECT(win) | + SHADOWCON_CHx_ENABLE(win) | + SHADOWCON_CHx_LOCAL_ENABLE(win)); + writel(reg, sfb->regs + SHADOWCON); + } } static int __devinit s3c_fb_probe(struct platform_device *pdev) -- cgit v0.10.2 From b67989515defba7412acff01162e5bb1f0f5923a Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 11 Jun 2012 11:27:27 +0900 Subject: video: s3c-fb: fix possible division by zero in s3c_fb_calc_pixclk Divider value can be zero and it makes division by zero from debug message in s3c_fb_calc_pixclk; therefore, it should be fixed. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index b5c2939..ea7b661 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -361,7 +361,7 @@ static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) result = (unsigned int)tmp / 1000; dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", - pixclk, clk, result, clk / result); + pixclk, clk, result, result ? clk / result : clk); return result; } -- cgit v0.10.2 From 954fba0274058d27c7c07b5ea07c41b3b7477894 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Jun 2012 19:30:21 +0000 Subject: netpoll: fix netpoll_send_udp() bugs Bogdan Hamciuc diagnosed and fixed following bug in netpoll_send_udp() : "skb->len += len;" instead of "skb_put(skb, len);" Meaning that _if_ a network driver needs to call skb_realloc_headroom(), only packet headers would be copied, leaving garbage in the payload. However the skb_realloc_headroom() must be avoided as much as possible since it requires memory and netpoll tries hard to work even if memory is exhausted (using a pool of preallocated skbs) It appears netpoll_send_udp() reserved 16 bytes for the ethernet header, which happens to work for typicall drivers but not all. Right thing is to use LL_RESERVED_SPACE(dev) (And also add dev->needed_tailroom of tailroom) This patch combines both fixes. Many thanks to Bogdan for raising this issue. Reported-by: Bogdan Hamciuc Signed-off-by: Eric Dumazet Tested-by: Bogdan Hamciuc Cc: Herbert Xu Cc: Neil Horman Reviewed-by: Neil Horman Reviewed-by: Cong Wang Signed-off-by: David S. Miller diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 3d84fb9..f9f40b9 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -362,22 +362,23 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev); void netpoll_send_udp(struct netpoll *np, const char *msg, int len) { - int total_len, eth_len, ip_len, udp_len; + int total_len, ip_len, udp_len; struct sk_buff *skb; struct udphdr *udph; struct iphdr *iph; struct ethhdr *eth; udp_len = len + sizeof(*udph); - ip_len = eth_len = udp_len + sizeof(*iph); - total_len = eth_len + ETH_HLEN + NET_IP_ALIGN; + ip_len = udp_len + sizeof(*iph); + total_len = ip_len + LL_RESERVED_SPACE(np->dev); - skb = find_skb(np, total_len, total_len - len); + skb = find_skb(np, total_len + np->dev->needed_tailroom, + total_len - len); if (!skb) return; skb_copy_to_linear_data(skb, msg, len); - skb->len += len; + skb_put(skb, len); skb_push(skb, sizeof(*udph)); skb_reset_transport_header(skb); -- cgit v0.10.2 From d6cb3e41386f20fb0777d0b59a2def82c65d37f7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Jun 2012 23:50:04 +0000 Subject: bnx2x: fix checksum validation bnx2x driver incorrectly sets ip_summed to CHECKSUM_UNNECESSARY on encapsulated segments. TCP stack happily accepts frames with bad checksums, if they are inside a GRE or IPIP encapsulation. Our understanding is that if no IP or L4 csum validation was done by the hardware, we should leave ip_summed as is (CHECKSUM_NONE), since hardware doesn't provide CHECKSUM_COMPLETE support in its cqe. Then, if IP/L4 checksumming was done by the hardware, set CHECKSUM_UNNECESSARY if no error was flagged. Patch based on findings and analysis from Robert Evans Signed-off-by: Eric Dumazet Cc: Eilon Greenstein Cc: Yaniv Rosner Cc: Merav Sicron Cc: Tom Herbert Cc: Robert Evans Cc: Willem de Bruijn Acked-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index e30e2a2..7de8241 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -747,21 +747,6 @@ struct bnx2x_fastpath { #define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG -#define BNX2X_IP_CSUM_ERR(cqe) \ - (!((cqe)->fast_path_cqe.status_flags & \ - ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \ - ((cqe)->fast_path_cqe.type_error_flags & \ - ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG)) - -#define BNX2X_L4_CSUM_ERR(cqe) \ - (!((cqe)->fast_path_cqe.status_flags & \ - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \ - ((cqe)->fast_path_cqe.type_error_flags & \ - ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) - -#define BNX2X_RX_CSUM_OK(cqe) \ - (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe))) - #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \ (((le16_to_cpu(flags) & \ PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ad0743b..cbc56f2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -617,6 +617,25 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp, return 0; } +static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, + struct bnx2x_fastpath *fp) +{ + /* Do nothing if no IP/L4 csum validation was done */ + + if (cqe->fast_path_cqe.status_flags & + (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) + return; + + /* If both IP/L4 validation were done, check if an error was found. */ + + if (cqe->fast_path_cqe.type_error_flags & + (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | + ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) + fp->eth_q_stats.hw_csum_err++; + else + skb->ip_summed = CHECKSUM_UNNECESSARY; +} int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) { @@ -806,13 +825,9 @@ reuse_rx: skb_checksum_none_assert(skb); - if (bp->dev->features & NETIF_F_RXCSUM) { + if (bp->dev->features & NETIF_F_RXCSUM) + bnx2x_csum_validate(skb, cqe, fp); - if (likely(BNX2X_RX_CSUM_OK(cqe))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - fp->eth_q_stats.hw_csum_err++; - } skb_record_rx_queue(skb, fp->rx_queue); -- cgit v0.10.2 From afff07e61a5243e14ee3f0a272a0380cd744a8a3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 13 Jun 2012 11:44:58 +0200 Subject: usb-storage: Add 090c:1000 to unusal-devs This device gives a bogus answer to get_capacity(16): [ 8628.278614] scsi 8:0:0:0: Direct-Access USB 2.0 USB Flash Drive 1100 PQ: 0 ANSI: 4 [ 8628.279452] sd 8:0:0:0: Attached scsi generic sg4 type 0 [ 8628.280338] sd 8:0:0:0: [sdd] 35747322042253313 512-byte logical blocks: (18.3 EB/15.8 EiB) So set the quirk flag to avoid using get_capacity(16) with it: [11731.386014] usb-storage 2-1.6:1.0: Quirks match for vid 090c pid 1000: 80000 [11731.386075] scsi9 : usb-storage 2-1.6:1.0 [11731.386172] usbcore: registered new interface driver usb-storage [11731.386175] USB Mass Storage support registered. [11732.387394] scsi 9:0:0:0: Direct-Access USB 2.0 USB Flash Drive 1100 PQ: 0 ANSI: 4 [11732.388462] sd 9:0:0:0: Attached scsi generic sg3 type 0 [11732.389432] sd 9:0:0:0: [sdc] 7975296 512-byte logical blocks: (4.08 GB/3.80 GiB) Which makes the capacity look a lot more sane :) Signed-off-by: Hans de Goede Tested-by: Simon Raffeiner Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1719886..caf22bf 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1107,6 +1107,13 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, USB_SC_RBC, USB_PR_BULK, NULL, 0 ), +/* Feiya QDI U2 DISK, reported by Hans de Goede */ +UNUSUAL_DEV( 0x090c, 0x1000, 0x0000, 0xffff, + "Feiya", + "QDI U2 DISK", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_READ_CAPACITY_16 ), + /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", -- cgit v0.10.2 From 55558c33d6d46cb6f426b729f4119e3b2f12f02b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 22 May 2012 20:54:34 +0300 Subject: USB: Checking the wrong variable in usb_disable_lpm() We check "u1_params" instead of checking "u2_params". Signed-off-by: Dan Carpenter Signed-off-by: Sarah Sharp diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 04fb834..25a7422 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3379,7 +3379,7 @@ int usb_disable_lpm(struct usb_device *udev) return 0; udev->lpm_disable_count++; - if ((udev->u1_params.timeout == 0 && udev->u1_params.timeout == 0)) + if ((udev->u1_params.timeout == 0 && udev->u2_params.timeout == 0)) return 0; /* If LPM is enabled, attempt to disable it. */ -- cgit v0.10.2 From e25e62aecac42379e113c63a674a86ae3ebbec8d Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 7 Jun 2012 11:10:32 -0700 Subject: xhci: Fix error path return value. This patch fixes an issue discovered by Dan Carpenter: The patch 3b3db026414b: "xhci: Add infrastructure for host-specific LPM policies." from May 9, 2012, leads to the following warning: drivers/usb/host/xhci.c:3909 xhci_get_timeout_no_hub_lpm() warn: signedness bug returning '-22' 3906 default: 3907 dev_warn(&udev->dev, "%s: Can't get timeout for non-U1 or U2 state.\n", 3908 __func__); 3909 return -EINVAL; ^^^^^^^^^^^^^^ This should be a u16 like USB3_LPM_DISABLED or something. 3910 } 3911 3912 if (sel <= max_sel_pel && pel <= max_sel_pel) 3913 return USB3_LPM_DEVICE_INITIATED; Signed-off-by: Sarah Sharp Reported-by: Dan Carpenter diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index afdc73e..1d4958f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3906,7 +3906,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, default: dev_warn(&udev->dev, "%s: Can't get timeout for non-U1 or U2 state.\n", __func__); - return -EINVAL; + return USB3_LPM_DISABLED; } if (sel <= max_sel_pel && pel <= max_sel_pel) -- cgit v0.10.2 From 46ed8f00d8982e49f8fe2c1a9cea192f640cb3ba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 1 Jun 2012 10:06:23 +0200 Subject: xhci: Fix invalid loop check in xhci_free_tt_info() xhci_free_tt_info() may access the invalid memory when it removes the last entry but the list is not empty. Then tt_next reaches to the list head but it still tries to check the tt_info of that entry. This patch fixes the bug and cleans up the messy code by rewriting with a simple list_for_each_entry_safe(). This patch should be backported to kernels as old as 3.2, that contain the commit 839c817ce67178ca3c7c7ad534c571bba1e69ebe "xhci: Store information about roothubs and TTs." Signed-off-by: Takashi Iwai Signed-off-by: Sarah Sharp Reviewed-by: Oliver Neukum Cc: diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index ec4338e..898dfc8 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -793,10 +793,9 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, int slot_id) { - struct list_head *tt; struct list_head *tt_list_head; - struct list_head *tt_next; - struct xhci_tt_bw_info *tt_info; + struct xhci_tt_bw_info *tt_info, *next; + bool slot_found = false; /* If the device never made it past the Set Address stage, * it may not have the real_port set correctly. @@ -808,34 +807,16 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, } tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts); - if (list_empty(tt_list_head)) - return; - - list_for_each(tt, tt_list_head) { - tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); - if (tt_info->slot_id == slot_id) + list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) { + /* Multi-TT hubs will have more than one entry */ + if (tt_info->slot_id == slot_id) { + slot_found = true; + list_del(&tt_info->tt_list); + kfree(tt_info); + } else if (slot_found) { break; + } } - /* Cautionary measure in case the hub was disconnected before we - * stored the TT information. - */ - if (tt_info->slot_id != slot_id) - return; - - tt_next = tt->next; - tt_info = list_entry(tt, struct xhci_tt_bw_info, - tt_list); - /* Multi-TT hubs will have more than one entry */ - do { - list_del(tt); - kfree(tt_info); - tt = tt_next; - if (list_empty(tt_list_head)) - break; - tt_next = tt->next; - tt_info = list_entry(tt, struct xhci_tt_bw_info, - tt_list); - } while (tt_info->slot_id == slot_id); } int xhci_alloc_tt_info(struct xhci_hcd *xhci, -- cgit v0.10.2 From 32f1d2c536d0c26c5814cb0e6a0606c42d02fac1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 1 Jun 2012 10:06:24 +0200 Subject: xhci: Don't free endpoints in xhci_mem_cleanup() This patch fixes a few issues introduced in the recent fix [f8a9e72d: USB: fix resource leak in xhci power loss path] - The endpoints listed in bw table are just links and each entry is an array member of dev->eps[]. But the commit above adds a kfree() call to these instances, and thus it results in memory corruption. - It clears only the first entry of rh_bw[], but there can be multiple ports. - It'd be safer to clear the list_head of ep as well, not only removing from the list, as it's checked in xhci_discover_or_reset_device(). This patch should be backported to kernels as old as 3.2, that contain the commit 839c817ce67178ca3c7c7ad534c571bba1e69ebe "xhci: Store information about roothubs and TTs." Signed-off-by: Takashi Iwai Signed-off-by: Sarah Sharp Reviewed-by: Oliver Neukum Cc: diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 898dfc8..77689bd 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1772,17 +1772,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; - struct list_head *tt_list_head; - struct list_head *tt; - struct list_head *endpoints; - struct list_head *ep, *q; - struct xhci_tt_bw_info *tt_info; - struct xhci_interval_bw_table *bwt; - struct xhci_virt_ep *virt_ep; - unsigned long flags; int size; - int i; + int i, j, num_ports; /* Free the Event Ring Segment Table and the actual Event Ring */ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); @@ -1841,21 +1833,22 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } spin_unlock_irqrestore(&xhci->lock, flags); - bwt = &xhci->rh_bw->bw_table; - for (i = 0; i < XHCI_MAX_INTERVAL; i++) { - endpoints = &bwt->interval_bw[i].endpoints; - list_for_each_safe(ep, q, endpoints) { - virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); - list_del(&virt_ep->bw_endpoint_list); - kfree(virt_ep); + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); + for (i = 0; i < num_ports; i++) { + struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; + for (j = 0; j < XHCI_MAX_INTERVAL; j++) { + struct list_head *ep = &bwt->interval_bw[j].endpoints; + while (!list_empty(ep)) + list_del_init(ep->next); } } - tt_list_head = &xhci->rh_bw->tts; - list_for_each_safe(tt, q, tt_list_head) { - tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); - list_del(tt); - kfree(tt_info); + for (i = 0; i < num_ports; i++) { + struct xhci_tt_bw_info *tt, *n; + list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) { + list_del(&tt->tt_list); + kfree(tt); + } } xhci->num_usb2_ports = 0; -- cgit v0.10.2 From 622eb783fe6ff4c1baa47db16c3a5db97f9e6e50 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Wed, 13 Jun 2012 10:51:57 +0800 Subject: xHCI: Increase the timeout for controller save/restore state operation When system software decides to power down the xHC with the intent of resuming operation at a later time, it will ask xHC to save the internal state and restore it when resume to correctly recover from a power event. Two bits are used to enable this operation: Save State and Restore State. xHCI spec 4.23.2 says software should "Set the Controller Save/Restore State flag in the USBCMD register and wait for the Save/Restore State Status flag in the USBSTS register to transition to '0'". However, it does not define how long software should wait for the SSS/RSS bit to transition to 0. Currently the timeout is set to 1ms. There is bug report (https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1002697) indicates that the timeout is too short for ASMedia ASM1042 host controller to save/restore the state successfully. Increase the timeout to 10ms helps to resolve the issue. This patch should be backported to stable kernels as old as 2.6.37, that contain the commit 5535b1d5f8885695c6ded783c692e3c0d0eda8ca "USB: xHCI: PCI power management implementation" Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Cc: Ming Lei Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1d4958f..a979cd0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -795,8 +795,8 @@ int xhci_suspend(struct xhci_hcd *xhci) command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_CSS; xhci_writel(xhci, command, &xhci->op_regs->command); - if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) { - xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n"); + if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { + xhci_warn(xhci, "WARN: xHC save state timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } @@ -848,8 +848,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) command |= CMD_CRS; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_RESTORE, 0, 10*100)) { - xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n"); + STS_RESTORE, 0, 10 * 1000)) { + xhci_warn(xhci, "WARN: xHC restore state timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } -- cgit v0.10.2 From 4f7a67e2dd49fbfba002c453bc24bf00e701cc71 Mon Sep 17 00:00:00 2001 From: Ricardo Martins Date: Tue, 22 May 2012 18:02:03 +0100 Subject: USB: fix PS3 EHCI systems After commit aaa0ef289afe9186f81e2340114ea413eef0492a "PS3 EHCI QH read work-around", Terratec Grabby (em28xx) stopped working with AMD Geode LX 800 (USB controller AMD CS5536). Since this is a PS3 only fix, the following patch adds a conditional block around it. Signed-off-by: Ricardo Martins Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b100f5f..800be38 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -671,7 +671,9 @@ static int ehci_init(struct usb_hcd *hcd) hw = ehci->async->hw; hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); +#if defined(CONFIG_PPC_PS3) hw->hw_info1 |= cpu_to_hc32(ehci, (1 << 7)); /* I = 1 */ +#endif hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); hw->hw_qtd_next = EHCI_LIST_END(ehci); ehci->async->qh_state = QH_STATE_LINKED; -- cgit v0.10.2 From 07828b10985393cd875eac1545fba47107e97bf9 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Tue, 22 May 2012 13:47:25 -0300 Subject: USB: EHCI: Fix build warning in xilinx ehci driver This fixes the following warning: In file included from drivers/usb/host/ehci-hcd.c:1246:0: drivers/usb/host/ehci-xilinx-of.c:293:2: warning: initialization from incompatible pointer type [enabled by default] drivers/usb/host/ehci-xilinx-of.c:293:2: warning: (near initialization for 'ehci_hcd_xilinx_of_driver.shutdown') [enabled by default] Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 9c2cc46..e9713d5 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -270,14 +270,12 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) * * Properly shutdown the hcd, call driver's shutdown routine. */ -static int ehci_hcd_xilinx_of_shutdown(struct platform_device *op) +static void ehci_hcd_xilinx_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); - - return 0; } -- cgit v0.10.2 From 0658a3366db7e27fa32c12e886230bb58c414c92 Mon Sep 17 00:00:00 2001 From: Jan Safrata Date: Tue, 22 May 2012 14:04:50 +0200 Subject: usb: use usb_serial_put in usb_serial_probe errors The use of kfree(serial) in error cases of usb_serial_probe was invalid - usb_serial structure allocated in create_serial() gets reference of usb_device that needs to be put, so we need to use usb_serial_put() instead of simple kfree(). Signed-off-by: Jan Safrata Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6e8c527..27483f9 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -757,7 +757,7 @@ static int usb_serial_probe(struct usb_interface *interface, if (retval) { dbg("sub driver rejected device"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return retval; } @@ -829,7 +829,7 @@ static int usb_serial_probe(struct usb_interface *interface, */ if (num_bulk_in == 0 || num_bulk_out == 0) { dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return -ENODEV; } @@ -843,7 +843,7 @@ static int usb_serial_probe(struct usb_interface *interface, if (num_ports == 0) { dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return -EIO; } -- cgit v0.10.2 From c4828d96900453f1ad506b1488928307711a8b28 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 11 Jun 2012 21:38:29 +0200 Subject: USB: ohci-hub: Mark ohci_finish_controller_resume() as __maybe_unused ohci_finish_controller_resume() is intended to be used in platform specific drivers ohci-*.c, included from ohci-hcd.c. Some of them don't actually use ohci_finish_controller_resume(), so mark it as __maybe_unused. Signed-off-by: Roland Stigge Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 836772d..2f3619e 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -317,7 +317,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) } /* Carry out the final steps of resuming the controller device */ -static void ohci_finish_controller_resume(struct usb_hcd *hcd) +static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int port; -- cgit v0.10.2 From 354ab8567ae3107a8cbe7228c3181990ba598aac Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Tue, 5 Jun 2012 15:34:27 +0300 Subject: Fix OMAP EHCI suspend/resume failure (i693) Its observed with some PHY, the 60Mhz clock gets cut too soon for OMAP EHCI, leaving OMAP-EHCI in a bad state. So on starting port suspend, make sure the 60Mhz clock to EHCI is kept alive using an internal clock, so that EHCi can cleanly transition its hw state machine on a port suspend. Its not proven if this is the issue hit on USB3333, but the symptoms look very similar. Signed-off-by: Anand Gadiyar Signed-off-by: Vikram Pandita Signed-off-by: Volodymyr Mieshkov Acked-by: Alan Stern Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index a44294d..17cfb8a 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -43,6 +43,7 @@ #include #include #include +#include /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) @@ -55,6 +56,15 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 +/* Errata i693 */ +static struct clk *utmi_p1_fck; +static struct clk *utmi_p2_fck; +static struct clk *xclk60mhsp1_ck; +static struct clk *xclk60mhsp2_ck; +static struct clk *usbhost_p1_fck; +static struct clk *usbhost_p2_fck; +static struct clk *init_60m_fclk; + /*-------------------------------------------------------------------------*/ static const struct hc_driver ehci_omap_hc_driver; @@ -70,6 +80,41 @@ static inline u32 ehci_read(void __iomem *base, u32 reg) return __raw_readl(base + reg); } +/* Erratum i693 workaround sequence */ +static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) +{ + int ret = 0; + + /* Switch to the internal 60 MHz clock */ + ret = clk_set_parent(utmi_p1_fck, init_60m_fclk); + if (ret != 0) + ehci_err(ehci, "init_60m_fclk set parent" + "failed error:%d\n", ret); + + ret = clk_set_parent(utmi_p2_fck, init_60m_fclk); + if (ret != 0) + ehci_err(ehci, "init_60m_fclk set parent" + "failed error:%d\n", ret); + + clk_enable(usbhost_p1_fck); + clk_enable(usbhost_p2_fck); + + /* Wait 1ms and switch back to the external clock */ + mdelay(1); + ret = clk_set_parent(utmi_p1_fck, xclk60mhsp1_ck); + if (ret != 0) + ehci_err(ehci, "xclk60mhsp1_ck set parent" + "failed error:%d\n", ret); + + ret = clk_set_parent(utmi_p2_fck, xclk60mhsp2_ck); + if (ret != 0) + ehci_err(ehci, "xclk60mhsp2_ck set parent" + "failed error:%d\n", ret); + + clk_disable(usbhost_p1_fck); + clk_disable(usbhost_p2_fck); +} + static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) { struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); @@ -100,6 +145,50 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) } } +static int omap_ehci_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; + u32 temp; + unsigned long flags; + int retval = 0; + + spin_lock_irqsave(&ehci->lock, flags); + + if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { + temp = ehci_readl(ehci, status_reg); + if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { + retval = -EPIPE; + goto done; + } + + temp &= ~PORT_WKCONN_E; + temp |= PORT_WKDISC_E | PORT_WKOC_E; + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); + + omap_ehci_erratum_i693(ehci); + + set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); + goto done; + } + + spin_unlock_irqrestore(&ehci->lock, flags); + + /* Handle the hub control events here */ + return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); +done: + spin_unlock_irqrestore(&ehci->lock, flags); + return retval; +} + static void disable_put_regulator( struct ehci_hcd_omap_platform_data *pdata) { @@ -264,8 +353,76 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) /* root ports should always stay powered */ ehci_port_power(omap_ehci, 1); + /* get clocks */ + utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); + if (IS_ERR(utmi_p1_fck)) { + ret = PTR_ERR(utmi_p1_fck); + dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); + goto err_add_hcd; + } + + xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); + if (IS_ERR(xclk60mhsp1_ck)) { + ret = PTR_ERR(xclk60mhsp1_ck); + dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); + goto err_utmi_p1_fck; + } + + utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); + if (IS_ERR(utmi_p2_fck)) { + ret = PTR_ERR(utmi_p2_fck); + dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); + goto err_xclk60mhsp1_ck; + } + + xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); + if (IS_ERR(xclk60mhsp2_ck)) { + ret = PTR_ERR(xclk60mhsp2_ck); + dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); + goto err_utmi_p2_fck; + } + + usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); + if (IS_ERR(usbhost_p1_fck)) { + ret = PTR_ERR(usbhost_p1_fck); + dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); + goto err_xclk60mhsp2_ck; + } + + usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); + if (IS_ERR(usbhost_p2_fck)) { + ret = PTR_ERR(usbhost_p2_fck); + dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); + goto err_usbhost_p1_fck; + } + + init_60m_fclk = clk_get(dev, "init_60m_fclk"); + if (IS_ERR(init_60m_fclk)) { + ret = PTR_ERR(init_60m_fclk); + dev_err(dev, "init_60m_fclk failed error:%d\n", ret); + goto err_usbhost_p2_fck; + } + return 0; +err_usbhost_p2_fck: + clk_put(usbhost_p2_fck); + +err_usbhost_p1_fck: + clk_put(usbhost_p1_fck); + +err_xclk60mhsp2_ck: + clk_put(xclk60mhsp2_ck); + +err_utmi_p2_fck: + clk_put(utmi_p2_fck); + +err_xclk60mhsp1_ck: + clk_put(xclk60mhsp1_ck); + +err_utmi_p1_fck: + clk_put(utmi_p1_fck); + err_add_hcd: disable_put_regulator(pdata); pm_runtime_put_sync(dev); @@ -294,6 +451,15 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) disable_put_regulator(dev->platform_data); iounmap(hcd->regs); usb_put_hcd(hcd); + + clk_put(utmi_p1_fck); + clk_put(utmi_p2_fck); + clk_put(xclk60mhsp1_ck); + clk_put(xclk60mhsp2_ck); + clk_put(usbhost_p1_fck); + clk_put(usbhost_p2_fck); + clk_put(init_60m_fclk); + pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -364,7 +530,7 @@ static const struct hc_driver ehci_omap_hc_driver = { * root hub support */ .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, + .hub_control = omap_ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, -- cgit v0.10.2 From a70270468234749741c5893ae78e5bb524771402 Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Wed, 13 Jun 2012 09:35:48 -0400 Subject: watchdog: Quiet down the boot messages A bunch of bugzillas have complained how noisy the nmi_watchdog is during boot-up especially with its expected failure cases (like virt and bios resource contention). This is my attempt to quiet them down and keep it less confusing for the end user. What I did is print the message for cpu0 and save it for future comparisons. If future cpus have an identical message as cpu0, then don't print the redundant info. However, if a future cpu has a different message, happily print that loudly. Before the change, you would see something like: ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 CPU0: Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz stepping 0a Performance Events: PEBS fmt0+, Core2 events, Intel PMU driver. ... version: 2 ... bit width: 40 ... generic registers: 2 ... value mask: 000000ffffffffff ... max period: 000000007fffffff ... fixed-purpose events: 3 ... event mask: 0000000700000003 NMI watchdog enabled, takes one hw-pmu counter. Booting Node 0, Processors #1 NMI watchdog enabled, takes one hw-pmu counter. #2 NMI watchdog enabled, takes one hw-pmu counter. #3 Ok. NMI watchdog enabled, takes one hw-pmu counter. Brought up 4 CPUs Total of 4 processors activated (22607.24 BogoMIPS). After the change, it is simplified to: ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 CPU0: Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz stepping 0a Performance Events: PEBS fmt0+, Core2 events, Intel PMU driver. ... version: 2 ... bit width: 40 ... generic registers: 2 ... value mask: 000000ffffffffff ... max period: 000000007fffffff ... fixed-purpose events: 3 ... event mask: 0000000700000003 NMI watchdog: enabled on all CPUs, permanently consumes one hw-PMU counter. Booting Node 0, Processors #1 #2 #3 Ok. Brought up 4 CPUs V2: little changes based on Joe Perches' feedback V3: printk cleanup based on Ingo's feedback; checkpatch fix V4: keep printk as one long line V5: Ingo fix ups Reported-and-tested-by: Nathan Zimmer Signed-off-by: Don Zickus Cc: nzimmer@sgi.com Cc: joe@perches.com Link: http://lkml.kernel.org/r/1339594548-17227-1-git-send-email-dzickus@redhat.com Signed-off-by: Ingo Molnar diff --git a/kernel/watchdog.c b/kernel/watchdog.c index e5e1d85..4b1dfba 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -372,6 +372,13 @@ static int watchdog(void *unused) #ifdef CONFIG_HARDLOCKUP_DETECTOR +/* + * People like the simple clean cpu node info on boot. + * Reduce the watchdog noise by only printing messages + * that are different from what cpu0 displayed. + */ +static unsigned long cpu0_err; + static int watchdog_nmi_enable(int cpu) { struct perf_event_attr *wd_attr; @@ -390,11 +397,21 @@ static int watchdog_nmi_enable(int cpu) /* Try to register using hardware perf events */ event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL); + + /* save cpu0 error for future comparision */ + if (cpu == 0 && IS_ERR(event)) + cpu0_err = PTR_ERR(event); + if (!IS_ERR(event)) { - pr_info("enabled, takes one hw-pmu counter.\n"); + /* only print for cpu0 or different than cpu0 */ + if (cpu == 0 || cpu0_err) + pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n"); goto out_save; } + /* skip displaying the same error again */ + if (cpu > 0 && (PTR_ERR(event) == cpu0_err)) + return PTR_ERR(event); /* vary the KERN level based on the returned errno */ if (PTR_ERR(event) == -EOPNOTSUPP) -- cgit v0.10.2 From c080e26edc3a2a3cdfa4c430c663ee1c3bbd8fae Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 14 Jun 2012 14:01:30 +0200 Subject: x86: dma-mapping: fix broken allocation when dma_mask has been provided Commit 0a2b9a6ea93 ("X86: integrate CMA with DMA-mapping subsystem") broke memory allocation with dma_mask. This patch fixes possible kernel ops caused by lack of resetting page variable when jumping to 'again' label. Reported-by: Konrad Rzeszutek Wilk Signed-off-by: Marek Szyprowski Acked-by: Michal Nazarewicz diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 62c9457..c0f420f 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -100,7 +100,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, struct dma_attrs *attrs) { unsigned long dma_mask; - struct page *page = NULL; + struct page *page; unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; dma_addr_t addr; @@ -108,6 +108,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, flag |= __GFP_ZERO; again: + page = NULL; if (!(flag & GFP_ATOMIC)) page = dma_alloc_from_contiguous(dev, count, get_order(size)); if (!page) -- cgit v0.10.2 From f617e2fd52484fb74236a597d0f9068ec7d9d2dd Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 14 Jun 2012 16:10:13 +0200 Subject: Btrfs: remove obsolete btrfs_next_leaf call from __resolve_indirect_ref When resolving indirect refs, we used to call btrfs_next_leaf in case we didn't find an exact match. While we should find exact matches most of the time, in case we don't, we must continue searching. Treating those matches differently depending on the level we're searching doesn't make sense. Even worse, we might end up searching for a key larger than the largest, in which case there is no next_leaf and subsequent jobs would fail. This commit drops the bogous lines. Signed-off-by: Jan Schmidt diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 3f75895..579131d 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -294,16 +294,8 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, goto out; } - if (level == 0) { - if (ret == 1 && path->slots[0] >= btrfs_header_nritems(eb)) { - ret = btrfs_next_leaf(root, path); - if (ret) - goto out; - eb = path->nodes[0]; - } - + if (level == 0) btrfs_item_key_to_cpu(eb, &key, path->slots[0]); - } ret = add_all_parents(root, path, parents, level, &key, ref->wanted_disk_byte, extent_item_pos); -- cgit v0.10.2 From 8ba97a15e7d4f70b9af71fa1db86a28dd17ad1b2 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 4 Jun 2012 16:54:57 +0200 Subject: Btrfs: use btrfs_read_lock_root_node in get_old_root get_old_root could race with root node updates because we weren't locking the node early enough. Use btrfs_read_lock_root_node to grab the root locked in the very beginning and release the lock as soon as possible (just like btrfs_search_slot does). Signed-off-by: Jan Schmidt diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 836e4e0..2cde7b0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1143,6 +1143,13 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, return eb_rewin; } +/* + * get_old_root() rewinds the state of @root's root node to the given @time_seq + * value. If there are no changes, the current root->root_node is returned. If + * anything changed in between, there's a fresh buffer allocated on which the + * rewind operations are done. In any case, the returned buffer is read locked. + * Returns NULL on error (with no locks held). + */ static inline struct extent_buffer * get_old_root(struct btrfs_root *root, u64 time_seq) { @@ -1151,6 +1158,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) struct tree_mod_root *old_root; u64 old_generation; + eb = btrfs_read_lock_root_node(root); tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); if (!tm) return root->node; @@ -1173,15 +1181,21 @@ get_old_root(struct btrfs_root *root, u64 time_seq) /* there's a root replace operation for the current root */ eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, root->nodesize); + } + btrfs_tree_read_unlock(root->node); + free_extent_buffer(root->node); + if (!eb) + return NULL; + btrfs_tree_read_lock(eb); + if (old_root->logical != root->node->start) { btrfs_set_header_bytenr(eb, eb->start); btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(eb, root->root_key.objectid); } - if (!eb) - return NULL; btrfs_set_header_level(eb, old_root->level); btrfs_set_header_generation(eb, old_generation); __tree_mod_log_rewind(eb, time_seq, tm); + extent_buffer_get(eb); return eb; } @@ -2612,9 +2626,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, again: b = get_old_root(root, time_seq); - extent_buffer_get(b); level = btrfs_header_level(b); - btrfs_tree_read_lock(b); p->locks[level] = BTRFS_READ_LOCK; while (b) { -- cgit v0.10.2 From a95236d99fa56766f11056903439f55fe5038bcf Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 5 Jun 2012 16:41:24 +0200 Subject: Btrfs: fix return value for __tree_mod_log_oldest_root In __tree_mod_log_oldest_root() we must return the found operation even if it's not a ROOT_REPLACE operation. Otherwise, the caller assumes that there are no operations to be rewinded and returns immediately. The code in the caller is modified to improve readability. Signed-off-by: Jan Schmidt diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 2cde7b0..50d7c99 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1023,6 +1023,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, looped = 1; } + /* if there's no old root to return, return what we found instead */ + if (!found) + found = tm; + return found; } @@ -1155,18 +1159,24 @@ get_old_root(struct btrfs_root *root, u64 time_seq) { struct tree_mod_elem *tm; struct extent_buffer *eb; - struct tree_mod_root *old_root; + struct tree_mod_root *old_root = NULL; u64 old_generation; + u64 logical; eb = btrfs_read_lock_root_node(root); tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); if (!tm) return root->node; - old_root = &tm->old_root; - old_generation = tm->generation; + if (tm->op == MOD_LOG_ROOT_REPLACE) { + old_root = &tm->old_root; + old_generation = tm->generation; + logical = old_root->logical; + } else { + logical = root->node->start; + } - tm = tree_mod_log_search(root->fs_info, old_root->logical, time_seq); + tm = tree_mod_log_search(root->fs_info, logical, time_seq); /* * there was an item in the log when __tree_mod_log_oldest_root * returned. this one must not go away, because the time_seq passed to @@ -1174,26 +1184,23 @@ get_old_root(struct btrfs_root *root, u64 time_seq) */ BUG_ON(!tm); - if (old_root->logical == root->node->start) { - /* there are logged operations for the current root */ - eb = btrfs_clone_extent_buffer(root->node); - } else { - /* there's a root replace operation for the current root */ + if (old_root) eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, root->nodesize); - } + else + eb = btrfs_clone_extent_buffer(root->node); btrfs_tree_read_unlock(root->node); free_extent_buffer(root->node); if (!eb) return NULL; btrfs_tree_read_lock(eb); - if (old_root->logical != root->node->start) { + if (old_root) { btrfs_set_header_bytenr(eb, eb->start); btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(eb, root->root_key.objectid); + btrfs_set_header_level(eb, old_root->level); + btrfs_set_header_generation(eb, old_generation); } - btrfs_set_header_level(eb, old_root->level); - btrfs_set_header_generation(eb, old_generation); __tree_mod_log_rewind(eb, time_seq, tm); extent_buffer_get(eb); -- cgit v0.10.2 From 3d7806eca43e73a9721d2e09369200ed93036bd0 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 11 Jun 2012 08:29:29 +0200 Subject: Btrfs: add btrfs_next_old_leaf To make sense of the tree mod log, the backref walker not only needs btrfs_search_old_slot, but it also called btrfs_next_leaf, which in turn was calling btrfs_search_slot. This obviously didn't give the correct result. This commit adds btrfs_next_old_leaf, a drop-in replacement for btrfs_next_leaf with a time_seq parameter. If it is zero, it behaves exactly like btrfs_next_leaf. If it is non-zero, it will use btrfs_search_old_slot with this time_seq parameter. Signed-off-by: Jan Schmidt diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 579131d..8f7d123 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -179,7 +179,8 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id, static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, struct ulist *parents, int level, - struct btrfs_key *key, u64 wanted_disk_byte, + struct btrfs_key *key, u64 time_seq, + u64 wanted_disk_byte, const u64 *extent_item_pos) { int ret; @@ -212,7 +213,7 @@ add_parent: */ while (1) { eie = NULL; - ret = btrfs_next_leaf(root, path); + ret = btrfs_next_old_leaf(root, path, time_seq); if (ret < 0) return ret; if (ret) @@ -297,7 +298,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, if (level == 0) btrfs_item_key_to_cpu(eb, &key, path->slots[0]); - ret = add_all_parents(root, path, parents, level, &key, + ret = add_all_parents(root, path, parents, level, &key, time_seq, ref->wanted_disk_byte, extent_item_pos); out: btrfs_free_path(path); diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 50d7c99..cb76b2a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -5017,6 +5017,12 @@ next: */ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) { + return btrfs_next_old_leaf(root, path, 0); +} + +int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + u64 time_seq) +{ int slot; int level; struct extent_buffer *c; @@ -5041,7 +5047,10 @@ again: path->keep_locks = 1; path->leave_spinning = 1; - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (time_seq) + ret = btrfs_search_old_slot(root, &key, path, time_seq); + else + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); path->keep_locks = 0; if (ret < 0) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 0151ca1..db15e9e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2753,6 +2753,8 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, } int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); +int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + u64 time_seq); static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p) { ++p->slots[0]; -- cgit v0.10.2 From 3310c36eef330766fd23d50796287ad764929e24 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 11 Jun 2012 10:52:38 +0200 Subject: Btrfs: fix race in tree mod log addition When adding to the tree modification log, we grab two locks at different stages. We must not drop the outer lock until we're done with section protected by the inner lock. This moves the unlock call for the outer lock to the appropriate position. Signed-off-by: Jan Schmidt diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index cb76b2a..04b06bc 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -467,6 +467,15 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, return 0; } +/* + * This allocates memory and gets a tree modification sequence number when + * needed. + * + * Returns 0 when no sequence number is needed, < 0 on error. + * Returns 1 when a sequence number was added. In this case, + * fs_info->tree_mod_seq_lock was acquired and must be released by the caller + * after inserting into the rb tree. + */ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, struct tree_mod_elem **tm_ret) { @@ -491,11 +500,11 @@ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, */ kfree(tm); seq = 0; + spin_unlock(&fs_info->tree_mod_seq_lock); } else { __get_tree_mod_seq(fs_info, &tm->elem); seq = tm->elem.seq; } - spin_unlock(&fs_info->tree_mod_seq_lock); return seq; } @@ -521,7 +530,9 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, tm->slot = slot; tm->generation = btrfs_node_ptr_generation(eb, slot); - return __tree_mod_log_insert(fs_info, tm); + ret = __tree_mod_log_insert(fs_info, tm); + spin_unlock(&fs_info->tree_mod_seq_lock); + return ret; } static noinline int @@ -559,7 +570,9 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, tm->move.nr_items = nr_items; tm->op = MOD_LOG_MOVE_KEYS; - return __tree_mod_log_insert(fs_info, tm); + ret = __tree_mod_log_insert(fs_info, tm); + spin_unlock(&fs_info->tree_mod_seq_lock); + return ret; } static noinline int @@ -580,7 +593,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, tm->generation = btrfs_header_generation(old_root); tm->op = MOD_LOG_ROOT_REPLACE; - return __tree_mod_log_insert(fs_info, tm); + ret = __tree_mod_log_insert(fs_info, tm); + spin_unlock(&fs_info->tree_mod_seq_lock); + return ret; } static struct tree_mod_elem * -- cgit v0.10.2 From 12918b10d59e975fd5241eef03ef9e6d5ea3dcfe Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Fri, 1 Jun 2012 13:55:47 +0400 Subject: NFS: hard-code init_net for NFS callback transports In case of destroying mount namespace on child reaper exit, nsproxy is zeroed to the point already. So, dereferencing of it is invalid. This patch hard-code "init_net" for all network namespace references for NFS callback services. This will be fixed with proper NFS callback containerization. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 970659d..23ff18f 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -17,7 +17,6 @@ #include #include #include -#include #include @@ -107,7 +106,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) { int ret; - ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET, + ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret <= 0) goto out_err; @@ -115,7 +114,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) dprintk("NFS: Callback listener port = %u (af %u)\n", nfs_callback_tcpport, PF_INET); - ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET6, + ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret > 0) { nfs_callback_tcpport6 = ret; @@ -184,7 +183,7 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) * fore channel connection. * Returns the input port (0) and sets the svc_serv bc_xprt on success */ - ret = svc_create_xprt(serv, "tcp-bc", xprt->xprt_net, PF_INET, 0, + ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, SVC_SOCK_ANONYMOUS); if (ret < 0) { rqstp = ERR_PTR(ret); @@ -254,7 +253,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) char svc_name[12]; int ret = 0; int minorversion_setup; - struct net *net = current->nsproxy->net_ns; + struct net *net = &init_net; mutex_lock(&nfs_callback_mutex); if (cb_info->users++ || cb_info->task != NULL) { @@ -330,7 +329,7 @@ void nfs_callback_down(int minorversion) cb_info->users--; if (cb_info->users == 0 && cb_info->task != NULL) { kthread_stop(cb_info->task); - svc_shutdown_net(cb_info->serv, current->nsproxy->net_ns); + svc_shutdown_net(cb_info->serv, &init_net); svc_exit_thread(cb_info->rqst); cb_info->serv = NULL; cb_info->rqst = NULL; -- cgit v0.10.2 From bc2df47a408f2d64cf81bcfd0f6e3e14c84cb0ab Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 12 Jun 2012 08:28:48 -0400 Subject: nfsd4: BUG_ON(!is_spin_locked()) no good on UP kernels Most frequent symptom was a BUG triggering in expire_client, with the server locking up shortly thereafter. Introduced by 508dc6e110c6dbdc0bbe84298ccfe22de7538486 "nfsd41: free_session/free_client must be called under the client_lock". Cc: stable@kernel.org Cc: Benny Halevy Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 8fdc9ec..94effd5 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -900,7 +900,7 @@ static void free_session(struct kref *kref) struct nfsd4_session *ses; int mem; - BUG_ON(!spin_is_locked(&client_lock)); + lockdep_assert_held(&client_lock); ses = container_of(kref, struct nfsd4_session, se_ref); nfsd4_del_conns(ses); spin_lock(&nfsd_drc_lock); @@ -1080,7 +1080,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) static inline void free_client(struct nfs4_client *clp) { - BUG_ON(!spin_is_locked(&client_lock)); + lockdep_assert_held(&client_lock); while (!list_empty(&clp->cl_sessions)) { struct nfsd4_session *ses; ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, -- cgit v0.10.2 From b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 23 May 2012 18:57:20 +0100 Subject: xen: mark local pages as FOREIGN in the m2p_override When the frontend and the backend reside on the same domain, even if we add pages to the m2p_override, these pages will never be returned by mfn_to_pfn because the check "get_phys_to_machine(pfn) != mfn" will always fail, so the pfn of the frontend will be returned instead (resulting in a deadlock because the frontend pages are already locked). INFO: task qemu-system-i38:1085 blocked for more than 120 seconds. "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. qemu-system-i38 D ffff8800cfc137c0 0 1085 1 0x00000000 ffff8800c47ed898 0000000000000282 ffff8800be4596b0 00000000000137c0 ffff8800c47edfd8 ffff8800c47ec010 00000000000137c0 00000000000137c0 ffff8800c47edfd8 00000000000137c0 ffffffff82213020 ffff8800be4596b0 Call Trace: [] ? __lock_page+0x70/0x70 [] schedule+0x29/0x70 [] io_schedule+0x60/0x80 [] sleep_on_page+0xe/0x20 [] __wait_on_bit_lock+0x5a/0xc0 [] __lock_page+0x67/0x70 [] ? autoremove_wake_function+0x40/0x40 [] ? bio_add_page+0x36/0x40 [] set_page_dirty_lock+0x52/0x60 [] bio_set_pages_dirty+0x51/0x70 [] do_blockdev_direct_IO+0xb24/0xeb0 [] ? ext3_get_blocks_handle+0xe00/0xe00 [] __blockdev_direct_IO+0x55/0x60 [] ? ext3_get_blocks_handle+0xe00/0xe00 [] ext3_direct_IO+0xf8/0x390 [] ? ext3_get_blocks_handle+0xe00/0xe00 [] ? xen_mc_flush+0xb0/0x1b0 [] generic_file_aio_read+0x737/0x780 [] ? gnttab_map_refs+0x15b/0x1e0 [] ? find_get_pages+0x150/0x150 [] aio_rw_vect_retry+0x7c/0x1d0 [] ? lookup_ioctx+0x90/0x90 [] aio_run_iocb+0x66/0x1a0 [] do_io_submit+0x708/0xb90 [] sys_io_submit+0x10/0x20 [] system_call_fastpath+0x16/0x1b The explanation is in the comment within the code: We need to do this because the pages shared by the frontend (xen-blkfront) can be already locked (lock_page, called by do_read_cache_page); when the userspace backend tries to use them with direct_IO, mfn_to_pfn returns the pfn of the frontend, so do_blockdev_direct_IO is going to try to lock the same pages again resulting in a deadlock. A simplified call graph looks like this: pygrub QEMU ----------------------------------------------- do_read_cache_page io_submit | | lock_page ext3_direct_IO | bio_add_page | lock_page Internally the xen-blkback uses m2p_add_override to swizzle (temporarily) a 'struct page' to have a different MFN (so that it can point to another guest). It also can easily find out whether another pfn corresponding to the mfn exists in the m2p, and can set the FOREIGN bit in the p2m, making sure that mfn_to_pfn returns the pfn of the backend. This allows the backend to perform direct_IO on these pages, but as a side effect prevents the frontend from using get_user_pages_fast on them while they are being shared with the backend. Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index ffd08c4..64effdc 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -706,6 +706,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; + int ret = 0; pfn = page_to_pfn(page); if (!PageHighMem(page)) { @@ -741,6 +742,24 @@ int m2p_add_override(unsigned long mfn, struct page *page, list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); spin_unlock_irqrestore(&m2p_override_lock, flags); + /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in + * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other + * pfn so that the following mfn_to_pfn(mfn) calls will return the + * pfn from the m2p_override (the backend pfn) instead. + * We need to do this because the pages shared by the frontend + * (xen-blkfront) can be already locked (lock_page, called by + * do_read_cache_page); when the userspace backend tries to use them + * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so + * do_blockdev_direct_IO is going to try to lock the same pages + * again resulting in a deadlock. + * As a side effect get_user_pages_fast might not be safe on the + * frontend pages while they are being shared with the backend, + * because mfn_to_pfn (that ends up being called by GUPF) will + * return the backend pfn rather than the frontend pfn. */ + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); + if (ret == 0 && get_phys_to_machine(pfn) == mfn) + set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); + return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); @@ -752,6 +771,7 @@ int m2p_remove_override(struct page *page, bool clear_pte) unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; + int ret = 0; pfn = page_to_pfn(page); mfn = get_phys_to_machine(pfn); @@ -821,6 +841,22 @@ int m2p_remove_override(struct page *page, bool clear_pte) } else set_phys_to_machine(pfn, page->index); + /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present + * somewhere in this domain, even before being added to the + * m2p_override (see comment above in m2p_add_override). + * If there are no other entries in the m2p_override corresponding + * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for + * the original pfn (the one shared by the frontend): the backend + * cannot do any IO on this page anymore because it has been + * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of + * the original pfn causes mfn_to_pfn(mfn) to return the frontend + * pfn again. */ + mfn &= ~FOREIGN_FRAME_BIT; + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); + if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && + m2p_find_override(mfn) == NULL) + set_phys_to_machine(pfn, mfn); + return 0; } EXPORT_SYMBOL_GPL(m2p_remove_override); -- cgit v0.10.2 From 6c4707f3f8c44ec18282e1c014c80e1c257042f9 Mon Sep 17 00:00:00 2001 From: Otto Meta Date: Wed, 6 Jun 2012 18:46:21 +0200 Subject: usb: cdc-acm: fix devices not unthrottled on open Currently CDC-ACM devices stay throttled when their TTY is closed while throttled, stalling further communication attempts after the next open. Unthrottling during open/activate got lost starting with kernel 3.0.0 and this patch reintroduces it. Signed-off-by: Otto Meta Cc: stable Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index f2a120e..36a2a0b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -567,6 +567,14 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) usb_autopm_put_interface(acm->control); + /* + * Unthrottle device in case the TTY was closed while throttled. + */ + spin_lock_irq(&acm->read_lock); + acm->throttled = 0; + acm->throttle_req = 0; + spin_unlock_irq(&acm->read_lock); + if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto error_submit_read_urbs; -- cgit v0.10.2 From 5897b038296ea84e501ba5f957e11939f8cf9be0 Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Tue, 12 Jun 2012 09:34:33 +0900 Subject: usb: ehci-sh: fix illegal phy_init() running when platform_data is NULL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the platform_data is not set, pdata will be uninitialized value. Since the driver has the following code, if the condition is true when the pdata is uninitialized value, the driver may jump to the illegal phy_init(). if (pdata && pdata->phy_init) pdata->phy_init(); This patch also fixes the following warning: CC drivers/usb/host/ehci-hcd.o drivers/usb/host/ehci-sh.c: In function ‘ehci_hcd_sh_probe’: drivers/usb/host/ehci-sh.c:104: warning: ‘pdata’ may be used uninitialized in this function Signed-off-by: Yoshihiro Shimoda Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index ca819cd..e7cb392 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -126,8 +126,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) goto fail_create_hcd; } - if (pdev->dev.platform_data != NULL) - pdata = pdev->dev.platform_data; + pdata = pdev->dev.platform_data; /* initialize hcd */ hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev, -- cgit v0.10.2 From b3a3dd074f7053ef824ad077e5331b52220ceba1 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 12 Jun 2012 20:23:52 +0200 Subject: USB: fix gathering of interface associations TEAC's UD-H01 (and probably other devices) have a gap in the interface number allocation of their descriptors: Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 220 bNumInterfaces 3 [...] Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 [...] Interface Association: bLength 8 bDescriptorType 11 bFirstInterface 2 bInterfaceCount 2 bFunctionClass 1 Audio bFunctionSubClass 0 bFunctionProtocol 32 iFunction 4 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 2 bAlternateSetting 0 [...] Once a configuration is selected, usb_set_configuration() walks the known interfaces of a given configuration and calls find_iad() on each of them to set the interface association pointer the interface is included in. The problem here is that the loop variable is taken for the interface number in the comparison logic that gathers the association. Which is fine as long as the descriptors are sane. In the case above, however, the logic gets out of sync and the interface association fields of all interfaces beyond the interface number gap are wrong. Fix this by passing the interface's bInterfaceNumber to find_iad() instead. Signed-off-by: Daniel Mack Reported-by: bEN Reported-by: Ivan Perrone Tested-by: ivan perrone Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b548cf1..bdd1c67 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1838,7 +1838,6 @@ free_interfaces: intfc = cp->intf_cache[i]; intf->altsetting = intfc->altsetting; intf->num_altsetting = intfc->num_altsetting; - intf->intf_assoc = find_iad(dev, cp, i); kref_get(&intfc->ref); alt = usb_altnum_to_altsetting(intf, 0); @@ -1851,6 +1850,8 @@ free_interfaces: if (!alt) alt = &intf->altsetting[0]; + intf->intf_assoc = + find_iad(dev, cp, alt->desc.bInterfaceNumber); intf->cur_altsetting = alt; usb_enable_interface(dev, intf, true); intf->dev.parent = &dev->dev; -- cgit v0.10.2 From beb42dd793193a3d4e72970bfa73cd8810f63cea Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 30 May 2012 15:35:17 -0400 Subject: Btrfs: pass locked_page into extent_clear_unlock_delalloc if theres an error While doing my enospc work I got a transaction abortion that resulted in a panic when we tried to unlock_page() an already unlocked page. This is because we aren't calling extent_clear_unlock_delalloc with the locked page so it was unlocking all the pages in the range. This is wrong since __extent_writepage expects to have the page locked still unless we return *page_started as 1. This should keep us from panicing. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 92df0a5..ccd6355 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -830,7 +830,7 @@ static noinline int cow_file_range(struct inode *inode, if (IS_ERR(trans)) { extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, - start, end, NULL, + start, end, locked_page, EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_UNLOCK | EXTENT_CLEAR_DELALLOC | @@ -963,7 +963,7 @@ out: out_unlock: extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, - start, end, NULL, + start, end, locked_page, EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_UNLOCK | EXTENT_CLEAR_DELALLOC | -- cgit v0.10.2 From b939d1ab76b4aa816343cdbd8b44ce9929a3b9ef Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 31 May 2012 11:06:33 -0400 Subject: Btrfs: fix locking in btrfs_destroy_delayed_refs The transaction abort stuff was throwing warnings from the list debugging code because we do a list_del_init outside of the delayed_refs spin lock. The delayed refs locking makes baby Jesus cry so it's not hard to get wrong, but we need to take the ref head mutex to make sure it's not being processed currently, and so if it is we need to drop the spin lock and then take and drop the mutex and do the search again. If we can take the mutex then we can safely remove the head from the list and carry on. Now when the transaction aborts I don't get the list debugging warnings. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index b99d512..c79ddc7 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3400,7 +3400,6 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, delayed_refs = &trans->delayed_refs; -again: spin_lock(&delayed_refs->lock); if (delayed_refs->num_entries == 0) { spin_unlock(&delayed_refs->lock); @@ -3408,31 +3407,36 @@ again: return ret; } - node = rb_first(&delayed_refs->root); - while (node) { + while ((node = rb_first(&delayed_refs->root)) != NULL) { ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); - node = rb_next(node); - - ref->in_tree = 0; - rb_erase(&ref->rb_node, &delayed_refs->root); - delayed_refs->num_entries--; atomic_set(&ref->refs, 1); if (btrfs_delayed_ref_is_head(ref)) { struct btrfs_delayed_ref_head *head; head = btrfs_delayed_node_to_head(ref); - spin_unlock(&delayed_refs->lock); - mutex_lock(&head->mutex); + if (!mutex_trylock(&head->mutex)) { + atomic_inc(&ref->refs); + spin_unlock(&delayed_refs->lock); + + /* Need to wait for the delayed ref to run */ + mutex_lock(&head->mutex); + mutex_unlock(&head->mutex); + btrfs_put_delayed_ref(ref); + + continue; + } + kfree(head->extent_op); delayed_refs->num_heads--; if (list_empty(&head->cluster)) delayed_refs->num_heads_ready--; list_del_init(&head->cluster); - mutex_unlock(&head->mutex); - btrfs_put_delayed_ref(ref); - goto again; } + ref->in_tree = 0; + rb_erase(&ref->rb_node, &delayed_refs->root); + delayed_refs->num_entries--; + spin_unlock(&delayed_refs->lock); btrfs_put_delayed_ref(ref); -- cgit v0.10.2 From d7096fc3ef8360f30f228344bc564d4f97d8a158 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 31 May 2012 15:49:57 -0400 Subject: Btrfs: wake up transaction waiters when aborting a transaction I was getting lots of hung tasks and a NULL pointer dereference because we are not cleaning up the transaction properly when it aborts. First we need to reset the running_transaction to NULL so we don't get a bad dereference for any start_transaction callers after this. Also we cannot rely on waitqueue_active() since it's just a list_empty(), so just call wake_up() directly since that will do the barrier for us and such. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c79ddc7..19b4db70 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3589,16 +3589,13 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, /* FIXME: cleanup wait for commit */ cur_trans->in_commit = 1; cur_trans->blocked = 1; - if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) - wake_up(&root->fs_info->transaction_blocked_wait); + wake_up(&root->fs_info->transaction_blocked_wait); cur_trans->blocked = 0; - if (waitqueue_active(&root->fs_info->transaction_wait)) - wake_up(&root->fs_info->transaction_wait); + wake_up(&root->fs_info->transaction_wait); cur_trans->commit_done = 1; - if (waitqueue_active(&cur_trans->commit_wait)) - wake_up(&cur_trans->commit_wait); + wake_up(&cur_trans->commit_wait); btrfs_destroy_pending_snapshots(cur_trans); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 1791c6e..59e0203 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1221,6 +1221,10 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, spin_lock(&root->fs_info->trans_lock); list_del_init(&cur_trans->list); + if (cur_trans == root->fs_info->running_transaction) { + root->fs_info->running_transaction = NULL; + root->fs_info->trans_no_join = 0; + } spin_unlock(&root->fs_info->trans_lock); btrfs_cleanup_one_transaction(trans->transaction, root); -- cgit v0.10.2 From 7b8b92af58db347de64a237861fcf13374b34a9c Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 31 May 2012 15:52:43 -0400 Subject: Btrfs: abort the transaction if the commit fails If a transaction commit fails we don't abort it so we don't set an error on the file system. This patch fixes that by actually calling the abort stuff and then adding a check for a fs error in the transaction start stuff to make sure it is caught properly. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 59e0203..b72b068 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -100,6 +100,10 @@ loop: kmem_cache_free(btrfs_transaction_cachep, cur_trans); cur_trans = fs_info->running_transaction; goto loop; + } else if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { + spin_unlock(&root->fs_info->trans_lock); + kmem_cache_free(btrfs_transaction_cachep, cur_trans); + return -EROFS; } atomic_set(&cur_trans->num_writers, 1); @@ -1213,12 +1217,14 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, static void cleanup_transaction(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_root *root, int err) { struct btrfs_transaction *cur_trans = trans->transaction; WARN_ON(trans->use_count > 1); + btrfs_abort_transaction(trans, root, err); + spin_lock(&root->fs_info->trans_lock); list_del_init(&cur_trans->list); if (cur_trans == root->fs_info->running_transaction) { @@ -1530,7 +1536,7 @@ cleanup_transaction: // WARN_ON(1); if (current->journal_info == trans) current->journal_info = NULL; - cleanup_transaction(trans, root); + cleanup_transaction(trans, root, ret); return ret; } -- cgit v0.10.2 From ee670f0af35871edb492db5ba406cef36d1b7c21 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 31 May 2012 15:54:30 -0400 Subject: Btrfs: fix btrfs_destroy_marked_extents So we're forcing the eb's to have their ref count set to 1 so invalidatepage works but this breaks lots of things, for example root nodes, and is just plain wrong, we don't need to just evict all of this stuff. Also drop the invalidatepage altogether and add a page_cache_release(). With this patch we no longer hang when trying to access the root nodes after an aborted transaction and we no longer leak memory. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 19b4db70..5a3bf32 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3524,11 +3524,9 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, &(&BTRFS_I(page->mapping->host)->io_tree)->buffer, offset >> PAGE_CACHE_SHIFT); spin_unlock(&dirty_pages->buffer_lock); - if (eb) { + if (eb) ret = test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); - atomic_set(&eb->refs, 1); - } if (PageWriteback(page)) end_page_writeback(page); @@ -3542,8 +3540,8 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, spin_unlock_irq(&page->mapping->tree_lock); } - page->mapping->a_ops->invalidatepage(page, 0); unlock_page(page); + page_cache_release(page); } } -- cgit v0.10.2 From 17ca04aff7e6171df684b7b65804df8830eb8c15 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 31 May 2012 15:58:55 -0400 Subject: Btrfs: unlock everything properly in the error case for nocow I was getting hung on umount when a transaction was aborted because a range of one of the free space inodes was still locked. This is because the nocow stuff doesn't unlock anything on error. This fixed the problem and I verified that is what was happening. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ccd6355..b7f398c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1136,8 +1136,18 @@ static noinline int run_delalloc_nocow(struct inode *inode, u64 ino = btrfs_ino(inode); path = btrfs_alloc_path(); - if (!path) + if (!path) { + extent_clear_unlock_delalloc(inode, + &BTRFS_I(inode)->io_tree, + start, end, locked_page, + EXTENT_CLEAR_UNLOCK_PAGE | + EXTENT_CLEAR_UNLOCK | + EXTENT_CLEAR_DELALLOC | + EXTENT_CLEAR_DIRTY | + EXTENT_SET_WRITEBACK | + EXTENT_END_WRITEBACK); return -ENOMEM; + } nolock = btrfs_is_free_space_inode(root, inode); @@ -1147,6 +1157,15 @@ static noinline int run_delalloc_nocow(struct inode *inode, trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { + extent_clear_unlock_delalloc(inode, + &BTRFS_I(inode)->io_tree, + start, end, locked_page, + EXTENT_CLEAR_UNLOCK_PAGE | + EXTENT_CLEAR_UNLOCK | + EXTENT_CLEAR_DELALLOC | + EXTENT_CLEAR_DIRTY | + EXTENT_SET_WRITEBACK | + EXTENT_END_WRITEBACK); btrfs_free_path(path); return PTR_ERR(trans); } @@ -1327,8 +1346,11 @@ out_check: } btrfs_release_path(path); - if (cur_offset <= end && cow_start == (u64)-1) + if (cur_offset <= end && cow_start == (u64)-1) { cow_start = cur_offset; + cur_offset = end; + } + if (cow_start != (u64)-1) { ret = cow_file_range(inode, locked_page, cow_start, end, page_started, nr_written, 1); @@ -1347,6 +1369,17 @@ error: if (!ret) ret = err; + if (ret && cur_offset < end) + extent_clear_unlock_delalloc(inode, + &BTRFS_I(inode)->io_tree, + cur_offset, end, locked_page, + EXTENT_CLEAR_UNLOCK_PAGE | + EXTENT_CLEAR_UNLOCK | + EXTENT_CLEAR_DELALLOC | + EXTENT_CLEAR_DIRTY | + EXTENT_SET_WRITEBACK | + EXTENT_END_WRITEBACK); + btrfs_free_path(path); return ret; } -- cgit v0.10.2 From 606686eeac4550d2212bf3d621a810407ef5e9bf Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 4 Jun 2012 14:03:51 -0400 Subject: Btrfs: use rcu to protect device->name Al pointed out that we can just toss out the old name on a device and add a new one arbitrarily, so anybody who uses device->name in printk could possibly use free'd memory. Instead of adding locking around all of this he suggested doing it with RCU, so I've introduced a struct rcu_string that does just that and have gone through and protected all accesses to device->name that aren't under the uuid_mutex with rcu_read_lock(). This protects us and I will use it for dealing with removing the device that we used to mount the file system in a later patch. Thanks, Reviewed-by: David Sterba Signed-off-by: Josef Bacik diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 9cebb1f..da6e936 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -93,6 +93,7 @@ #include "print-tree.h" #include "locking.h" #include "check-integrity.h" +#include "rcu-string.h" #define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000 #define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000 @@ -843,13 +844,14 @@ static int btrfsic_process_superblock_dev_mirror( superblock_tmp->never_written = 0; superblock_tmp->mirror_num = 1 + superblock_mirror_num; if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE) - printk(KERN_INFO "New initial S-block (bdev %p, %s)" - " @%llu (%s/%llu/%d)\n", - superblock_bdev, device->name, - (unsigned long long)dev_bytenr, - dev_state->name, - (unsigned long long)dev_bytenr, - superblock_mirror_num); + printk_in_rcu(KERN_INFO "New initial S-block (bdev %p, %s)" + " @%llu (%s/%llu/%d)\n", + superblock_bdev, + rcu_str_deref(device->name), + (unsigned long long)dev_bytenr, + dev_state->name, + (unsigned long long)dev_bytenr, + superblock_mirror_num); list_add(&superblock_tmp->all_blocks_node, &state->all_blocks_list); btrfsic_block_hashtable_add(superblock_tmp, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5a3bf32..1c9664b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -44,6 +44,7 @@ #include "free-space-cache.h" #include "inode-map.h" #include "check-integrity.h" +#include "rcu-string.h" static struct extent_io_ops btree_extent_io_ops; static void end_workqueue_fn(struct btrfs_work *work); @@ -2575,8 +2576,9 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) struct btrfs_device *device = (struct btrfs_device *) bh->b_private; - printk_ratelimited(KERN_WARNING "lost page write due to " - "I/O error on %s\n", device->name); + printk_ratelimited_in_rcu(KERN_WARNING "lost page write due to " + "I/O error on %s\n", + rcu_str_deref(device->name)); /* note, we dont' set_buffer_write_io_error because we have * our own ways of dealing with the IO errors */ @@ -2749,8 +2751,8 @@ static int write_dev_flush(struct btrfs_device *device, int wait) wait_for_completion(&device->flush_wait); if (bio_flagged(bio, BIO_EOPNOTSUPP)) { - printk("btrfs: disabling barriers on dev %s\n", - device->name); + printk_in_rcu("btrfs: disabling barriers on dev %s\n", + rcu_str_deref(device->name)); device->nobarriers = 1; } if (!bio_flagged(bio, BIO_UPTODATE)) { diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 2c8f7b2..aaa12c1 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -20,6 +20,7 @@ #include "volumes.h" #include "check-integrity.h" #include "locking.h" +#include "rcu-string.h" static struct kmem_cache *extent_state_cache; static struct kmem_cache *extent_buffer_cache; @@ -1917,9 +1918,9 @@ int repair_io_failure(struct btrfs_mapping_tree *map_tree, u64 start, return -EIO; } - printk(KERN_INFO "btrfs read error corrected: ino %lu off %llu (dev %s " - "sector %llu)\n", page->mapping->host->i_ino, start, - dev->name, sector); + printk_in_rcu(KERN_INFO "btrfs read error corrected: ino %lu off %llu " + "(dev %s sector %llu)\n", page->mapping->host->i_ino, + start, rcu_str_deref(dev->name), sector); bio_put(bio); return 0; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 24b776c..c5254dd 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -52,6 +52,7 @@ #include "locking.h" #include "inode-map.h" #include "backref.h" +#include "rcu-string.h" /* Mask out flags that are inappropriate for the given type of inode. */ static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) @@ -1345,8 +1346,9 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, do_div(new_size, root->sectorsize); new_size *= root->sectorsize; - printk(KERN_INFO "btrfs: new size for %s is %llu\n", - device->name, (unsigned long long)new_size); + printk_in_rcu(KERN_INFO "btrfs: new size for %s is %llu\n", + rcu_str_deref(device->name), + (unsigned long long)new_size); if (new_size > old_size) { trans = btrfs_start_transaction(root, 0); @@ -2264,7 +2266,12 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) di_args->total_bytes = dev->total_bytes; memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); if (dev->name) { - strncpy(di_args->path, dev->name, sizeof(di_args->path)); + struct rcu_string *name; + + rcu_read_lock(); + name = rcu_dereference(dev->name); + strncpy(di_args->path, name->str, sizeof(di_args->path)); + rcu_read_unlock(); di_args->path[sizeof(di_args->path) - 1] = 0; } else { di_args->path[0] = '\0'; diff --git a/fs/btrfs/rcu-string.h b/fs/btrfs/rcu-string.h new file mode 100644 index 0000000..9e111e4 --- /dev/null +++ b/fs/btrfs/rcu-string.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Red Hat. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +struct rcu_string { + struct rcu_head rcu; + char str[0]; +}; + +static inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask) +{ + size_t len = strlen(src) + 1; + struct rcu_string *ret = kzalloc(sizeof(struct rcu_string) + + (len * sizeof(char)), mask); + if (!ret) + return ret; + strncpy(ret->str, src, len); + return ret; +} + +static inline void rcu_string_free(struct rcu_string *str) +{ + if (str) + kfree_rcu(str, rcu); +} + +#define printk_in_rcu(fmt, ...) do { \ + rcu_read_lock(); \ + printk(fmt, __VA_ARGS__); \ + rcu_read_unlock(); \ +} while (0) + +#define printk_ratelimited_in_rcu(fmt, ...) do { \ + rcu_read_lock(); \ + printk_ratelimited(fmt, __VA_ARGS__); \ + rcu_read_unlock(); \ +} while (0) + +#define rcu_str_deref(rcu_str) ({ \ + struct rcu_string *__str = rcu_dereference(rcu_str); \ + __str->str; \ +}) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index a38cfa4..b223620 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -26,6 +26,7 @@ #include "backref.h" #include "extent_io.h" #include "check-integrity.h" +#include "rcu-string.h" /* * This is only the first step towards a full-features scrub. It reads all @@ -320,10 +321,10 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx) * hold all of the paths here */ for (i = 0; i < ipath->fspath->elem_cnt; ++i) - printk(KERN_WARNING "btrfs: %s at logical %llu on dev " + printk_in_rcu(KERN_WARNING "btrfs: %s at logical %llu on dev " "%s, sector %llu, root %llu, inode %llu, offset %llu, " "length %llu, links %u (path: %s)\n", swarn->errstr, - swarn->logical, swarn->dev->name, + swarn->logical, rcu_str_deref(swarn->dev->name), (unsigned long long)swarn->sector, root, inum, offset, min(isize - offset, (u64)PAGE_SIZE), nlink, (char *)(unsigned long)ipath->fspath->val[i]); @@ -332,10 +333,10 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx) return 0; err: - printk(KERN_WARNING "btrfs: %s at logical %llu on dev " + printk_in_rcu(KERN_WARNING "btrfs: %s at logical %llu on dev " "%s, sector %llu, root %llu, inode %llu, offset %llu: path " "resolving failed with ret=%d\n", swarn->errstr, - swarn->logical, swarn->dev->name, + swarn->logical, rcu_str_deref(swarn->dev->name), (unsigned long long)swarn->sector, root, inum, offset, ret); free_ipath(ipath); @@ -390,10 +391,11 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) do { ret = tree_backref_for_extent(&ptr, eb, ei, item_size, &ref_root, &ref_level); - printk(KERN_WARNING + printk_in_rcu(KERN_WARNING "btrfs: %s at logical %llu on dev %s, " "sector %llu: metadata %s (level %d) in tree " - "%llu\n", errstr, swarn.logical, dev->name, + "%llu\n", errstr, swarn.logical, + rcu_str_deref(dev->name), (unsigned long long)swarn.sector, ref_level ? "node" : "leaf", ret < 0 ? -1 : ref_level, @@ -580,9 +582,11 @@ out: spin_lock(&sdev->stat_lock); ++sdev->stat.uncorrectable_errors; spin_unlock(&sdev->stat_lock); - printk_ratelimited(KERN_ERR + + printk_ratelimited_in_rcu(KERN_ERR "btrfs: unable to fixup (nodatasum) error at logical %llu on dev %s\n", - (unsigned long long)fixup->logical, sdev->dev->name); + (unsigned long long)fixup->logical, + rcu_str_deref(sdev->dev->name)); } btrfs_free_path(path); @@ -936,18 +940,20 @@ corrected_error: spin_lock(&sdev->stat_lock); sdev->stat.corrected_errors++; spin_unlock(&sdev->stat_lock); - printk_ratelimited(KERN_ERR + printk_ratelimited_in_rcu(KERN_ERR "btrfs: fixed up error at logical %llu on dev %s\n", - (unsigned long long)logical, sdev->dev->name); + (unsigned long long)logical, + rcu_str_deref(sdev->dev->name)); } } else { did_not_correct_error: spin_lock(&sdev->stat_lock); sdev->stat.uncorrectable_errors++; spin_unlock(&sdev->stat_lock); - printk_ratelimited(KERN_ERR + printk_ratelimited_in_rcu(KERN_ERR "btrfs: unable to fixup (regular) error at logical %llu on dev %s\n", - (unsigned long long)logical, sdev->dev->name); + (unsigned long long)logical, + rcu_str_deref(sdev->dev->name)); } out: diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 7782020..8a3d259 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -35,6 +35,7 @@ #include "volumes.h" #include "async-thread.h" #include "check-integrity.h" +#include "rcu-string.h" static int init_first_rw_device(struct btrfs_trans_handle *trans, struct btrfs_root *root, @@ -64,7 +65,7 @@ static void free_fs_devices(struct btrfs_fs_devices *fs_devices) device = list_entry(fs_devices->devices.next, struct btrfs_device, dev_list); list_del(&device->dev_list); - kfree(device->name); + rcu_string_free(device->name); kfree(device); } kfree(fs_devices); @@ -334,8 +335,8 @@ static noinline int device_list_add(const char *path, { struct btrfs_device *device; struct btrfs_fs_devices *fs_devices; + struct rcu_string *name; u64 found_transid = btrfs_super_generation(disk_super); - char *name; fs_devices = find_fsid(disk_super->fsid); if (!fs_devices) { @@ -369,11 +370,13 @@ static noinline int device_list_add(const char *path, memcpy(device->uuid, disk_super->dev_item.uuid, BTRFS_UUID_SIZE); spin_lock_init(&device->io_lock); - device->name = kstrdup(path, GFP_NOFS); - if (!device->name) { + + name = rcu_string_strdup(path, GFP_NOFS); + if (!name) { kfree(device); return -ENOMEM; } + rcu_assign_pointer(device->name, name); INIT_LIST_HEAD(&device->dev_alloc_list); /* init readahead state */ @@ -390,12 +393,12 @@ static noinline int device_list_add(const char *path, device->fs_devices = fs_devices; fs_devices->num_devices++; - } else if (!device->name || strcmp(device->name, path)) { - name = kstrdup(path, GFP_NOFS); + } else if (!device->name || strcmp(device->name->str, path)) { + name = rcu_string_strdup(path, GFP_NOFS); if (!name) return -ENOMEM; - kfree(device->name); - device->name = name; + rcu_string_free(device->name); + rcu_assign_pointer(device->name, name); if (device->missing) { fs_devices->missing_devices--; device->missing = 0; @@ -430,15 +433,22 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) /* We have held the volume lock, it is safe to get the devices. */ list_for_each_entry(orig_dev, &orig->devices, dev_list) { + struct rcu_string *name; + device = kzalloc(sizeof(*device), GFP_NOFS); if (!device) goto error; - device->name = kstrdup(orig_dev->name, GFP_NOFS); - if (!device->name) { + /* + * This is ok to do without rcu read locked because we hold the + * uuid mutex so nothing we touch in here is going to disappear. + */ + name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS); + if (!name) { kfree(device); goto error; } + rcu_assign_pointer(device->name, name); device->devid = orig_dev->devid; device->work.func = pending_bios_fn; @@ -491,7 +501,7 @@ again: } list_del_init(&device->dev_list); fs_devices->num_devices--; - kfree(device->name); + rcu_string_free(device->name); kfree(device); } @@ -516,7 +526,7 @@ static void __free_device(struct work_struct *work) if (device->bdev) blkdev_put(device->bdev, device->mode); - kfree(device->name); + rcu_string_free(device->name); kfree(device); } @@ -540,6 +550,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) mutex_lock(&fs_devices->device_list_mutex); list_for_each_entry(device, &fs_devices->devices, dev_list) { struct btrfs_device *new_device; + struct rcu_string *name; if (device->bdev) fs_devices->open_devices--; @@ -555,8 +566,11 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) new_device = kmalloc(sizeof(*new_device), GFP_NOFS); BUG_ON(!new_device); /* -ENOMEM */ memcpy(new_device, device, sizeof(*new_device)); - new_device->name = kstrdup(device->name, GFP_NOFS); - BUG_ON(device->name && !new_device->name); /* -ENOMEM */ + + /* Safe because we are under uuid_mutex */ + name = rcu_string_strdup(device->name->str, GFP_NOFS); + BUG_ON(device->name && !name); /* -ENOMEM */ + rcu_assign_pointer(new_device->name, name); new_device->bdev = NULL; new_device->writeable = 0; new_device->in_fs_metadata = 0; @@ -621,9 +635,9 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, if (!device->name) continue; - bdev = blkdev_get_by_path(device->name, flags, holder); + bdev = blkdev_get_by_path(device->name->str, flags, holder); if (IS_ERR(bdev)) { - printk(KERN_INFO "open %s failed\n", device->name); + printk(KERN_INFO "open %s failed\n", device->name->str); goto error; } filemap_write_and_wait(bdev->bd_inode->i_mapping); @@ -1632,6 +1646,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) struct block_device *bdev; struct list_head *devices; struct super_block *sb = root->fs_info->sb; + struct rcu_string *name; u64 total_bytes; int seeding_dev = 0; int ret = 0; @@ -1671,23 +1686,24 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) goto error; } - device->name = kstrdup(device_path, GFP_NOFS); - if (!device->name) { + name = rcu_string_strdup(device_path, GFP_NOFS); + if (!name) { kfree(device); ret = -ENOMEM; goto error; } + rcu_assign_pointer(device->name, name); ret = find_next_devid(root, &device->devid); if (ret) { - kfree(device->name); + rcu_string_free(device->name); kfree(device); goto error; } trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) { - kfree(device->name); + rcu_string_free(device->name); kfree(device); ret = PTR_ERR(trans); goto error; @@ -1796,7 +1812,7 @@ error_trans: unlock_chunks(root); btrfs_abort_transaction(trans, root, ret); btrfs_end_transaction(trans, root); - kfree(device->name); + rcu_string_free(device->name); kfree(device); error: blkdev_put(bdev, FMODE_EXCL); @@ -4204,10 +4220,17 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, bio->bi_sector = bbio->stripes[dev_nr].physical >> 9; dev = bbio->stripes[dev_nr].dev; if (dev && dev->bdev && (rw != WRITE || dev->writeable)) { +#ifdef DEBUG + struct rcu_string *name; + + rcu_read_lock(); + name = rcu_dereference(dev->name); pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu " "(%s id %llu), size=%u\n", rw, (u64)bio->bi_sector, (u_long)dev->bdev->bd_dev, - dev->name, dev->devid, bio->bi_size); + name->str, dev->devid, bio->bi_size); + rcu_read_unlock(); +#endif bio->bi_bdev = dev->bdev; if (async_submit) schedule_bio(root, dev, rw, bio); @@ -4694,8 +4717,9 @@ int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info) key.offset = device->devid; ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0); if (ret) { - printk(KERN_WARNING "btrfs: no dev_stats entry found for device %s (devid %llu) (OK on first mount after mkfs)\n", - device->name, (unsigned long long)device->devid); + printk_in_rcu(KERN_WARNING "btrfs: no dev_stats entry found for device %s (devid %llu) (OK on first mount after mkfs)\n", + rcu_str_deref(device->name), + (unsigned long long)device->devid); __btrfs_reset_dev_stats(device); device->dev_stats_valid = 1; btrfs_release_path(path); @@ -4747,8 +4771,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans, BUG_ON(!path); ret = btrfs_search_slot(trans, dev_root, &key, path, -1, 1); if (ret < 0) { - printk(KERN_WARNING "btrfs: error %d while searching for dev_stats item for device %s!\n", - ret, device->name); + printk_in_rcu(KERN_WARNING "btrfs: error %d while searching for dev_stats item for device %s!\n", + ret, rcu_str_deref(device->name)); goto out; } @@ -4757,8 +4781,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans, /* need to delete old one and insert a new one */ ret = btrfs_del_item(trans, dev_root, path); if (ret != 0) { - printk(KERN_WARNING "btrfs: delete too small dev_stats item for device %s failed %d!\n", - device->name, ret); + printk_in_rcu(KERN_WARNING "btrfs: delete too small dev_stats item for device %s failed %d!\n", + rcu_str_deref(device->name), ret); goto out; } ret = 1; @@ -4770,8 +4794,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans, ret = btrfs_insert_empty_item(trans, dev_root, path, &key, sizeof(*ptr)); if (ret < 0) { - printk(KERN_WARNING "btrfs: insert dev_stats item for device %s failed %d!\n", - device->name, ret); + printk_in_rcu(KERN_WARNING "btrfs: insert dev_stats item for device %s failed %d!\n", + rcu_str_deref(device->name), ret); goto out; } } @@ -4823,9 +4847,9 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev) { if (!dev->dev_stats_valid) return; - printk_ratelimited(KERN_ERR + printk_ratelimited_in_rcu(KERN_ERR "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", - dev->name, + rcu_str_deref(dev->name), btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS), btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS), btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS), @@ -4837,8 +4861,8 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev) static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev) { - printk(KERN_INFO "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", - dev->name, + printk_in_rcu(KERN_INFO "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", + rcu_str_deref(dev->name), btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS), btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS), btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS), diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 3406a88..74366f2 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -58,7 +58,7 @@ struct btrfs_device { /* the mode sent to blkdev_get */ fmode_t mode; - char *name; + struct rcu_string *name; /* the internal btrfs device id */ u64 devid; -- cgit v0.10.2 From 9c5085c147989d48dfe74194b48affc23f376650 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 5 Jun 2012 14:13:12 -0400 Subject: Btrfs: implement ->show_devname Because btrfs can remove the device that was mounted we need to have a ->show_devname so that in this case we can print out some other device in the file system to /proc/mount. So if there are multiple devices in a btrfs file system we will just print the device with the lowest devid that we can find. This will make everything consistent and deal with device removal properly. The drawback is if you mount with a device that is higher than the lowest devicd it won't show up as the mounted device in /proc/mounts, but this is a small price to pay. This was inspired by Miao Xie's patch. Thanks, Reviewed-by: Miao Xie Signed-off-by: Josef Bacik diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 96eb9fe..0eb9a4d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -54,6 +54,7 @@ #include "version.h" #include "export.h" #include "compression.h" +#include "rcu-string.h" #define CREATE_TRACE_POINTS #include @@ -1482,12 +1483,44 @@ static void btrfs_fs_dirty_inode(struct inode *inode, int flags) "error %d\n", btrfs_ino(inode), ret); } +static int btrfs_show_devname(struct seq_file *m, struct dentry *root) +{ + struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb); + struct btrfs_fs_devices *cur_devices; + struct btrfs_device *dev, *first_dev = NULL; + struct list_head *head; + struct rcu_string *name; + + mutex_lock(&fs_info->fs_devices->device_list_mutex); + cur_devices = fs_info->fs_devices; + while (cur_devices) { + head = &cur_devices->devices; + list_for_each_entry(dev, head, dev_list) { + if (!first_dev || dev->devid < first_dev->devid) + first_dev = dev; + } + cur_devices = cur_devices->seed; + } + + if (first_dev) { + rcu_read_lock(); + name = rcu_dereference(first_dev->name); + seq_escape(m, name->str, " \t\n\\"); + rcu_read_unlock(); + } else { + WARN_ON(1); + } + mutex_unlock(&fs_info->fs_devices->device_list_mutex); + return 0; +} + static const struct super_operations btrfs_super_ops = { .drop_inode = btrfs_drop_inode, .evict_inode = btrfs_evict_inode, .put_super = btrfs_put_super, .sync_fs = btrfs_sync_fs, .show_options = btrfs_show_options, + .show_devname = btrfs_show_devname, .write_inode = btrfs_write_inode, .dirty_inode = btrfs_fs_dirty_inode, .alloc_inode = btrfs_alloc_inode, -- cgit v0.10.2 From 8180ef8894fa402443205cff1e23417e8d3434df Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 8 Jun 2012 15:16:12 -0400 Subject: Btrfs: keep inode pinned when compressing writes A user reported lots of problems using compression on the new code and it turns out part of the problem was that igrab() was failing when we added a new ordered extent. This is because when writing out an inode under compression we immediately return without actually doing anything to the pages, and then in another thread at some point down the line actually do the ordered dance. The problem is between the point that we start writeback and we actually add the ordered extent we could be trying to reclaim the inode, which makes igrab() return NULL. So we need to do an igrab() when we create the async extent and then drop it when we are done with it. This makes sure we stay pinned in memory until the ordered extent can get a reference on it and we are good to go. With this patch we no longer panic in btrfs_finish_ordered_io(). Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b7f398c..06075043 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -986,8 +986,10 @@ static noinline void async_cow_start(struct btrfs_work *work) compress_file_range(async_cow->inode, async_cow->locked_page, async_cow->start, async_cow->end, async_cow, &num_added); - if (num_added == 0) + if (num_added == 0) { + iput(async_cow->inode); async_cow->inode = NULL; + } } /* @@ -1020,6 +1022,8 @@ static noinline void async_cow_free(struct btrfs_work *work) { struct async_cow *async_cow; async_cow = container_of(work, struct async_cow, work); + if (async_cow->inode) + iput(async_cow->inode); kfree(async_cow); } @@ -1038,7 +1042,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, while (start < end) { async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); BUG_ON(!async_cow); /* -ENOMEM */ - async_cow->inode = inode; + async_cow->inode = igrab(inode); async_cow->root = root; async_cow->locked_page = locked_page; async_cow->start = start; -- cgit v0.10.2 From 7ddf5a42d311d74fd9f7373cb56def0843c219f8 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 8 Jun 2012 15:26:47 -0400 Subject: Btrfs: call filemap_fdatawrite twice for compression I removed this in an earlier commit and I was wrong. Because compression can return from filemap_fdatawrite() without having actually set any of it's pages as writeback() it can make filemap_fdatawait() do essentially nothing, and then we won't find any ordered extents because they may not have been created yet. So not only does this make fsync() completely useless, but it will also screw up if you truncate on a non-page aligned offset since we zero out the end and then wait on ordered extents and then call drop caches. We can drop the cache before the io completes and then we try to unpin the extent we just wrote we won't find it and everything goes sideways. So fix this by putting it back and put a giant comment there to keep me from trying to remove it in the future. Thanks, Signed-off-by: Josef Bacik diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index e616f887..12394a9 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -37,6 +37,7 @@ #define BTRFS_INODE_IN_DEFRAG 3 #define BTRFS_INODE_DELALLOC_META_RESERVED 4 #define BTRFS_INODE_HAS_ORPHAN_ITEM 5 +#define BTRFS_INODE_HAS_ASYNC_EXTENT 6 /* in memory btrfs inode */ struct btrfs_inode { diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 06075043..7a090fb 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1398,20 +1398,23 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, int ret; struct btrfs_root *root = BTRFS_I(inode)->root; - if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) + if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) { ret = run_delalloc_nocow(inode, locked_page, start, end, page_started, 1, nr_written); - else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC) + } else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC) { ret = run_delalloc_nocow(inode, locked_page, start, end, page_started, 0, nr_written); - else if (!btrfs_test_opt(root, COMPRESS) && - !(BTRFS_I(inode)->force_compress) && - !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) + } else if (!btrfs_test_opt(root, COMPRESS) && + !(BTRFS_I(inode)->force_compress) && + !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) { ret = cow_file_range(inode, locked_page, start, end, page_started, nr_written, 1); - else + } else { + set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, + &BTRFS_I(inode)->runtime_flags); ret = cow_file_range_async(inode, locked_page, start, end, page_started, nr_written); + } return ret; } diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 9e138cd..643335a 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -627,7 +627,27 @@ void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) /* start IO across the range first to instantiate any delalloc * extents */ - filemap_write_and_wait_range(inode->i_mapping, start, orig_end); + filemap_fdatawrite_range(inode->i_mapping, start, orig_end); + + /* + * So with compression we will find and lock a dirty page and clear the + * first one as dirty, setup an async extent, and immediately return + * with the entire range locked but with nobody actually marked with + * writeback. So we can't just filemap_write_and_wait_range() and + * expect it to work since it will just kick off a thread to do the + * actual work. So we need to call filemap_fdatawrite_range _again_ + * since it will wait on the page lock, which won't be unlocked until + * after the pages have been marked as writeback and so we're good to go + * from there. We have to do this otherwise we'll miss the ordered + * extents and that results in badness. Please Josef, do not think you + * know better and pull this out at some point in the future, it is + * right and you are wrong. + */ + if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, + &BTRFS_I(inode)->runtime_flags)) + filemap_fdatawrite_range(inode->i_mapping, start, orig_end); + + filemap_fdatawait_range(inode->i_mapping, start, orig_end); end = orig_end; found = 0; -- cgit v0.10.2 From 6c282eb40ed6f64a51ff447707714df551d85b8e Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 11 Jun 2012 16:03:35 +0800 Subject: Btrfs: fix defrag regression If a file has 3 small extents: | ext1 | ext2 | ext3 | Running "btrfs fi defrag" will only defrag the last two extents, if those extent mappings hasn't been read into memory from disk. This bug was introduced by commit 17ce6ef8d731af5edac8c39e806db4c7e1f6956f ("Btrfs: add a check to decide if we should defrag the range") The cause is, that commit looked into previous and next extents using lookup_extent_mapping() only. While at it, remove the code that checks the previous extent, since it's sufficient to check the next extent. Signed-off-by: Li Zefan diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c5254dd..a98f7d2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -786,39 +786,57 @@ none: return -ENOENT; } -/* - * Validaty check of prev em and next em: - * 1) no prev/next em - * 2) prev/next em is an hole/inline extent - */ -static int check_adjacent_extents(struct inode *inode, struct extent_map *em) +static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start) { struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; - struct extent_map *prev = NULL, *next = NULL; - int ret = 0; + struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; + struct extent_map *em; + u64 len = PAGE_CACHE_SIZE; + /* + * hopefully we have this extent in the tree already, try without + * the full extent lock + */ read_lock(&em_tree->lock); - prev = lookup_extent_mapping(em_tree, em->start - 1, (u64)-1); - next = lookup_extent_mapping(em_tree, em->start + em->len, (u64)-1); + em = lookup_extent_mapping(em_tree, start, len); read_unlock(&em_tree->lock); - if ((!prev || prev->block_start >= EXTENT_MAP_LAST_BYTE) && - (!next || next->block_start >= EXTENT_MAP_LAST_BYTE)) - ret = 1; - free_extent_map(prev); - free_extent_map(next); + if (!em) { + /* get the big lock and read metadata off disk */ + lock_extent(io_tree, start, start + len - 1); + em = btrfs_get_extent(inode, NULL, 0, start, len, 0); + unlock_extent(io_tree, start, start + len - 1); + if (IS_ERR(em)) + return NULL; + } + + return em; +} + +static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em) +{ + struct extent_map *next; + bool ret = true; + + /* this is the last extent */ + if (em->start + em->len >= i_size_read(inode)) + return false; + + next = defrag_lookup_extent(inode, em->start + em->len); + if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE) + ret = false; + + free_extent_map(next); return ret; } -static int should_defrag_range(struct inode *inode, u64 start, u64 len, - int thresh, u64 *last_len, u64 *skip, - u64 *defrag_end) +static int should_defrag_range(struct inode *inode, u64 start, int thresh, + u64 *last_len, u64 *skip, u64 *defrag_end) { - struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; - struct extent_map *em = NULL; - struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; + struct extent_map *em; int ret = 1; + bool next_mergeable = true; /* * make sure that once we start defragging an extent, we keep on @@ -829,23 +847,9 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, *skip = 0; - /* - * hopefully we have this extent in the tree already, try without - * the full extent lock - */ - read_lock(&em_tree->lock); - em = lookup_extent_mapping(em_tree, start, len); - read_unlock(&em_tree->lock); - - if (!em) { - /* get the big lock and read metadata off disk */ - lock_extent(io_tree, start, start + len - 1); - em = btrfs_get_extent(inode, NULL, 0, start, len, 0); - unlock_extent(io_tree, start, start + len - 1); - - if (IS_ERR(em)) - return 0; - } + em = defrag_lookup_extent(inode, start); + if (!em) + return 0; /* this will cover holes, and inline extents */ if (em->block_start >= EXTENT_MAP_LAST_BYTE) { @@ -853,18 +857,15 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, goto out; } - /* If we have nothing to merge with us, just skip. */ - if (check_adjacent_extents(inode, em)) { - ret = 0; - goto out; - } + next_mergeable = defrag_check_next_extent(inode, em); /* - * we hit a real extent, if it is big don't bother defragging it again + * we hit a real extent, if it is big or the next extent is not a + * real extent, don't bother defragging it */ - if ((*last_len == 0 || *last_len >= thresh) && em->len >= thresh) + if ((*last_len == 0 || *last_len >= thresh) && + (em->len >= thresh || !next_mergeable)) ret = 0; - out: /* * last_len ends up being a counter of how many bytes we've defragged. @@ -1143,8 +1144,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, break; if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, - PAGE_CACHE_SIZE, extent_thresh, - &last_len, &skip, &defrag_end)) { + extent_thresh, &last_len, &skip, + &defrag_end)) { unsigned long next; /* * the should_defrag function tells us how much to skip -- cgit v0.10.2 From 69e380d176e73653e09ce2cf3a5dc09682a69229 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 11 Jun 2012 17:10:51 +0800 Subject: Btrfs: fix incompat flags setting It's a bug, but it happens to work, as BTRFS_COMPRESS_LZO == 2, which has only one bit set. Signed-off-by: Li Zefan diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 1c9664b..9a569ae 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2119,7 +2119,7 @@ int open_ctree(struct super_block *sb, features = btrfs_super_incompat_flags(disk_super); features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; - if (tree_root->fs_info->compress_type & BTRFS_COMPRESS_LZO) + if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO) features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; /* -- cgit v0.10.2 From f948501b36c6b3d9352ce212a197098a7e958971 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 15 Jun 2012 14:51:39 +1000 Subject: Make hard_irq_disable() actually hard-disable interrupts At present, hard_irq_disable() does nothing on powerpc because of this code in include/linux/interrupt.h: #ifndef hard_irq_disable #define hard_irq_disable() do { } while(0) #endif So we need to make our hard_irq_disable be a macro. It was previously a macro until commit 7230c56441 ("powerpc: Rework lazy-interrupt handling") changed it to a static inline function. Cc: stable@vger.kernel.org Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras -- arch/powerpc/include/asm/hw_irq.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index c9aac24..32b394f 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -100,6 +100,9 @@ static inline void hard_irq_disable(void) get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; } +/* include/linux/interrupt.h needs hard_irq_disable to be a macro */ +#define hard_irq_disable hard_irq_disable + /* * This is called by asynchronous interrupts to conditionally * re-enable hard interrupts when soft-disabled after having -- cgit v0.10.2 From bc1782374b128103ae9689e0753e0610f35b6bfd Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 14 Jun 2012 02:23:18 -0600 Subject: Btrfs: fix missing inherited flag in rename When we move a file into a directory with compression flag, we need to inherite BTRFS_INODE_COMPRESS and clear BTRFS_INODE_NOCOMPRESS as well. But if we move a file into a directory without compression flag, we need to clear both of them. It is the way how our setflags deals with compression flag, so keep the same behaviour here. Signed-off-by: Liu Bo Signed-off-by: Chris Mason diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7a090fb..3f2c8cb 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7122,10 +7122,13 @@ static void fixup_inode_flags(struct inode *dir, struct inode *inode) else b_inode->flags &= ~BTRFS_INODE_NODATACOW; - if (b_dir->flags & BTRFS_INODE_COMPRESS) + if (b_dir->flags & BTRFS_INODE_COMPRESS) { b_inode->flags |= BTRFS_INODE_COMPRESS; - else - b_inode->flags &= ~BTRFS_INODE_COMPRESS; + b_inode->flags &= ~BTRFS_INODE_NOCOMPRESS; + } else { + b_inode->flags &= ~(BTRFS_INODE_COMPRESS | + BTRFS_INODE_NOCOMPRESS); + } } static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, -- cgit v0.10.2 From 4e42ae1bdcda77fc958a17d7ff4ba5a9c9c207da Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 14 Jun 2012 02:23:19 -0600 Subject: Btrfs: do not resize a seeding device Seeding devices are not supposed to change any more. Signed-off-by: Liu Bo Signed-off-by: Chris Mason diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a98f7d2..58adbd0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1306,6 +1306,13 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, ret = -EINVAL; goto out_free; } + if (device->fs_devices && device->fs_devices->seeding) { + printk(KERN_INFO "btrfs: resizer unable to apply on " + "seeding device %llu\n", devid); + ret = -EINVAL; + goto out_free; + } + if (!strcmp(sizestr, "max")) new_size = device->bdev->bd_inode->i_size; else { -- cgit v0.10.2 From 6e841e32b159e298debbb2cb0e9158e894fcaf05 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 14 Jun 2012 02:23:20 -0600 Subject: Btrfs: avoid memory leak of extent state in error handling routine We've forgotten to clear extent states in pinned tree, which will results in space counter mismatch and memory leak: WARNING: at fs/btrfs/extent-tree.c:7537 btrfs_free_block_groups+0x1f3/0x2e0 [btrfs]() ... space_info 2 has 8380416 free, is not full space_info total=12582912, used=4096, pinned=4096, reserved=0, may_use=0, readonly=4194304 btrfs state leak: start 29364224 end 29376511 state 1 in tree ffff880075f20090 refs 1 ... Signed-off-by: Liu Bo Signed-off-by: Chris Mason diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9a569ae..63a3623 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3601,6 +3601,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, EXTENT_DIRTY); + btrfs_destroy_pinned_extent(root, + root->fs_info->pinned_extents); /* memset(cur_trans, 0, sizeof(*cur_trans)); -- cgit v0.10.2 From ed0eaa14981e87a1e185b61e4ef621c440e3930c Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 14 Jun 2012 02:23:21 -0600 Subject: Btrfs: make sure that we've made everything in pinned tree clean Since we have two trees for recording pinned extents, we need to go through both of them to make sure that we've done everything clean. Signed-off-by: Liu Bo Signed-off-by: Chris Mason diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 63a3623..ffdd76b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3557,8 +3557,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, u64 start; u64 end; int ret; + bool loop = true; unpin = pinned_extents; +again: while (1) { ret = find_first_extent_bit(unpin, 0, &start, &end, EXTENT_DIRTY); @@ -3576,6 +3578,15 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, cond_resched(); } + if (loop) { + if (unpin == &root->fs_info->freed_extents[0]) + unpin = &root->fs_info->freed_extents[1]; + else + unpin = &root->fs_info->freed_extents[0]; + loop = false; + goto again; + } + return 0; } -- cgit v0.10.2 From 67cde3448d951b55088a6ea3bb1aee0160068fb9 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Thu, 14 Jun 2012 02:23:22 -0600 Subject: Btrfs: destroy the items of the delayed inodes in error handling routine the items of the delayed inodes were forgotten to be freed, this patch fixes it. Signed-off-by: Miao Xie Signed-off-by: Chris Mason diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index c18d044..2399f40 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1879,3 +1879,21 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root) } } } + +void btrfs_destroy_delayed_inodes(struct btrfs_root *root) +{ + struct btrfs_delayed_root *delayed_root; + struct btrfs_delayed_node *curr_node, *prev_node; + + delayed_root = btrfs_get_delayed_root(root); + + curr_node = btrfs_first_delayed_node(delayed_root); + while (curr_node) { + __btrfs_kill_delayed_node(curr_node); + + prev_node = curr_node; + curr_node = btrfs_next_delayed_node(curr_node); + btrfs_release_delayed_node(prev_node); + } +} + diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 7083d08..f5aa402 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -124,6 +124,9 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev); /* Used for drop dead root */ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); +/* Used for clean the transaction */ +void btrfs_destroy_delayed_inodes(struct btrfs_root *root); + /* Used for readdir() */ void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, struct list_head *del_list); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index ffdd76b..e22c5bb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3608,6 +3608,9 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, cur_trans->commit_done = 1; wake_up(&cur_trans->commit_wait); + btrfs_destroy_delayed_inodes(root); + btrfs_assert_delayed_root_empty(root); + btrfs_destroy_pending_snapshots(cur_trans); btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, @@ -3662,6 +3665,9 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) if (waitqueue_active(&t->commit_wait)) wake_up(&t->commit_wait); + btrfs_destroy_delayed_inodes(root); + btrfs_assert_delayed_root_empty(root); + btrfs_destroy_pending_snapshots(t); btrfs_destroy_delalloc_inodes(root); -- cgit v0.10.2 From 9c106405ddf893fcd04cd46555464417d2df8451 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 14 Jun 2012 02:23:25 -0600 Subject: Btrfs: update MAINTAINERS info for BTRFS FILE SYSTEM Update to the latest btrfs's maintainer mail and git repo. Signed-off-by: Liu Bo Signed-off-by: Chris Mason diff --git a/MAINTAINERS b/MAINTAINERS index b362709..8bfa7f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1630,11 +1630,11 @@ S: Maintained F: drivers/gpio/gpio-bt8xx.c BTRFS FILE SYSTEM -M: Chris Mason +M: Chris Mason L: linux-btrfs@vger.kernel.org W: http://btrfs.wiki.kernel.org/ Q: http://patchwork.kernel.org/project/linux-btrfs/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git S: Maintained F: Documentation/filesystems/btrfs.txt F: fs/btrfs/ -- cgit v0.10.2 From 4325edd0786fdd3909f9550e52a963b2fe54f78b Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 15 Jun 2012 20:02:02 -0400 Subject: Btrfs: init old_generation in get_old_root gcc was giving an uninit variable warning here. Strictly speaking we don't need to init it, but this will make things much less error prone. Signed-off-by: Chris Mason diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 04b06bc..15cbc2b 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1175,7 +1175,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) struct tree_mod_elem *tm; struct extent_buffer *eb; struct tree_mod_root *old_root = NULL; - u64 old_generation; + u64 old_generation = 0; u64 logical; eb = btrfs_read_lock_root_node(root); -- cgit v0.10.2 From a8c4a33b98b097e69cd1a10672c43d17ad0ffb25 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 15 Jun 2012 20:07:17 -0400 Subject: Btrfs: cast devid to unsigned long long for printk %llu Avoid warning in 32 bit machines Signed-off-by: Chris Mason diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 58adbd0..0e92e57 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1308,7 +1308,8 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, } if (device->fs_devices && device->fs_devices->seeding) { printk(KERN_INFO "btrfs: resizer unable to apply on " - "seeding device %llu\n", devid); + "seeding device %llu\n", + (unsigned long long)devid); ret = -EINVAL; goto out_free; } -- cgit v0.10.2 From 9b15b817f3d62409290fd56fe3cbb076a931bb0a Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 15 Jun 2012 17:55:50 -0700 Subject: swap: fix shmem swapping when more than 8 areas Minchan Kim reports that when a system has many swap areas, and tmpfs swaps out to the ninth or more, shmem_getpage_gfp()'s attempts to read back the page cannot locate it, and the read fails with -ENOMEM. Whoops. Yes, I blindly followed read_swap_header()'s pte_to_swp_entry( swp_entry_to_pte()) technique for determining maximum usable swap offset, without stopping to realize that that actually depends upon the pte swap encoding shifting swap offset to the higher bits and truncating it there. Whereas our radix_tree swap encoding leaves offset in the lower bits: it's swap "type" (that is, index of swap area) that was truncated. Fix it by reducing the SWP_TYPE_SHIFT() in swapops.h, and removing the broken radix_to_swp_entry(swp_to_radix_entry()) from read_swap_header(). This does not reduce the usable size of a swap area any further, it leaves it as claimed when making the original commit: no change from 3.0 on x86_64, nor on i386 without PAE; but 3.0's 512GB is reduced to 128GB per swapfile on i386 with PAE. It's not a change I would have risked five years ago, but with x86_64 supported for ten years, I believe it's appropriate now. Hmm, and what if some architecture implements its swap pte with offset encoded below type? That would equally break the maximum usable swap offset check. Happily, they all follow the same tradition of encoding offset above type, but I'll prepare a check on that for next. Reported-and-Reviewed-and-Tested-by: Minchan Kim Signed-off-by: Hugh Dickins Cc: stable@vger.kernel.org [3.1, 3.2, 3.3, 3.4] Signed-off-by: Linus Torvalds diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 792d16d..47ead51 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -9,13 +9,15 @@ * get good packing density in that tree, so the index should be dense in * the low-order bits. * - * We arrange the `type' and `offset' fields so that `type' is at the five + * We arrange the `type' and `offset' fields so that `type' is at the seven * high-order bits of the swp_entry_t and `offset' is right-aligned in the - * remaining bits. + * remaining bits. Although `type' itself needs only five bits, we allow for + * shmem/tmpfs to shift it all up a further two bits: see swp_to_radix_entry(). * * swp_entry_t's are *never* stored anywhere in their arch-dependent format. */ -#define SWP_TYPE_SHIFT(e) (sizeof(e.val) * 8 - MAX_SWAPFILES_SHIFT) +#define SWP_TYPE_SHIFT(e) ((sizeof(e.val) * 8) - \ + (MAX_SWAPFILES_SHIFT + RADIX_TREE_EXCEPTIONAL_SHIFT)) #define SWP_OFFSET_MASK(e) ((1UL << SWP_TYPE_SHIFT(e)) - 1) /* diff --git a/mm/swapfile.c b/mm/swapfile.c index de5bc51..71373d0 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1916,24 +1916,20 @@ static unsigned long read_swap_header(struct swap_info_struct *p, /* * Find out how many pages are allowed for a single swap - * device. There are three limiting factors: 1) the number + * device. There are two limiting factors: 1) the number * of bits for the swap offset in the swp_entry_t type, and * 2) the number of bits in the swap pte as defined by the - * the different architectures, and 3) the number of free bits - * in an exceptional radix_tree entry. In order to find the + * different architectures. In order to find the * largest possible bit mask, a swap entry with swap type 0 * and swap offset ~0UL is created, encoded to a swap pte, * decoded to a swp_entry_t again, and finally the swap * offset is extracted. This will mask all the bits from * the initial ~0UL mask that can't be encoded in either * the swp_entry_t or the architecture definition of a - * swap pte. Then the same is done for a radix_tree entry. + * swap pte. */ maxpages = swp_offset(pte_to_swp_entry( - swp_entry_to_pte(swp_entry(0, ~0UL)))); - maxpages = swp_offset(radix_to_swp_entry( - swp_to_radix_entry(swp_entry(0, maxpages)))) + 1; - + swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; if (maxpages > swap_header->info.last_page) { maxpages = swap_header->info.last_page + 1; /* p->max is an unsigned int: don't overflow it */ -- cgit v0.10.2 From 6699c8cda36f296e315068ed9bbe4f03e6ed4044 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Sat, 16 Jun 2012 16:53:06 -0400 Subject: tile: fix bug in get_user() for 4-byte values The definition of 32-bit values in the 64-bit tilegx architecture is that they should be sign-extended regardless of whether they are considered signed or unsigned by the compiler. Accordingly, we need to use an "ld4s" rather than "ld4u" to load and sign-extend for get_user(). This fixes glibc bug 14238 (see http://sourceware.org/bugzilla), introduced during the 3.5 merge window. Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h index c3dd275..9ab078a 100644 --- a/arch/tile/include/asm/uaccess.h +++ b/arch/tile/include/asm/uaccess.h @@ -146,7 +146,7 @@ extern int fixup_exception(struct pt_regs *regs); #ifdef __tilegx__ #define __get_user_1(x, ptr, ret) __get_user_asm(ld1u, x, ptr, ret) #define __get_user_2(x, ptr, ret) __get_user_asm(ld2u, x, ptr, ret) -#define __get_user_4(x, ptr, ret) __get_user_asm(ld4u, x, ptr, ret) +#define __get_user_4(x, ptr, ret) __get_user_asm(ld4s, x, ptr, ret) #define __get_user_8(x, ptr, ret) __get_user_asm(ld, x, ptr, ret) #else #define __get_user_1(x, ptr, ret) __get_user_asm(lb_u, x, ptr, ret) -- cgit v0.10.2 From 485802a6c524e62b5924849dd727ddbb1497cc71 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Jun 2012 17:25:17 -0700 Subject: Linux 3.5-rc3 diff --git a/Makefile b/Makefile index d845c2a..b771af5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 5 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit v0.10.2