From d7124073add4cd04508f9ae3adc2746c61d7e78b Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@linux-foundation.org> Date: Mon, 17 Dec 2012 15:59:22 -0800 Subject: [PATCH 001/180] create non-empty arch/x86/include/uapi/asm/ files patch(1) doesn't create zero-length files, so my kernel didn't compile. Put something in these files so patch(1) actually creates them. Cc: David Howells <dhowells@redhat.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Dave Jones <davej@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/include/uapi/asm/hw_breakpoint.h | 1 + arch/x86/include/uapi/asm/setup.h | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/include/uapi/asm/hw_breakpoint.h b/arch/x86/include/uapi/asm/hw_breakpoint.h index e69de29bb2d1..79a9626b5500 100644 --- a/arch/x86/include/uapi/asm/hw_breakpoint.h +++ b/arch/x86/include/uapi/asm/hw_breakpoint.h @@ -0,0 +1 @@ +/* */ diff --git a/arch/x86/include/uapi/asm/setup.h b/arch/x86/include/uapi/asm/setup.h index e69de29bb2d1..79a9626b5500 100644 --- a/arch/x86/include/uapi/asm/setup.h +++ b/arch/x86/include/uapi/asm/setup.h @@ -0,0 +1 @@ +/* */ From b3dd20709db2cab0da0ade1f246fd6e6ab1396eb Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@linux-foundation.org> Date: Mon, 17 Dec 2012 15:59:24 -0800 Subject: [PATCH 002/180] mm/memory.c: suppress warning gcc-4.4.4 screws this up. mm/memory.c: In function 'do_pmd_numa_page': mm/memory.c:3594: warning: no return statement in function returning non-void Cc: Mel Gorman <mgorman@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- mm/memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memory.c b/mm/memory.c index e6a3b933517e..23f1fdfdfcf1 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3590,6 +3590,7 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, pmd_t *pmdp) { BUG(); + return 0; } #endif /* CONFIG_NUMA_BALANCING */ From 275b8b8917b92822442d6739807a3e033ddbeb5e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Mon, 17 Dec 2012 15:59:26 -0800 Subject: [PATCH 003/180] frv: fix use of extinct _sbss and _ebss in debug code Nowadays it should probably use __bss_start and __bss_stop Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/frv/kernel/setup.c | 2 +- arch/frv/mm/init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index b8993c87d3de..961e18495589 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -817,7 +817,7 @@ void __init setup_arch(char **cmdline_p) printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, (int) &_sdata, (int) &_edata, - (int) &_sbss, (int) &_ebss); + (int) &__bss_start, (int) &__bss_stop); #endif #ifdef CONFIG_VT diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index a19effcccb34..92e97b0894a6 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -146,7 +146,7 @@ void __init mem_init(void) #else codek = (_etext - _stext) >> 10; - datak = 0; //(_ebss - _sdata) >> 10; + datak = 0; //(__bss_stop - _sdata) >> 10; #endif tmp = nr_free_pages() << PAGE_SHIFT; From 3515b737d3c1377874c5cba8b7db3d2477da3af3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Mon, 17 Dec 2012 15:59:27 -0800 Subject: [PATCH 004/180] frv: properly use the declarations provided by <asm/sections.h> - Remove the superfluous address-of ('&') operators, - Remove the unneeded casts, use %p to format pointers instead. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/frv/kernel/setup.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 961e18495589..3cb3392f799e 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -804,9 +804,9 @@ void __init setup_arch(char **cmdline_p) BUG_ON(memory_start == memory_end); - init_mm.start_code = (unsigned long) &_stext; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; + init_mm.start_code = (unsigned long) _stext; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; #if 0 /* DAVIDM - don't set brk just incase someone decides to use it */ init_mm.brk = (unsigned long) &_end; #else @@ -814,10 +814,8 @@ void __init setup_arch(char **cmdline_p) #endif #ifdef DEBUG - printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x BSS=0x%06x-0x%06x\n", - (int) &_stext, (int) &_etext, - (int) &_sdata, (int) &_edata, - (int) &__bss_start, (int) &__bss_stop); + printk("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", + _stext, _etext, _sdata, _edata, __bss_start, __bss_stop); #endif #ifdef CONFIG_VT From fbb97d87802247a7bb32a207a8275372e79e6b88 Mon Sep 17 00:00:00 2001 From: Wen Congyang <wency@cn.fujitsu.com> Date: Mon, 17 Dec 2012 15:59:29 -0800 Subject: [PATCH 005/180] Documentation/kernel-parameters.txt: update mem= option's spec according to its implementation Current mem= implementation seems buggy because the specification and implementation don't match. The current mem= has been working for many years and it's not buggy - it works as expected. So we should update the specification. Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Cc: Rob Landley <rob@landley.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/kernel-parameters.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ea8e5b485576..ddd84d627185 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1503,9 +1503,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory Amount of memory to be used when the kernel is not able to see the whole system memory or for test. - [X86-32] Use together with memmap= to avoid physical - address space collisions. Without memmap= PCI devices - could be placed at addresses belonging to unused RAM. + [X86] Work as limiting max address. Use together + with memmap= to avoid physical address space collisions. + Without memmap= PCI devices could be placed at addresses + belonging to unused RAM. mem=nopentium [BUGS=X86-32] Disable usage of 4MB pages for kernel memory. From 7929d407e47fbf843fe1337fd95ed57785ae5e9d Mon Sep 17 00:00:00 2001 From: Matthew Leach <matthew@mattleach.net> Date: Mon, 17 Dec 2012 15:59:32 -0800 Subject: [PATCH 006/180] include/linux/init.h: use the stringify operator for the __define_initcall macro Currently the __define_initcall() macro takes three arguments, fn, id and level. The level argument is exactly the same as the id argument but wrapped in quotes. To overcome this need to specify three arguments to the __define_initcall macro, where one argument is the stringification of another, we can just use the stringification macro instead. Signed-off-by: Matthew Leach <matthew@mattleach.net> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/powerpc/include/asm/machdep.h | 34 +++++++++++++------------- include/linux/init.h | 38 +++++++++++++++--------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index c4231973edd3..3c82daf8be99 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -320,28 +320,28 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal) ppc_md.log_error(buf, err_type, fatal); } -#define __define_machine_initcall(mach,level,fn,id) \ +#define __define_machine_initcall(mach, fn, id) \ static int __init __machine_initcall_##mach##_##fn(void) { \ if (machine_is(mach)) return fn(); \ return 0; \ } \ - __define_initcall(level,__machine_initcall_##mach##_##fn,id); + __define_initcall(__machine_initcall_##mach##_##fn, id); -#define machine_core_initcall(mach,fn) __define_machine_initcall(mach,"1",fn,1) -#define machine_core_initcall_sync(mach,fn) __define_machine_initcall(mach,"1s",fn,1s) -#define machine_postcore_initcall(mach,fn) __define_machine_initcall(mach,"2",fn,2) -#define machine_postcore_initcall_sync(mach,fn) __define_machine_initcall(mach,"2s",fn,2s) -#define machine_arch_initcall(mach,fn) __define_machine_initcall(mach,"3",fn,3) -#define machine_arch_initcall_sync(mach,fn) __define_machine_initcall(mach,"3s",fn,3s) -#define machine_subsys_initcall(mach,fn) __define_machine_initcall(mach,"4",fn,4) -#define machine_subsys_initcall_sync(mach,fn) __define_machine_initcall(mach,"4s",fn,4s) -#define machine_fs_initcall(mach,fn) __define_machine_initcall(mach,"5",fn,5) -#define machine_fs_initcall_sync(mach,fn) __define_machine_initcall(mach,"5s",fn,5s) -#define machine_rootfs_initcall(mach,fn) __define_machine_initcall(mach,"rootfs",fn,rootfs) -#define machine_device_initcall(mach,fn) __define_machine_initcall(mach,"6",fn,6) -#define machine_device_initcall_sync(mach,fn) __define_machine_initcall(mach,"6s",fn,6s) -#define machine_late_initcall(mach,fn) __define_machine_initcall(mach,"7",fn,7) -#define machine_late_initcall_sync(mach,fn) __define_machine_initcall(mach,"7s",fn,7s) +#define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1) +#define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s) +#define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2) +#define machine_postcore_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 2s) +#define machine_arch_initcall(mach, fn) __define_machine_initcall(mach, fn, 3) +#define machine_arch_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 3s) +#define machine_subsys_initcall(mach, fn) __define_machine_initcall(mach, fn, 4) +#define machine_subsys_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 4s) +#define machine_fs_initcall(mach, fn) __define_machine_initcall(mach, fn, 5) +#define machine_fs_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 5s) +#define machine_rootfs_initcall(mach, fn) __define_machine_initcall(mach, fn, rootfs) +#define machine_device_initcall(mach, fn) __define_machine_initcall(mach, fn, 6) +#define machine_device_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 6s) +#define machine_late_initcall(mach, fn) __define_machine_initcall(mach, fn, 7) +#define machine_late_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 7s) #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MACHDEP_H */ diff --git a/include/linux/init.h b/include/linux/init.h index f63692d6902e..a799273714ac 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -182,16 +182,16 @@ extern bool initcall_debug; * can point at the same handler without causing duplicate-symbol build errors. */ -#define __define_initcall(level,fn,id) \ +#define __define_initcall(fn, id) \ static initcall_t __initcall_##fn##id __used \ - __attribute__((__section__(".initcall" level ".init"))) = fn + __attribute__((__section__(".initcall" #id ".init"))) = fn /* * Early initcalls run before initializing SMP. * * Only for built-in code, not modules. */ -#define early_initcall(fn) __define_initcall("early",fn,early) +#define early_initcall(fn) __define_initcall(fn, early) /* * A "pure" initcall has no dependencies on anything else, and purely @@ -200,23 +200,23 @@ extern bool initcall_debug; * This only exists for built-in code, not for modules. * Keep main.c:initcall_level_names[] in sync. */ -#define pure_initcall(fn) __define_initcall("0",fn,0) +#define pure_initcall(fn) __define_initcall(fn, 0) -#define core_initcall(fn) __define_initcall("1",fn,1) -#define core_initcall_sync(fn) __define_initcall("1s",fn,1s) -#define postcore_initcall(fn) __define_initcall("2",fn,2) -#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s) -#define arch_initcall(fn) __define_initcall("3",fn,3) -#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s) -#define subsys_initcall(fn) __define_initcall("4",fn,4) -#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s) -#define fs_initcall(fn) __define_initcall("5",fn,5) -#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s) -#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs) -#define device_initcall(fn) __define_initcall("6",fn,6) -#define device_initcall_sync(fn) __define_initcall("6s",fn,6s) -#define late_initcall(fn) __define_initcall("7",fn,7) -#define late_initcall_sync(fn) __define_initcall("7s",fn,7s) +#define core_initcall(fn) __define_initcall(fn, 1) +#define core_initcall_sync(fn) __define_initcall(fn, 1s) +#define postcore_initcall(fn) __define_initcall(fn, 2) +#define postcore_initcall_sync(fn) __define_initcall(fn, 2s) +#define arch_initcall(fn) __define_initcall(fn, 3) +#define arch_initcall_sync(fn) __define_initcall(fn, 3s) +#define subsys_initcall(fn) __define_initcall(fn, 4) +#define subsys_initcall_sync(fn) __define_initcall(fn, 4s) +#define fs_initcall(fn) __define_initcall(fn, 5) +#define fs_initcall_sync(fn) __define_initcall(fn, 5s) +#define rootfs_initcall(fn) __define_initcall(fn, rootfs) +#define device_initcall(fn) __define_initcall(fn, 6) +#define device_initcall_sync(fn) __define_initcall(fn, 6s) +#define late_initcall(fn) __define_initcall(fn, 7) +#define late_initcall_sync(fn) __define_initcall(fn, 7s) #define __initcall(fn) device_initcall(fn) From 66d93341b507185d6934756fb6f6b69b42ff43e4 Mon Sep 17 00:00:00 2001 From: Tao Ma <boyu.mt@taobao.com> Date: Mon, 17 Dec 2012 15:59:33 -0800 Subject: [PATCH 007/180] Documentation: remove reference to feature-removal-schedule.txt In commit 9c0ece069b32 ("Get rid of Documentation/feature-removal.txt"), Linus removed feature-removal-schedule.txt from Documentation, but there is still some reference to this file. So remove them. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/00-INDEX | 2 -- Documentation/ABI/README | 3 --- 2 files changed, 5 deletions(-) diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index ceb1ff735469..8afe64fb2009 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -136,8 +136,6 @@ fault-injection/ - dir with docs about the fault injection capabilities infrastructure. fb/ - directory with info on the frame buffer graphics abstraction layer. -feature-removal-schedule.txt - - list of files and features that are going to be removed. filesystems/ - info on the vfs and the various filesystems that Linux supports. firmware_class/ diff --git a/Documentation/ABI/README b/Documentation/ABI/README index 9feaf16f1617..10069828568b 100644 --- a/Documentation/ABI/README +++ b/Documentation/ABI/README @@ -36,9 +36,6 @@ The different levels of stability are: the kernel, but are marked to be removed at some later point in time. The description of the interface will document the reason why it is obsolete and when it can be expected to be removed. - The file Documentation/feature-removal-schedule.txt may describe - some of these interfaces, giving a schedule for when they will - be removed. removed/ This directory contains a list of the old interfaces that have From 8ec7d50f1ed2b072d23ce810f86df09ee0568d4b Mon Sep 17 00:00:00 2001 From: Tao Ma <boyu.mt@taobao.com> Date: Mon, 17 Dec 2012 15:59:36 -0800 Subject: [PATCH 008/180] kernel: remove reference to feature-removal-schedule.txt In commit 9c0ece069b32 ("Get rid of Documentation/feature-removal.txt"), Linus removed feature-removal-schedule.txt from Documentation, but there is still some reference to this file. So remove them. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- kernel/cgroup.c | 1 - kernel/module.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index f34c41bfaa37..571264830a29 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1333,7 +1333,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) if (ret) goto out_unlock; - /* See feature-removal-schedule.txt */ if (opts.subsys_mask != root->actual_subsys_mask || opts.release_agent) pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n", task_tgid_nr(current), current->comm); diff --git a/kernel/module.c b/kernel/module.c index 6e48c3a43599..808bd62e1723 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -372,9 +372,6 @@ static bool check_symbol(const struct symsearch *syms, printk(KERN_WARNING "Symbol %s is being used " "by a non-GPL module, which will not " "be allowed in the future\n", fsa->name); - printk(KERN_WARNING "Please see the file " - "Documentation/feature-removal-schedule.txt " - "in the kernel source tree for more details.\n"); } } From 8f6e60419645f7fea84c361ca2c16dd1feee08e4 Mon Sep 17 00:00:00 2001 From: Tao Ma <boyu.mt@taobao.com> Date: Mon, 17 Dec 2012 15:59:37 -0800 Subject: [PATCH 009/180] sound: remove reference to feature-removal-schedule.txt In commit 9c0ece069b32 ("Get rid of Documentation/feature-removal.txt"), Linus removed feature-removal-schedule.txt from Documentation, but there is still some reference to this file. So remove them. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- sound/Kconfig | 3 --- sound/sound_core.c | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/Kconfig b/sound/Kconfig index 261a03c8a209..c710ce2c5c37 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -52,9 +52,6 @@ config SOUND_OSS_CORE_PRECLAIM Disabling this allows alternative OSS implementations. - Please read Documentation/feature-removal-schedule.txt for - details. - If unsure, say Y. source "sound/oss/dmasound/Kconfig" diff --git a/sound/sound_core.c b/sound/sound_core.c index fb9255cca214..bb23009edc8d 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -146,8 +146,7 @@ extern int msnd_pinnacle_init(void); * devices only the standard chrdev aliases are requested. * * All these clutters are scheduled to be removed along with - * sound-slot/service-* module aliases. Please take a look at - * feature-removal-schedule.txt for details. + * sound-slot/service-* module aliases. */ #ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM static int preclaim_oss = 1; From c0f041602c33bae10b8e321c49024490d03ced3d Mon Sep 17 00:00:00 2001 From: Tao Ma <boyu.mt@taobao.com> Date: Mon, 17 Dec 2012 15:59:38 -0800 Subject: [PATCH 010/180] drivers: remove reference to feature-removal-schedule.txt In commit 9c0ece069b32 ("Get rid of Documentation/feature-removal.txt"), Linus removed feature-removal-schedule.txt from Documentation, but there is still some reference to this file. So remove them. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/net/wireless/Kconfig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 6deaae18db57..28aa05f60c26 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -156,11 +156,7 @@ config PRISM54 ---help--- This enables support for FullMAC PCI/Cardbus prism54 devices. This driver is now deprecated in favor for the SoftMAC driver, p54pci. - p54pci supports FullMAC PCI/Cardbus devices as well. For details on - the scheduled removal of this driver on the kernel see the feature - removal schedule: - - Documentation/feature-removal-schedule.txt + p54pci supports FullMAC PCI/Cardbus devices as well. For more information refer to the p54 wiki: From 965c8e59cfcf845ecde2265a1d1bfee5f011d302 Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@linux-foundation.org> Date: Mon, 17 Dec 2012 15:59:39 -0800 Subject: [PATCH 011/180] lseek: the "whence" argument is called "whence" But the kernel decided to call it "origin" instead. Fix most of the sites. Acked-by: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/bad_inode.c | 2 +- fs/block_dev.c | 4 ++-- fs/btrfs/file.c | 16 ++++++++-------- fs/ceph/dir.c | 4 ++-- fs/ceph/file.c | 6 +++--- fs/cifs/cifsfs.c | 8 ++++---- fs/configfs/dir.c | 4 ++-- fs/ext3/dir.c | 6 +++--- fs/ext4/dir.c | 6 +++--- fs/ext4/file.c | 22 +++++++++++----------- fs/fuse/file.c | 8 ++++---- fs/gfs2/file.c | 10 +++++----- fs/libfs.c | 4 ++-- fs/nfs/dir.c | 6 +++--- fs/nfs/file.c | 10 +++++----- fs/ocfs2/extent_map.c | 12 ++++++------ fs/ocfs2/file.c | 6 +++--- fs/pstore/inode.c | 6 +++--- fs/read_write.c | 40 ++++++++++++++++++++-------------------- fs/seq_file.c | 4 ++-- fs/ubifs/dir.c | 4 ++-- include/linux/fs.h | 12 ++++++------ include/linux/ftrace.h | 4 ++-- include/linux/syscalls.h | 4 ++-- kernel/trace/ftrace.c | 4 ++-- mm/shmem.c | 20 ++++++++++---------- 26 files changed, 116 insertions(+), 116 deletions(-) diff --git a/fs/bad_inode.c b/fs/bad_inode.c index b1342ffb3cf6..922ad460bff9 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -16,7 +16,7 @@ #include <linux/poll.h> -static loff_t bad_file_llseek(struct file *file, loff_t offset, int origin) +static loff_t bad_file_llseek(struct file *file, loff_t offset, int whence) { return -EIO; } diff --git a/fs/block_dev.c b/fs/block_dev.c index ab3a456f6650..172f8491a2bd 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -321,7 +321,7 @@ static int blkdev_write_end(struct file *file, struct address_space *mapping, * for a block special file file->f_path.dentry->d_inode->i_size is zero * so we compute the size by hand (just as in block_read/write above) */ -static loff_t block_llseek(struct file *file, loff_t offset, int origin) +static loff_t block_llseek(struct file *file, loff_t offset, int whence) { struct inode *bd_inode = file->f_mapping->host; loff_t size; @@ -331,7 +331,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin) size = i_size_read(bd_inode); retval = -EINVAL; - switch (origin) { + switch (whence) { case SEEK_END: offset += size; break; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index a8ee75cb96ee..9c6673a9231f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2120,7 +2120,7 @@ out: return ret; } -static int find_desired_extent(struct inode *inode, loff_t *offset, int origin) +static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) { struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_map *em; @@ -2154,7 +2154,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin) * before the position we want in case there is outstanding delalloc * going on here. */ - if (origin == SEEK_HOLE && start != 0) { + if (whence == SEEK_HOLE && start != 0) { if (start <= root->sectorsize) em = btrfs_get_extent_fiemap(inode, NULL, 0, 0, root->sectorsize, 0); @@ -2188,13 +2188,13 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin) } } - if (origin == SEEK_HOLE) { + if (whence == SEEK_HOLE) { *offset = start; free_extent_map(em); break; } } else { - if (origin == SEEK_DATA) { + if (whence == SEEK_DATA) { if (em->block_start == EXTENT_MAP_DELALLOC) { if (start >= inode->i_size) { free_extent_map(em); @@ -2231,16 +2231,16 @@ out: return ret; } -static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) +static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; int ret; mutex_lock(&inode->i_mutex); - switch (origin) { + switch (whence) { case SEEK_END: case SEEK_CUR: - offset = generic_file_llseek(file, offset, origin); + offset = generic_file_llseek(file, offset, whence); goto out; case SEEK_DATA: case SEEK_HOLE: @@ -2249,7 +2249,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) return -ENXIO; } - ret = find_desired_extent(inode, &offset, origin); + ret = find_desired_extent(inode, &offset, whence); if (ret) { mutex_unlock(&inode->i_mutex); return ret; diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index e5b77319c97b..8c1aabe93b67 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -454,7 +454,7 @@ static void reset_readdir(struct ceph_file_info *fi) fi->flags &= ~CEPH_F_ATEND; } -static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) +static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence) { struct ceph_file_info *fi = file->private_data; struct inode *inode = file->f_mapping->host; @@ -463,7 +463,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) mutex_lock(&inode->i_mutex); retval = -EINVAL; - switch (origin) { + switch (whence) { case SEEK_END: offset += inode->i_size + 2; /* FIXME */ break; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 5840d2aaed15..d4dfdcf76d7f 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -797,7 +797,7 @@ out: /* * llseek. be sure to verify file size on SEEK_END. */ -static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) +static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; int ret; @@ -805,7 +805,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) mutex_lock(&inode->i_mutex); __ceph_do_pending_vmtruncate(inode); - if (origin == SEEK_END || origin == SEEK_DATA || origin == SEEK_HOLE) { + if (whence == SEEK_END || whence == SEEK_DATA || whence == SEEK_HOLE) { ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); if (ret < 0) { offset = ret; @@ -813,7 +813,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) } } - switch (origin) { + switch (whence) { case SEEK_END: offset += inode->i_size; break; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 210f0af83fc4..ce9f3c5421bf 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -695,13 +695,13 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, return written; } -static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) +static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) { /* - * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate + * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate * the cached file length */ - if (origin != SEEK_SET && origin != SEEK_CUR) { + if (whence != SEEK_SET && whence != SEEK_CUR) { int rc; struct inode *inode = file->f_path.dentry->d_inode; @@ -728,7 +728,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) if (rc < 0) return (loff_t)rc; } - return generic_file_llseek(file, offset, origin); + return generic_file_llseek(file, offset, whence); } static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7414ae24a79b..712b10f64c70 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1613,12 +1613,12 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir return 0; } -static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) +static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence) { struct dentry * dentry = file->f_path.dentry; mutex_lock(&dentry->d_inode->i_mutex); - switch (origin) { + switch (whence) { case 1: offset += file->f_pos; case 0: diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index c8fff930790d..dd91264ba94f 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -296,17 +296,17 @@ static inline loff_t ext3_get_htree_eof(struct file *filp) * NOTE: offsets obtained *before* ext3_set_inode_flag(dir, EXT3_INODE_INDEX) * will be invalid once the directory was converted into a dx directory */ -loff_t ext3_dir_llseek(struct file *file, loff_t offset, int origin) +loff_t ext3_dir_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; int dx_dir = is_dx_dir(inode); loff_t htree_max = ext3_get_htree_eof(file); if (likely(dx_dir)) - return generic_file_llseek_size(file, offset, origin, + return generic_file_llseek_size(file, offset, whence, htree_max, htree_max); else - return generic_file_llseek(file, offset, origin); + return generic_file_llseek(file, offset, whence); } /* diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index b8d877f6c1fa..80a28b297279 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -333,17 +333,17 @@ static inline loff_t ext4_get_htree_eof(struct file *filp) * * For non-htree, ext4_llseek already chooses the proper max offset. */ -loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin) +loff_t ext4_dir_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; int dx_dir = is_dx_dir(inode); loff_t htree_max = ext4_get_htree_eof(file); if (likely(dx_dir)) - return generic_file_llseek_size(file, offset, origin, + return generic_file_llseek_size(file, offset, whence, htree_max, htree_max); else - return ext4_llseek(file, offset, origin); + return ext4_llseek(file, offset, whence); } /* diff --git a/fs/ext4/file.c b/fs/ext4/file.c index b64a60bf105a..d07c27ca594a 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -303,7 +303,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) * page cache has data or not. */ static int ext4_find_unwritten_pgoff(struct inode *inode, - int origin, + int whence, struct ext4_map_blocks *map, loff_t *offset) { @@ -333,10 +333,10 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, (pgoff_t)num); if (nr_pages == 0) { - if (origin == SEEK_DATA) + if (whence == SEEK_DATA) break; - BUG_ON(origin != SEEK_HOLE); + BUG_ON(whence != SEEK_HOLE); /* * If this is the first time to go into the loop and * offset is not beyond the end offset, it will be a @@ -352,7 +352,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, * offset is smaller than the first page offset, it will be a * hole at this offset. */ - if (lastoff == startoff && origin == SEEK_HOLE && + if (lastoff == startoff && whence == SEEK_HOLE && lastoff < page_offset(pvec.pages[0])) { found = 1; break; @@ -366,7 +366,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, * If the current offset is not beyond the end of given * range, it will be a hole. */ - if (lastoff < endoff && origin == SEEK_HOLE && + if (lastoff < endoff && whence == SEEK_HOLE && page->index > end) { found = 1; *offset = lastoff; @@ -391,10 +391,10 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, do { if (buffer_uptodate(bh) || buffer_unwritten(bh)) { - if (origin == SEEK_DATA) + if (whence == SEEK_DATA) found = 1; } else { - if (origin == SEEK_HOLE) + if (whence == SEEK_HOLE) found = 1; } if (found) { @@ -416,7 +416,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, * The no. of pages is less than our desired, that would be a * hole in there. */ - if (nr_pages < num && origin == SEEK_HOLE) { + if (nr_pages < num && whence == SEEK_HOLE) { found = 1; *offset = lastoff; break; @@ -609,7 +609,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) * by calling generic_file_llseek_size() with the appropriate maxbytes * value for each. */ -loff_t ext4_llseek(struct file *file, loff_t offset, int origin) +loff_t ext4_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; loff_t maxbytes; @@ -619,11 +619,11 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin) else maxbytes = inode->i_sb->s_maxbytes; - switch (origin) { + switch (whence) { case SEEK_SET: case SEEK_CUR: case SEEK_END: - return generic_file_llseek_size(file, offset, origin, + return generic_file_llseek_size(file, offset, whence, maxbytes, i_size_read(inode)); case SEEK_DATA: return ext4_seek_data(file, offset, maxbytes); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 78d2837bc940..e21d4d8f87e3 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1599,19 +1599,19 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) return err ? 0 : outarg.block; } -static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) +static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence) { loff_t retval; struct inode *inode = file->f_path.dentry->d_inode; /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */ - if (origin == SEEK_CUR || origin == SEEK_SET) - return generic_file_llseek(file, offset, origin); + if (whence == SEEK_CUR || whence == SEEK_SET) + return generic_file_llseek(file, offset, whence); mutex_lock(&inode->i_mutex); retval = fuse_update_attributes(inode, NULL, file, NULL); if (!retval) - retval = generic_file_llseek(file, offset, origin); + retval = generic_file_llseek(file, offset, whence); mutex_unlock(&inode->i_mutex); return retval; diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index dfe2d8cb9b2c..991ab2d484dd 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -44,7 +44,7 @@ * gfs2_llseek - seek to a location in a file * @file: the file * @offset: the offset - * @origin: Where to seek from (SEEK_SET, SEEK_CUR, or SEEK_END) + * @whence: Where to seek from (SEEK_SET, SEEK_CUR, or SEEK_END) * * SEEK_END requires the glock for the file because it references the * file's size. @@ -52,26 +52,26 @@ * Returns: The new offset, or errno */ -static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) +static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence) { struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_holder i_gh; loff_t error; - switch (origin) { + switch (whence) { case SEEK_END: /* These reference inode->i_size */ case SEEK_DATA: case SEEK_HOLE: error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (!error) { - error = generic_file_llseek(file, offset, origin); + error = generic_file_llseek(file, offset, whence); gfs2_glock_dq_uninit(&i_gh); } break; case SEEK_CUR: case SEEK_SET: - error = generic_file_llseek(file, offset, origin); + error = generic_file_llseek(file, offset, whence); break; default: error = -EINVAL; diff --git a/fs/libfs.c b/fs/libfs.c index 7cc37ca19cd8..35fc6e74cd88 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -81,11 +81,11 @@ int dcache_dir_close(struct inode *inode, struct file *file) return 0; } -loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) +loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) { struct dentry *dentry = file->f_path.dentry; mutex_lock(&dentry->d_inode->i_mutex); - switch (origin) { + switch (whence) { case 1: offset += file->f_pos; case 0: diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index b9e66b7e0c14..1cc71f60b491 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -871,7 +871,7 @@ out: return res; } -static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) +static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; @@ -880,10 +880,10 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - offset, origin); + offset, whence); mutex_lock(&inode->i_mutex); - switch (origin) { + switch (whence) { case 1: offset += filp->f_pos; case 0: diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 582bb8866131..3c2b893665ba 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -119,18 +119,18 @@ force_reval: return __nfs_revalidate_inode(server, inode); } -loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) +loff_t nfs_file_llseek(struct file *filp, loff_t offset, int whence) { dprintk("NFS: llseek file(%s/%s, %lld, %d)\n", filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_name.name, - offset, origin); + offset, whence); /* - * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate + * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate * the cached file length */ - if (origin != SEEK_SET && origin != SEEK_CUR) { + if (whence != SEEK_SET && whence != SEEK_CUR) { struct inode *inode = filp->f_mapping->host; int retval = nfs_revalidate_file_size(inode, filp); @@ -138,7 +138,7 @@ loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) return (loff_t)retval; } - return generic_file_llseek(filp, offset, origin); + return generic_file_llseek(filp, offset, whence); } EXPORT_SYMBOL_GPL(nfs_file_llseek); diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 70b5863a2d64..f487aa343442 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -832,7 +832,7 @@ out: return ret; } -int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin) +int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int whence) { struct inode *inode = file->f_mapping->host; int ret; @@ -843,7 +843,7 @@ int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin) struct buffer_head *di_bh = NULL; struct ocfs2_extent_rec rec; - BUG_ON(origin != SEEK_DATA && origin != SEEK_HOLE); + BUG_ON(whence != SEEK_DATA && whence != SEEK_HOLE); ret = ocfs2_inode_lock(inode, &di_bh, 0); if (ret) { @@ -859,7 +859,7 @@ int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin) } if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { - if (origin == SEEK_HOLE) + if (whence == SEEK_HOLE) *offset = inode->i_size; goto out_unlock; } @@ -888,8 +888,8 @@ int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin) is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ? 0 : 1; } - if ((!is_data && origin == SEEK_HOLE) || - (is_data && origin == SEEK_DATA)) { + if ((!is_data && whence == SEEK_HOLE) || + (is_data && whence == SEEK_DATA)) { if (extoff > *offset) *offset = extoff; goto out_unlock; @@ -899,7 +899,7 @@ int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin) cpos += clen; } - if (origin == SEEK_HOLE) { + if (whence == SEEK_HOLE) { extoff = cpos; extoff <<= cs_bits; extlen = clen; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index dda089804942..fe492e1a3cfc 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2637,14 +2637,14 @@ bail: } /* Refer generic_file_llseek_unlocked() */ -static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin) +static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; int ret = 0; mutex_lock(&inode->i_mutex); - switch (origin) { + switch (whence) { case SEEK_SET: break; case SEEK_END: @@ -2659,7 +2659,7 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin) break; case SEEK_DATA: case SEEK_HOLE: - ret = ocfs2_seek_data_hole_offset(file, &offset, origin); + ret = ocfs2_seek_data_hole_offset(file, &offset, whence); if (ret) goto out; break; diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index ed1d8c7212da..67de74ca85f4 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -151,13 +151,13 @@ static int pstore_file_open(struct inode *inode, struct file *file) return 0; } -static loff_t pstore_file_llseek(struct file *file, loff_t off, int origin) +static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence) { struct seq_file *sf = file->private_data; if (sf->op) - return seq_lseek(file, off, origin); - return default_llseek(file, off, origin); + return seq_lseek(file, off, whence); + return default_llseek(file, off, whence); } static const struct file_operations pstore_file_operations = { diff --git a/fs/read_write.c b/fs/read_write.c index d06534857e9e..1edaf099ddd7 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -54,7 +54,7 @@ static loff_t lseek_execute(struct file *file, struct inode *inode, * generic_file_llseek_size - generic llseek implementation for regular files * @file: file structure to seek on * @offset: file offset to seek to - * @origin: type of seek + * @whence: type of seek * @size: max size of this file in file system * @eof: offset used for SEEK_END position * @@ -67,12 +67,12 @@ static loff_t lseek_execute(struct file *file, struct inode *inode, * read/writes behave like SEEK_SET against seeks. */ loff_t -generic_file_llseek_size(struct file *file, loff_t offset, int origin, +generic_file_llseek_size(struct file *file, loff_t offset, int whence, loff_t maxsize, loff_t eof) { struct inode *inode = file->f_mapping->host; - switch (origin) { + switch (whence) { case SEEK_END: offset += eof; break; @@ -122,17 +122,17 @@ EXPORT_SYMBOL(generic_file_llseek_size); * generic_file_llseek - generic llseek implementation for regular files * @file: file structure to seek on * @offset: file offset to seek to - * @origin: type of seek + * @whence: type of seek * * This is a generic implemenation of ->llseek useable for all normal local * filesystems. It just updates the file offset to the value specified by - * @offset and @origin under i_mutex. + * @offset and @whence under i_mutex. */ -loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) +loff_t generic_file_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; - return generic_file_llseek_size(file, offset, origin, + return generic_file_llseek_size(file, offset, whence, inode->i_sb->s_maxbytes, i_size_read(inode)); } @@ -142,32 +142,32 @@ EXPORT_SYMBOL(generic_file_llseek); * noop_llseek - No Operation Performed llseek implementation * @file: file structure to seek on * @offset: file offset to seek to - * @origin: type of seek + * @whence: type of seek * * This is an implementation of ->llseek useable for the rare special case when * userspace expects the seek to succeed but the (device) file is actually not * able to perform the seek. In this case you use noop_llseek() instead of * falling back to the default implementation of ->llseek. */ -loff_t noop_llseek(struct file *file, loff_t offset, int origin) +loff_t noop_llseek(struct file *file, loff_t offset, int whence) { return file->f_pos; } EXPORT_SYMBOL(noop_llseek); -loff_t no_llseek(struct file *file, loff_t offset, int origin) +loff_t no_llseek(struct file *file, loff_t offset, int whence) { return -ESPIPE; } EXPORT_SYMBOL(no_llseek); -loff_t default_llseek(struct file *file, loff_t offset, int origin) +loff_t default_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_path.dentry->d_inode; loff_t retval; mutex_lock(&inode->i_mutex); - switch (origin) { + switch (whence) { case SEEK_END: offset += i_size_read(inode); break; @@ -216,7 +216,7 @@ out: } EXPORT_SYMBOL(default_llseek); -loff_t vfs_llseek(struct file *file, loff_t offset, int origin) +loff_t vfs_llseek(struct file *file, loff_t offset, int whence) { loff_t (*fn)(struct file *, loff_t, int); @@ -225,11 +225,11 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int origin) if (file->f_op && file->f_op->llseek) fn = file->f_op->llseek; } - return fn(file, offset, origin); + return fn(file, offset, whence); } EXPORT_SYMBOL(vfs_llseek); -SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin) +SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) { off_t retval; struct fd f = fdget(fd); @@ -237,8 +237,8 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin) return -EBADF; retval = -EINVAL; - if (origin <= SEEK_MAX) { - loff_t res = vfs_llseek(f.file, offset, origin); + if (whence <= SEEK_MAX) { + loff_t res = vfs_llseek(f.file, offset, whence); retval = res; if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ @@ -250,7 +250,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin) #ifdef __ARCH_WANT_SYS_LLSEEK SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, unsigned long, offset_low, loff_t __user *, result, - unsigned int, origin) + unsigned int, whence) { int retval; struct fd f = fdget(fd); @@ -260,11 +260,11 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, return -EBADF; retval = -EINVAL; - if (origin > SEEK_MAX) + if (whence > SEEK_MAX) goto out_putf; offset = vfs_llseek(f.file, ((loff_t) offset_high << 32) | offset_low, - origin); + whence); retval = (int)offset; if (offset >= 0) { diff --git a/fs/seq_file.c b/fs/seq_file.c index 99dffab4c4e4..9d863fb501f9 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -300,14 +300,14 @@ EXPORT_SYMBOL(seq_read); * * Ready-made ->f_op->llseek() */ -loff_t seq_lseek(struct file *file, loff_t offset, int origin) +loff_t seq_lseek(struct file *file, loff_t offset, int whence) { struct seq_file *m = file->private_data; loff_t retval = -EINVAL; mutex_lock(&m->lock); m->version = file->f_version; - switch (origin) { + switch (whence) { case 1: offset += file->f_pos; case 0: diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index e271fba1651b..8a574776a493 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -453,11 +453,11 @@ out: } /* If a directory is seeked, we have to free saved readdir() state */ -static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin) +static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) { kfree(file->private_data); file->private_data = NULL; - return generic_file_llseek(file, offset, origin); + return generic_file_llseek(file, offset, whence); } /* Free saved readdir() state when the directory is closed */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 408fb1e77a0a..029552ff774c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2286,9 +2286,9 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *); #include <linux/err.h> /* needed for stackable file system support */ -extern loff_t default_llseek(struct file *file, loff_t offset, int origin); +extern loff_t default_llseek(struct file *file, loff_t offset, int whence); -extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); +extern loff_t vfs_llseek(struct file *file, loff_t offset, int whence); extern int inode_init_always(struct super_block *, struct inode *); extern void inode_init_once(struct inode *); @@ -2396,11 +2396,11 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); -extern loff_t noop_llseek(struct file *file, loff_t offset, int origin); -extern loff_t no_llseek(struct file *file, loff_t offset, int origin); -extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); +extern loff_t noop_llseek(struct file *file, loff_t offset, int whence); +extern loff_t no_llseek(struct file *file, loff_t offset, int whence); +extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence); extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, - int origin, loff_t maxsize, loff_t eof); + int whence, loff_t maxsize, loff_t eof); extern int generic_file_open(struct inode * inode, struct file * filp); extern int nonseekable_open(struct inode * inode, struct file * filp); diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index a52f2f4fe030..92691d85c320 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -394,7 +394,7 @@ ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos); ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos); -loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin); +loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence); int ftrace_regex_release(struct inode *inode, struct file *file); void __init @@ -559,7 +559,7 @@ static inline ssize_t ftrace_filter_write(struct file *file, const char __user * size_t cnt, loff_t *ppos) { return -ENODEV; } static inline ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { return -ENODEV; } -static inline loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin) +static inline loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence) { return -ENODEV; } diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 91835e7f364d..36c3b07c5119 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -560,10 +560,10 @@ asmlinkage long sys_utime(char __user *filename, asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes); asmlinkage long sys_lseek(unsigned int fd, off_t offset, - unsigned int origin); + unsigned int whence); asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t __user *result, - unsigned int origin); + unsigned int whence); asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count); asmlinkage long sys_readahead(int fd, loff_t offset, size_t count); asmlinkage long sys_readv(unsigned long fd, diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index afd092de45b7..3ffe4c5ad3f3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2675,12 +2675,12 @@ ftrace_notrace_open(struct inode *inode, struct file *file) } loff_t -ftrace_regex_lseek(struct file *file, loff_t offset, int origin) +ftrace_regex_lseek(struct file *file, loff_t offset, int whence) { loff_t ret; if (file->f_mode & FMODE_READ) - ret = seq_lseek(file, offset, origin); + ret = seq_lseek(file, offset, whence); else file->f_pos = ret = 1; diff --git a/mm/shmem.c b/mm/shmem.c index 03f9ba8fb8e5..5c90d84c2b02 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1719,7 +1719,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, * llseek SEEK_DATA or SEEK_HOLE through the radix_tree. */ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, - pgoff_t index, pgoff_t end, int origin) + pgoff_t index, pgoff_t end, int whence) { struct page *page; struct pagevec pvec; @@ -1733,13 +1733,13 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, pvec.nr = shmem_find_get_pages_and_swap(mapping, index, pvec.nr, pvec.pages, indices); if (!pvec.nr) { - if (origin == SEEK_DATA) + if (whence == SEEK_DATA) index = end; break; } for (i = 0; i < pvec.nr; i++, index++) { if (index < indices[i]) { - if (origin == SEEK_HOLE) { + if (whence == SEEK_HOLE) { done = true; break; } @@ -1751,8 +1751,8 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, page = NULL; } if (index >= end || - (page && origin == SEEK_DATA) || - (!page && origin == SEEK_HOLE)) { + (page && whence == SEEK_DATA) || + (!page && whence == SEEK_HOLE)) { done = true; break; } @@ -1765,15 +1765,15 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, return index; } -static loff_t shmem_file_llseek(struct file *file, loff_t offset, int origin) +static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence) { struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; pgoff_t start, end; loff_t new_offset; - if (origin != SEEK_DATA && origin != SEEK_HOLE) - return generic_file_llseek_size(file, offset, origin, + if (whence != SEEK_DATA && whence != SEEK_HOLE) + return generic_file_llseek_size(file, offset, whence, MAX_LFS_FILESIZE, i_size_read(inode)); mutex_lock(&inode->i_mutex); /* We're holding i_mutex so we can access i_size directly */ @@ -1785,12 +1785,12 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int origin) else { start = offset >> PAGE_CACHE_SHIFT; end = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - new_offset = shmem_seek_hole_data(mapping, start, end, origin); + new_offset = shmem_seek_hole_data(mapping, start, end, whence); new_offset <<= PAGE_CACHE_SHIFT; if (new_offset > offset) { if (new_offset < inode->i_size) offset = new_offset; - else if (origin == SEEK_DATA) + else if (whence == SEEK_DATA) offset = -ENXIO; else offset = inode->i_size; From ac5f121b8f2cad52b7671f9af872f8761b0ea1d4 Mon Sep 17 00:00:00 2001 From: Tushar Behera <tushar.behera@linaro.org> Date: Mon, 17 Dec 2012 15:59:40 -0800 Subject: [PATCH 012/180] fs/notify/inode_mark.c: make fsnotify_find_inode_mark_locked() static Fixes following sparse warning: fs/notify/inode_mark.c:127:22: warning: symbol 'fsnotify_find_inode_mark_locked' was not declared. Should it be static? Signed-off-by: Tushar Behera <tushar.behera@linaro.org> Cc: Eric Paris <eparis@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/notify/inode_mark.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index b13c00ac48eb..f3035691f528 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -116,8 +116,9 @@ void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) * given a group and inode, find the mark associated with that combination. * if found take a reference to that mark and return it, else return NULL */ -struct fsnotify_mark *fsnotify_find_inode_mark_locked(struct fsnotify_group *group, - struct inode *inode) +static struct fsnotify_mark *fsnotify_find_inode_mark_locked( + struct fsnotify_group *group, + struct inode *inode) { struct fsnotify_mark *mark; struct hlist_node *pos; From da01ee3c8e7954fb7ed0ceb002d482c79f8b2ccd Mon Sep 17 00:00:00 2001 From: Jonathan Austin <jonathan.austin@arm.com> Date: Mon, 17 Dec 2012 15:59:41 -0800 Subject: [PATCH 013/180] .gitignore: remove stale entry for generated version.h Since userspace headers were moved to generated/uapi it possible to have a stale copy of linux/version.h at that file's old location. This causes confusion after building an older kernel version, then checking out and building a new one; the old (stale) version header will still get picked up until it is manually removed. This upsets the C library. Since the uapi changes, include/linux/version.h is no longer generated and should not be ignored, so this patch removes it from .gitignore. Signed-off-by: Jonathan Austin <jonathan.austin@arm.com> Reported-by: Kevin Petit <kevin.petit@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 92bd0e45dfa1..3b8b9b33be38 100644 --- a/.gitignore +++ b/.gitignore @@ -60,7 +60,6 @@ modules.builtin # Generated include files # include/config -include/linux/version.h include/generated arch/*/include/generated From 41739ee355abc39d36bde6feed32ad16c63ceea2 Mon Sep 17 00:00:00 2001 From: Will Deacon <will.deacon@arm.com> Date: Mon, 17 Dec 2012 15:59:42 -0800 Subject: [PATCH 014/180] asm-generic: io: don't perform swab during {in,out} string functions The {in,out}s{b,w,l} functions are designed to operate on a stream of bytes and therefore should not perform any byte-swapping, regardless of the CPU byte order. This patch fixes the generic IO header so that {in,out}s{b,w,l} call the __raw_{read,write} functions directly rather than going via the endian-correcting accessors. Signed-off-by: Will Deacon <will.deacon@arm.com> Cc: Mike Frysinger <vapier@gentoo.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Ben Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/asm-generic/io.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 9e0ebe051243..d1e93284d72a 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -154,7 +154,7 @@ static inline void insb(unsigned long addr, void *buffer, int count) if (count) { u8 *buf = buffer; do { - u8 x = inb(addr); + u8 x = __raw_readb(addr + PCI_IOBASE); *buf++ = x; } while (--count); } @@ -167,7 +167,7 @@ static inline void insw(unsigned long addr, void *buffer, int count) if (count) { u16 *buf = buffer; do { - u16 x = inw(addr); + u16 x = __raw_readw(addr + PCI_IOBASE); *buf++ = x; } while (--count); } @@ -180,7 +180,7 @@ static inline void insl(unsigned long addr, void *buffer, int count) if (count) { u32 *buf = buffer; do { - u32 x = inl(addr); + u32 x = __raw_readl(addr + PCI_IOBASE); *buf++ = x; } while (--count); } @@ -193,7 +193,7 @@ static inline void outsb(unsigned long addr, const void *buffer, int count) if (count) { const u8 *buf = buffer; do { - outb(*buf++, addr); + __raw_writeb(*buf++, addr + PCI_IOBASE); } while (--count); } } @@ -205,7 +205,7 @@ static inline void outsw(unsigned long addr, const void *buffer, int count) if (count) { const u16 *buf = buffer; do { - outw(*buf++, addr); + __raw_writew(*buf++, addr + PCI_IOBASE); } while (--count); } } @@ -217,7 +217,7 @@ static inline void outsl(unsigned long addr, const void *buffer, int count) if (count) { const u32 *buf = buffer; do { - outl(*buf++, addr); + __raw_writel(*buf++, addr + PCI_IOBASE); } while (--count); } } From 56c82cdc36a836f564cf4ea09da16fd9297ab3b5 Mon Sep 17 00:00:00 2001 From: Matthew Leach <matthew@mattleach.net> Date: Mon, 17 Dec 2012 15:59:45 -0800 Subject: [PATCH 015/180] musb: tusb6010: use io{read,write}*_rep accessors The {read,write}s{b,w,l} operations are not defined by all architectures and are being removed from the asm-generic/io.h interface. This patch replaces the usage of these string functions in the tusb6010 accessors with io{read,write}{8,16,32}_rep calls instead. Signed-off-by: Matthew Leach <matthew@mattleach.net> Signed-off-by: Will Deacon <will.deacon@arm.com> Cc: Felipe Balbi <balbi@ti.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Ben Herrenschmidt <benh@kernel.crashing.org> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/musb/tusb6010.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 8bde6fc5eb75..3969813c217d 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -22,6 +22,7 @@ #include <linux/prefetch.h> #include <linux/usb.h> #include <linux/irq.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/usb/nop-usb-xceiv.h> @@ -198,7 +199,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf) /* Best case is 32bit-aligned destination address */ if ((0x02 & (unsigned long) buf) == 0) { if (len >= 4) { - writesl(fifo, buf, len >> 2); + iowrite32_rep(fifo, buf, len >> 2); buf += (len & ~0x03); len &= 0x03; } @@ -245,7 +246,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) /* Best case is 32bit-aligned destination address */ if ((0x02 & (unsigned long) buf) == 0) { if (len >= 4) { - readsl(fifo, buf, len >> 2); + ioread32_rep(fifo, buf, len >> 2); buf += (len & ~0x03); len &= 0x03; } From 2bf0a8f67fae9906c6497886203f6e5cb7168df6 Mon Sep 17 00:00:00 2001 From: Matthew Leach <matthew@mattleach.net> Date: Mon, 17 Dec 2012 15:59:48 -0800 Subject: [PATCH 016/180] usb: musb: use io{read,write}*_rep accessors The {read,write}s{b,w,l} operations are not defined by all architectures and are being removed from the asm-generic/io.h interface. This patch replaces the usage of these string functions in the musb accessors with io{read,write}{8,16,32}_rep calls instead. Signed-off-by: Matthew Leach <matthew@mattleach.net> Signed-off-by: Will Deacon <will.deacon@arm.com> Cc: Felipe Balbi <balbi@ti.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Ben Herrenschmidt <benh@kernel.crashing.org> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/musb/musb_core.c | 12 ++++++------ drivers/usb/musb/musb_io.h | 21 --------------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 57cc9c6eaa9f..f1c6c5470b92 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -251,7 +251,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) /* best case is 32bit-aligned source address */ if ((0x02 & (unsigned long) src) == 0) { if (len >= 4) { - writesl(fifo, src + index, len >> 2); + iowrite32_rep(fifo, src + index, len >> 2); index += len & ~0x03; } if (len & 0x02) { @@ -260,7 +260,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) } } else { if (len >= 2) { - writesw(fifo, src + index, len >> 1); + iowrite16_rep(fifo, src + index, len >> 1); index += len & ~0x01; } } @@ -268,7 +268,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) musb_writeb(fifo, 0, src[index]); } else { /* byte aligned */ - writesb(fifo, src, len); + iowrite8_rep(fifo, src, len); } } @@ -294,7 +294,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) /* best case is 32bit-aligned destination address */ if ((0x02 & (unsigned long) dst) == 0) { if (len >= 4) { - readsl(fifo, dst, len >> 2); + ioread32_rep(fifo, dst, len >> 2); index = len & ~0x03; } if (len & 0x02) { @@ -303,7 +303,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) } } else { if (len >= 2) { - readsw(fifo, dst, len >> 1); + ioread16_rep(fifo, dst, len >> 1); index = len & ~0x01; } } @@ -311,7 +311,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) dst[index] = musb_readb(fifo, 0); } else { /* byte aligned */ - readsb(fifo, dst, len); + ioread8_rep(fifo, dst, len); } } #endif diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 565ad1617832..eebeed78edd6 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -37,27 +37,6 @@ #include <linux/io.h> -#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ - && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ - && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \ - && !defined(CONFIG_MIPS) && !defined(CONFIG_M68K) \ - && !defined(CONFIG_XTENSA) -static inline void readsl(const void __iomem *addr, void *buf, int len) - { insl((unsigned long)addr, buf, len); } -static inline void readsw(const void __iomem *addr, void *buf, int len) - { insw((unsigned long)addr, buf, len); } -static inline void readsb(const void __iomem *addr, void *buf, int len) - { insb((unsigned long)addr, buf, len); } - -static inline void writesl(const void __iomem *addr, const void *buf, int len) - { outsl((unsigned long)addr, buf, len); } -static inline void writesw(const void __iomem *addr, const void *buf, int len) - { outsw((unsigned long)addr, buf, len); } -static inline void writesb(const void __iomem *addr, const void *buf, int len) - { outsb((unsigned long)addr, buf, len); } - -#endif - #ifndef CONFIG_BLACKFIN /* NOTE: these offsets are all in bytes */ From 0f34c400914f165b7b3812459be2d77b8aa1f1e4 Mon Sep 17 00:00:00 2001 From: Chuansheng Liu <chuansheng.liu@intel.com> Date: Mon, 17 Dec 2012 15:59:50 -0800 Subject: [PATCH 017/180] watchdog: store the watchdog sample period as a variable Currently getting the sample period is always thru a complex calculation: get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5). We can store the sample period as a variable, and set it as __read_mostly type. Signed-off-by: liu chuansheng <chuansheng.liu@intel.com> Cc: Don Zickus <dzickus@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- kernel/watchdog.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index c8c21be11ab4..997c6a16ec22 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -31,6 +31,7 @@ int watchdog_enabled = 1; int __read_mostly watchdog_thresh = 10; static int __read_mostly watchdog_disabled; +static u64 __read_mostly sample_period; static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); static DEFINE_PER_CPU(struct task_struct *, softlockup_watchdog); @@ -116,7 +117,7 @@ static unsigned long get_timestamp(int this_cpu) return cpu_clock(this_cpu) >> 30LL; /* 2^30 ~= 10^9 */ } -static u64 get_sample_period(void) +static void set_sample_period(void) { /* * convert watchdog_thresh from seconds to ns @@ -125,7 +126,7 @@ static u64 get_sample_period(void) * and hard thresholds) to increment before the * hardlockup detector generates a warning */ - return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); + sample_period = get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); } /* Commands for resetting the watchdog */ @@ -275,7 +276,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) wake_up_process(__this_cpu_read(softlockup_watchdog)); /* .. and repeat */ - hrtimer_forward_now(hrtimer, ns_to_ktime(get_sample_period())); + hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period)); if (touch_ts == 0) { if (unlikely(__this_cpu_read(softlockup_touch_sync))) { @@ -356,7 +357,7 @@ static void watchdog_enable(unsigned int cpu) hrtimer->function = watchdog_timer_fn; /* done here because hrtimer_start can only pin to smp_processor_id() */ - hrtimer_start(hrtimer, ns_to_ktime(get_sample_period()), + hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL_PINNED); /* initialize timestamp */ @@ -386,7 +387,7 @@ static int watchdog_should_run(unsigned int cpu) /* * The watchdog thread function - touches the timestamp. * - * It only runs once every get_sample_period() seconds (4 seconds by + * It only runs once every sample_period seconds (4 seconds by * default) to reset the softlockup timestamp. If this gets delayed * for more than 2*watchdog_thresh seconds then the debug-printout * triggers in watchdog_timer_fn(). @@ -519,6 +520,7 @@ int proc_dowatchdog(struct ctl_table *table, int write, if (ret || !write) return ret; + set_sample_period(); if (watchdog_enabled && watchdog_thresh) watchdog_enable_all_cpus(); else @@ -540,6 +542,7 @@ static struct smp_hotplug_thread watchdog_threads = { void __init lockup_detector_init(void) { + set_sample_period(); if (smpboot_register_percpu_thread(&watchdog_threads)) { pr_err("Failed to create watchdog threads, disabled\n"); watchdog_disabled = -ENODEV; From 632fd28326c0cc7be9c51ea0d76d8bec39a695e9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 15:59:52 -0800 Subject: [PATCH 018/180] dmatest: implement two helpers to unmap dma memory The unmap_src() and unmap_dst() will be used later as well. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/dma/dmatest.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 24225f0fdcd8..6be893baadd9 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -228,6 +228,20 @@ static void dmatest_callback(void *arg) wake_up_all(done->wait); } +static inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len, + unsigned int count) +{ + while (count--) + dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE); +} + +static inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len, + unsigned int count) +{ + while (count--) + dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL); +} + /* * This function repeatedly tests DMA transfers of various lengths and * offsets for a given operation type until it is told to exit by @@ -383,13 +397,8 @@ static int dmatest_func(void *data) } if (!tx) { - for (i = 0; i < src_cnt; i++) - dma_unmap_single(dev->dev, dma_srcs[i], len, - DMA_TO_DEVICE); - for (i = 0; i < dst_cnt; i++) - dma_unmap_single(dev->dev, dma_dsts[i], - test_buf_size, - DMA_BIDIRECTIONAL); + unmap_src(dev->dev, dma_srcs, len, src_cnt); + unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); pr_warning("%s: #%u: prep error with src_off=0x%x " "dst_off=0x%x len=0x%x\n", thread_name, total_tests - 1, @@ -443,9 +452,7 @@ static int dmatest_func(void *data) } /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ - for (i = 0; i < dst_cnt; i++) - dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size, - DMA_BIDIRECTIONAL); + unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); error_count = 0; From afde3be121efcc658e26f8cc71ead04af96d38f9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 15:59:53 -0800 Subject: [PATCH 019/180] dmatest: check for dma mapping error The kernel emits a warning if CONFIG_DMA_API_DEBUG=y: WARNING: at lib/dma-debug.c:933 check_unmap+0x5d6/0x6ac() dw_dmac dw_dmac.0: DMA-API: device driver failed to check map error[device address=0x0000000035698305] [size=14365 bytes] [mapped as single] Fix this by adding the required checking of the dma_map_single() return value. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/dma/dmatest.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 6be893baadd9..64b048d7fba7 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -367,15 +367,35 @@ static int dmatest_func(void *data) dma_srcs[i] = dma_map_single(dev->dev, buf, len, DMA_TO_DEVICE); + ret = dma_mapping_error(dev->dev, dma_srcs[i]); + if (ret) { + unmap_src(dev->dev, dma_srcs, len, i); + pr_warn("%s: #%u: mapping error %d with " + "src_off=0x%x len=0x%x\n", + thread_name, total_tests - 1, ret, + src_off, len); + failed_tests++; + continue; + } } /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ for (i = 0; i < dst_cnt; i++) { dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], test_buf_size, DMA_BIDIRECTIONAL); + ret = dma_mapping_error(dev->dev, dma_dsts[i]); + if (ret) { + unmap_src(dev->dev, dma_srcs, len, src_cnt); + unmap_dst(dev->dev, dma_dsts, test_buf_size, i); + pr_warn("%s: #%u: mapping error %d with " + "dst_off=0x%x len=0x%x\n", + thread_name, total_tests - 1, ret, + dst_off, test_buf_size); + failed_tests++; + continue; + } } - if (thread->type == DMA_MEMCPY) tx = dev->device_prep_dma_memcpy(chan, dma_dsts[0] + dst_off, From 2fa72c8fa5d03c4e07894ccb9f0be72e8687a455 Mon Sep 17 00:00:00 2001 From: Andrew Cooks <acooks@gmail.com> Date: Mon, 17 Dec 2012 15:59:56 -0800 Subject: [PATCH 020/180] printk: boot_delay should only affect output The boot_delay parameter affects all printk(), even if the log level prevents visible output from the call. It results in delays greater than the user intended without purpose. This patch changes the behaviour of boot_delay to only delay output. Signed-off-by: Andrew Cooks <acooks@gmail.com> Acked-by: Randy Dunlap <rdunlap@infradead.org> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- kernel/printk.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index 22e070f3470a..19c0d7bcf24a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -747,6 +747,21 @@ void __init setup_log_buf(int early) free, (free * 100) / __LOG_BUF_LEN); } +static bool __read_mostly ignore_loglevel; + +static int __init ignore_loglevel_setup(char *str) +{ + ignore_loglevel = 1; + printk(KERN_INFO "debug: ignoring loglevel setting.\n"); + + return 0; +} + +early_param("ignore_loglevel", ignore_loglevel_setup); +module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to" + "print all kernel messages to the console."); + #ifdef CONFIG_BOOT_PRINTK_DELAY static int boot_delay; /* msecs delay after each printk during bootup */ @@ -770,13 +785,15 @@ static int __init boot_delay_setup(char *str) } __setup("boot_delay=", boot_delay_setup); -static void boot_delay_msec(void) +static void boot_delay_msec(int level) { unsigned long long k; unsigned long timeout; - if (boot_delay == 0 || system_state != SYSTEM_BOOTING) + if ((boot_delay == 0 || system_state != SYSTEM_BOOTING) + || (level >= console_loglevel && !ignore_loglevel)) { return; + } k = (unsigned long long)loops_per_msec * boot_delay; @@ -795,7 +812,7 @@ static void boot_delay_msec(void) } } #else -static inline void boot_delay_msec(void) +static inline void boot_delay_msec(int level) { } #endif @@ -1238,21 +1255,6 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) return do_syslog(type, buf, len, SYSLOG_FROM_CALL); } -static bool __read_mostly ignore_loglevel; - -static int __init ignore_loglevel_setup(char *str) -{ - ignore_loglevel = 1; - printk(KERN_INFO "debug: ignoring loglevel setting.\n"); - - return 0; -} - -early_param("ignore_loglevel", ignore_loglevel_setup); -module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to" - "print all kernel messages to the console."); - /* * Call the console drivers, asking them to write out * log_buf[start] to log_buf[end - 1]. @@ -1498,7 +1500,7 @@ asmlinkage int vprintk_emit(int facility, int level, int this_cpu; int printed_len = 0; - boot_delay_msec(); + boot_delay_msec(level); printk_delay(); /* This stops the holder of console_sem just where we want him */ From ef12496022d5917cfe0b04cf8fd685fc6bc08400 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Date: Mon, 17 Dec 2012 15:59:58 -0800 Subject: [PATCH 021/180] lib/vsprintf.c: fix handling of %zd when using ssize_t Documentation/printk-formats.txt says to use %zd for a ssize_t argument and some drivers do. Unfortunately this prints a positive number for negative values eg: tpm_tis 70030000.tpm_tis: tpm_transmit: tpm_send: error 4294967234 Add a case to va_args a ssize_t type if the interpretation should be signed. Tested on PPC32. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- lib/vsprintf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 39c99fea7c03..41da0741a663 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1485,7 +1485,10 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) num = va_arg(args, long); break; case FORMAT_TYPE_SIZE_T: - num = va_arg(args, size_t); + if (spec.flags & SIGN) + num = va_arg(args, ssize_t); + else + num = va_arg(args, size_t); break; case FORMAT_TYPE_PTRDIFF: num = va_arg(args, ptrdiff_t); From 9740153c49dc6f0d0d90ba5226ffdc6f9974d3f6 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:00:00 -0800 Subject: [PATCH 022/180] MAINTAINERS: CHINESE MAINTAINERS mailing list is subscribers only Mark it so. Signed-off-by: Joe Perches <joe@perches.com> Cc: Harry Wei <harryxiyou@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6892b26025ba..8175ca8a0eed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1929,7 +1929,7 @@ F: scripts/checkpatch.pl CHINESE DOCUMENTATION M: Harry Wei <harryxiyou@gmail.com> -L: xiyoulinuxkernelgroup@googlegroups.com +L: xiyoulinuxkernelgroup@googlegroups.com (subscribers-only) L: linux-kernel@zh-kernel.org (moderated for non-subscribers) S: Maintained F: Documentation/zh_CN/ From ba28853daa2912dff9b42fbc477af8ea27ef8ad0 Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros <cesarb@cesarb.net> Date: Mon, 17 Dec 2012 16:00:03 -0800 Subject: [PATCH 023/180] MAINTAINERS: remove include/linux/ext3* Moved to fs/ext3/ext3.h by commit 4613ad180d19 ("ext3: move headers to fs/ext3/"). Signed-off-by: Cesar Eduardo Barros <cesarb@cesarb.net> Cc: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8175ca8a0eed..503455b142b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2982,7 +2982,6 @@ L: linux-ext4@vger.kernel.org S: Maintained F: Documentation/filesystems/ext3.txt F: fs/ext3/ -F: include/linux/ext3* EXT4 FILE SYSTEM M: "Theodore Ts'o" <tytso@mit.edu> @@ -4314,7 +4313,6 @@ M: Jan Kara <jack@suse.cz> L: linux-ext4@vger.kernel.org S: Maintained F: fs/jbd/ -F: include/linux/ext3_jbd.h F: include/linux/jbd.h JOURNALLING LAYER FOR BLOCK DEVICES (JBD2) From 5909c654a6f20dd61cc5ac952f8eaa3a29e59078 Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentin.chary@gmail.com> Date: Mon, 17 Dec 2012 16:00:05 -0800 Subject: [PATCH 024/180] Corentin has moved Signed-off-by: Corentin Chary <corentin.chary@gmail.com> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 4 ++-- drivers/platform/x86/asus-nb-wmi.c | 2 +- drivers/platform/x86/asus-wmi.c | 2 +- drivers/platform/x86/eeepc-wmi.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 503455b142b7..b0aef8fd077d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1280,7 +1280,7 @@ F: Documentation/hwmon/asc7621 F: drivers/hwmon/asc7621.c ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS -M: Corentin Chary <corentincj@iksaif.net> +M: Corentin Chary <corentin.chary@gmail.com> L: acpi4asus-user@lists.sourceforge.net L: platform-driver-x86@vger.kernel.org W: http://acpi4asus.sf.net @@ -6490,7 +6490,7 @@ F: drivers/media/pci/saa7146/ F: include/media/saa7146* SAMSUNG LAPTOP DRIVER -M: Corentin Chary <corentincj@iksaif.net> +M: Corentin Chary <corentin.chary@gmail.com> L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/samsung-laptop.c diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 6b0ebdeae916..be790402e0f1 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -32,7 +32,7 @@ #define ASUS_NB_WMI_FILE "asus-nb-wmi" -MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>"); +MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c0e9ff489b24..f80ae4d10f68 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -51,7 +51,7 @@ #include "asus-wmi.h" -MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, " +MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>, " "Yong Wang <yong.y.wang@intel.com>"); MODULE_DESCRIPTION("Asus Generic WMI Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 5838332ea5bd..60cb76a5b513 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -39,7 +39,7 @@ #define EEEPC_WMI_FILE "eeepc-wmi" -MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>"); +MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); MODULE_LICENSE("GPL"); From 8f06ce3b5e53b43c0434f823a17f5f5d4e14aa1a Mon Sep 17 00:00:00 2001 From: Stefan Richter <stefanr@s5r6.in-berlin.de> Date: Mon, 17 Dec 2012 16:00:07 -0800 Subject: [PATCH 025/180] MAINTAINERS: adjust for UAPI: firewire Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b0aef8fd077d..c0e5c06f7be7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3128,7 +3128,8 @@ W: http://ieee1394.wiki.kernel.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git S: Maintained F: drivers/firewire/ -F: include/linux/firewire*.h +F: include/linux/firewire.h +F: include/uapi/linux/firewire*.h F: tools/firewire/ FIRMWARE LOADER (request_firmware) From f0f13cd0918a8a0d4d378727135922691a2981fe Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:10 -0800 Subject: [PATCH 026/180] backlight: da903x_bl: use dev_get_drvdata() instead of platform_get_drvdata() dev_get_drvdata() can be used instead of platform_get_drvdata() to make the code smaller. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/da903x_bl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 573c7ece0fde..6891754143d4 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -164,15 +164,14 @@ static int da903x_backlight_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int da903x_backlight_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct backlight_device *bl = platform_get_drvdata(pdev); + struct backlight_device *bl = dev_get_drvdata(dev); + return da903x_backlight_set(bl, 0); } static int da903x_backlight_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct backlight_device *bl = platform_get_drvdata(pdev); + struct backlight_device *bl = dev_get_drvdata(dev); backlight_update_status(bl); return 0; From 20c5a93210e9146c16041e46150b1e54f77b983d Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:11 -0800 Subject: [PATCH 027/180] backlight: 88pm860x_bl: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: quoted string split across lines Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/88pm860x_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index b7ec34c57f46..6e509d995093 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -117,8 +117,8 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness) data->current_brightness = value; return 0; out: - dev_dbg(chip->dev, "set brightness %d failure with return " - "value:%d\n", value, ret); + dev_dbg(chip->dev, "set brightness %d failure with return value: %d\n", + value, ret); return ret; } From 16a63149379e2279eb887dc28cad17e98d95500f Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:12 -0800 Subject: [PATCH 028/180] backlight: atmel-pwm-bl: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: quoted string split across lines Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/atmel-pwm-bl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index df1cbb7ef6ca..de5e5e74e2a7 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -106,10 +106,9 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl) pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD, pwmbl->pdata->pwm_compare_max); - dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver " - "(%lu Hz)\n", pwmbl->pwmc.mck / - pwmbl->pdata->pwm_compare_max / - (1 << prescale)); + dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver (%lu Hz)\n", + pwmbl->pwmc.mck / pwmbl->pdata->pwm_compare_max / + (1 << prescale)); return pwm_channel_enable(&pwmbl->pwmc); } From 08851261b5a95291ca8eddd97f19898bfe3b5b59 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:14 -0800 Subject: [PATCH 029/180] backlight: corgi_lcd: fix checkpatch error and warning This patch fixes the checkpatch error and warning as below: WARNING: please, no space before tabs WARNING: quoted string split across lines ERROR: space required before the open parenthesis '(' Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/corgi_lcd.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index eaaebf21993e..e2e1b62bebb1 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -6,8 +6,8 @@ * Based on Sharp's 2.4 Backlight Driver * * Copyright (c) 2008 Marvell International Ltd. - * Converted to SPI device based LCD/Backlight device driver - * by Eric Miao <eric.miao@marvell.com> + * Converted to SPI device based LCD/Backlight device driver + * by Eric Miao <eric.miao@marvell.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -192,7 +192,7 @@ static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode) { int adj; - switch(mode) { + switch (mode) { case CORGI_LCD_MODE_VGA: /* Setting for VGA */ adj = sharpsl_param.phadadj; @@ -495,8 +495,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on, "BL_ON"); if (err) { - dev_err(&spi->dev, "failed to request GPIO%d for " - "backlight_on\n", pdata->gpio_backlight_on); + dev_err(&spi->dev, + "failed to request GPIO%d for backlight_on\n", + pdata->gpio_backlight_on); return err; } @@ -508,8 +509,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont, "BL_CONT"); if (err) { - dev_err(&spi->dev, "failed to request GPIO%d for " - "backlight_cont\n", pdata->gpio_backlight_cont); + dev_err(&spi->dev, + "failed to request GPIO%d for backlight_cont\n", + pdata->gpio_backlight_cont); return err; } From 685746d407a1b93affb20f04988959a3da14c33c Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:15 -0800 Subject: [PATCH 030/180] backlight: da903x_bl: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: please, no space before tabs WARNING: quoted string split across lines Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/da903x_bl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 6891754143d4..8179cef0730f 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -2,10 +2,10 @@ * Backlight driver for Dialog Semiconductor DA9030/DA9034 * * Copyright (C) 2008 Compulab, Ltd. - * Mike Rapoport <mike@compulab.co.il> + * Mike Rapoport <mike@compulab.co.il> * * Copyright (C) 2006-2008 Marvell International Ltd. - * Eric Miao <eric.miao@marvell.com> + * Eric Miao <eric.miao@marvell.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -198,7 +198,7 @@ static struct platform_driver da903x_backlight_driver = { module_platform_driver(da903x_backlight_driver); MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); -MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" - "Mike Rapoport <mike@compulab.co.il>"); +MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); +MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:da903x-backlight"); From 933bd9b3fda5482e88a84a1a3678bb1fbb11a60a Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:17 -0800 Subject: [PATCH 031/180] backlight: generic_bl: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/generic_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index 8c660fcd250d..0ae155be9c89 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c @@ -97,8 +97,8 @@ static int genericbl_probe(struct platform_device *pdev) props.max_brightness = machinfo->max_intensity; bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, &props); - if (IS_ERR (bd)) - return PTR_ERR (bd); + if (IS_ERR(bd)) + return PTR_ERR(bd); platform_set_drvdata(pdev, bd); From ff10b0741236b42ec7e97b4ba2d682be53868050 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:18 -0800 Subject: [PATCH 032/180] backlight: hp680_bl: fix checkpatch error and warning This patch fixes the checkpatch error and warning as below: WARNING: please, no space before tabs WARNING: please, no spaces at the start of a line ERROR: do not initialise statics to 0 or NULL ERROR: code indent should use tabs where possible Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/hp680_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index c99966342448..5cefd73526f8 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -26,7 +26,7 @@ #define HP680_DEFAULT_INTENSITY 10 static int hp680bl_suspended; -static int current_intensity = 0; +static int current_intensity; static DEFINE_SPINLOCK(bl_lock); static void hp680bl_send_intensity(struct backlight_device *bd) @@ -168,7 +168,7 @@ static int __init hp680bl_init(void) static void __exit hp680bl_exit(void) { platform_device_unregister(hp680bl_device); - platform_driver_unregister(&hp680bl_driver); + platform_driver_unregister(&hp680bl_driver); } module_init(hp680bl_init); From c0b6cc499c1a214b51bac45d2c74ba66953efedc Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:19 -0800 Subject: [PATCH 033/180] backlight: ili9320: fix checkpatch error and warning This patch fixes the checkpatch error and warning as below: WARNING: please, no space before tabs WARNING: please, no spaces at the start of a line WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable WARNING: braces {} are not necessary for single statement blocks ERROR: code indent should use tabs where possible Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/ili9320.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c index 66cc313185ad..69e253b7c24b 100644 --- a/drivers/video/backlight/ili9320.c +++ b/drivers/video/backlight/ili9320.c @@ -45,7 +45,7 @@ static inline int ili9320_write_spi(struct ili9320 *ili, /* second message is the data to transfer */ data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE; - data[1] = value >> 8; + data[1] = value >> 8; data[2] = value; return spi_sync(spi->dev, &spi->message); @@ -56,7 +56,6 @@ int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value) dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value); return ili->write(ili, reg, value); } - EXPORT_SYMBOL_GPL(ili9320_write); int ili9320_write_regs(struct ili9320 *ili, @@ -74,7 +73,6 @@ int ili9320_write_regs(struct ili9320 *ili, return 0; } - EXPORT_SYMBOL_GPL(ili9320_write_regs); static void ili9320_reset(struct ili9320 *lcd) @@ -260,7 +258,6 @@ int ili9320_probe_spi(struct spi_device *spi, return ret; } - EXPORT_SYMBOL_GPL(ili9320_probe_spi); int ili9320_remove(struct ili9320 *ili) @@ -271,7 +268,6 @@ int ili9320_remove(struct ili9320 *ili) return 0; } - EXPORT_SYMBOL_GPL(ili9320_remove); #ifdef CONFIG_PM @@ -296,20 +292,17 @@ int ili9320_suspend(struct ili9320 *lcd, pm_message_t state) return 0; } - EXPORT_SYMBOL_GPL(ili9320_suspend); int ili9320_resume(struct ili9320 *lcd) { dev_info(lcd->dev, "resuming from power state %d\n", lcd->power); - if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) { + if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) ili9320_write(lcd, ILI9320_POWER1, 0x00); - } return ili9320_power(lcd, FB_BLANK_UNBLANK); } - EXPORT_SYMBOL_GPL(ili9320_resume); #endif @@ -318,7 +311,6 @@ void ili9320_shutdown(struct ili9320 *lcd) { ili9320_power(lcd, FB_BLANK_POWERDOWN); } - EXPORT_SYMBOL_GPL(ili9320_shutdown); MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); From 0a75a568b3ad31976f8b2606936227495cd3c5da Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:21 -0800 Subject: [PATCH 034/180] backlight: jornada720: fix checkpatch error and warning This patch fixes the checkpatch error and warning as below: ERROR: return is not a function, parentheses are not required Also, long comments are fixed for the preferred style. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/jornada720_bl.c | 31 +++++++++++++++---------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index 16f593b64427..fef6ce4fad71 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -48,7 +48,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd) jornada_ssp_end(); - return (BL_MAX_BRIGHT - ret); + return BL_MAX_BRIGHT - ret; } static int jornada_bl_update_status(struct backlight_device *bd) @@ -77,18 +77,23 @@ static int jornada_bl_update_status(struct backlight_device *bd) goto out; } - /* at this point we expect that the mcu has accepted - our command and is waiting for our new value - please note that maximum brightness is 255, - but due to physical layout it is equal to 0, so we simply - invert the value (MAX VALUE - NEW VALUE). */ - if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) { + /* + * at this point we expect that the mcu has accepted + * our command and is waiting for our new value + * please note that maximum brightness is 255, + * but due to physical layout it is equal to 0, so we simply + * invert the value (MAX VALUE - NEW VALUE). + */ + if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) + != TXDUMMY) { pr_err("set brightness failed\n"); ret = -ETIMEDOUT; } - /* If infact we get an TXDUMMY as output we are happy and dont - make any further comments about it */ + /* + * If infact we get an TXDUMMY as output we are happy and dont + * make any further comments about it + */ out: jornada_ssp_end(); @@ -121,9 +126,11 @@ static int jornada_bl_probe(struct platform_device *pdev) bd->props.power = FB_BLANK_UNBLANK; bd->props.brightness = BL_DEF_BRIGHT; - /* note. make sure max brightness is set otherwise - you will get seemingly non-related errors when - trying to change brightness */ + /* + * note. make sure max brightness is set otherwise + * you will get seemingly non-related errors when + * trying to change brightness + */ jornada_bl_update_status(bd); platform_set_drvdata(pdev, bd); From e4f8ae708043865294bfbc12e5249187566b1260 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:23 -0800 Subject: [PATCH 035/180] backlight: l4f00242t03: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: please, no space before tabs Also, unnecessary line is removed. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/l4f00242t03.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index f5aa0a5961d6..9a35196d12d7 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -4,7 +4,7 @@ * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved. * * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> - * Inspired by Marek Vasut work in l4f00242t03.c + * Inspired by Marek Vasut work in l4f00242t03.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -33,7 +33,6 @@ struct l4f00242t03_priv { struct regulator *core_reg; }; - static void l4f00242t03_reset(unsigned int gpio) { pr_debug("l4f00242t03_reset.\n"); From d7b6bdaaa60889aeb5fb1fc70c92114e881e1fc7 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:26 -0800 Subject: [PATCH 036/180] backlight: lm3630: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: static const char * array should probably be static const char * const Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lm3630_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c index 0207bc0a4407..a6d637b5c68f 100644 --- a/drivers/video/backlight/lm3630_bl.c +++ b/drivers/video/backlight/lm3630_bl.c @@ -37,7 +37,7 @@ enum lm3630_leds { BLED_2 }; -static const char *bled_name[] = { +static const char * const bled_name[] = { [BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */ [BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */ [BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */ From 7a94f653edd964f2d3d2266212dc4e86cf47ed32 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:29 -0800 Subject: [PATCH 037/180] backlight: omap1: fix checkpatch warning This patch fixes the checkpatch warning as below: ERROR: inline keyword should sit between storage class and type Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/omap1_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 9a046a4c98f5..af31c269baa6 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -42,12 +42,12 @@ struct omap_backlight { struct omap_backlight_config *pdata; }; -static void inline omapbl_send_intensity(int intensity) +static inline void omapbl_send_intensity(int intensity) { omap_writeb(intensity, OMAP_PWL_ENABLE); } -static void inline omapbl_send_enable(int enable) +static inline void omapbl_send_enable(int enable) { omap_writeb(enable, OMAP_PWL_CLK_ENABLE); } From ae872dbba92efbbaa7486fe84326427a66ed8335 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:30 -0800 Subject: [PATCH 038/180] backlight: pcf50633: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: please, no spaces at the start of a line Also, long comments are fixed for the preferred style. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/pcf50633-backlight.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c index 0087396007e4..e87c7a3394f3 100644 --- a/drivers/video/backlight/pcf50633-backlight.c +++ b/drivers/video/backlight/pcf50633-backlight.c @@ -52,7 +52,7 @@ int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit) pcf_bl->brightness_limit = limit & 0x3f; backlight_update_status(pcf_bl->bl); - return 0; + return 0; } static int pcf50633_bl_update_status(struct backlight_device *bl) @@ -136,8 +136,10 @@ static int pcf50633_bl_probe(struct platform_device *pdev) pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); - /* Should be different from bl_props.brightness, so we do not exit - * update_status early the first time it's called */ + /* + * Should be different from bl_props.brightness, so we do not exit + * update_status early the first time it's called + */ pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; backlight_update_status(pcf_bl->bl); From 8690c70ea846a50e18241428cfbc3eade4104fb9 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:31 -0800 Subject: [PATCH 039/180] backlight: platform_lcd: fix checkpatch error This patch fixes the checkpatch error as below: ERROR: spaces prohibited around that ':' (ctx:WxW) Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/platform_lcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index 894bfc5ce422..17a6b83f97af 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c @@ -27,7 +27,7 @@ struct platform_lcd { struct plat_lcd_data *pdata; unsigned int power; - unsigned int suspended : 1; + unsigned int suspended:1; }; static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd) From 97d9655c7fcc8e408d06ac6fb4cdffecd51cf5e8 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:33 -0800 Subject: [PATCH 040/180] backlight: tdo24m: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: please, no space before tabs Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/tdo24m.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 146ffb9404d1..76bbde19d349 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -2,7 +2,7 @@ * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels * * Copyright (C) 2008 Marvell International Ltd. - * Eric Miao <eric.miao@marvell.com> + * Eric Miao <eric.miao@marvell.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -90,7 +90,7 @@ static uint32_t lcd_qvga_pass_through_tdo24m[] = { }; static uint32_t lcd_vga_transfer_tdo24m[] = { - CMD1(0xcf, 0x02), /* Blanking period control (1) */ + CMD1(0xcf, 0x02), /* Blanking period control (1) */ CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ CMD1(0xd1, 0x01), /* CKV timing control on/off */ CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */ @@ -132,7 +132,7 @@ static uint32_t lcd_qvga_pass_through_tdo35s[] = { }; static uint32_t lcd_vga_transfer_tdo35s[] = { - CMD1(0xcf, 0x02), /* Blanking period control (1) */ + CMD1(0xcf, 0x02), /* Blanking period control (1) */ CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ CMD1(0xd1, 0x01), /* CKV timing control on/off */ CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */ From 8ab77f46ea3ac295859dec2533653a65c54b9a22 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:36 -0800 Subject: [PATCH 041/180] backlight: tosa: fix checkpatch error and warning This patch fixes the checkpatch error and warning as below: ERROR: spaces required around that '?' (ctx:VxW) ERROR: space required after that ',' (ctx:VxV) Also, unnecessary lines are removed. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/tosa_bl.c | 1 - drivers/video/backlight/tosa_lcd.c | 16 +++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index a0521abdcd8a..07ee31a4951c 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -163,7 +163,6 @@ static const struct i2c_device_id tosa_bl_id[] = { { }, }; - static struct i2c_driver tosa_bl_driver = { .driver = { .name = "tosa-bl", diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 86fff88c2e4a..2a2d506f08c0 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -63,7 +63,7 @@ static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data) int tosa_bl_enable(struct spi_device *spi, int enable) { /* bl_enable GP04=1 otherwise GP04=0*/ - return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00); + return tosa_tg_send(spi, TG_GPODR2, enable ? 0x01 : 0x00); } EXPORT_SYMBOL(tosa_bl_enable); @@ -91,15 +91,17 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data) tosa_tg_send(spi, TG_PNLCTL, value); /* TG LCD pannel power up */ - tosa_tg_send(spi, TG_PINICTL,0x4); + tosa_tg_send(spi, TG_PINICTL, 0x4); mdelay(50); /* TG LCD GVSS */ - tosa_tg_send(spi, TG_PINICTL,0x0); + tosa_tg_send(spi, TG_PINICTL, 0x0); if (!data->i2c) { - /* after the pannel is powered up the first time, we can access the i2c bus */ - /* so probe for the DAC */ + /* + * after the pannel is powered up the first time, + * we can access the i2c bus so probe for the DAC + */ struct i2c_adapter *adap = i2c_get_adapter(0); struct i2c_board_info info = { .type = "tosa-bl", @@ -115,11 +117,11 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data) struct spi_device *spi = data->spi; /* TG LCD VHSA off */ - tosa_tg_send(spi, TG_PINICTL,0x4); + tosa_tg_send(spi, TG_PINICTL, 0x4); mdelay(50); /* TG LCD signal off */ - tosa_tg_send(spi, TG_PINICTL,0x6); + tosa_tg_send(spi, TG_PINICTL, 0x6); mdelay(50); /* TG Off */ From 9a8fe5d8cc180b9c2c3c08509b458199c26bc5ff Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:38 -0800 Subject: [PATCH 042/180] backlight: vgg2432a4: fix checkpatch warning This patch fixes the checkpatch warning as below: WARNING: please, no space before tabs Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/vgg2432a4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 712b0acfd339..5ba7fbd7e405 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c @@ -217,7 +217,7 @@ static int vgg2432a4_resume(struct spi_device *spi) } #else #define vgg2432a4_suspend NULL -#define vgg2432a4_resume NULL +#define vgg2432a4_resume NULL #endif static struct ili9320_client vgg2432a4_client = { From 5a5a07436669b3072fbe9f06d27667ec6db62bf5 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:40 -0800 Subject: [PATCH 043/180] backlight: lms283gf05: use devm_gpio_request_one By using devm_gpio_request_one it is possible to set the direction and initial value in one shot. Thus, using devm_gpio_request_one can make the code simpler. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Acked-by: Marek Vasut <marex@denx.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lms283gf05.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index b29c7071c9db..b7ad0d526bf7 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -158,13 +158,9 @@ static int lms283gf05_probe(struct spi_device *spi) int ret = 0; if (pdata != NULL) { - ret = devm_gpio_request(&spi->dev, pdata->reset_gpio, - "LMS285GF05 RESET"); - if (ret) - return ret; - - ret = gpio_direction_output(pdata->reset_gpio, - !pdata->reset_inverted); + ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio, + GPIOF_DIR_OUT | !pdata->reset_inverted, + "LMS285GF05 RESET"); if (ret) return ret; } From 05a5d4d2640dfe934ec78ba577dd21baccb11aa6 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:41 -0800 Subject: [PATCH 044/180] backlight: tosa: use devm_gpio_request_one By using devm_gpio_request_one it is possible to set the direction and initial value in one shot. Thus, using devm_gpio_request_one can make the code simpler. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Dmitry Baryshkov <dbaryshkov@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/tosa_bl.c | 6 ++---- drivers/video/backlight/tosa_lcd.c | 8 ++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index 07ee31a4951c..588682cc1614 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -92,14 +92,12 @@ static int tosa_bl_probe(struct i2c_client *client, data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; - ret = devm_gpio_request(&client->dev, TOSA_GPIO_BL_C20MA, "backlight"); + ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA, + GPIOF_OUT_INIT_LOW, "backlight"); if (ret) { dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); return ret; } - ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0); - if (ret) - return ret; i2c_set_clientdata(client, data); data->i2c = client; diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 2a2d506f08c0..96bae941585a 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -195,17 +195,13 @@ static int tosa_lcd_probe(struct spi_device *spi) data->spi = spi; dev_set_drvdata(&spi->dev, data); - ret = devm_gpio_request(&spi->dev, TOSA_GPIO_TG_ON, "tg #pwr"); + ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON, + GPIOF_OUT_INIT_LOW, "tg #pwr"); if (ret < 0) goto err_gpio_tg; mdelay(60); - ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0); - if (ret < 0) - goto err_gpio_tg; - - mdelay(60); tosa_lcd_tg_init(data); tosa_lcd_tg_on(data); From 8cc9764c9c7d01a6e2c3ddac8f0ac7716be01868 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" <Milo.Kim@ti.com> Date: Mon, 17 Dec 2012 16:00:43 -0800 Subject: [PATCH 045/180] drivers/video/backlight/lp855x_bl.c: use generic PWM functions The LP855x family devices support the PWM input for the backlight control. Period of the PWM is configurable in the platform side. Platform specific functions are unnecessary anymore because generic PWM functions are used inside the driver. (PWM input mode) To set the brightness, new lp855x_pwm_ctrl() is used. If a PWM device is not allocated, devm_pwm_get() is called. The PWM consumer name is from the chip name such as 'lp8550' and 'lp8556'. To get the brightness value, no additional handling is required. Just the value of 'props.brightness' is returned. If the PWM driver is not ready while initializing the LP855x driver, it's OK. The PWM device can be retrieved later, when the brightness value is changed. Documentation is updated with an example. [akpm@linux-foundation.org: coding-style simplification, per Thierry] Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com> Cc: Thierry Reding <thierry.reding@avionic-design.de> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Bryan Wu <bryan.wu@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/backlight/lp855x-driver.txt | 10 ++---- drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++------- include/linux/platform_data/lp855x.h | 9 ++---- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Documentation/backlight/lp855x-driver.txt b/Documentation/backlight/lp855x-driver.txt index f5e4caafab7d..1529394cfe8b 100644 --- a/Documentation/backlight/lp855x-driver.txt +++ b/Documentation/backlight/lp855x-driver.txt @@ -35,11 +35,8 @@ For supporting platform specific data, the lp855x platform data can be used. * mode : Brightness control mode. PWM or register based. * device_control : Value of DEVICE CONTROL register. * initial_brightness : Initial value of backlight brightness. -* pwm_data : Platform specific pwm generation functions. +* period_ns : Platform specific PWM period value. unit is nano. Only valid when brightness is pwm input mode. - Functions should be implemented by PWM driver. - - pwm_set_intensity() : set duty of PWM - - pwm_get_intensity() : get current duty of PWM * load_new_rom_data : 0 : use default configuration data 1 : update values of eeprom or eprom registers on loading driver @@ -71,8 +68,5 @@ static struct lp855x_platform_data lp8556_pdata = { .mode = PWM_BASED, .device_control = PWM_CONFIG(LP8556), .initial_brightness = INITIAL_BRT, - .pwm_data = { - .pwm_set_intensity = platform_pwm_set_intensity, - .pwm_get_intensity = platform_pwm_get_intensity, - }, + .period_ns = 1000000, }; diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index fd985e0681e9..b437541555ff 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -15,6 +15,7 @@ #include <linux/backlight.h> #include <linux/err.h> #include <linux/platform_data/lp855x.h> +#include <linux/pwm.h> /* Registers */ #define BRIGHTNESS_CTRL 0x00 @@ -36,6 +37,7 @@ struct lp855x { struct device *dev; struct mutex xfer_lock; struct lp855x_platform_data *pdata; + struct pwm_device *pwm; }; static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) @@ -121,6 +123,28 @@ static int lp855x_init_registers(struct lp855x *lp) return ret; } +static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br) +{ + unsigned int period = lp->pdata->period_ns; + unsigned int duty = br * period / max_br; + struct pwm_device *pwm; + + /* request pwm device with the consumer name */ + if (!lp->pwm) { + pwm = devm_pwm_get(lp->dev, lp->chipname); + if (IS_ERR(pwm)) + return; + + lp->pwm = pwm; + } + + pwm_config(lp->pwm, duty, period); + if (duty) + pwm_enable(lp->pwm); + else + pwm_disable(lp->pwm); +} + static int lp855x_bl_update_status(struct backlight_device *bl) { struct lp855x *lp = bl_get_data(bl); @@ -130,12 +154,10 @@ static int lp855x_bl_update_status(struct backlight_device *bl) bl->props.brightness = 0; if (mode == PWM_BASED) { - struct lp855x_pwm_data *pd = &lp->pdata->pwm_data; int br = bl->props.brightness; int max_br = bl->props.max_brightness; - if (pd->pwm_set_intensity) - pd->pwm_set_intensity(br, max_br); + lp855x_pwm_ctrl(lp, br, max_br); } else if (mode == REGISTER_BASED) { u8 val = bl->props.brightness; @@ -150,14 +172,7 @@ static int lp855x_bl_get_brightness(struct backlight_device *bl) struct lp855x *lp = bl_get_data(bl); enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; - if (mode == PWM_BASED) { - struct lp855x_pwm_data *pd = &lp->pdata->pwm_data; - int max_br = bl->props.max_brightness; - - if (pd->pwm_get_intensity) - bl->props.brightness = pd->pwm_get_intensity(max_br); - - } else if (mode == REGISTER_BASED) { + if (mode == REGISTER_BASED) { u8 val = 0; lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val); diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h index 761f31752367..e81f62d24ee2 100644 --- a/include/linux/platform_data/lp855x.h +++ b/include/linux/platform_data/lp855x.h @@ -89,11 +89,6 @@ enum lp8556_brightness_source { LP8556_COMBINED2, /* pwm + i2c after the shaper block */ }; -struct lp855x_pwm_data { - void (*pwm_set_intensity) (int brightness, int max_brightness); - int (*pwm_get_intensity) (int max_brightness); -}; - struct lp855x_rom_data { u8 addr; u8 val; @@ -105,7 +100,7 @@ struct lp855x_rom_data { * @mode : brightness control by pwm or lp855x register * @device_control : value of DEVICE CONTROL register * @initial_brightness : initial value of backlight brightness - * @pwm_data : platform specific pwm generation functions. + * @period_ns : platform specific pwm period value. unit is nano. Only valid when mode is PWM_BASED. * @load_new_rom_data : 0 : use default configuration data @@ -118,7 +113,7 @@ struct lp855x_platform_data { enum lp855x_brightness_ctrl_mode mode; u8 device_control; int initial_brightness; - struct lp855x_pwm_data pwm_data; + unsigned int period_ns; u8 load_new_rom_data; int size_program; struct lp855x_rom_data *rom_data; From eaa4d02fbaf49e57f8a18f68e736e34c514030a2 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" <Milo.Kim@ti.com> Date: Mon, 17 Dec 2012 16:00:45 -0800 Subject: [PATCH 046/180] drivers/video/backlight/lp855x_bl.c: remove unnecessary mutex code The mutex for accessing lp855x registers is used in case of the user-space interaction. When the brightness is changed via sysfs, the mutex is required. But the backlight class device already provides it. Thus, the lp855x mutex is unnecessary. Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com> Cc: Thierry Reding <thierry.reding@avionic-design.de> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Bryan Wu <bryan.wu@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lp855x_bl.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index b437541555ff..6e4db0c874c8 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -35,7 +35,6 @@ struct lp855x { struct i2c_client *client; struct backlight_device *bl; struct device *dev; - struct mutex xfer_lock; struct lp855x_platform_data *pdata; struct pwm_device *pwm; }; @@ -44,14 +43,11 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) { int ret; - mutex_lock(&lp->xfer_lock); ret = i2c_smbus_read_byte_data(lp->client, reg); if (ret < 0) { - mutex_unlock(&lp->xfer_lock); dev_err(lp->dev, "failed to read 0x%.2x\n", reg); return ret; } - mutex_unlock(&lp->xfer_lock); *data = (u8)ret; return 0; @@ -59,13 +55,7 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) { - int ret; - - mutex_lock(&lp->xfer_lock); - ret = i2c_smbus_write_byte_data(lp->client, reg, data); - mutex_unlock(&lp->xfer_lock); - - return ret; + return i2c_smbus_write_byte_data(lp->client, reg, data); } static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) @@ -281,8 +271,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) lp->chip_id = id->driver_data; i2c_set_clientdata(cl, lp); - mutex_init(&lp->xfer_lock); - ret = lp855x_init_registers(lp); if (ret) { dev_err(lp->dev, "i2c communication err: %d", ret); From b5d6904babd4a57b1035e048f74fc5b12fc06d8f Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:48 -0800 Subject: [PATCH 047/180] drivers/video/backlight/da9052_bl.c: add missing const Add 'const' to static array that was missing it in its definition. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Ashish Jangam <ashish.jangam@kpitcummins.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/da9052_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c index ac196181fe45..842da5a3ac4f 100644 --- a/drivers/video/backlight/da9052_bl.c +++ b/drivers/video/backlight/da9052_bl.c @@ -34,7 +34,7 @@ enum { DA9052_TYPE_WLED3, }; -static unsigned char wled_bank[] = { +static const unsigned char wled_bank[] = { DA9052_LED1_CONF_REG, DA9052_LED2_CONF_REG, DA9052_LED3_CONF_REG, From c22e61b339146ed80eb0125f18d698883f99825a Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:50 -0800 Subject: [PATCH 048/180] drivers/video/backlight/lms283gf05.c: add missing const Add 'const' to static array that was missing it in its definition. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Marek Vasut <marex@denx.de> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lms283gf05.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index b7ad0d526bf7..13e24d52887c 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -31,7 +31,7 @@ struct lms283gf05_seq { }; /* Magic sequences supplied by manufacturer, for details refer to datasheet */ -static struct lms283gf05_seq disp_initseq[] = { +static const struct lms283gf05_seq disp_initseq[] = { /* REG, VALUE, DELAY */ { 0x07, 0x0000, 0 }, { 0x13, 0x0000, 10 }, @@ -78,7 +78,7 @@ static struct lms283gf05_seq disp_initseq[] = { { 0x22, 0x0000, 0 } }; -static struct lms283gf05_seq disp_pdwnseq[] = { +static const struct lms283gf05_seq disp_pdwnseq[] = { { 0x07, 0x0016, 30 }, { 0x07, 0x0004, 0 }, @@ -104,7 +104,7 @@ static void lms283gf05_reset(unsigned long gpio, bool inverted) } static void lms283gf05_toggle(struct spi_device *spi, - struct lms283gf05_seq *seq, int sz) + const struct lms283gf05_seq *seq, int sz) { char buf[3]; int i; From 53c7a2fffd71787299d6c7a7107b233d37ad7284 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:52 -0800 Subject: [PATCH 049/180] drivers/video/backlight/tdo24m.c: add missing const Add 'const' to static array that was missing it in its definition. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Eric Miao <eric.y.miao@gmail.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/tdo24m.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 76bbde19d349..ad2325f3d652 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -47,7 +47,7 @@ struct tdo24m { ((x1) << 9) | 0x100 | (x2)) #define CMD_NULL (-1) -static uint32_t lcd_panel_reset[] = { +static const uint32_t lcd_panel_reset[] = { CMD0(0x1), /* reset */ CMD0(0x0), /* nop */ CMD0(0x0), /* nop */ @@ -55,7 +55,7 @@ static uint32_t lcd_panel_reset[] = { CMD_NULL, }; -static uint32_t lcd_panel_on[] = { +static const uint32_t lcd_panel_on[] = { CMD0(0x29), /* Display ON */ CMD2(0xB8, 0xFF, 0xF9), /* Output Control */ CMD0(0x11), /* Sleep out */ @@ -63,7 +63,7 @@ static uint32_t lcd_panel_on[] = { CMD_NULL, }; -static uint32_t lcd_panel_off[] = { +static const uint32_t lcd_panel_off[] = { CMD0(0x28), /* Display OFF */ CMD2(0xB8, 0x80, 0x02), /* Output Control */ CMD0(0x10), /* Sleep in */ @@ -71,7 +71,7 @@ static uint32_t lcd_panel_off[] = { CMD_NULL, }; -static uint32_t lcd_vga_pass_through_tdo24m[] = { +static const uint32_t lcd_vga_pass_through_tdo24m[] = { CMD1(0xB0, 0x16), CMD1(0xBC, 0x80), CMD1(0xE1, 0x00), @@ -80,7 +80,7 @@ static uint32_t lcd_vga_pass_through_tdo24m[] = { CMD_NULL, }; -static uint32_t lcd_qvga_pass_through_tdo24m[] = { +static const uint32_t lcd_qvga_pass_through_tdo24m[] = { CMD1(0xB0, 0x16), CMD1(0xBC, 0x81), CMD1(0xE1, 0x00), @@ -89,7 +89,7 @@ static uint32_t lcd_qvga_pass_through_tdo24m[] = { CMD_NULL, }; -static uint32_t lcd_vga_transfer_tdo24m[] = { +static const uint32_t lcd_vga_transfer_tdo24m[] = { CMD1(0xcf, 0x02), /* Blanking period control (1) */ CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ CMD1(0xd1, 0x01), /* CKV timing control on/off */ @@ -102,7 +102,7 @@ static uint32_t lcd_vga_transfer_tdo24m[] = { CMD_NULL, }; -static uint32_t lcd_qvga_transfer[] = { +static const uint32_t lcd_qvga_transfer[] = { CMD1(0xd6, 0x02), /* Blanking period control (1) */ CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */ CMD1(0xd8, 0x01), /* CKV timing control on/off */ @@ -115,7 +115,7 @@ static uint32_t lcd_qvga_transfer[] = { CMD_NULL, }; -static uint32_t lcd_vga_pass_through_tdo35s[] = { +static const uint32_t lcd_vga_pass_through_tdo35s[] = { CMD1(0xB0, 0x16), CMD1(0xBC, 0x80), CMD1(0xE1, 0x00), @@ -123,7 +123,7 @@ static uint32_t lcd_vga_pass_through_tdo35s[] = { CMD_NULL, }; -static uint32_t lcd_qvga_pass_through_tdo35s[] = { +static const uint32_t lcd_qvga_pass_through_tdo35s[] = { CMD1(0xB0, 0x16), CMD1(0xBC, 0x81), CMD1(0xE1, 0x00), @@ -131,7 +131,7 @@ static uint32_t lcd_qvga_pass_through_tdo35s[] = { CMD_NULL, }; -static uint32_t lcd_vga_transfer_tdo35s[] = { +static const uint32_t lcd_vga_transfer_tdo35s[] = { CMD1(0xcf, 0x02), /* Blanking period control (1) */ CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ CMD1(0xd1, 0x01), /* CKV timing control on/off */ @@ -144,7 +144,7 @@ static uint32_t lcd_vga_transfer_tdo35s[] = { CMD_NULL, }; -static uint32_t lcd_panel_config[] = { +static const uint32_t lcd_panel_config[] = { CMD2(0xb8, 0xff, 0xf9), /* Output control */ CMD0(0x11), /* sleep out */ CMD1(0xba, 0x01), /* Display mode (1) */ @@ -175,10 +175,11 @@ static uint32_t lcd_panel_config[] = { CMD_NULL, }; -static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array) +static int tdo24m_writes(struct tdo24m *lcd, const uint32_t *array) { struct spi_transfer *x = &lcd->xfer; - uint32_t data, *p = array; + const uint32_t *p = array; + uint32_t data; int nparams, err = 0; for (; *p != CMD_NULL; p++) { From 3fd00432df3c4ae3c54a10360634f6d3a4a787c4 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:54 -0800 Subject: [PATCH 050/180] drivers/video/backlight/vgg2432a4.c: add missing const Add 'const' to static array that was missing it in its definition. Also, 'const' is added to ili9320_write_regs(), because it is called by vgg2432a4 driver. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Ben Dooks <ben-linux@fluff.org> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/ili9320.c | 2 +- drivers/video/backlight/ili9320.h | 2 +- drivers/video/backlight/vgg2432a4.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c index 69e253b7c24b..1235bf9defc4 100644 --- a/drivers/video/backlight/ili9320.c +++ b/drivers/video/backlight/ili9320.c @@ -59,7 +59,7 @@ int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value) EXPORT_SYMBOL_GPL(ili9320_write); int ili9320_write_regs(struct ili9320 *ili, - struct ili9320_reg *values, + const struct ili9320_reg *values, int nr_values) { int index; diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h index e388eca7cac5..e0db738f7bb9 100644 --- a/drivers/video/backlight/ili9320.h +++ b/drivers/video/backlight/ili9320.h @@ -63,7 +63,7 @@ extern int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value); extern int ili9320_write_regs(struct ili9320 *ili, - struct ili9320_reg *values, + const struct ili9320_reg *values, int nr_values); /* Device probe */ diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 5ba7fbd7e405..45e81b4cf8b4 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c @@ -26,7 +26,7 @@ /* Device initialisation sequences */ -static struct ili9320_reg vgg_init1[] = { +static const struct ili9320_reg vgg_init1[] = { { .address = ILI9320_POWER1, .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0), @@ -43,7 +43,7 @@ static struct ili9320_reg vgg_init1[] = { }, }; -static struct ili9320_reg vgg_init2[] = { +static const struct ili9320_reg vgg_init2[] = { { .address = ILI9320_POWER1, .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE | @@ -54,7 +54,7 @@ static struct ili9320_reg vgg_init2[] = { } }; -static struct ili9320_reg vgg_gamma[] = { +static const struct ili9320_reg vgg_gamma[] = { { .address = ILI9320_GAMMA1, .value = 0x0000, @@ -89,7 +89,7 @@ static struct ili9320_reg vgg_gamma[] = { }; -static struct ili9320_reg vgg_init0[] = { +static const struct ili9320_reg vgg_init0[] = { [0] = { /* set direction and scan mode gate */ .address = ILI9320_DRIVER, From 3c48d1f2539cf3a42adc5fe4f77950eeb28bef3b Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:55 -0800 Subject: [PATCH 051/180] drivers/video/backlight/s6e63m0.c: remove unnecessary cast of void pointer Remove unnecessary cast of void pointer for platform data in probe function. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/s6e63m0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 484e10dd1a8e..3e1c1135f6df 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c @@ -757,7 +757,7 @@ static int s6e63m0_probe(struct spi_device *spi) lcd->spi = spi; lcd->dev = &spi->dev; - lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data; + lcd->lcd_pd = spi->dev.platform_data; if (!lcd->lcd_pd) { dev_err(&spi->dev, "platform data is NULL.\n"); return -EFAULT; From 3a1f9462dbdf4d671f2f21290d507d1ae89d141a Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:57 -0800 Subject: [PATCH 052/180] drivers/video/backlight/88pm860x_bl.c: drop devm_kfree of devm_kzalloc'd data devm_kfree() allocates memory that is released when a driver detaches. Thus, there is no reason to explicitly call devm_kfree() in probe or remove functions. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/88pm860x_bl.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 6e509d995093..bb21412547a9 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -208,22 +208,19 @@ static int pm860x_backlight_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle"); if (!res) { dev_err(&pdev->dev, "No REG resource for duty cycle\n"); - ret = -ENXIO; - goto out; + return -ENXIO; } data->reg_duty_cycle = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on"); if (!res) { dev_err(&pdev->dev, "No REG resorce for always on\n"); - ret = -ENXIO; - goto out; + return -ENXIO; } data->reg_always_on = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current"); if (!res) { dev_err(&pdev->dev, "No REG resource for current\n"); - ret = -ENXIO; - goto out; + return -ENXIO; } data->reg_current = res->start; @@ -263,8 +260,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev) return 0; out_brt: backlight_device_unregister(bl); -out: - devm_kfree(&pdev->dev, data); return ret; } From 2c114cb4edb741822ea48e80be8c525032206e9a Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:00:58 -0800 Subject: [PATCH 053/180] drivers/video/backlight/max8925_bl.c: drop devm_kfree of devm_kzalloc'd data devm_kfree() allocates memory that is released when a driver detaches. Thus, there is no reason to explicitly call devm_kfree in probe or remove functions. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/max8925_bl.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index c6bec7aab87b..2c9bce050aa9 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c @@ -120,15 +120,13 @@ static int max8925_backlight_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_REG, 0); if (!res) { dev_err(&pdev->dev, "No REG resource for mode control!\n"); - ret = -ENXIO; - goto out; + return -ENXIO; } data->reg_mode_cntl = res->start; res = platform_get_resource(pdev, IORESOURCE_REG, 1); if (!res) { dev_err(&pdev->dev, "No REG resource for control!\n"); - ret = -ENXIO; - goto out; + return -ENXIO; } data->reg_cntl = res->start; @@ -142,8 +140,7 @@ static int max8925_backlight_probe(struct platform_device *pdev) &max8925_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); - ret = PTR_ERR(bl); - goto out; + return PTR_ERR(bl); } bl->props.brightness = MAX_BRIGHTNESS; @@ -166,8 +163,6 @@ static int max8925_backlight_probe(struct platform_device *pdev) return 0; out_brt: backlight_device_unregister(bl); -out: - devm_kfree(&pdev->dev, data); return ret; } From fb08cd9b111c6a922f468ef5e33acc67eb91d40b Mon Sep 17 00:00:00 2001 From: Axel Lin <axel.lin@ingics.com> Date: Mon, 17 Dec 2012 16:00:59 -0800 Subject: [PATCH 054/180] drivers/video/backlight/lm3639_bl.c: fix up world writable sysfs file We don't need the sysfs file to be world writable or group writable. This file is write-only, change it to S_IWUSR (0200). Signed-off-by: Axel Lin <axel.lin@ingics.com> Acked-by: "G.Shark Jeong" <gshark.jeong@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lm3639_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index b0e1e8ba4d9f..7ab2d2a04e41 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -214,7 +214,7 @@ out_input: } -static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store); +static DEVICE_ATTR(bled_mode, S_IWUSR, NULL, lm3639_bled_mode_store); /* torch */ static void lm3639_torch_brightness_set(struct led_classdev *cdev, From 762a936fba7bd9225ca9a96e4860f6969b6b5670 Mon Sep 17 00:00:00 2001 From: Thierry Reding <thierry.reding@avionic-design.de> Date: Mon, 17 Dec 2012 16:01:06 -0800 Subject: [PATCH 055/180] backlight: add of_find_backlight_by_node() This function finds the struct backlight_device for a given device tree node. A dummy function is provided so that it safely compiles out if OF support is disabled. [akpm@linux-foundation.org: Don't use IS_ENABLED(CONFIG_OF)] Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Acked-by: Jingoo Han <jg1.han@samsung.com> Reviewed-by: Grant Likely <grant.likely@secretlab.ca> Cc: Thierry Reding <thierry.reding@avionic-design.de> Reviewed-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/backlight.c | 29 +++++++++++++++++++++++++++++ include/linux/backlight.h | 10 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 297db2fa91f5..345f6660d4b3 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -370,6 +370,35 @@ void backlight_device_unregister(struct backlight_device *bd) } EXPORT_SYMBOL(backlight_device_unregister); +#ifdef CONFIG_OF +static int of_parent_match(struct device *dev, void *data) +{ + return dev->parent && dev->parent->of_node == data; +} + +/** + * of_find_backlight_by_node() - find backlight device by device-tree node + * @node: device-tree node of the backlight device + * + * Returns a pointer to the backlight device corresponding to the given DT + * node or NULL if no such backlight device exists or if the device hasn't + * been probed yet. + * + * This function obtains a reference on the backlight device and it is the + * caller's responsibility to drop the reference by calling put_device() on + * the backlight device's .dev field. + */ +struct backlight_device *of_find_backlight_by_node(struct device_node *node) +{ + struct device *dev; + + dev = class_find_device(backlight_class, NULL, node, of_parent_match); + + return dev ? to_backlight_device(dev) : NULL; +} +EXPORT_SYMBOL(of_find_backlight_by_node); +#endif + static void __exit backlight_class_exit(void) { class_destroy(backlight_class); diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 5ffc6dda4675..da9a0825e007 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -134,4 +134,14 @@ struct generic_bl_info { void (*kick_battery)(void); }; +#ifdef CONFIG_OF +struct backlight_device *of_find_backlight_by_node(struct device_node *node); +#else +static inline struct backlight_device * +of_find_backlight_by_node(struct device_node *node) +{ + return NULL; +} +#endif + #endif From b444df2f7267e1a431989ad95169f0c13ac790e2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi <peter.ujfalusi@ti.com> Date: Mon, 17 Dec 2012 16:01:08 -0800 Subject: [PATCH 056/180] drivers/video/backlight/pandora_bl.c: change TWL4030_MODULE_PWM0 to TWL_MODULE_PWM TWL_MODULE_PWM is defined as: #define TWL_MODULE_PWM TWL4030_MODULE_PWM0 Use the common module ID define here which will facilitate the upcoming twl-core cleanup. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: Grazvydas Ignotas <notasas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/pandora_bl.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c index 4ec30748b447..633b0a22fd64 100644 --- a/drivers/video/backlight/pandora_bl.c +++ b/drivers/video/backlight/pandora_bl.c @@ -71,8 +71,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl) * set PWM duty cycle to max. TPS61161 seems to use this * to calibrate it's PWM sensitivity when it starts. */ - twl_i2c_write_u8(TWL4030_MODULE_PWM0, MAX_VALUE, - TWL_PWM0_OFF); + twl_i2c_write_u8(TWL_MODULE_PWM, MAX_VALUE, TWL_PWM0_OFF); /* first enable clock, then PWM0 out */ twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1); @@ -90,8 +89,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl) usleep_range(2000, 10000); } - twl_i2c_write_u8(TWL4030_MODULE_PWM0, MIN_VALUE + brightness, - TWL_PWM0_OFF); + twl_i2c_write_u8(TWL_MODULE_PWM, MIN_VALUE + brightness, TWL_PWM0_OFF); done: if (brightness != 0) @@ -132,7 +130,7 @@ static int pandora_backlight_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bl); /* 64 cycle period, ON position 0 */ - twl_i2c_write_u8(TWL4030_MODULE_PWM0, 0x80, TWL_PWM0_ON); + twl_i2c_write_u8(TWL_MODULE_PWM, 0x80, TWL_PWM0_ON); bl->props.state |= PANDORABL_WAS_OFF; bl->props.brightness = MAX_USER_VALUE; From 2fe2380e354d3bb634de673c498a262fb0d632ad Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:01:09 -0800 Subject: [PATCH 057/180] backlight: 88pm860x_bl: remove an unnecessary line continuation Remove an unnecessary line continuation in pm860x_backlight_probe(). Also, a checkpatch warning is fixed as below: WARNING: Avoid unnecessary line continuations [akpm@linux-foundation.org: remove newline] Signed-off-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/88pm860x_bl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index bb21412547a9..c072ed9aea36 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -228,8 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) sprintf(name, "backlight-%d", pdev->id); data->port = pdev->id; data->chip = chip; - data->i2c = (chip->id == CHIP_PM8606) ? chip->client \ - : chip->companion; + data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; data->current_brightness = MAX_BRIGHTNESS; if (pm860x_backlight_dt_init(pdev, data, name)) { if (pdata) { From 424e06e3da2cbf986d7421f98b90fe5cf4b57be5 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:01:10 -0800 Subject: [PATCH 058/180] drivers/video/backlight/lcd.c: return ENXIO when ops functions cannot be called Previously, when ops functions cannot be called, lcd_show_contrast() and lcd_store_contrast() returned 0, instead of ENXIO. Thus, in this case, a local variable 'rc' for return value should be initialized as ENXIO, after kstrtoul() is called. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lcd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index a5d0d024bb92..34fb6bd798c8 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -108,7 +108,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr, static ssize_t lcd_store_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int rc = -ENXIO; + int rc; struct lcd_device *ld = to_lcd_device(dev); unsigned long power; @@ -116,6 +116,8 @@ static ssize_t lcd_store_power(struct device *dev, if (rc) return rc; + rc = -ENXIO; + mutex_lock(&ld->ops_lock); if (ld->ops && ld->ops->set_power) { pr_debug("set power to %lu\n", power); @@ -144,7 +146,7 @@ static ssize_t lcd_show_contrast(struct device *dev, static ssize_t lcd_store_contrast(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int rc = -ENXIO; + int rc; struct lcd_device *ld = to_lcd_device(dev); unsigned long contrast; @@ -152,6 +154,8 @@ static ssize_t lcd_store_contrast(struct device *dev, if (rc) return rc; + rc = -ENXIO; + mutex_lock(&ld->ops_lock); if (ld->ops && ld->ops->set_contrast) { pr_debug("set contrast to %lu\n", contrast); From 1eddd9770f7e809228ae761ecc575f214f571e51 Mon Sep 17 00:00:00 2001 From: Jingoo Han <jg1.han@samsung.com> Date: Mon, 17 Dec 2012 16:01:12 -0800 Subject: [PATCH 059/180] drivers/video/backlight/lms283gf05.c: use GPIOF_INIT flags when using devm_gpio_request_one() GPIOF_DIR_OUT and GPIOF_DIR_IN are defined as below: GPIOF_DIR_OUT (0 << 0) GPIOF_DIR_IN (1 << 0) So, when !pdata->reset_inverted is 1, the gpio pin can be set as input, instead of output. To prevent this problem, GPIOF_INIT flag should be used when using devm_gpio_request_one(). Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Marek Vasut <marex@denx.de> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/lms283gf05.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 13e24d52887c..55819b384701 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -159,7 +159,8 @@ static int lms283gf05_probe(struct spi_device *spi) if (pdata != NULL) { ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio, - GPIOF_DIR_OUT | !pdata->reset_inverted, + GPIOF_DIR_OUT | (!pdata->reset_inverted ? + GPIOF_INIT_HIGH : GPIOF_INIT_LOW), "LMS285GF05 RESET"); if (ret) return ret; From 1581b088fc91cbb974ad2b98431a8ecabb4852ee Mon Sep 17 00:00:00 2001 From: Marko Katic <dromede@gmail.com> Date: Mon, 17 Dec 2012 16:01:14 -0800 Subject: [PATCH 060/180] backlight: corgi_lcd: Use gpio_set_value_cansleep() to avoid WARN_ON Changing backlight intensity on an Akita (Sharp Zaurus C-1000) triggers WARN_ON message: WARNING: at drivers/gpio/gpiolib.c:1672 __gpio_set_value+0x38/0xa4() Modules linked in: Backtrace: corgi_bl_set_intensity+0x0/0x74 corgi_bl_update_status+0x0/0x64 corgi_lcd_probe+0x0/0x258 spi_drv_probe+0x0/0x24 driver_probe_device+0x0/0x208 __driver_attach+0x0/0x94 bus_for_each_dev+0x0/0x90 driver_attach+0x0/0x28 bus_add_driver+0x0/0x22c driver_register+0x0/0x134 spi_register_driver+0x0/0x60 corgi_lcd_driver_init+0x0/0x1c do_one_initcall+0x0/0x174 kernel_init+0x0/0x2a8 Akita machines have backlight controls hooked to a gpio expander chip, max7310 using i2c transfers which can sleep. In this case, pca953x_gpio_set_value() can be called to control gpio, and pca953x_setup_gpio() sets can_sleep flag. Therefore, gpio_set_value_cansleep() should be used in order to avoid WARN_ON on akita machines. Akita is the only exception in this case since other users of corgi_lcd access backlight gpio controls through a different gpio expander which does not set the can_sleep flag. Signed-off-by: Marko Katic <dromede@gmail.com> Signed-off-by: Jingoo Han <jg1.han@samsung.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/backlight/corgi_lcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index e2e1b62bebb1..e323fcbe884e 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -409,10 +409,10 @@ static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity) cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted; if (gpio_is_valid(lcd->gpio_backlight_cont)) - gpio_set_value(lcd->gpio_backlight_cont, cont); + gpio_set_value_cansleep(lcd->gpio_backlight_cont, cont); if (gpio_is_valid(lcd->gpio_backlight_on)) - gpio_set_value(lcd->gpio_backlight_on, intensity); + gpio_set_value_cansleep(lcd->gpio_backlight_on, intensity); if (lcd->kick_battery) lcd->kick_battery(); From 0edd807dc96522d9a8e8b5298552cd8adf810cc5 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" <Milo.Kim@ti.com> Date: Mon, 17 Dec 2012 16:01:17 -0800 Subject: [PATCH 061/180] MAINTAINERS: add LP855x backlight driver entry Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com> Cc: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c0e5c06f7be7..4e2a1f67a1fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7545,6 +7545,13 @@ S: Maintained F: sound/soc/codecs/lm49453* F: sound/soc/codecs/isabelle* +TI LP855x BACKLIGHT DRIVER +M: Milo Kim <milo.kim@ti.com> +S: Maintained +F: Documentation/backlight/lp855x-driver.txt +F: drivers/video/backlight/lp855x_bl.c +F: include/linux/platform_data/lp855x.h + TI TWL4030 SERIES SOC CODEC DRIVER M: Peter Ujfalusi <peter.ujfalusi@ti.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) From b18888ab256f05626193be955a7a03f01d676f8c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 16:01:18 -0800 Subject: [PATCH 062/180] string: introduce helper to get base file name from given path There are several places in the kernel that use functionality like basename(3) with the exception: in case of '/foo/bar/' we expect to get an empty string. Let's do it common helper for them. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Jason Baron <jbaron@redhat.com> Cc: YAMANE Toshiaki <yamanetoshi@gmail.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/string.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index 630125818ca8..ac889c5ea11b 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -143,4 +143,15 @@ static inline bool strstarts(const char *str, const char *prefix) extern size_t memweight(const void *ptr, size_t bytes); +/** + * kbasename - return the last part of a pathname. + * + * @path: path to extract the filename from. + */ +static inline const char *kbasename(const char *path) +{ + const char *tail = strrchr(path, '/'); + return tail ? tail + 1 : path; +} + #endif /* _LINUX_STRING_H_ */ From 35367ab28d024ef026dbd797b4076c8f008ec08c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 16:01:21 -0800 Subject: [PATCH 063/180] lib: dynamic_debug: use kbasename() Remove the custom implementation of the functionality similar to kbasename(). Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Jason Baron <jbaron@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- lib/dynamic_debug.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index e7f7d993357a..1db1fc660538 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -62,13 +62,6 @@ static LIST_HEAD(ddebug_tables); static int verbose = 0; module_param(verbose, int, 0644); -/* Return the last part of a pathname */ -static inline const char *basename(const char *path) -{ - const char *tail = strrchr(path, '/'); - return tail ? tail+1 : path; -} - /* Return the path relative to source root */ static inline const char *trim_prefix(const char *path) { @@ -154,7 +147,7 @@ static int ddebug_change(const struct ddebug_query *query, /* match against the source filename */ if (query->filename && strcmp(query->filename, dp->filename) && - strcmp(query->filename, basename(dp->filename)) && + strcmp(query->filename, kbasename(dp->filename)) && strcmp(query->filename, trim_prefix(dp->filename))) continue; From 2fbc57c53a815ea30b926dd7627897a02daae302 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 16:01:23 -0800 Subject: [PATCH 064/180] mm: use kbasename() Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- mm/memory.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 23f1fdfdfcf1..e0a9b0ce4f10 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -58,6 +58,7 @@ #include <linux/elf.h> #include <linux/gfp.h> #include <linux/migrate.h> +#include <linux/string.h> #include <asm/io.h> #include <asm/pgalloc.h> @@ -4118,15 +4119,12 @@ void print_vma_addr(char *prefix, unsigned long ip) struct file *f = vma->vm_file; char *buf = (char *)__get_free_page(GFP_KERNEL); if (buf) { - char *p, *s; + char *p; p = d_path(&f->f_path, buf, PAGE_SIZE); if (IS_ERR(p)) p = "?"; - s = strrchr(p, '/'); - if (s) - p = s+1; - printk("%s%s[%lx+%lx]", prefix, p, + printk("%s%s[%lx+%lx]", prefix, kbasename(p), vma->vm_start, vma->vm_end - vma->vm_start); free_page((unsigned long)buf); From f9a00e8738c209d95493cf97d3a82ab2655892e5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 16:01:25 -0800 Subject: [PATCH 065/180] procfs: use kbasename() [yongjun_wei@trendmicro.com.cn: remove duplicated include] Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/proc/proc_devtree.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index df7dd08d4391..de20ec480fa0 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -195,11 +195,7 @@ void proc_device_tree_add_node(struct device_node *np, set_node_proc_entry(np, de); for (child = NULL; (child = of_get_next_child(np, child));) { /* Use everything after the last slash, or the full name */ - p = strrchr(child->full_name, '/'); - if (!p) - p = child->full_name; - else - ++p; + p = kbasename(child->full_name); if (duplicate_name(de, p)) p = fixup_name(np, de, p); From b2e902f024fa6f6f27b335c478d81bab0cb2c768 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 16:01:27 -0800 Subject: [PATCH 066/180] trace: use kbasename() Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- kernel/trace/trace_uprobe.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 9614db8b0f8c..c86e6d4f67fb 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -22,6 +22,7 @@ #include <linux/uaccess.h> #include <linux/uprobes.h> #include <linux/namei.h> +#include <linux/string.h> #include "trace_probe.h" @@ -263,16 +264,15 @@ static int create_trace_uprobe(int argc, char **argv) /* setup a probe */ if (!event) { - char *tail = strrchr(filename, '/'); + char *tail; char *ptr; - ptr = kstrdup((tail ? tail + 1 : filename), GFP_KERNEL); - if (!ptr) { + tail = kstrdup(kbasename(filename), GFP_KERNEL); + if (!tail) { ret = -ENOMEM; goto fail_address_parse; } - tail = ptr; ptr = strpbrk(tail, ".-_"); if (ptr) *ptr = '\0'; From 375da3a76dc49f10c35e243ebef62df12e3adf4e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Date: Mon, 17 Dec 2012 16:01:28 -0800 Subject: [PATCH 067/180] drivers/of/fdt.c: re-use kernel's kbasename() Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Fabio Estevam <fabio.estevam@freescale.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/of/fdt.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a65c39c473bf..808be06bb67e 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -488,14 +488,8 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, depth++; pathp = (char *)p; p = ALIGN(p + strlen(pathp) + 1, 4); - if ((*pathp) == '/') { - const char *lp, *np; - for (lp = NULL, np = pathp; *np; np++) - if ((*np) == '/') - lp = np+1; - if (lp != NULL) - pathp = lp; - } + if (*pathp == '/') + pathp = kbasename(pathp); rc = it(p, pathp, depth, data); if (rc != 0) break; From 53809751ac230a3611b5cdd375f3389f3207d471 Mon Sep 17 00:00:00 2001 From: Jan Beulich <JBeulich@suse.com> Date: Mon, 17 Dec 2012 16:01:31 -0800 Subject: [PATCH 068/180] sscanf: don't ignore field widths for numeric conversions This is another step towards better standard conformance. Rather than adding a local buffer to store the specified portion of the string (with the need to enforce an arbitrary maximum supported width to limit the buffer size), do a maximum width conversion and then drop as much of it as is necessary to meet the caller's request. Also fail on negative field widths. Uses the deprecated simple_strto*() functions because kstrtoXX() fail on non-zero terminated strings. Signed-off-by: Jan Beulich <jbeulich@suse.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- lib/vsprintf.c | 96 ++++++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 41da0741a663..292fcb174a32 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -23,12 +23,12 @@ #include <linux/ctype.h> #include <linux/kernel.h> #include <linux/kallsyms.h> +#include <linux/math64.h> #include <linux/uaccess.h> #include <linux/ioport.h> #include <net/addrconf.h> #include <asm/page.h> /* for PAGE_SIZE */ -#include <asm/div64.h> #include <asm/sections.h> /* for dereference_function_descriptor() */ #include "kstrtox.h" @@ -2016,7 +2016,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args) char digit; int num = 0; u8 qualifier; - u8 base; + unsigned int base; + union { + long long s; + unsigned long long u; + } val; s16 field_width; bool is_sign; @@ -2056,8 +2060,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args) /* get field width */ field_width = -1; - if (isdigit(*fmt)) + if (isdigit(*fmt)) { field_width = skip_atoi(&fmt); + if (field_width <= 0) + break; + } /* get conversion qualifier */ qualifier = -1; @@ -2157,58 +2164,61 @@ int vsscanf(const char *buf, const char *fmt, va_list args) || (base == 0 && !isdigit(digit))) break; + if (is_sign) + val.s = qualifier != 'L' ? + simple_strtol(str, &next, base) : + simple_strtoll(str, &next, base); + else + val.u = qualifier != 'L' ? + simple_strtoul(str, &next, base) : + simple_strtoull(str, &next, base); + + if (field_width > 0 && next - str > field_width) { + if (base == 0) + _parse_integer_fixup_radix(str, &base); + while (next - str > field_width) { + if (is_sign) + val.s = div_s64(val.s, base); + else + val.u = div_u64(val.u, base); + --next; + } + } + switch (qualifier) { case 'H': /* that's 'hh' in format */ - if (is_sign) { - signed char *s = (signed char *)va_arg(args, signed char *); - *s = (signed char)simple_strtol(str, &next, base); - } else { - unsigned char *s = (unsigned char *)va_arg(args, unsigned char *); - *s = (unsigned char)simple_strtoul(str, &next, base); - } + if (is_sign) + *va_arg(args, signed char *) = val.s; + else + *va_arg(args, unsigned char *) = val.u; break; case 'h': - if (is_sign) { - short *s = (short *)va_arg(args, short *); - *s = (short)simple_strtol(str, &next, base); - } else { - unsigned short *s = (unsigned short *)va_arg(args, unsigned short *); - *s = (unsigned short)simple_strtoul(str, &next, base); - } + if (is_sign) + *va_arg(args, short *) = val.s; + else + *va_arg(args, unsigned short *) = val.u; break; case 'l': - if (is_sign) { - long *l = (long *)va_arg(args, long *); - *l = simple_strtol(str, &next, base); - } else { - unsigned long *l = (unsigned long *)va_arg(args, unsigned long *); - *l = simple_strtoul(str, &next, base); - } + if (is_sign) + *va_arg(args, long *) = val.s; + else + *va_arg(args, unsigned long *) = val.u; break; case 'L': - if (is_sign) { - long long *l = (long long *)va_arg(args, long long *); - *l = simple_strtoll(str, &next, base); - } else { - unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *); - *l = simple_strtoull(str, &next, base); - } + if (is_sign) + *va_arg(args, long long *) = val.s; + else + *va_arg(args, unsigned long long *) = val.u; break; case 'Z': case 'z': - { - size_t *s = (size_t *)va_arg(args, size_t *); - *s = (size_t)simple_strtoul(str, &next, base); - } - break; + *va_arg(args, size_t *) = val.u; + break; default: - if (is_sign) { - int *i = (int *)va_arg(args, int *); - *i = (int)simple_strtol(str, &next, base); - } else { - unsigned int *i = (unsigned int *)va_arg(args, unsigned int*); - *i = (unsigned int)simple_strtoul(str, &next, base); - } + if (is_sign) + *va_arg(args, int *) = val.s; + else + *va_arg(args, unsigned int *) = val.u; break; } num++; From a1fd3e24d8a484b3265a6d485202afe093c058f3 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov <oleg@redhat.com> Date: Mon, 17 Dec 2012 16:01:32 -0800 Subject: [PATCH 069/180] percpu_rw_semaphore: reimplement to not block the readers unnecessarily Currently the writer does msleep() plus synchronize_sched() 3 times to acquire/release the semaphore, and during this time the readers are blocked completely. Even if the "write" section was not actually started or if it was already finished. With this patch down_write/up_write does synchronize_sched() twice and down_read/up_read are still possible during this time, just they use the slow path. percpu_down_write() first forces the readers to use rw_semaphore and increment the "slow" counter to take the lock for reading, then it takes that rw_semaphore for writing and blocks the readers. Also. With this patch the code relies on the documented behaviour of synchronize_sched(), it doesn't try to pair synchronize_sched() with barrier. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mikulas Patocka <mpatocka@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Anton Arapov <anton@redhat.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/percpu-rwsem.h | 83 +++---------------- lib/Makefile | 2 +- lib/percpu-rwsem.c | 154 +++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 71 deletions(-) create mode 100644 lib/percpu-rwsem.c diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index bd1e86071e57..592f0d610d8e 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -2,82 +2,25 @@ #define _LINUX_PERCPU_RWSEM_H #include <linux/mutex.h> +#include <linux/rwsem.h> #include <linux/percpu.h> -#include <linux/rcupdate.h> -#include <linux/delay.h> +#include <linux/wait.h> struct percpu_rw_semaphore { - unsigned __percpu *counters; - bool locked; - struct mutex mtx; + unsigned int __percpu *fast_read_ctr; + struct mutex writer_mutex; + struct rw_semaphore rw_sem; + atomic_t slow_read_ctr; + wait_queue_head_t write_waitq; }; -#define light_mb() barrier() -#define heavy_mb() synchronize_sched_expedited() +extern void percpu_down_read(struct percpu_rw_semaphore *); +extern void percpu_up_read(struct percpu_rw_semaphore *); -static inline void percpu_down_read(struct percpu_rw_semaphore *p) -{ - rcu_read_lock_sched(); - if (unlikely(p->locked)) { - rcu_read_unlock_sched(); - mutex_lock(&p->mtx); - this_cpu_inc(*p->counters); - mutex_unlock(&p->mtx); - return; - } - this_cpu_inc(*p->counters); - rcu_read_unlock_sched(); - light_mb(); /* A, between read of p->locked and read of data, paired with D */ -} +extern void percpu_down_write(struct percpu_rw_semaphore *); +extern void percpu_up_write(struct percpu_rw_semaphore *); -static inline void percpu_up_read(struct percpu_rw_semaphore *p) -{ - light_mb(); /* B, between read of the data and write to p->counter, paired with C */ - this_cpu_dec(*p->counters); -} - -static inline unsigned __percpu_count(unsigned __percpu *counters) -{ - unsigned total = 0; - int cpu; - - for_each_possible_cpu(cpu) - total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu)); - - return total; -} - -static inline void percpu_down_write(struct percpu_rw_semaphore *p) -{ - mutex_lock(&p->mtx); - p->locked = true; - synchronize_sched_expedited(); /* make sure that all readers exit the rcu_read_lock_sched region */ - while (__percpu_count(p->counters)) - msleep(1); - heavy_mb(); /* C, between read of p->counter and write to data, paired with B */ -} - -static inline void percpu_up_write(struct percpu_rw_semaphore *p) -{ - heavy_mb(); /* D, between write to data and write to p->locked, paired with A */ - p->locked = false; - mutex_unlock(&p->mtx); -} - -static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p) -{ - p->counters = alloc_percpu(unsigned); - if (unlikely(!p->counters)) - return -ENOMEM; - p->locked = false; - mutex_init(&p->mtx); - return 0; -} - -static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p) -{ - free_percpu(p->counters); - p->counters = NULL; /* catch use after free bugs */ -} +extern int percpu_init_rwsem(struct percpu_rw_semaphore *); +extern void percpu_free_rwsem(struct percpu_rw_semaphore *); #endif diff --git a/lib/Makefile b/lib/Makefile index e2152fa7ff4d..e959c20efb24 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ endif lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\ - idr.o int_sqrt.o extable.o \ + idr.o int_sqrt.o extable.o percpu-rwsem.o \ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ diff --git a/lib/percpu-rwsem.c b/lib/percpu-rwsem.c new file mode 100644 index 000000000000..2e03bcfe48f9 --- /dev/null +++ b/lib/percpu-rwsem.c @@ -0,0 +1,154 @@ +#include <linux/mutex.h> +#include <linux/rwsem.h> +#include <linux/percpu.h> +#include <linux/wait.h> +#include <linux/percpu-rwsem.h> +#include <linux/rcupdate.h> +#include <linux/sched.h> +#include <linux/errno.h> + +int percpu_init_rwsem(struct percpu_rw_semaphore *brw) +{ + brw->fast_read_ctr = alloc_percpu(int); + if (unlikely(!brw->fast_read_ctr)) + return -ENOMEM; + + mutex_init(&brw->writer_mutex); + init_rwsem(&brw->rw_sem); + atomic_set(&brw->slow_read_ctr, 0); + init_waitqueue_head(&brw->write_waitq); + return 0; +} + +void percpu_free_rwsem(struct percpu_rw_semaphore *brw) +{ + free_percpu(brw->fast_read_ctr); + brw->fast_read_ctr = NULL; /* catch use after free bugs */ +} + +/* + * This is the fast-path for down_read/up_read, it only needs to ensure + * there is no pending writer (!mutex_is_locked() check) and inc/dec the + * fast per-cpu counter. The writer uses synchronize_sched_expedited() to + * serialize with the preempt-disabled section below. + * + * The nontrivial part is that we should guarantee acquire/release semantics + * in case when + * + * R_W: down_write() comes after up_read(), the writer should see all + * changes done by the reader + * or + * W_R: down_read() comes after up_write(), the reader should see all + * changes done by the writer + * + * If this helper fails the callers rely on the normal rw_semaphore and + * atomic_dec_and_test(), so in this case we have the necessary barriers. + * + * But if it succeeds we do not have any barriers, mutex_is_locked() or + * __this_cpu_add() below can be reordered with any LOAD/STORE done by the + * reader inside the critical section. See the comments in down_write and + * up_write below. + */ +static bool update_fast_ctr(struct percpu_rw_semaphore *brw, unsigned int val) +{ + bool success = false; + + preempt_disable(); + if (likely(!mutex_is_locked(&brw->writer_mutex))) { + __this_cpu_add(*brw->fast_read_ctr, val); + success = true; + } + preempt_enable(); + + return success; +} + +/* + * Like the normal down_read() this is not recursive, the writer can + * come after the first percpu_down_read() and create the deadlock. + */ +void percpu_down_read(struct percpu_rw_semaphore *brw) +{ + if (likely(update_fast_ctr(brw, +1))) + return; + + down_read(&brw->rw_sem); + atomic_inc(&brw->slow_read_ctr); + up_read(&brw->rw_sem); +} + +void percpu_up_read(struct percpu_rw_semaphore *brw) +{ + if (likely(update_fast_ctr(brw, -1))) + return; + + /* false-positive is possible but harmless */ + if (atomic_dec_and_test(&brw->slow_read_ctr)) + wake_up_all(&brw->write_waitq); +} + +static int clear_fast_ctr(struct percpu_rw_semaphore *brw) +{ + unsigned int sum = 0; + int cpu; + + for_each_possible_cpu(cpu) { + sum += per_cpu(*brw->fast_read_ctr, cpu); + per_cpu(*brw->fast_read_ctr, cpu) = 0; + } + + return sum; +} + +/* + * A writer takes ->writer_mutex to exclude other writers and to force the + * readers to switch to the slow mode, note the mutex_is_locked() check in + * update_fast_ctr(). + * + * After that the readers can only inc/dec the slow ->slow_read_ctr counter, + * ->fast_read_ctr is stable. Once the writer moves its sum into the slow + * counter it represents the number of active readers. + * + * Finally the writer takes ->rw_sem for writing and blocks the new readers, + * then waits until the slow counter becomes zero. + */ +void percpu_down_write(struct percpu_rw_semaphore *brw) +{ + /* also blocks update_fast_ctr() which checks mutex_is_locked() */ + mutex_lock(&brw->writer_mutex); + + /* + * 1. Ensures mutex_is_locked() is visible to any down_read/up_read + * so that update_fast_ctr() can't succeed. + * + * 2. Ensures we see the result of every previous this_cpu_add() in + * update_fast_ctr(). + * + * 3. Ensures that if any reader has exited its critical section via + * fast-path, it executes a full memory barrier before we return. + * See R_W case in the comment above update_fast_ctr(). + */ + synchronize_sched_expedited(); + + /* nobody can use fast_read_ctr, move its sum into slow_read_ctr */ + atomic_add(clear_fast_ctr(brw), &brw->slow_read_ctr); + + /* block the new readers completely */ + down_write(&brw->rw_sem); + + /* wait for all readers to complete their percpu_up_read() */ + wait_event(brw->write_waitq, !atomic_read(&brw->slow_read_ctr)); +} + +void percpu_up_write(struct percpu_rw_semaphore *brw) +{ + /* allow the new readers, but only the slow-path */ + up_write(&brw->rw_sem); + + /* + * Insert the barrier before the next fast-path in down_read, + * see W_R case in the comment above update_fast_ctr(). + */ + synchronize_sched_expedited(); + mutex_unlock(&brw->writer_mutex); +} From 9390ef0c85fd065f01045fef708b046c98cda04c Mon Sep 17 00:00:00 2001 From: Oleg Nesterov <oleg@redhat.com> Date: Mon, 17 Dec 2012 16:01:36 -0800 Subject: [PATCH 070/180] percpu_rw_semaphore: kill ->writer_mutex, add ->write_ctr percpu_rw_semaphore->writer_mutex was only added to simplify the initial rewrite, the only thing it protects is clear_fast_ctr() which otherwise could be called by multiple writers. ->rw_sem is enough to serialize the writers. Kill this mutex and add "atomic_t write_ctr" instead. The writers increment/decrement this counter, the readers check it is zero instead of mutex_is_locked(). Move atomic_add(clear_fast_ctr(), slow_read_ctr) under down_write() to avoid the race with other writers. This is a bit sub-optimal, only the first writer needs this and we do not need to exclude the readers at this stage. But this is simple, we do not want another internal lock until we add more features. And this speeds up the write-contended case. Before this patch the racing writers sleep in synchronize_sched_expedited() sequentially, with this patch multiple synchronize_sched_expedited's can "overlap" with each other. Note: we can do more optimizations, this is only the first step. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Anton Arapov <anton@redhat.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michal Marek <mmarek@suse.cz> Cc: Mikulas Patocka <mpatocka@redhat.com> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/percpu-rwsem.h | 4 ++-- lib/percpu-rwsem.c | 34 ++++++++++++++++------------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index 592f0d610d8e..d2146a4f833e 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -1,14 +1,14 @@ #ifndef _LINUX_PERCPU_RWSEM_H #define _LINUX_PERCPU_RWSEM_H -#include <linux/mutex.h> +#include <linux/atomic.h> #include <linux/rwsem.h> #include <linux/percpu.h> #include <linux/wait.h> struct percpu_rw_semaphore { unsigned int __percpu *fast_read_ctr; - struct mutex writer_mutex; + atomic_t write_ctr; struct rw_semaphore rw_sem; atomic_t slow_read_ctr; wait_queue_head_t write_waitq; diff --git a/lib/percpu-rwsem.c b/lib/percpu-rwsem.c index 2e03bcfe48f9..ce92ab563a08 100644 --- a/lib/percpu-rwsem.c +++ b/lib/percpu-rwsem.c @@ -1,4 +1,4 @@ -#include <linux/mutex.h> +#include <linux/atomic.h> #include <linux/rwsem.h> #include <linux/percpu.h> #include <linux/wait.h> @@ -13,8 +13,8 @@ int percpu_init_rwsem(struct percpu_rw_semaphore *brw) if (unlikely(!brw->fast_read_ctr)) return -ENOMEM; - mutex_init(&brw->writer_mutex); init_rwsem(&brw->rw_sem); + atomic_set(&brw->write_ctr, 0); atomic_set(&brw->slow_read_ctr, 0); init_waitqueue_head(&brw->write_waitq); return 0; @@ -28,7 +28,7 @@ void percpu_free_rwsem(struct percpu_rw_semaphore *brw) /* * This is the fast-path for down_read/up_read, it only needs to ensure - * there is no pending writer (!mutex_is_locked() check) and inc/dec the + * there is no pending writer (atomic_read(write_ctr) == 0) and inc/dec the * fast per-cpu counter. The writer uses synchronize_sched_expedited() to * serialize with the preempt-disabled section below. * @@ -44,7 +44,7 @@ void percpu_free_rwsem(struct percpu_rw_semaphore *brw) * If this helper fails the callers rely on the normal rw_semaphore and * atomic_dec_and_test(), so in this case we have the necessary barriers. * - * But if it succeeds we do not have any barriers, mutex_is_locked() or + * But if it succeeds we do not have any barriers, atomic_read(write_ctr) or * __this_cpu_add() below can be reordered with any LOAD/STORE done by the * reader inside the critical section. See the comments in down_write and * up_write below. @@ -54,7 +54,7 @@ static bool update_fast_ctr(struct percpu_rw_semaphore *brw, unsigned int val) bool success = false; preempt_disable(); - if (likely(!mutex_is_locked(&brw->writer_mutex))) { + if (likely(!atomic_read(&brw->write_ctr))) { __this_cpu_add(*brw->fast_read_ctr, val); success = true; } @@ -101,9 +101,8 @@ static int clear_fast_ctr(struct percpu_rw_semaphore *brw) } /* - * A writer takes ->writer_mutex to exclude other writers and to force the - * readers to switch to the slow mode, note the mutex_is_locked() check in - * update_fast_ctr(). + * A writer increments ->write_ctr to force the readers to switch to the + * slow mode, note the atomic_read() check in update_fast_ctr(). * * After that the readers can only inc/dec the slow ->slow_read_ctr counter, * ->fast_read_ctr is stable. Once the writer moves its sum into the slow @@ -114,11 +113,10 @@ static int clear_fast_ctr(struct percpu_rw_semaphore *brw) */ void percpu_down_write(struct percpu_rw_semaphore *brw) { - /* also blocks update_fast_ctr() which checks mutex_is_locked() */ - mutex_lock(&brw->writer_mutex); - + /* tell update_fast_ctr() there is a pending writer */ + atomic_inc(&brw->write_ctr); /* - * 1. Ensures mutex_is_locked() is visible to any down_read/up_read + * 1. Ensures that write_ctr != 0 is visible to any down_read/up_read * so that update_fast_ctr() can't succeed. * * 2. Ensures we see the result of every previous this_cpu_add() in @@ -130,25 +128,25 @@ void percpu_down_write(struct percpu_rw_semaphore *brw) */ synchronize_sched_expedited(); + /* exclude other writers, and block the new readers completely */ + down_write(&brw->rw_sem); + /* nobody can use fast_read_ctr, move its sum into slow_read_ctr */ atomic_add(clear_fast_ctr(brw), &brw->slow_read_ctr); - /* block the new readers completely */ - down_write(&brw->rw_sem); - /* wait for all readers to complete their percpu_up_read() */ wait_event(brw->write_waitq, !atomic_read(&brw->slow_read_ctr)); } void percpu_up_write(struct percpu_rw_semaphore *brw) { - /* allow the new readers, but only the slow-path */ + /* release the lock, but the readers can't use the fast-path */ up_write(&brw->rw_sem); - /* * Insert the barrier before the next fast-path in down_read, * see W_R case in the comment above update_fast_ctr(). */ synchronize_sched_expedited(); - mutex_unlock(&brw->writer_mutex); + /* the last writer unblocks update_fast_ctr() */ + atomic_dec(&brw->write_ctr); } From 8ebe34731a0d1a9d89b536430afd98d0fadec99b Mon Sep 17 00:00:00 2001 From: Oleg Nesterov <oleg@redhat.com> Date: Mon, 17 Dec 2012 16:01:38 -0800 Subject: [PATCH 071/180] percpu_rw_semaphore: add lockdep annotations Add lockdep annotations. Not only this can help to find the potential problems, we do not want the false warnings if, say, the task takes two different percpu_rw_semaphore's for reading. IOW, at least ->rw_sem should not use a single class. This patch exposes this internal lock to lockdep so that it represents the whole percpu_rw_semaphore. This way we do not need to add another "fake" ->lockdep_map and lock_class_key. More importantly, this also makes the output from lockdep much more understandable if it finds the problem. In short, with this patch from lockdep pov percpu_down_read() and percpu_up_read() acquire/release ->rw_sem for reading, this matches the actual semantics. This abuses __up_read() but I hope this is fine and in fact I'd like to have down_read_no_lockdep() as well, percpu_down_read_recursive_readers() will need it. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Anton Arapov <anton@redhat.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michal Marek <mmarek@suse.cz> Cc: Mikulas Patocka <mpatocka@redhat.com> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/percpu-rwsem.h | 10 +++++++++- lib/percpu-rwsem.c | 21 +++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index d2146a4f833e..3e88c9a7d57f 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -5,6 +5,7 @@ #include <linux/rwsem.h> #include <linux/percpu.h> #include <linux/wait.h> +#include <linux/lockdep.h> struct percpu_rw_semaphore { unsigned int __percpu *fast_read_ctr; @@ -20,7 +21,14 @@ extern void percpu_up_read(struct percpu_rw_semaphore *); extern void percpu_down_write(struct percpu_rw_semaphore *); extern void percpu_up_write(struct percpu_rw_semaphore *); -extern int percpu_init_rwsem(struct percpu_rw_semaphore *); +extern int __percpu_init_rwsem(struct percpu_rw_semaphore *, + const char *, struct lock_class_key *); extern void percpu_free_rwsem(struct percpu_rw_semaphore *); +#define percpu_init_rwsem(brw) \ +({ \ + static struct lock_class_key rwsem_key; \ + __percpu_init_rwsem(brw, #brw, &rwsem_key); \ +}) + #endif diff --git a/lib/percpu-rwsem.c b/lib/percpu-rwsem.c index ce92ab563a08..652a8ee8efe9 100644 --- a/lib/percpu-rwsem.c +++ b/lib/percpu-rwsem.c @@ -2,18 +2,21 @@ #include <linux/rwsem.h> #include <linux/percpu.h> #include <linux/wait.h> +#include <linux/lockdep.h> #include <linux/percpu-rwsem.h> #include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/errno.h> -int percpu_init_rwsem(struct percpu_rw_semaphore *brw) +int __percpu_init_rwsem(struct percpu_rw_semaphore *brw, + const char *name, struct lock_class_key *rwsem_key) { brw->fast_read_ctr = alloc_percpu(int); if (unlikely(!brw->fast_read_ctr)) return -ENOMEM; - init_rwsem(&brw->rw_sem); + /* ->rw_sem represents the whole percpu_rw_semaphore for lockdep */ + __init_rwsem(&brw->rw_sem, name, rwsem_key); atomic_set(&brw->write_ctr, 0); atomic_set(&brw->slow_read_ctr, 0); init_waitqueue_head(&brw->write_waitq); @@ -66,19 +69,29 @@ static bool update_fast_ctr(struct percpu_rw_semaphore *brw, unsigned int val) /* * Like the normal down_read() this is not recursive, the writer can * come after the first percpu_down_read() and create the deadlock. + * + * Note: returns with lock_is_held(brw->rw_sem) == T for lockdep, + * percpu_up_read() does rwsem_release(). This pairs with the usage + * of ->rw_sem in percpu_down/up_write(). */ void percpu_down_read(struct percpu_rw_semaphore *brw) { - if (likely(update_fast_ctr(brw, +1))) + might_sleep(); + if (likely(update_fast_ctr(brw, +1))) { + rwsem_acquire_read(&brw->rw_sem.dep_map, 0, 0, _RET_IP_); return; + } down_read(&brw->rw_sem); atomic_inc(&brw->slow_read_ctr); - up_read(&brw->rw_sem); + /* avoid up_read()->rwsem_release() */ + __up_read(&brw->rw_sem); } void percpu_up_read(struct percpu_rw_semaphore *brw) { + rwsem_release(&brw->rw_sem.dep_map, 1, _RET_IP_); + if (likely(update_fast_ctr(brw, -1))) return; From 22b361d1df7bc25b558e52f22e779286a3d323e4 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov <oleg@redhat.com> Date: Mon, 17 Dec 2012 16:01:39 -0800 Subject: [PATCH 072/180] percpu_rw_semaphore: introduce CONFIG_PERCPU_RWSEM Currently only block_dev and uprobes use percpu_rw_semaphore, add the config option selected by BLOCK || UPROBES. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Anton Arapov <anton@redhat.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michal Marek <mmarek@suse.cz> Cc: Mikulas Patocka <mpatocka@redhat.com> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/Kconfig | 1 + block/Kconfig | 1 + lib/Kconfig | 3 +++ lib/Makefile | 3 ++- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index 34884faf98cd..54ffd0f9df21 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -80,6 +80,7 @@ config UPROBES bool "Transparent user-space probes (EXPERIMENTAL)" depends on UPROBE_EVENT && PERF_EVENTS default n + select PERCPU_RWSEM help Uprobes is the user-space counterpart to kprobes: they enable instrumentation applications (such as 'perf probe') diff --git a/block/Kconfig b/block/Kconfig index a7e40a7c8214..4a85ccf8d4cf 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -4,6 +4,7 @@ menuconfig BLOCK bool "Enable the block layer" if EXPERT default y + select PERCPU_RWSEM help Provide block layer support for the kernel. diff --git a/lib/Kconfig b/lib/Kconfig index 4b31a46fb307..75cdb77fa49d 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -42,6 +42,9 @@ config GENERIC_IO config STMP_DEVICE bool +config PERCPU_RWSEM + boolean + config CRC_CCITT tristate "CRC-CCITT functions" help diff --git a/lib/Makefile b/lib/Makefile index e959c20efb24..5558e35170cd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ endif lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\ - idr.o int_sqrt.o extable.o percpu-rwsem.o \ + idr.o int_sqrt.o extable.o \ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ @@ -40,6 +40,7 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o +lib-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o From 918854a65e856574523d94763ef2a2b48ad55a25 Mon Sep 17 00:00:00 2001 From: Cong Ding <dinggnu@gmail.com> Date: Mon, 17 Dec 2012 16:01:43 -0800 Subject: [PATCH 073/180] lib/rbtree_test.c: fix uninitialized variable warning Fix this warning: lib/rbtree_test.c: In function `check': lib/rbtree_test.c:121: warning: `blacks' may be used uninitialized in this function Signed-off-by: Cong Ding <dinggnu@gmail.com> Cc: Michel Lespinasse <walken@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- lib/rbtree_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c index 268b23951fec..d7f491a54579 100644 --- a/lib/rbtree_test.c +++ b/lib/rbtree_test.c @@ -118,7 +118,7 @@ static void check(int nr_nodes) { struct rb_node *rb; int count = 0; - int blacks; + int blacks = 0; u32 prev_key = 0; for (rb = rb_first(&root); rb; rb = rb_next(rb)) { From 0ad50c3896afbb3c103409a18260e601b87a744c Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Mon, 17 Dec 2012 16:01:45 -0800 Subject: [PATCH 074/180] compat: generic compat_sys_sched_rr_get_interval() implementation This function is used by sparc, powerpc tile and arm64 for compat support. The patch adds a generic implementation with a wrapper for PowerPC to do the u32->int sign extension. The reason for a single patch covering powerpc, tile, sparc and arm64 is to keep it bisectable, otherwise kernel building may fail with mismatched function declarations. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Chris Metcalf <cmetcalf@tilera.com> [for tile] Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Arnd Bergmann <arnd@arndb.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/arm64/include/asm/unistd.h | 1 + arch/arm64/kernel/sys_compat.c | 15 --------------- arch/powerpc/include/asm/systbl.h | 2 +- arch/powerpc/include/asm/unistd.h | 1 + arch/powerpc/kernel/sys_ppc32.c | 15 +++------------ arch/sparc/include/asm/unistd.h | 1 + arch/sparc/kernel/sys_sparc32.c | 14 -------------- arch/tile/include/asm/compat.h | 2 -- arch/tile/include/asm/unistd.h | 1 + arch/tile/kernel/compat.c | 18 ------------------ include/linux/compat.h | 3 +++ kernel/compat.c | 17 +++++++++++++++++ 12 files changed, 28 insertions(+), 62 deletions(-) diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index d69aeea6da1e..76fb7dd3350a 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -20,6 +20,7 @@ #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE +#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index f7b05edf8ce3..26e9c4eeaba8 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c @@ -28,21 +28,6 @@ #include <asm/cacheflush.h> #include <asm/unistd32.h> -asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec __user *interval) -{ - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); - set_fs(old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; -} - static inline void do_compat_cache_op(unsigned long start, unsigned long end, int flags) { diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 840838769853..cec8aae5cbf8 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -164,7 +164,7 @@ COMPAT_SYS_SPU(sched_getscheduler) SYSCALL_SPU(sched_yield) COMPAT_SYS_SPU(sched_get_priority_max) COMPAT_SYS_SPU(sched_get_priority_min) -COMPAT_SYS_SPU(sched_rr_get_interval) +SYSX_SPU(sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval_wrapper,sys_sched_rr_get_interval) COMPAT_SYS_SPU(nanosleep) SYSCALL_SPU(mremap) SYSCALL_SPU(setresuid) diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 76fe846ec40e..bcbbe413c606 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -54,6 +54,7 @@ #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_NEWFSTATAT #define __ARCH_WANT_COMPAT_SYS_SENDFILE +#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL #endif #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_FORK diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index 9c2ed90ece8f..8a93778ed9f5 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -175,19 +175,10 @@ asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 a * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */ -asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval) +asmlinkage long compat_sys_sched_rr_get_interval_wrapper(u32 pid, + struct compat_timespec __user *interval) { - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs (); - - /* The __user pointer cast is valid because of the set_fs() */ - set_fs (KERNEL_DS); - ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t); - set_fs (old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; + return compat_sys_sched_rr_get_interval((int)pid, interval); } /* Note: it is necessary to treat mode as an unsigned int, diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index c3e5d8b64171..497386a7ed28 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -45,6 +45,7 @@ #define __ARCH_WANT_COMPAT_SYS_TIME #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_COMPAT_SYS_SENDFILE +#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL #endif #define __ARCH_WANT_SYS_EXECVE diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index 03c7e929ec34..4a4cdc633f6b 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -211,20 +211,6 @@ asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2) return sys_sysfs(option, arg1, arg2); } -asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) -{ - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t); - set_fs (old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; -} - asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index ca61fb4296b3..88f3c227afd9 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h @@ -296,8 +296,6 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags, long compat_sys_fallocate(int fd, int mode, u32 offset_lo, u32 offset_hi, u32 len_lo, u32 len_hi); -long compat_sys_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec __user *interval); /* Assembly trampoline to avoid clobbering r0. */ long _compat_sys_rt_sigreturn(void); diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h index b51c6ee3cd6c..fe841e7d4963 100644 --- a/arch/tile/include/asm/unistd.h +++ b/arch/tile/include/asm/unistd.h @@ -14,6 +14,7 @@ /* In compat mode, we use sys_llseek() for compat_sys_llseek(). */ #ifdef CONFIG_COMPAT #define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL #endif #define __ARCH_WANT_SYS_NEWFSTATAT #define __ARCH_WANT_SYS_EXECVE diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index 9cd7cb6041c0..7f72401b4f45 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c @@ -76,24 +76,6 @@ long compat_sys_fallocate(int fd, int mode, ((loff_t)len_hi << 32) | len_lo); } - - -long compat_sys_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec __user *interval) -{ - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, - (struct timespec __force __user *)&t); - set_fs(old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; -} - /* Provide the compat syscall number to call mapping. */ #undef __SYSCALL #define __SYSCALL(nr, call) [nr] = (call), diff --git a/include/linux/compat.h b/include/linux/compat.h index 784ebfe63c48..e4920bd58a47 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -588,6 +588,9 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid, asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, compat_size_t count); +asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, + struct compat_timespec __user *interval); + #else #define is_compat_task() (0) diff --git a/kernel/compat.c b/kernel/compat.c index c28a306ae05c..f6150e92dfc9 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -1215,6 +1215,23 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) return 0; } +#ifdef __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL +asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, + struct compat_timespec __user *interval) +{ + struct timespec t; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); + set_fs(old_fs); + if (put_compat_timespec(&t, interval)) + return -EFAULT; + return ret; +} +#endif /* __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL */ + /* * Allocate user-space memory for the duration of a single system call, * in order to marshall parameters inside a compat thunk. From 5023d3472d444747bfa12e9798d7993e7efb8287 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:01:47 -0800 Subject: [PATCH 075/180] checkpatch: warn on unnecessary line continuations When the previous line is not a line continuation and the current line has a line continuation but is not a #define, emit a warning. Signed-off-by: Joe Perches <joe@perches.com> Cc: Peter Hurley <peter@hurleysoftware.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f18750e3bd6c..d4f61a6fed5d 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3013,6 +3013,15 @@ sub process { "Macros with complex values should be enclosed in parenthesis\n" . "$herectx"); } } + +# check for line continuations outside of #defines + + } else { + if ($prevline !~ /^..*\\$/ && + $line =~ /^\+.*\\$/) { + WARN("LINE_CONTINUATIONS", + "Avoid unnecessary line continuations\n" . $herecurr); + } } # do {} while (0) macro tests: From 1ba8dfd17ead04de18bfca7b68c2a144c8be736a Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> Date: Mon, 17 Dec 2012 16:01:48 -0800 Subject: [PATCH 076/180] checkpatch: warn about using CONFIG_EXPERIMENTAL This config item has not carried much meaning for a while now and is almost always enabled by default. As agreed during the Linux kernel summit, it is being removed. This will discourage future addition of CONFIG_EXPERIMENTAL while it is being phased out. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Andy Whitcroft <apw@canonical.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index d4f61a6fed5d..cd251d5f3f1a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1757,6 +1757,13 @@ sub process { #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; } +# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig. + if ($realfile =~ /Kconfig/ && + $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) { + WARN("CONFIG_EXPERIMENTAL", + "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); + } + if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { my $flag = $1; @@ -1912,6 +1919,12 @@ sub process { # check we are in a valid C source file if not then ignore this hunk next if ($realfile !~ /\.(h|c)$/); +# discourage the addition of CONFIG_EXPERIMENTAL in #if(def). + if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { + WARN("CONFIG_EXPERIMENTAL", + "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); + } + # check for RCS/CVS revision markers if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { WARN("CVS_KEYWORD", From 78e3f1f01d23c1a0d5828669d35afa2e7951987d Mon Sep 17 00:00:00 2001 From: Tao Ma <boyu.mt@taobao.com> Date: Mon, 17 Dec 2012 16:01:49 -0800 Subject: [PATCH 077/180] checkpatch: remove reference to feature-removal-schedule.txt In commit 9c0ece069b32 ("Get rid of Documentation/feature-removal.txt"), Linus removes feature-removal-schedule.txt from Documentation, but there is still some reference to this file. So remove them. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Acked-by: Andy Whitcroft <apw@canonical.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index cd251d5f3f1a..d2d5ba17ad6c 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -352,27 +352,6 @@ sub deparenthesize { $chk_signoff = 0 if ($file); -my @dep_includes = (); -my @dep_functions = (); -my $removal = "Documentation/feature-removal-schedule.txt"; -if ($tree && -f "$root/$removal") { - open(my $REMOVE, '<', "$root/$removal") || - die "$P: $removal: open failed - $!\n"; - while (<$REMOVE>) { - if (/^Check:\s+(.*\S)/) { - for my $entry (split(/[, ]+/, $1)) { - if ($entry =~ m@include/(.*)@) { - push(@dep_includes, $1); - - } elsif ($entry !~ m@/@) { - push(@dep_functions, $entry); - } - } - } - } - close($REMOVE); -} - my @rawlines = (); my @lines = (); my $vname; @@ -3205,22 +3184,6 @@ sub process { } } -# don't include deprecated include files (uses RAW line) - for my $inc (@dep_includes) { - if ($rawline =~ m@^.\s*\#\s*include\s*\<$inc>@) { - ERROR("DEPRECATED_INCLUDE", - "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr); - } - } - -# don't use deprecated functions - for my $func (@dep_functions) { - if ($line =~ /\b$func\b/) { - ERROR("DEPRECATED_FUNCTION", - "Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr); - } - } - # no volatiles please my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { From 03df4b51f33e1fdd35fe7bc19f1f450726395207 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft <apw@canonical.com> Date: Mon, 17 Dec 2012 16:01:52 -0800 Subject: [PATCH 078/180] checkpatch: consolidate if (foo) bar(foo) checks and add debugfs_remove Consolidate the if (foo) bar(foo) detectors into a single check. Add debugfs_remove and family. Based on a patch by Constantine Shulyupin. Signed-off-by: Andy Whitcroft <apw@canonical.com> Cc: Constantine Shulyupin <const@MakeLinux.com>. Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index d2d5ba17ad6c..a1b870d188c4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3198,20 +3198,12 @@ sub process { $herecurr); } -# check for needless kfree() checks - if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { - my $expr = $1; - if ($line =~ /\bkfree\(\Q$expr\E\);/) { - WARN("NEEDLESS_KFREE", - "kfree(NULL) is safe this check is probably not required\n" . $hereprev); - } - } -# check for needless usb_free_urb() checks - if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { - my $expr = $1; - if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) { - WARN("NEEDLESS_USB_FREE_URB", - "usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev); +# check for needless "if (<foo>) fn(<foo>)" uses + if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { + my $expr = '\s*\(\s*' . quotemeta($1) . '\s*\)\s*;'; + if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?)$expr/) { + WARN('NEEDLESS_IF', + "$1(NULL) is safe this check is probably not required\n" . $hereprev); } } From 6cd7f3869c925622bbf420e1107a026d91dbd7f2 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:01:54 -0800 Subject: [PATCH 079/180] checkpatch: allow control over line length warning, default remains 80 Some projects might want a longer line length so allow a command line --max-line-length=n control over the long line warnings. The default line length is 80. Signed-off-by: Joe Perches <joe@perches.com> Cc: Constantine Shulyupin <const@makelinux.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index a1b870d188c4..6fa167758f82 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -33,6 +33,7 @@ my %ignore_type = (); my @ignore = (); my $help = 0; my $configuration_file = ".checkpatch.conf"; +my $max_line_length = 80; sub help { my ($exitcode) = @_; @@ -51,6 +52,7 @@ Options: -f, --file treat FILE as regular source file --subjective, --strict enable more subjective tests --ignore TYPE(,TYPE2...) ignore various comma separated message types + --max-line-length=n set the maximum line length, if exceeded, warn --show-types show the message "types" in the output --root=PATH PATH to the kernel tree root --no-summary suppress the per-file summary @@ -107,6 +109,7 @@ GetOptions( 'strict!' => \$check, 'ignore=s' => \@ignore, 'show-types!' => \$show_types, + 'max-line-length=i' => \$max_line_length, 'root=s' => \$root, 'summary!' => \$summary, 'mailback!' => \$mailback, @@ -1760,15 +1763,15 @@ sub process { # check we are in a valid source file if not then ignore this hunk next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/); -#80 column limit +#line length limit if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ && $rawline !~ /^.\s*\*\s*\@$Ident\s/ && !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ || $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) && - $length > 80) + $length > $max_line_length) { WARN("LONG_LINE", - "line over 80 characters\n" . $herecurr); + "line over $max_line_length characters\n" . $herecurr); } # Check for user-visible strings broken across lines, which breaks the ability From 481eb486a88c9b068f0168ac4c21291802720933 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:01:56 -0800 Subject: [PATCH 080/180] checkpatch: extend line continuation test Preprocessor directives and asm statements should be allowed to have a line continuation. Signed-off-by: Joe Perches <joe@perches.com> Tested-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 6fa167758f82..3e9fee60642c 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3009,10 +3009,12 @@ sub process { } } -# check for line continuations outside of #defines +# check for line continuations outside of #defines, preprocessor #, and asm } else { if ($prevline !~ /^..*\\$/ && + $line !~ /^\+\s*\#.*\\$/ && # preprocessor + $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm $line =~ /^\+.*\\$/) { WARN("LINE_CONTINUATIONS", "Avoid unnecessary line continuations\n" . $herecurr); From 0979ae66464bd9793c6701861bccb21f9f118a52 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:01:59 -0800 Subject: [PATCH 081/180] checkpatch: Add --strict messages for blank lines around braces Blank lines around braces are not unnecessary. Emit a message on the use of these blank lines only when using --strict. int foo(int bar) { something or other.... } is generally written in the kernel as: int foo(int bar) { something or other... } Signed-off-by: Joe Perches <joe@perches.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3e9fee60642c..e0a674f471ee 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3189,6 +3189,16 @@ sub process { } } +# check for unnecessary blank lines around braces + if (($line =~ /^..*}\s*$/ && $prevline =~ /^.\s*$/)) { + CHK("BRACES", + "Blank lines aren't necessary before a close brace '}'\n" . $hereprev); + } + if (($line =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { + CHK("BRACES", + "Blank lines aren't necessary after an open brace '{'\n" . $hereprev); + } + # no volatiles please my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { From 88982fea52d0115d44b77619afef576f24cdb844 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:02:00 -0800 Subject: [PATCH 082/180] checkpatch: warn when declaring "struct spinlock foo;" spinlock_t should always be used. Signed-off-by: Joe Perches <joe@perches.com> Acked-by: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e0a674f471ee..f27b0b53e3ea 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3336,6 +3336,12 @@ sub process { "Avoid line continuations in quoted strings\n" . $herecurr); } +# check for struct spinlock declarations + if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { + WARN("USE_SPINLOCK_T", + "struct spinlock should be spinlock_t\n" . $herecurr); + } + # Check for misused memsets if ($^V && $^V ge 5.10.0 && defined $stat && From d1e2ad07e78c4bbac9fce4d2e3c0fe60bce091d8 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:02:01 -0800 Subject: [PATCH 083/180] checkpatch: add --strict test for switch/default missing break switch default case is sometimes written as "default:;". This can cause new cases added below the default to be defective. Suggest adding a break; after empty default cases to avoid fallthrough defects. Fixed indentation in the other semicolon test above it. Suggested-by: Peter Senna Tschudin <peter.senna@gmail.com> Signed-off-by: Joe Perches <joe@perches.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f27b0b53e3ea..725c59611e97 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3448,8 +3448,22 @@ sub process { # check for multiple semicolons if ($line =~ /;\s*;\s*$/) { - WARN("ONE_SEMICOLON", - "Statements terminations use 1 semicolon\n" . $herecurr); + WARN("ONE_SEMICOLON", + "Statements terminations use 1 semicolon\n" . $herecurr); + } + +# check for switch/default statements without a break; + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { + my $ctx = ''; + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($stat); + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + WARN("DEFAULT_NO_BREAK", + "switch default: should use break\n" . $herectx); } # check for gcc specific __FUNCTION__ From 6b7eaf6e1428be33f731287de963862e3846cd42 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:02:02 -0800 Subject: [PATCH 084/180] checkpatch: find hex constants as a single IDENT Hexadecimal values are current found in 2 parts. A hex constant like 0x123456abcdef is found as 0 and then x123456abcdef and later coalesced. Instead, reverse the order of the 2 searches in $Constant to find 0x first, then 0 so that the entire hex constant is found all at once. Signed-off-by: Joe Perches <joe@perches.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 725c59611e97..8cb9bfc7c14f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -230,7 +230,7 @@ our $Inline = qr{inline|__always_inline|noinline}; our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; our $Lval = qr{$Ident(?:$Member)*}; -our $Constant = qr{(?i:(?:[0-9]+|0x[0-9a-f]+)[ul]*)}; +our $Constant = qr{(?i:(?:0x[0-9a-f]+|[0-9]+)[ul]*)}; our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; our $Compare = qr{<=|>=|==|!=|<|>}; our $Operators = qr{ From 74349bccedb3e34b4f1fd9c7efd2dda7905e3335 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:02:05 -0800 Subject: [PATCH 085/180] checkpatch: add support for floating point constants Even though the kernel doesn't support using floating point constants, add a regex for them. Support forms like: 0x123p1, 123e-1, 1.23, 1.5e23f Signed-off-by: Joe Perches <joe@perches.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8cb9bfc7c14f..9de3a69260e1 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -230,7 +230,11 @@ our $Inline = qr{inline|__always_inline|noinline}; our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; our $Lval = qr{$Ident(?:$Member)*}; -our $Constant = qr{(?i:(?:0x[0-9a-f]+|[0-9]+)[ul]*)}; +our $Float_hex = qr{(?i:0x[0-9a-f]+p-?[0-9]+[fl]?)}; +our $Float_dec = qr{(?i:((?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?))}; +our $Float_int = qr{(?i:[0-9]+e-?[0-9]+[fl]?)}; +our $Float = qr{$Float_hex|$Float_dec|$Float_int}; +our $Constant = qr{(?:$Float|(?i:(?:0x[0-9a-f]+|[0-9]+)[ul]*))}; our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; our $Compare = qr{<=|>=|==|!=|<|>}; our $Operators = qr{ From 323c1260ba2c4b5c4b2a1e9ab6657cde54ccf554 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 17 Dec 2012 16:02:07 -0800 Subject: [PATCH 086/180] checkpatch: warn on CamelCase variable names Store the camelcase variables in a hash and only emit a warning on the first use of each new variable. Signed-off-by: Joe Perches <joe@perches.com> Cc: Andy Whitcroft <apw@canonical.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/checkpatch.pl | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9de3a69260e1..1d6e4c541370 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1398,6 +1398,8 @@ sub process { my %suppress_export; my $suppress_statement = 0; + my %camelcase = (); + # Pre-scan the patch sanitizing the lines. # Pre-scan the patch looking for any __setup documentation. # @@ -2905,12 +2907,17 @@ sub process { } } -#studly caps, commented out until figure out how to distinguish between use of existing and adding new -# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) { -# print "No studly caps, use _\n"; -# print "$herecurr"; -# $clean = 0; -# } +#CamelCase + while ($line =~ m{($Constant|$Lval)}g) { + my $var = $1; + if ($var !~ /$Constant/ && + $var =~ /[A-Z]\w*[a-z]|[a-z]\w*[A-Z]/ && + !defined $camelcase{$var}) { + $camelcase{$var} = 1; + WARN("CAMELCASE", + "Avoid CamelCase: <$var>\n" . $herecurr); + } + } #no spaces allowed after \ in define if ($line=~/\#\s*define.*\\\s$/) { From 6899e92d65c490c5292752718ff277b123f8c00a Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Mon, 17 Dec 2012 16:02:09 -0800 Subject: [PATCH 087/180] binfmt_elf: fix corner case kfree of uninitialized data If elf_core_dump() is called and fill_note_info() fails in the kmalloc() then it returns 0 but has not yet initialised all the needed fields. As a result we do a kfree(randomness) after correctly skipping the thread data. [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/binfmt_elf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6d7d1647a68c..0c42cdbabecf 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1601,8 +1601,10 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, info->thread = NULL; psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); - if (psinfo == NULL) + if (psinfo == NULL) { + info->psinfo.data = NULL; /* So we don't free this wrongly */ return 0; + } fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); From cab1458c8c4fdfc993e86454eef785bc39517dd8 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed <afzal@ti.com> Date: Mon, 17 Dec 2012 16:02:11 -0800 Subject: [PATCH 088/180] rtc: omap: kicker mechanism support OMAP RTC IP can have kicker feature. This prevents spurious writes to register. To write to registers kicker lock has to be released. Procedure to do it as follows, 1. write to kick0 register, 0x83e70b13 2. write to kick1 register, 0x95a4f1e0 Writing value other than 0x83e70b13 to kick0 enables write locking, more details about kicker mechanism can be found in section 20.3.3.5.3 of AM335X TRM @www.ti.com/am335x Here id table information is added and is used to distinguish those that require kicker handling and the ones that doesn't need it. There are more features in the newer IP's compared to legacy ones other than kicker, which driver currently doesn't handle, supporting additional features would be easier with the addition of id table. Older IP (of OMAP1) doesn't have revision register as per TRM, so revision register can't be relied always to find features, hence id table is being used. While at it, replace __raw_writeb/__raw_readb with writeb/readb; this driver is used on ARMv7 (AM335X SoC) Signed-off-by: Afzal Mohammed <afzal@ti.com> Acked-by: Sekhar Nori <nsekhar@ti.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sekhar Nori <nsekhar@ti.com> Cc: Kevin Hilman <khilman@ti.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Daniel Mack <zonque@gmail.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-omap.c | 44 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0b614e32653d..d948426283db 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -38,6 +38,8 @@ * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. */ +#define DRIVER_NAME "omap_rtc" + #define OMAP_RTC_BASE 0xfffb4800 /* RTC registers */ @@ -64,6 +66,9 @@ #define OMAP_RTC_COMP_MSB_REG 0x50 #define OMAP_RTC_OSC_REG 0x54 +#define OMAP_RTC_KICK0_REG 0x6c +#define OMAP_RTC_KICK1_REG 0x70 + /* OMAP_RTC_CTRL_REG bit fields: */ #define OMAP_RTC_CTRL_SPLIT (1<<7) #define OMAP_RTC_CTRL_DISABLE (1<<6) @@ -88,10 +93,18 @@ #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) +/* OMAP_RTC_KICKER values */ +#define KICK0_VALUE 0x83e70b13 +#define KICK1_VALUE 0x95a4f1e0 + +#define OMAP_RTC_HAS_KICKER 0x1 + static void __iomem *rtc_base; -#define rtc_read(addr) __raw_readb(rtc_base + (addr)) -#define rtc_write(val, addr) __raw_writeb(val, rtc_base + (addr)) +#define rtc_read(addr) readb(rtc_base + (addr)) +#define rtc_write(val, addr) writeb(val, rtc_base + (addr)) + +#define rtc_writel(val, addr) writel(val, rtc_base + (addr)) /* we rely on the rtc framework to handle locking (rtc->ops_lock), @@ -285,11 +298,23 @@ static struct rtc_class_ops omap_rtc_ops = { static int omap_rtc_alarm; static int omap_rtc_timer; +static struct platform_device_id omap_rtc_devtype[] = { + { + .name = DRIVER_NAME, + }, { + .name = "da830-rtc", + .driver_data = OMAP_RTC_HAS_KICKER, + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); + static int __init omap_rtc_probe(struct platform_device *pdev) { struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; + const struct platform_device_id *id_entry; omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { @@ -322,6 +347,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) goto fail; } + id_entry = platform_get_device_id(pdev); + if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { + rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); + rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); + } + rtc = rtc_device_register(pdev->name, &pdev->dev, &omap_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { @@ -398,6 +429,8 @@ fail2: fail1: rtc_device_unregister(rtc); fail0: + if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) + rtc_writel(0, OMAP_RTC_KICK0_REG); iounmap(rtc_base); fail: release_mem_region(mem->start, resource_size(mem)); @@ -408,6 +441,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) { struct rtc_device *rtc = platform_get_drvdata(pdev); struct resource *mem = dev_get_drvdata(&rtc->dev); + const struct platform_device_id *id_entry = + platform_get_device_id(pdev); device_init_wakeup(&pdev->dev, 0); @@ -420,6 +455,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) free_irq(omap_rtc_alarm, rtc); rtc_device_unregister(rtc); + if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) + rtc_writel(0, OMAP_RTC_KICK0_REG); iounmap(rtc_base); release_mem_region(mem->start, resource_size(mem)); return 0; @@ -471,9 +508,10 @@ static struct platform_driver omap_rtc_driver = { .resume = omap_rtc_resume, .shutdown = omap_rtc_shutdown, .driver = { - .name = "omap_rtc", + .name = DRIVER_NAME, .owner = THIS_MODULE, }, + .id_table = omap_rtc_devtype, }; static int __init rtc_init(void) From 852168c92322d3b28de01514dccf25945be92b0b Mon Sep 17 00:00:00 2001 From: Afzal Mohammed <afzal@ti.com> Date: Mon, 17 Dec 2012 16:02:13 -0800 Subject: [PATCH 089/180] ARM: davinci: remove rtc kicker release rtc-omap driver is now capable of handling kicker mechanism, hence remove kicker handling at platform level, instead provide proper device name so that driver can handle kicker mechanism by itself Signed-off-by: Afzal Mohammed <afzal@ti.com> Acked-by: Sekhar Nori <nsekhar@ti.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sekhar Nori <nsekhar@ti.com> Cc: Kevin Hilman <khilman@ti.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Daniel Mack <zonque@gmail.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/arm/mach-davinci/devices-da8xx.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index fcdbe437409e..2d5502d84a22 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -725,7 +725,7 @@ static struct resource da8xx_rtc_resources[] = { }; static struct platform_device da8xx_rtc_device = { - .name = "omap_rtc", + .name = "da830-rtc", .id = -1, .num_resources = ARRAY_SIZE(da8xx_rtc_resources), .resource = da8xx_rtc_resources, @@ -734,17 +734,6 @@ static struct platform_device da8xx_rtc_device = { int da8xx_register_rtc(void) { int ret; - void __iomem *base; - - base = ioremap(DA8XX_RTC_BASE, SZ_4K); - if (WARN_ON(!base)) - return -ENOMEM; - - /* Unlock the rtc's registers */ - __raw_writel(0x83e70b13, base + 0x6c); - __raw_writel(0x95a4f1e0, base + 0x70); - - iounmap(base); ret = platform_device_register(&da8xx_rtc_device); if (!ret) From 9e0344dcc225fe1a0e8b8af9ff7df44ec4613580 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed <afzal@ti.com> Date: Mon, 17 Dec 2012 16:02:15 -0800 Subject: [PATCH 090/180] rtc: omap: dt support Enhance rtc-omap driver with DT capability Signed-off-by: Afzal Mohammed <afzal@ti.com> Acked-by: Sekhar Nori <nsekhar@ti.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sekhar Nori <nsekhar@ti.com> Cc: Kevin Hilman <khilman@ti.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Daniel Mack <zonque@gmail.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- .../devicetree/bindings/rtc/rtc-omap.txt | 17 +++++++++++++++++ drivers/rtc/rtc-omap.c | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/rtc-omap.txt diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt new file mode 100644 index 000000000000..b47aa415c820 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt @@ -0,0 +1,17 @@ +TI Real Time Clock + +Required properties: +- compatible: "ti,da830-rtc" +- reg: Address range of rtc register set +- interrupts: rtc timer, alarm interrupts in order +- interrupt-parent: phandle for the interrupt controller + +Example: + +rtc@1c23000 { + compatible = "ti,da830-rtc"; + reg = <0x23000 0x1000>; + interrupts = <19 + 19>; + interrupt-parent = <&intc>; +}; diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index d948426283db..dff9ff476b0d 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -20,6 +20,8 @@ #include <linux/rtc.h> #include <linux/bcd.h> #include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/io.h> @@ -298,6 +300,8 @@ static struct rtc_class_ops omap_rtc_ops = { static int omap_rtc_alarm; static int omap_rtc_timer; +#define OMAP_RTC_DATA_DA830_IDX 1 + static struct platform_device_id omap_rtc_devtype[] = { { .name = DRIVER_NAME, @@ -309,12 +313,25 @@ static struct platform_device_id omap_rtc_devtype[] = { }; MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); +static const struct of_device_id omap_rtc_of_match[] = { + { .compatible = "ti,da830-rtc", + .data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX], + }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap_rtc_of_match); + static int __init omap_rtc_probe(struct platform_device *pdev) { struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; const struct platform_device_id *id_entry; + const struct of_device_id *of_id; + + of_id = of_match_device(omap_rtc_of_match, &pdev->dev); + if (of_id) + pdev->id_entry = of_id->data; omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { @@ -510,6 +527,7 @@ static struct platform_driver omap_rtc_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(omap_rtc_of_match), }, .id_table = omap_rtc_devtype, }; From 427af9a6216b5845d428f27111add5311c381797 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed <afzal@ti.com> Date: Mon, 17 Dec 2012 16:02:17 -0800 Subject: [PATCH 091/180] rtc: omap: depend on am33xx rtc-omap driver can be reused for AM33xx RTC. Provide dependency in Kconfig. Signed-off-by: Afzal Mohammed <afzal@ti.com> Acked-by: Sekhar Nori <nsekhar@ti.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sekhar Nori <nsekhar@ti.com> Cc: Kevin Hilman <khilman@ti.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Daniel Mack <zonque@gmail.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/Kconfig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 19c03ab2bdcb..4f7ecb683d6b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -777,11 +777,13 @@ config RTC_DRV_IMXDI config RTC_DRV_OMAP tristate "TI OMAP1" - depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX + depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX help - Say "yes" here to support the real time clock on TI OMAP1 and - DA8xx/OMAP-L13x chips. This driver can also be built as a - module called rtc-omap. + Say "yes" here to support the on chip real time clock + present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x. + + This driver can also be built as a module, if so, module + will be called rtc-omap. config HAVE_S3C_RTC bool From fc9bd9022e8d5863f3efce34cc38cb0c6187271c Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <hvaibhav@ti.com> Date: Mon, 17 Dec 2012 16:02:18 -0800 Subject: [PATCH 092/180] rtc: omap: add runtime pm support OMAP1 RTC driver is used in multiple devices like, OMAPL138 and AM33XX. Driver currently doesn't handle any clocks, which may be right for OMAP1 architecture but in case of AM33XX, the clock/module needs to be enabled in order to access the registers. So convert this driver to runtime pm, which internally handles rest. [afzal@ti.com: handle error path] Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Afzal Mohammed <afzal@ti.com> Acked-by: Sekhar Nori <nsekhar@ti.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sekhar Nori <nsekhar@ti.com> Cc: Kevin Hilman <khilman@ti.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Daniel Mack <zonque@gmail.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-omap.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index dff9ff476b0d..600971407aac 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/pm_runtime.h> #include <asm/io.h> @@ -364,6 +365,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev) goto fail; } + /* Enable the clock/module so that we can access the registers */ + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + id_entry = platform_get_device_id(pdev); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); @@ -448,6 +453,8 @@ fail1: fail0: if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); iounmap(rtc_base); fail: release_mem_region(mem->start, resource_size(mem)); @@ -474,6 +481,11 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) rtc_device_unregister(rtc); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); + + /* Disable the clock/module */ + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + iounmap(rtc_base); release_mem_region(mem->start, resource_size(mem)); return 0; @@ -496,11 +508,17 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) else rtc_write(0, OMAP_RTC_INTERRUPTS_REG); + /* Disable the clock/module */ + pm_runtime_put_sync(&pdev->dev); + return 0; } static int omap_rtc_resume(struct platform_device *pdev) { + /* Enable the clock/module so that we can access the registers */ + pm_runtime_get_sync(&pdev->dev); + if (device_may_wakeup(&pdev->dev)) disable_irq_wake(omap_rtc_alarm); else From ef216ad01728ecb8cf6c604ecb5f69e7fd671b52 Mon Sep 17 00:00:00 2001 From: Roland Stigge <stigge@antcom.de> Date: Mon, 17 Dec 2012 16:02:22 -0800 Subject: [PATCH 093/180] drivers/rtc/rtc-imxdi: support for i.MX53 Enable support for i.MX53 in addition to i.MX25 by enabling the driver on ARCH_MXC generally. Signed-off-by: Roland Stigge <stigge@antcom.de> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sascha Hauer <kernel@pengutronix.de> Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4f7ecb683d6b..608a7b1794e3 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -768,7 +768,7 @@ config RTC_DRV_DAVINCI config RTC_DRV_IMXDI tristate "Freescale IMX DryIce Real Time Clock" - depends on SOC_IMX25 + depends on ARCH_MXC help Support for Freescale IMX DryIce RTC From 968d21c2cf01bde4b0e3ff0b0f821b51b9da8ffd Mon Sep 17 00:00:00 2001 From: Roland Stigge <stigge@antcom.de> Date: Mon, 17 Dec 2012 16:02:23 -0800 Subject: [PATCH 094/180] drivers/rtc/rtc-imxdi.c: add devicetree support Add device tree support to the rtc-imxdi driver. Signed-off-by: Roland Stigge <stigge@antcom.de> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Sascha Hauer <kernel@pengutronix.de> Cc: Russell King <linux@arm.linux.org.uk> Cc: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- .../devicetree/bindings/rtc/imxdi-rtc.txt | 17 +++++++++++++++++ drivers/rtc/rtc-imxdi.c | 11 +++++++++++ 2 files changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/imxdi-rtc.txt diff --git a/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt new file mode 100644 index 000000000000..c9d80d7da141 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt @@ -0,0 +1,17 @@ +* i.MX25 Real Time Clock controller + +This binding supports the following chips: i.MX25, i.MX53 + +Required properties: +- compatible: should be: "fsl,imx25-rtc" +- reg: physical base address of the controller and length of memory mapped + region. +- interrupts: rtc alarm interrupt + +Example: + +rtc@80056000 { + compatible = "fsl,imx53-rtc", "fsl,imx25-rtc"; + reg = <0x80056000 2000>; + interrupts = <29>; +}; diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 4eed51044c5d..18a4f0dd78a3 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -37,6 +37,7 @@ #include <linux/rtc.h> #include <linux/sched.h> #include <linux/workqueue.h> +#include <linux/of.h> /* DryIce Register Definitions */ @@ -495,10 +496,20 @@ static int __devexit dryice_rtc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id dryice_dt_ids[] = { + { .compatible = "fsl,imx25-rtc" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, dryice_dt_ids); +#endif + static struct platform_driver dryice_rtc_driver = { .driver = { .name = "imxdi_rtc", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(dryice_dt_ids), }, .remove = __devexit_p(dryice_rtc_remove), }; From 0d7ecb8389a34f650f0d4ab23a56c94595a75ccf Mon Sep 17 00:00:00 2001 From: Devendra Naga <devendra.aaru@gmail.com> Date: Mon, 17 Dec 2012 16:02:26 -0800 Subject: [PATCH 095/180] drivers/rtc/rtc-vt8500.c: convert to use devm_kzalloc Replace the kzalloc() and kfree() calls with devm_kzalloc(). Signed-off-by: Devendra Naga <devendra.aaru@gmail.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Alexey Charkov <alchark@gmail.com> Acked-by: Tony Prisk <linux@prisktech.co.nz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-vt8500.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 07bf19364a74..14e2d8cfcc83 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -210,7 +210,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) struct vt8500_rtc *vt8500_rtc; int ret; - vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL); + vt8500_rtc = devm_kzalloc(&pdev->dev, + sizeof(struct vt8500_rtc), GFP_KERNEL); if (!vt8500_rtc) return -ENOMEM; @@ -220,15 +221,13 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!vt8500_rtc->res) { dev_err(&pdev->dev, "No I/O memory resource defined\n"); - ret = -ENXIO; - goto err_free; + return -ENXIO; } vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0); if (vt8500_rtc->irq_alarm < 0) { dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); - ret = -ENXIO; - goto err_free; + return -ENXIO; } vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, @@ -236,8 +235,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) "vt8500-rtc"); if (vt8500_rtc->res == NULL) { dev_err(&pdev->dev, "failed to request I/O memory\n"); - ret = -EBUSY; - goto err_free; + return -EBUSY; } vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, @@ -278,8 +276,6 @@ err_unmap: err_release: release_mem_region(vt8500_rtc->res->start, resource_size(vt8500_rtc->res)); -err_free: - kfree(vt8500_rtc); return ret; } @@ -297,7 +293,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev) release_mem_region(vt8500_rtc->res->start, resource_size(vt8500_rtc->res)); - kfree(vt8500_rtc); platform_set_drvdata(pdev, NULL); return 0; From 942bfb3ed08b677e0a447096c501d6b0b49f44f9 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yongjun_wei@trendmicro.com.cn> Date: Mon, 17 Dec 2012 16:02:27 -0800 Subject: [PATCH 096/180] drivers/rtc/rtc-test.c: avoid calling platform_device_put() twice In case of error, test_init() needs to call platform_device_del() instead of platform_device_unregister(). Otherwise, we may call platform_device_put() twice. dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) [akpm@linux-foundation.org: improve label naming] Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-test.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 7e96254bd365..974b9ae252ab 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -152,24 +152,24 @@ static int __init test_init(void) if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { err = -ENOMEM; - goto exit_free_test0; + goto exit_put_test0; } if ((err = platform_device_add(test0))) - goto exit_free_test1; + goto exit_put_test1; if ((err = platform_device_add(test1))) - goto exit_device_unregister; + goto exit_del_test0; return 0; -exit_device_unregister: - platform_device_unregister(test0); +exit_del_test0: + platform_device_del(test0); -exit_free_test1: +exit_put_test1: platform_device_put(test1); -exit_free_test0: +exit_put_test0: platform_device_put(test0); exit_driver_unregister: From bdaa2c63b060ae082ab4f20378c1a6307b59b8db Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 17 Dec 2012 16:02:29 -0800 Subject: [PATCH 097/180] rtc: rtc-spear: use devm_*() routines Free the rtc-spear driver from tension of freeing resources :) devm_* derivatives of multiple routines are used while allocating resources, which would be freed automatically by kernel. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: Deepak Sikri <deepak.sikri@st.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-spear.c | 93 ++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 62 deletions(-) diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index bb507d23f6ce..311a5274b528 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -363,34 +363,41 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "no resource defined\n"); return -EBUSY; } - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "rtc region already claimed\n"); - return -EBUSY; - } - config = kzalloc(sizeof(*config), GFP_KERNEL); + config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); if (!config) { dev_err(&pdev->dev, "out of memory\n"); - status = -ENOMEM; - goto err_release_region; + return -ENOMEM; } - config->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(config->clk)) { - status = PTR_ERR(config->clk); - goto err_kfree; + /* alarm irqs */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no update irq?\n"); + return irq; } + status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name, + config); + if (status) { + dev_err(&pdev->dev, "Alarm interrupt IRQ%d already claimed\n", + irq); + return status; + } + + config->ioaddr = devm_request_and_ioremap(&pdev->dev, res); + if (!config->ioaddr) { + dev_err(&pdev->dev, "request-ioremap fail\n"); + return -ENOMEM; + } + + config->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(config->clk)) + return PTR_ERR(config->clk); + status = clk_enable(config->clk); if (status < 0) - goto err_clk_put; - - config->ioaddr = ioremap(res->start, resource_size(res)); - if (!config->ioaddr) { - dev_err(&pdev->dev, "ioremap fail\n"); - status = -ENOMEM; - goto err_disable_clock; - } + return status; spin_lock_init(&config->lock); platform_set_drvdata(pdev, config); @@ -401,22 +408,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(config->rtc)); status = PTR_ERR(config->rtc); - goto err_iounmap; - } - - /* alarm irqs */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no update irq?\n"); - status = irq; - goto err_clear_platdata; - } - - status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config); - if (status) { - dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ - claimed\n", irq); - goto err_clear_platdata; + goto err_disable_clock; } if (!device_can_wakeup(&pdev->dev)) @@ -424,19 +416,9 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) return 0; -err_clear_platdata: - platform_set_drvdata(pdev, NULL); - rtc_device_unregister(config->rtc); -err_iounmap: - iounmap(config->ioaddr); err_disable_clock: + platform_set_drvdata(pdev, NULL); clk_disable(config->clk); -err_clk_put: - clk_put(config->clk); -err_kfree: - kfree(config); -err_release_region: - release_mem_region(res->start, resource_size(res)); return status; } @@ -444,24 +426,11 @@ err_release_region: static int __devexit spear_rtc_remove(struct platform_device *pdev) { struct spear_rtc_config *config = platform_get_drvdata(pdev); - int irq; - struct resource *res; - /* leave rtc running, but disable irqs */ - spear_rtc_disable_interrupt(config); - device_init_wakeup(&pdev->dev, 0); - irq = platform_get_irq(pdev, 0); - if (irq) - free_irq(irq, pdev); - clk_disable(config->clk); - clk_put(config->clk); - iounmap(config->ioaddr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); rtc_device_unregister(config->rtc); - kfree(config); + spear_rtc_disable_interrupt(config); + clk_disable(config->clk); + device_init_wakeup(&pdev->dev, 0); return 0; } From 93d78394ac5ec72315e7f9a7193c6649d817a9eb Mon Sep 17 00:00:00 2001 From: Deepak Sikri <deepak.sikri@st.com> Date: Mon, 17 Dec 2012 16:02:32 -0800 Subject: [PATCH 098/180] rtc: rtc-spear: Add clk_{un}prepare() support clk_{un}prepare is mandatory for platforms using common clock framework. Because for SPEAr we don't do anything in clk_{un}prepare() calls, just call them once in probe/remove. Signed-off-by: Deepak Sikri <deepak.sikri@st.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-spear.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 311a5274b528..c96f56cfc1d8 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -395,7 +395,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) if (IS_ERR(config->clk)) return PTR_ERR(config->clk); - status = clk_enable(config->clk); + status = clk_prepare_enable(config->clk); if (status < 0) return status; @@ -418,7 +418,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) err_disable_clock: platform_set_drvdata(pdev, NULL); - clk_disable(config->clk); + clk_disable_unprepare(config->clk); return status; } @@ -429,7 +429,7 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev) rtc_device_unregister(config->rtc); spear_rtc_disable_interrupt(config); - clk_disable(config->clk); + clk_disable_unprepare(config->clk); device_init_wakeup(&pdev->dev, 0); return 0; From c9f5c7e7a84f1b7e274566851a1fb3531629343e Mon Sep 17 00:00:00 2001 From: Deepak Sikri <deepak.sikri@st.com> Date: Mon, 17 Dec 2012 16:02:34 -0800 Subject: [PATCH 099/180] rtc: rtc-spear: Provide flag for no support of UIE mode The applications can set the RTC hardware to trigger interrupts in one of three modes: * AIE: Alarm interrupt * UIE: Update interrupt (ie: once per second) * PIE: Periodic interrupt (sub-second irqs) The above defined 3 modes are to be supported in the RTC HW in form of interrupts. The SPEAr RTC hardware does not support the later two modes. There have been refinements in the RTC core in mainline related to use of timer queue infrastructure to manage events in RTC. Please refer the below mentioned patch for details: * RTC: Rework RTC code to use timerqueue for events * SHA ID: 6610e0893b8bc6f59b14fed7f089c5997f035f88 There have been provisions added to support hardware that do not have support the UIE mode. Please refer the following patch. * rtc: Provide flag for rtc devices that don't support UIE * SHA ID: 4a649903f91232d02284d53724b0a45728111767 The patch makes use of the provision defined in the above patch to update the hardware status of UIE mode. Signed-off-by: Deepak Sikri <deepak.sikri@st.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-spear.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index c96f56cfc1d8..141fc945295f 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -411,6 +411,8 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) goto err_disable_clock; } + config->rtc->uie_unsupported = 1; + if (!device_can_wakeup(&pdev->dev)) device_init_wakeup(&pdev->dev, 1); From 32c4746c24728a047a1ef985215edec798bfce1f Mon Sep 17 00:00:00 2001 From: Sivaram Nair <sivaramn@nvidia.com> Date: Mon, 17 Dec 2012 16:02:37 -0800 Subject: [PATCH 100/180] drivers/rtc/rtc-tps65910.c: rename irq to match device A cosmetic change to rename the irq name to match the device name. Signed-off-by: Sivaram Nair <sivaramn@nvidia.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-tps65910.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 073108dcf9e7..687006f31727 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -261,7 +261,7 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, - "rtc-tps65910", &pdev->dev); + dev_name(&pdev->dev), &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); return ret; From 9ed39bf931cbd95b30755dcb1ad724fe05565c3f Mon Sep 17 00:00:00 2001 From: Devendra Naga <devendra.aaru@gmail.com> Date: Mon, 17 Dec 2012 16:02:39 -0800 Subject: [PATCH 101/180] rtc: rtc-davinci: return correct error code if rtc_device_register() fails rtc_device_register() returns a pointer containing error code in case of error. Use that in the error return. Signed-off-by: Devendra Naga <devendra.aaru@gmail.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Miguel Aguilar <miguel.aguilar@ridgerun.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-davinci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 14c2109dbaa3..fd95316743c9 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -529,8 +529,9 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &davinci_rtc_ops, THIS_MODULE); if (IS_ERR(davinci_rtc->rtc)) { - dev_err(dev, "unable to register RTC device, err %ld\n", - PTR_ERR(davinci_rtc->rtc)); + ret = PTR_ERR(davinci_rtc->rtc); + dev_err(dev, "unable to register RTC device, err %d\n", + ret); goto fail3; } From f288cf416ec22de3c5bc18148b6f7620aa32409b Mon Sep 17 00:00:00 2001 From: Devendra Naga <devendra.aaru@gmail.com> Date: Mon, 17 Dec 2012 16:02:41 -0800 Subject: [PATCH 102/180] rtc: rtc-davinci: use devm_kzalloc() Use devm_kzalloc() and remove the error path free and the unload free as devm functions take care of freeing resources. Signed-off-by: Devendra Naga <devendra.aaru@gmail.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Miguel Aguilar <miguel.aguilar@ridgerun.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-davinci.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index fd95316743c9..07cd03eae606 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -485,7 +485,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) struct resource *res, *mem; int ret = 0; - davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL); + davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL); if (!davinci_rtc) { dev_dbg(dev, "could not allocate memory for private data\n"); return -ENOMEM; @@ -494,15 +494,13 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) davinci_rtc->irq = platform_get_irq(pdev, 0); if (davinci_rtc->irq < 0) { dev_err(dev, "no RTC irq\n"); - ret = davinci_rtc->irq; - goto fail1; + return davinci_rtc->irq; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "no mem resource\n"); - ret = -EINVAL; - goto fail1; + return -EINVAL; } davinci_rtc->pbase = res->start; @@ -513,8 +511,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) if (!mem) { dev_err(dev, "RTC registers at %08x are not free\n", davinci_rtc->pbase); - ret = -EBUSY; - goto fail1; + return -EBUSY; } davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); @@ -567,9 +564,6 @@ fail3: iounmap(davinci_rtc->base); fail2: release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); -fail1: - kfree(davinci_rtc); - return ret; } @@ -590,8 +584,6 @@ static int __devexit davinci_rtc_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - kfree(davinci_rtc); - return 0; } From f803f0d079ded4272d7a1c9813bfd24c58b8ee5f Mon Sep 17 00:00:00 2001 From: Thierry Reding <thierry.reding@avionic-design.de> Date: Mon, 17 Dec 2012 16:02:44 -0800 Subject: [PATCH 103/180] rtc: add NXP PCF8523 support Add an RTC driver for PCF8523 chips by NXP Semiconductors. No support is currently provided for the alarm and interrupt functions. Only the time and date functionality is implemented. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/Kconfig | 9 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-pcf8523.c | 326 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 drivers/rtc/rtc-pcf8523.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 608a7b1794e3..5bb031461d75 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -269,6 +269,15 @@ config RTC_DRV_X1205 This driver can also be built as a module. If so, the module will be called rtc-x1205. +config RTC_DRV_PCF8523 + tristate "NXP PCF8523" + help + If you say yes here you get support for the NXP PCF8523 RTC + chips. + + This driver can also be built as a module. If so, the module + will be called rtc-pcf8523. + config RTC_DRV_PCF8563 tristate "Philips PCF8563/Epson RTC8564" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 56297f0fd388..59e2132a1c14 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o +obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c new file mode 100644 index 000000000000..be05a645f99e --- /dev/null +++ b/drivers/rtc/rtc-pcf8523.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/bcd.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/of.h> + +#define DRIVER_NAME "rtc-pcf8523" + +#define REG_CONTROL1 0x00 +#define REG_CONTROL1_CAP_SEL (1 << 7) +#define REG_CONTROL1_STOP (1 << 5) + +#define REG_CONTROL3 0x02 +#define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */ +#define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */ +#define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */ +#define REG_CONTROL3_PM_MASK 0xe0 + +#define REG_SECONDS 0x03 +#define REG_SECONDS_OS (1 << 7) + +#define REG_MINUTES 0x04 +#define REG_HOURS 0x05 +#define REG_DAYS 0x06 +#define REG_WEEKDAYS 0x07 +#define REG_MONTHS 0x08 +#define REG_YEARS 0x09 + +struct pcf8523 { + struct rtc_device *rtc; +}; + +static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep) +{ + struct i2c_msg msgs[2]; + u8 value = 0; + int err; + + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = sizeof(reg); + msgs[0].buf = ® + + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = sizeof(value); + msgs[1].buf = &value; + + err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (err < 0) + return err; + + *valuep = value; + + return 0; +} + +static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value) +{ + u8 buffer[2] = { reg, value }; + struct i2c_msg msg; + int err; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = sizeof(buffer); + msg.buf = buffer; + + err = i2c_transfer(client->adapter, &msg, 1); + if (err < 0) + return err; + + return 0; +} + +static int pcf8523_select_capacitance(struct i2c_client *client, bool high) +{ + u8 value; + int err; + + err = pcf8523_read(client, REG_CONTROL1, &value); + if (err < 0) + return err; + + if (!high) + value &= ~REG_CONTROL1_CAP_SEL; + else + value |= REG_CONTROL1_CAP_SEL; + + err = pcf8523_write(client, REG_CONTROL1, value); + if (err < 0) + return err; + + return err; +} + +static int pcf8523_set_pm(struct i2c_client *client, u8 pm) +{ + u8 value; + int err; + + err = pcf8523_read(client, REG_CONTROL3, &value); + if (err < 0) + return err; + + value = (value & ~REG_CONTROL3_PM_MASK) | pm; + + err = pcf8523_write(client, REG_CONTROL3, value); + if (err < 0) + return err; + + return 0; +} + +static int pcf8523_stop_rtc(struct i2c_client *client) +{ + u8 value; + int err; + + err = pcf8523_read(client, REG_CONTROL1, &value); + if (err < 0) + return err; + + value |= REG_CONTROL1_STOP; + + err = pcf8523_write(client, REG_CONTROL1, value); + if (err < 0) + return err; + + return 0; +} + +static int pcf8523_start_rtc(struct i2c_client *client) +{ + u8 value; + int err; + + err = pcf8523_read(client, REG_CONTROL1, &value); + if (err < 0) + return err; + + value &= ~REG_CONTROL1_STOP; + + err = pcf8523_write(client, REG_CONTROL1, value); + if (err < 0) + return err; + + return 0; +} + +static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 start = REG_SECONDS, regs[7]; + struct i2c_msg msgs[2]; + int err; + + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = &start; + + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = sizeof(regs); + msgs[1].buf = regs; + + err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (err < 0) + return err; + + if (regs[0] & REG_SECONDS_OS) { + /* + * If the oscillator was stopped, try to clear the flag. Upon + * power-up the flag is always set, but if we cannot clear it + * the oscillator isn't running properly for some reason. The + * sensible thing therefore is to return an error, signalling + * that the clock cannot be assumed to be correct. + */ + + regs[0] &= ~REG_SECONDS_OS; + + err = pcf8523_write(client, REG_SECONDS, regs[0]); + if (err < 0) + return err; + + err = pcf8523_read(client, REG_SECONDS, ®s[0]); + if (err < 0) + return err; + + if (regs[0] & REG_SECONDS_OS) + return -EAGAIN; + } + + tm->tm_sec = bcd2bin(regs[0] & 0x7f); + tm->tm_min = bcd2bin(regs[1] & 0x7f); + tm->tm_hour = bcd2bin(regs[2] & 0x3f); + tm->tm_mday = bcd2bin(regs[3] & 0x3f); + tm->tm_wday = regs[4] & 0x7; + tm->tm_mon = bcd2bin(regs[5] & 0x1f); + tm->tm_year = bcd2bin(regs[6]) + 100; + + return rtc_valid_tm(tm); +} + +static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_msg msg; + u8 regs[8]; + int err; + + err = pcf8523_stop_rtc(client); + if (err < 0) + return err; + + regs[0] = REG_SECONDS; + regs[1] = bin2bcd(tm->tm_sec); + regs[2] = bin2bcd(tm->tm_min); + regs[3] = bin2bcd(tm->tm_hour); + regs[4] = bin2bcd(tm->tm_mday); + regs[5] = tm->tm_wday; + regs[6] = bin2bcd(tm->tm_mon); + regs[7] = bin2bcd(tm->tm_year - 100); + + msg.addr = client->addr; + msg.flags = 0; + msg.len = sizeof(regs); + msg.buf = regs; + + err = i2c_transfer(client->adapter, &msg, 1); + if (err < 0) { + /* + * If the time cannot be set, restart the RTC anyway. Note + * that errors are ignored if the RTC cannot be started so + * that we have a chance to propagate the original error. + */ + pcf8523_start_rtc(client); + return err; + } + + return pcf8523_start_rtc(client); +} + +static const struct rtc_class_ops pcf8523_rtc_ops = { + .read_time = pcf8523_rtc_read_time, + .set_time = pcf8523_rtc_set_time, +}; + +static int pcf8523_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pcf8523 *pcf; + int err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL); + if (!pcf) + return -ENOMEM; + + err = pcf8523_select_capacitance(client, true); + if (err < 0) + return err; + + err = pcf8523_set_pm(client, 0); + if (err < 0) + return err; + + pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev, + &pcf8523_rtc_ops, THIS_MODULE); + if (IS_ERR(pcf->rtc)) + return PTR_ERR(pcf->rtc); + + i2c_set_clientdata(client, pcf); + + return 0; +} + +static int pcf8523_remove(struct i2c_client *client) +{ + struct pcf8523 *pcf = i2c_get_clientdata(client); + + rtc_device_unregister(pcf->rtc); + + return 0; +} + +static const struct i2c_device_id pcf8523_id[] = { + { "pcf8523", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcf8523_id); + +#ifdef CONFIG_OF +static const struct of_device_id pcf8523_of_match[] = { + { .compatible = "nxp,pcf8523" }, + { } +}; +MODULE_DEVICE_TABLE(of, pcf8523_of_match); +#endif + +static struct i2c_driver pcf8523_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pcf8523_of_match), + }, + .probe = pcf8523_probe, + .remove = pcf8523_remove, + .id_table = pcf8523_id, +}; +module_i2c_driver(pcf8523_driver); + +MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); +MODULE_DESCRIPTION("NXP PCF8523 RTC driver"); +MODULE_LICENSE("GPL v2"); From 076c7265488cc4016c6502f3f9d8dbf1e97fd147 Mon Sep 17 00:00:00 2001 From: Tushar Behera <tushar.behera@linaro.org> Date: Mon, 17 Dec 2012 16:02:45 -0800 Subject: [PATCH 104/180] drivers/rtc/rtc-s3c.c: remove unnecessary err_nores label err_nores label redirects to a simple return statement. Move the return statement to caller location and remove the label. Signed-off-by: Tushar Behera <tushar.behera@linaro.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Rob Herring <rob.herring@calxeda.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-s3c.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a7a2a998fa91..d9da51193bc3 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -501,8 +501,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) if (s3c_rtc_mem == NULL) { dev_err(&pdev->dev, "failed to reserve memory region\n"); - ret = -ENOENT; - goto err_nores; + return -ENOENT; } s3c_rtc_base = ioremap(res->start, resource_size(res)); @@ -612,8 +611,6 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) err_nomap: release_resource(s3c_rtc_mem); - - err_nores: return ret; } From 1b99732932e1e398ec84baf6024afa23f5388716 Mon Sep 17 00:00:00 2001 From: Tushar Behera <tushar.behera@linaro.org> Date: Mon, 17 Dec 2012 16:02:48 -0800 Subject: [PATCH 105/180] drivers/rtc/rtc-s3c.c: convert to use devm_* API rtc-s3c driver is modified to use devm_request_and_ioremap() (combining request_mem_region and ioremap), devm_clk_get() and devm_request_irq() APIs. Since this removes the necessity of freeing the related resources the return path is also simplified. Signed-off-by: Tushar Behera <tushar.behera@linaro.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Rob Herring <rob.herring@calxeda.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-s3c.c | 45 ++++++++----------------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index d9da51193bc3..e33df1bfe27e 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -47,8 +47,6 @@ struct s3c_rtc_drv_data { /* I have yet to find an S3C implementation with more than one * of these rtc blocks in */ -static struct resource *s3c_rtc_mem; - static struct clk *rtc_clk; static void __iomem *s3c_rtc_base; static int s3c_rtc_alarmno = NO_IRQ; @@ -427,21 +425,13 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) { struct rtc_device *rtc = platform_get_drvdata(dev); - free_irq(s3c_rtc_alarmno, rtc); - free_irq(s3c_rtc_tickno, rtc); - platform_set_drvdata(dev, NULL); rtc_device_unregister(rtc); s3c_rtc_setaie(&dev->dev, 0); - clk_put(rtc_clk); rtc_clk = NULL; - iounmap(s3c_rtc_base); - release_resource(s3c_rtc_mem); - kfree(s3c_rtc_mem); - return 0; } @@ -496,27 +486,18 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) return -ENOENT; } - s3c_rtc_mem = request_mem_region(res->start, resource_size(res), - pdev->name); - - if (s3c_rtc_mem == NULL) { - dev_err(&pdev->dev, "failed to reserve memory region\n"); - return -ENOENT; - } - - s3c_rtc_base = ioremap(res->start, resource_size(res)); + s3c_rtc_base = devm_request_and_ioremap(&pdev->dev, res); if (s3c_rtc_base == NULL) { - dev_err(&pdev->dev, "failed ioremap()\n"); - ret = -EINVAL; - goto err_nomap; + dev_err(&pdev->dev, "failed to ioremap memory region\n"); + return -EINVAL; } - rtc_clk = clk_get(&pdev->dev, "rtc"); + rtc_clk = devm_clk_get(&pdev->dev, "rtc"); if (IS_ERR(rtc_clk)) { dev_err(&pdev->dev, "failed to find rtc clock source\n"); ret = PTR_ERR(rtc_clk); rtc_clk = NULL; - goto err_clk; + return ret; } clk_enable(rtc_clk); @@ -575,28 +556,24 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_setfreq(&pdev->dev, 1); - ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, + ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq, 0, "s3c2410-rtc alarm", rtc); if (ret) { dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); goto err_alarm_irq; } - ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, + ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq, 0, "s3c2410-rtc tick", rtc); if (ret) { dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); - free_irq(s3c_rtc_alarmno, rtc); - goto err_tick_irq; + goto err_alarm_irq; } clk_disable(rtc_clk); return 0; - err_tick_irq: - free_irq(s3c_rtc_alarmno, rtc); - err_alarm_irq: platform_set_drvdata(pdev, NULL); rtc_device_unregister(rtc); @@ -604,13 +581,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) err_nortc: s3c_rtc_enable(pdev, 0); clk_disable(rtc_clk); - clk_put(rtc_clk); - err_clk: - iounmap(s3c_rtc_base); - - err_nomap: - release_resource(s3c_rtc_mem); return ret; } From 162a96ea4bc77ad8d553ea5de6300b6ed70d13e1 Mon Sep 17 00:00:00 2001 From: Sachin Kamat <sachin.kamat@linaro.org> Date: Mon, 17 Dec 2012 16:02:49 -0800 Subject: [PATCH 106/180] drivers/rtc/rtc-dev.c: remove unused code from rtc-dev.c This code is under #if 0 and not used. Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-dev.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index cace6d3aed9a..9a86b4bd8699 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -379,25 +379,6 @@ static long rtc_dev_ioctl(struct file *file, err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); break; -#if 0 - case RTC_EPOCH_SET: -#ifndef rtc_epoch - /* - * There were no RTC clocks before 1900. - */ - if (arg < 1900) { - err = -EINVAL; - break; - } - rtc_epoch = arg; - err = 0; -#endif - break; - - case RTC_EPOCH_READ: - err = put_user(rtc_epoch, (unsigned long __user *)uarg); - break; -#endif case RTC_WKALM_SET: mutex_unlock(&rtc->ops_lock); if (copy_from_user(&alarm, uarg, sizeof(alarm))) From 18c701a9dbe91768e1629f1aece9d50543b3abfa Mon Sep 17 00:00:00 2001 From: "Kim, Milo" <Milo.Kim@ti.com> Date: Mon, 17 Dec 2012 16:02:51 -0800 Subject: [PATCH 107/180] drivers/rtc/rtc-tps65910.c: enable RTC power domain on initialization Enabling RTC HW block depends on the default value of TPS65910 register. In some mode, RTC block is disabled by default.(eg. AM3517 Craneboard) In this case, RTC_PWDN(RTC power down) bit should be cleared to enable the RTC HW block. This patch also works in case that RTC block is active by default, because there is no side effect even if the bit is updated again. Tested on AM3517 Craneboard. Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com> Acked-by: Venu Byravarasu <vbyravarasu@nvidia.com> Cc: Samuel Ortiz <sameo@linux.intel.com> Cc: Sivaram Nair <sivaramn@nvidia.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-tps65910.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 687006f31727..22eb4ebfa1a6 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -247,6 +247,13 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev) return ret; dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); + + /* Enable RTC digital power domain */ + ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, + DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT); + if (ret < 0) + return ret; + rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); if (ret < 0) From 04a373fdc9b0cbb4f076dd0e6c6433dc3bc48724 Mon Sep 17 00:00:00 2001 From: Sachin Kamat <sachin.kamat@linaro.org> Date: Mon, 17 Dec 2012 16:02:52 -0800 Subject: [PATCH 108/180] drivers/rtc/rtc-s3c: use of_match_ptr() macro This eliminates having an #ifdef returning NULL for the case when OF is disabled. Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-s3c.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e33df1bfe27e..4bd9414aee65 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -663,8 +663,6 @@ static const struct of_device_id s3c_rtc_dt_match[] = { {}, }; MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); -#else -#define s3c_rtc_dt_match NULL #endif static struct platform_device_id s3c_rtc_driver_ids[] = { @@ -695,7 +693,7 @@ static struct platform_driver s3c_rtc_driver = { .driver = { .name = "s3c-rtc", .owner = THIS_MODULE, - .of_match_table = s3c_rtc_dt_match, + .of_match_table = of_match_ptr(s3c_rtc_dt_match), }, }; From 6920d996e3fee4ac5dcb7d34cb290b6f67bb69d0 Mon Sep 17 00:00:00 2001 From: Ashish Jangam <ashish.jangam@kpitcummins.com> Date: Mon, 17 Dec 2012 16:02:53 -0800 Subject: [PATCH 109/180] rtc: DA9055 RTC driver A driver for the DA9055 PMIC. This has a dependency upon the DA9055 MFD core. Functionally tested on Samsung SMDKV6410. Signed-off-by: David Dajun Chen <dchen@diasemi.com> Signed-off-by: Ashish Jangam <ashish.jangam@kpitcummins.com> Cc: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-da9055.c | 413 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 424 insertions(+) create mode 100644 drivers/rtc/rtc-da9055.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5bb031461d75..d0cea02b5dfc 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -609,6 +609,16 @@ config RTC_DRV_DA9052 Say y here to support the RTC driver for Dialog Semiconductor DA9052-BC and DA9053-AA/Bx PMICs. +config RTC_DRV_DA9055 + tristate "Dialog Semiconductor DA9055 RTC" + depends on MFD_DA9055 + help + If you say yes here you will get support for the + RTC of the Dialog DA9055 PMIC. + + This driver can also be built as a module. If so, the module + will be called rtc-da9055 + config RTC_DRV_EFI tristate "EFI RTC" depends on IA64 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 59e2132a1c14..c3f62c80dc06 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o +obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c new file mode 100644 index 000000000000..96bafc5c3bf8 --- /dev/null +++ b/drivers/rtc/rtc-da9055.c @@ -0,0 +1,413 @@ +/* + * Real time clock driver for DA9055 + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: Dajun Dajun Chen <dajun.chen@diasemi.com> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + +#include <linux/mfd/da9055/core.h> +#include <linux/mfd/da9055/reg.h> +#include <linux/mfd/da9055/pdata.h> + +struct da9055_rtc { + struct rtc_device *rtc; + struct da9055 *da9055; + int alarm_enable; +}; + +static int da9055_rtc_enable_alarm(struct da9055_rtc *rtc, bool enable) +{ + int ret; + if (enable) { + ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y, + DA9055_RTC_ALM_EN, + DA9055_RTC_ALM_EN); + if (ret != 0) + dev_err(rtc->da9055->dev, "Failed to enable ALM: %d\n", + ret); + rtc->alarm_enable = 1; + } else { + ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y, + DA9055_RTC_ALM_EN, 0); + if (ret != 0) + dev_err(rtc->da9055->dev, + "Failed to disable ALM: %d\n", ret); + rtc->alarm_enable = 0; + } + return ret; +} + +static irqreturn_t da9055_rtc_alm_irq(int irq, void *data) +{ + struct da9055_rtc *rtc = data; + + da9055_rtc_enable_alarm(rtc, 0); + rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); + + return IRQ_HANDLED; +} + +static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) +{ + int ret; + uint8_t v[5]; + + ret = da9055_group_read(da9055, DA9055_REG_ALARM_MI, 5, v); + if (ret != 0) { + dev_err(da9055->dev, "Failed to group read ALM: %d\n", ret); + return ret; + } + + rtc_tm->tm_year = (v[4] & DA9055_RTC_ALM_YEAR) + 100; + rtc_tm->tm_mon = (v[3] & DA9055_RTC_ALM_MONTH) - 1; + rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY; + rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR; + rtc_tm->tm_min = v[0] & DA9055_RTC_ALM_MIN; + + return rtc_valid_tm(rtc_tm); +} + +static int da9055_set_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) +{ + int ret; + uint8_t v[2]; + + rtc_tm->tm_year -= 100; + rtc_tm->tm_mon += 1; + + ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MI, + DA9055_RTC_ALM_MIN, rtc_tm->tm_min); + if (ret != 0) { + dev_err(da9055->dev, "Failed to write ALRM MIN: %d\n", ret); + return ret; + } + + v[0] = rtc_tm->tm_hour; + v[1] = rtc_tm->tm_mday; + + ret = da9055_group_write(da9055, DA9055_REG_ALARM_H, 2, v); + if (ret < 0) + return ret; + + ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO, + DA9055_RTC_ALM_MONTH, rtc_tm->tm_mon); + if (ret < 0) + dev_err(da9055->dev, "Failed to write ALM Month:%d\n", ret); + + ret = da9055_reg_update(da9055, DA9055_REG_ALARM_Y, + DA9055_RTC_ALM_YEAR, rtc_tm->tm_year); + if (ret < 0) + dev_err(da9055->dev, "Failed to write ALM Year:%d\n", ret); + + return ret; +} + +static int da9055_rtc_get_alarm_status(struct da9055 *da9055) +{ + int ret; + + ret = da9055_reg_read(da9055, DA9055_REG_ALARM_Y); + if (ret < 0) { + dev_err(da9055->dev, "Failed to read ALM: %d\n", ret); + return ret; + } + ret &= DA9055_RTC_ALM_EN; + return (ret > 0) ? 1 : 0; +} + +static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) +{ + struct da9055_rtc *rtc = dev_get_drvdata(dev); + uint8_t v[6]; + int ret; + + ret = da9055_reg_read(rtc->da9055, DA9055_REG_COUNT_S); + if (ret < 0) + return ret; + + /* + * Registers are only valid when RTC_READ + * status bit is asserted + */ + if (!(ret & DA9055_RTC_READ)) + return -EBUSY; + + ret = da9055_group_read(rtc->da9055, DA9055_REG_COUNT_S, 6, v); + if (ret < 0) { + dev_err(rtc->da9055->dev, "Failed to read RTC time : %d\n", + ret); + return ret; + } + + rtc_tm->tm_year = (v[5] & DA9055_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[4] & DA9055_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[3] & DA9055_RTC_DAY; + rtc_tm->tm_hour = v[2] & DA9055_RTC_HOUR; + rtc_tm->tm_min = v[1] & DA9055_RTC_MIN; + rtc_tm->tm_sec = v[0] & DA9055_RTC_SEC; + + return rtc_valid_tm(rtc_tm); +} + +static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct da9055_rtc *rtc; + uint8_t v[6]; + + rtc = dev_get_drvdata(dev); + + v[0] = tm->tm_sec; + v[1] = tm->tm_min; + v[2] = tm->tm_hour; + v[3] = tm->tm_mday; + v[4] = tm->tm_mon + 1; + v[5] = tm->tm_year - 100; + + return da9055_group_write(rtc->da9055, DA9055_REG_COUNT_S, 6, v); +} + +static int da9055_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + struct rtc_time *tm = &alrm->time; + struct da9055_rtc *rtc = dev_get_drvdata(dev); + + ret = da9055_read_alarm(rtc->da9055, tm); + + if (ret) + return ret; + + alrm->enabled = da9055_rtc_get_alarm_status(rtc->da9055); + + return 0; +} + +static int da9055_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + struct rtc_time *tm = &alrm->time; + struct da9055_rtc *rtc = dev_get_drvdata(dev); + + ret = da9055_rtc_enable_alarm(rtc, 0); + if (ret < 0) + return ret; + + ret = da9055_set_alarm(rtc->da9055, tm); + if (ret) + return ret; + + ret = da9055_rtc_enable_alarm(rtc, 1); + + return ret; +} + +static int da9055_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct da9055_rtc *rtc = dev_get_drvdata(dev); + + return da9055_rtc_enable_alarm(rtc, enabled); +} + +static const struct rtc_class_ops da9055_rtc_ops = { + .read_time = da9055_rtc_read_time, + .set_time = da9055_rtc_set_time, + .read_alarm = da9055_rtc_read_alarm, + .set_alarm = da9055_rtc_set_alarm, + .alarm_irq_enable = da9055_rtc_alarm_irq_enable, +}; + +static int __init da9055_rtc_device_init(struct da9055 *da9055, + struct da9055_pdata *pdata) +{ + int ret; + + /* Enable RTC and the internal Crystal */ + ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, + DA9055_RTC_EN, DA9055_RTC_EN); + if (ret < 0) + return ret; + ret = da9055_reg_update(da9055, DA9055_REG_EN_32K, + DA9055_CRYSTAL_EN, DA9055_CRYSTAL_EN); + if (ret < 0) + return ret; + + /* Enable RTC in Power Down mode */ + ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, + DA9055_RTC_MODE_PD, DA9055_RTC_MODE_PD); + if (ret < 0) + return ret; + + /* Enable RTC in Reset mode */ + if (pdata && pdata->reset_enable) { + ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, + DA9055_RTC_MODE_SD, + DA9055_RTC_MODE_SD << + DA9055_RTC_MODE_SD_SHIFT); + if (ret < 0) + return ret; + } + + /* Disable the RTC TICK ALM */ + ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO, + DA9055_RTC_TICK_WAKE_MASK, 0); + if (ret < 0) + return ret; + + return 0; +} + +static int da9055_rtc_probe(struct platform_device *pdev) +{ + struct da9055_rtc *rtc; + struct da9055_pdata *pdata = NULL; + int ret, alm_irq; + + rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9055_rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->da9055 = dev_get_drvdata(pdev->dev.parent); + pdata = rtc->da9055->dev->platform_data; + platform_set_drvdata(pdev, rtc); + + ret = da9055_rtc_device_init(rtc->da9055, pdata); + if (ret < 0) + goto err_rtc; + + ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y); + if (ret < 0) + goto err_rtc; + + if (ret & DA9055_RTC_ALM_EN) + rtc->alarm_enable = 1; + + device_init_wakeup(&pdev->dev, 1); + + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + &da9055_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + goto err_rtc; + } + + alm_irq = platform_get_irq_byname(pdev, "ALM"); + alm_irq = regmap_irq_get_virq(rtc->da9055->irq_data, alm_irq); + ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, + da9055_rtc_alm_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ALM", rtc); + if (ret != 0) + dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret); + +err_rtc: + return ret; + +} + +static int da9055_rtc_remove(struct platform_device *pdev) +{ + struct da9055_rtc *rtc = pdev->dev.platform_data; + + rtc_device_unregister(rtc->rtc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +#ifdef CONFIG_PM +/* Turn off the alarm if it should not be a wake source. */ +static int da9055_rtc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); + int ret; + + if (!device_may_wakeup(&pdev->dev)) { + /* Disable the ALM IRQ */ + ret = da9055_rtc_enable_alarm(rtc, 0); + if (ret < 0) + dev_err(&pdev->dev, "Failed to disable RTC ALM\n"); + } + + return 0; +} + +/* Enable the alarm if it should be enabled (in case it was disabled to + * prevent use as a wake source). + */ +static int da9055_rtc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); + int ret; + + if (!device_may_wakeup(&pdev->dev)) { + if (rtc->alarm_enable) { + ret = da9055_rtc_enable_alarm(rtc, 1); + if (ret < 0) + dev_err(&pdev->dev, + "Failed to restart RTC ALM\n"); + } + } + + return 0; +} + +/* Unconditionally disable the alarm */ +static int da9055_rtc_freeze(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); + int ret; + + ret = da9055_rtc_enable_alarm(rtc, 0); + if (ret < 0) + dev_err(&pdev->dev, "Failed to freeze RTC ALMs\n"); + + return 0; + +} +#else +#define da9055_rtc_suspend NULL +#define da9055_rtc_resume NULL +#define da9055_rtc_freeze NULL +#endif + +static const struct dev_pm_ops da9055_rtc_pm_ops = { + .suspend = da9055_rtc_suspend, + .resume = da9055_rtc_resume, + + .freeze = da9055_rtc_freeze, + .thaw = da9055_rtc_resume, + .restore = da9055_rtc_resume, + + .poweroff = da9055_rtc_suspend, +}; + +static struct platform_driver da9055_rtc_driver = { + .probe = da9055_rtc_probe, + .remove = da9055_rtc_remove, + .driver = { + .name = "da9055-rtc", + .owner = THIS_MODULE, + .pm = &da9055_rtc_pm_ops, + }, +}; + +module_platform_driver(da9055_rtc_driver); + +MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); +MODULE_DESCRIPTION("RTC driver for Dialog DA9055 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9055-rtc"); From f562146a3daf6aa0bbf2a1bc4b6b7da031ed5dcd Mon Sep 17 00:00:00 2001 From: Namjae Jeon <linkinjeon@gmail.com> Date: Mon, 17 Dec 2012 16:02:56 -0800 Subject: [PATCH 110/180] fat: notify when discard is not supported Change fatfs so that a warning is emitted when an attempt is made to mount a filesystem with the unsupported `discard' option. ext4 aready does this: http://patchwork.ozlabs.org/patch/192668/ Signed-off-by: Namjae Jeon <linkinjeon@gmail.com> Signed-off-by: Amit Sahrawat <amit.sahrawat83@gmail.com> Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/fat/inode.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 5bafaad00530..7b186a5d51b1 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -26,6 +26,7 @@ #include <linux/writeback.h> #include <linux/log2.h> #include <linux/hash.h> +#include <linux/blkdev.h> #include <asm/unaligned.h> #include "fat.h" @@ -1431,6 +1432,14 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, goto out_fail; } + if (sbi->options.discard) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + if (!blk_queue_discard(q)) + fat_msg(sb, KERN_WARNING, + "mounting with \"discard\" option, but " + "the device does not support discard"); + } + return 0; out_invalid: From 58156c8fbf43e71dd091848d4dbfd780d04016e6 Mon Sep 17 00:00:00 2001 From: Jan Kara <jack@suse.cz> Date: Mon, 17 Dec 2012 16:02:58 -0800 Subject: [PATCH 111/180] fat: provide option for setting timezone offset So far FAT either offsets time stamps by sys_tz.minuteswest or leaves them as they are (when tz=UTC mount option is used). However in some cases it is useful if one can specify time stamp offset on his own (e.g. when time zone of the camera connected is different from time zone of the computer, or when HW clock is in UTC and thus sys_tz.minuteswest == 0). So provide a mount option time_offset= which allows user to specify offset in minutes that should be applied to time stamps on the filesystem. akpm: this code would work incorrectly when used via `mount -o remount', because cached inodes would not be updated. But fatfs's fat_remount() is basically a no-op anyway. Signed-off-by: Jan Kara <jack@suse.cz> Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/filesystems/vfat.txt | 9 +++++++++ fs/fat/fat.h | 3 ++- fs/fat/inode.c | 25 ++++++++++++++++++++----- fs/fat/misc.c | 9 ++++++--- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index de1e6c4dccff..d230dd9c99b0 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -111,6 +111,15 @@ tz=UTC -- Interpret timestamps as UTC rather than local time. useful when mounting devices (like digital cameras) that are set to UTC in order to avoid the pitfalls of local time. +time_offset=minutes + -- Set offset for conversion of timestamps from local time + used by FAT to UTC. I.e. <minutes> minutes will be subtracted + from each timestamp to convert it to UTC used internally by + Linux. This is useful when time zone set in sys_tz is + not the time zone used by the filesystem. Note that this + option still does not provide correct time stamps in all + cases in presence of DST - time stamps in a different DST + setting will be off by one hour. showexec -- If set, the execute permission bits of the file will be allowed only if the extension part of the name is .EXE, diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 623f36f0423b..12701a567752 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -29,6 +29,7 @@ struct fat_mount_options { unsigned short fs_fmask; unsigned short fs_dmask; unsigned short codepage; /* Codepage for shortname conversions */ + int time_offset; /* Offset of timestamps from UTC (in minutes) */ char *iocharset; /* Charset used for filename input/display */ unsigned short shortname; /* flags for shortname display/create rule */ unsigned char name_check; /* r = relaxed, n = normal, s = strict */ @@ -45,7 +46,7 @@ struct fat_mount_options { flush:1, /* write things quickly */ nocase:1, /* Does this need case conversion? 0=need case conversion*/ usefree:1, /* Use free_clusters for FAT32 */ - tz_utc:1, /* Filesystem timestamps are in UTC */ + tz_set:1, /* Filesystem timestamps' offset set */ rodir:1, /* allow ATTR_RO for directory */ discard:1, /* Issue discard requests on deletions */ nfs:1; /* Do extra work needed for NFS export */ diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7b186a5d51b1..59ac83be2d5b 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -778,8 +778,12 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) } if (opts->flush) seq_puts(m, ",flush"); - if (opts->tz_utc) - seq_puts(m, ",tz=UTC"); + if (opts->tz_set) { + if (opts->time_offset) + seq_printf(m, ",time_offset=%d", opts->time_offset); + else + seq_puts(m, ",tz=UTC"); + } if (opts->errors == FAT_ERRORS_CONT) seq_puts(m, ",errors=continue"); else if (opts->errors == FAT_ERRORS_PANIC) @@ -801,7 +805,8 @@ enum { Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, - Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_err, + Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, + Opt_err, }; static const match_table_t fat_tokens = { @@ -826,6 +831,7 @@ static const match_table_t fat_tokens = { {Opt_immutable, "sys_immutable"}, {Opt_flush, "flush"}, {Opt_tz_utc, "tz=UTC"}, + {Opt_time_offset, "time_offset=%d"}, {Opt_err_cont, "errors=continue"}, {Opt_err_panic, "errors=panic"}, {Opt_err_ro, "errors=remount-ro"}, @@ -910,7 +916,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, opts->utf8 = opts->unicode_xlate = 0; opts->numtail = 1; opts->usefree = opts->nocase = 0; - opts->tz_utc = 0; + opts->tz_set = 0; opts->nfs = 0; opts->errors = FAT_ERRORS_RO; *debug = 0; @@ -1006,8 +1012,17 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, case Opt_flush: opts->flush = 1; break; + case Opt_time_offset: + if (match_int(&args[0], &option)) + return 0; + if (option < -12 * 60 || option > 12 * 60) + return 0; + opts->tz_set = 1; + opts->time_offset = option; + break; case Opt_tz_utc: - opts->tz_utc = 1; + opts->tz_set = 1; + opts->time_offset = 0; break; case Opt_err_cont: opts->errors = FAT_ERRORS_CONT; diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 6d93360ca0cc..5eb600dc43a9 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -212,8 +212,10 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, + days_in_year[month] + day + DAYS_DELTA) * SECS_PER_DAY; - if (!sbi->options.tz_utc) + if (!sbi->options.tz_set) second += sys_tz.tz_minuteswest * SECS_PER_MIN; + else + second -= sbi->options.time_offset * SECS_PER_MIN; if (time_cs) { ts->tv_sec = second + (time_cs / 100); @@ -229,8 +231,9 @@ void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, __le16 *time, __le16 *date, u8 *time_cs) { struct tm tm; - time_to_tm(ts->tv_sec, sbi->options.tz_utc ? 0 : - -sys_tz.tz_minuteswest * 60, &tm); + time_to_tm(ts->tv_sec, + (sbi->options.tz_set ? sbi->options.time_offset : + -sys_tz.tz_minuteswest) * SECS_PER_MIN, &tm); /* FAT can only support year between 1980 to 2107 */ if (tm.tm_year < 1980 - 1900) { From 5b3d5aeaa333850756f41350fed2fc95912b2a4f Mon Sep 17 00:00:00 2001 From: Jan Kara <jack@suse.cz> Date: Mon, 17 Dec 2012 16:02:59 -0800 Subject: [PATCH 112/180] fat: ix mount option parsing parse_options() is supposed to return value < 0 on error however we returned 0 (success) in a lot of cases. This actually was not a problem in practice because match_token() used by parse_options() is clever and catches most of the problems for us. Signed-off-by: Jan Kara <jack@suse.cz> Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/fat/inode.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 59ac83be2d5b..3b733a730952 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -972,41 +972,41 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, break; case Opt_uid: if (match_int(&args[0], &option)) - return 0; + return -EINVAL; opts->fs_uid = make_kuid(current_user_ns(), option); if (!uid_valid(opts->fs_uid)) - return 0; + return -EINVAL; break; case Opt_gid: if (match_int(&args[0], &option)) - return 0; + return -EINVAL; opts->fs_gid = make_kgid(current_user_ns(), option); if (!gid_valid(opts->fs_gid)) - return 0; + return -EINVAL; break; case Opt_umask: if (match_octal(&args[0], &option)) - return 0; + return -EINVAL; opts->fs_fmask = opts->fs_dmask = option; break; case Opt_dmask: if (match_octal(&args[0], &option)) - return 0; + return -EINVAL; opts->fs_dmask = option; break; case Opt_fmask: if (match_octal(&args[0], &option)) - return 0; + return -EINVAL; opts->fs_fmask = option; break; case Opt_allow_utime: if (match_octal(&args[0], &option)) - return 0; + return -EINVAL; opts->allow_utime = option & (S_IWGRP | S_IWOTH); break; case Opt_codepage: if (match_int(&args[0], &option)) - return 0; + return -EINVAL; opts->codepage = option; break; case Opt_flush: @@ -1014,9 +1014,9 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, break; case Opt_time_offset: if (match_int(&args[0], &option)) - return 0; + return -EINVAL; if (option < -12 * 60 || option > 12 * 60) - return 0; + return -EINVAL; opts->tz_set = 1; opts->time_offset = option; break; From c6c20372bbb2f70d2757eed0a8d6860884bae11f Mon Sep 17 00:00:00 2001 From: Dave Reisner <dreisner@archlinux.org> Date: Mon, 17 Dec 2012 16:03:01 -0800 Subject: [PATCH 113/180] fs/fat: strip "cp" prefix from codepage in display Option parsing code expects an unsigned integer for the codepage option, but prefixes and stores this option with "cp" before passing to load_nls(). This makes the displayed option in /proc an invalid one. Strip the prefix when printing so that the displayed option is valid for reuse. Signed-off-by: Dave Reisner <dreisner@archlinux.org> Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/fat/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 3b733a730952..35806813ea4e 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -726,7 +726,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) if (opts->allow_utime) seq_printf(m, ",allow_utime=%04o", opts->allow_utime); if (sbi->nls_disk) - seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); + /* strip "cp" prefix from displayed option */ + seq_printf(m, ",codepage=%s", &sbi->nls_disk->charset[2]); if (isvfat) { if (sbi->nls_io) seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); From 543f56c19c3e926d33b50a6bcbc37c408631601e Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Date: Mon, 17 Dec 2012 16:03:02 -0800 Subject: [PATCH 114/180] Documentation: fix Documentation/security/00-INDEX keys-ecryptfs.txt was missing from 00-INDEX. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/security/00-INDEX | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/security/00-INDEX b/Documentation/security/00-INDEX index eeed1de546d4..414235c1fcfc 100644 --- a/Documentation/security/00-INDEX +++ b/Documentation/security/00-INDEX @@ -12,6 +12,8 @@ apparmor.txt - documentation on the AppArmor security extension. credentials.txt - documentation about credentials in Linux. +keys-ecryptfs.txt + - description of the encryption keys for the ecryptfs filesystem. keys-request-key.txt - description of the kernel key request service. keys-trusted-encrypted.txt From 4c925d6031f719fad6ea8b1c94a636f4c0fea39b Mon Sep 17 00:00:00 2001 From: Eldad Zack <eldad@fogrefinery.com> Date: Mon, 17 Dec 2012 16:03:04 -0800 Subject: [PATCH 115/180] kstrto*: add documentation As Bruce Fields pointed out, kstrto* is currently lacking kerneldoc comments. This patch adds kerneldoc comments to common variants of kstrto*: kstrto(u)l, kstrto(u)ll and kstrto(u)int. Signed-off-by: Eldad Zack <eldad@fogrefinery.com> Cc: J. Bruce Fields <bfields@fieldses.org> Cc: Joe Perches <joe@perches.com> Cc: Randy Dunlap <rdunlap@xenotime.net> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Rob Landley <rob@landley.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/DocBook/kernel-api.tmpl | 3 ++ include/linux/kernel.h | 33 ++++++++++++++ lib/kstrtox.c | 64 +++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 00687ee9d363..f75ab4c1b281 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -58,6 +58,9 @@ <sect1><title>String Conversions</title> !Elib/vsprintf.c +!Finclude/linux/kernel.h kstrtol +!Finclude/linux/kernel.h kstrtoul +!Elib/kstrtox.c </sect1> <sect1><title>String Manipulation</title> <!-- All functions are exported at now diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d97ed5897447..d140e8fb075f 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -220,6 +220,23 @@ int __must_check _kstrtol(const char *s, unsigned int base, long *res); int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res); int __must_check kstrtoll(const char *s, unsigned int base, long long *res); + +/** + * kstrtoul - convert a string to an unsigned long + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign, but not a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. +*/ static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res) { /* @@ -233,6 +250,22 @@ static inline int __must_check kstrtoul(const char *s, unsigned int base, unsign return _kstrtoul(s, base, res); } +/** + * kstrtol - convert a string to a long + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign or a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ static inline int __must_check kstrtol(const char *s, unsigned int base, long *res) { /* diff --git a/lib/kstrtox.c b/lib/kstrtox.c index c3615eab0cc3..f78ae0c0c4e2 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -104,6 +104,22 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) return 0; } +/** + * kstrtoull - convert a string to an unsigned long long + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign, but not a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ int kstrtoull(const char *s, unsigned int base, unsigned long long *res) { if (s[0] == '+') @@ -112,6 +128,22 @@ int kstrtoull(const char *s, unsigned int base, unsigned long long *res) } EXPORT_SYMBOL(kstrtoull); +/** + * kstrtoll - convert a string to a long long + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign or a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ int kstrtoll(const char *s, unsigned int base, long long *res) { unsigned long long tmp; @@ -168,6 +200,22 @@ int _kstrtol(const char *s, unsigned int base, long *res) } EXPORT_SYMBOL(_kstrtol); +/** + * kstrtouint - convert a string to an unsigned int + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign, but not a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ int kstrtouint(const char *s, unsigned int base, unsigned int *res) { unsigned long long tmp; @@ -183,6 +231,22 @@ int kstrtouint(const char *s, unsigned int base, unsigned int *res) } EXPORT_SYMBOL(kstrtouint); +/** + * kstrtoint - convert a string to an int + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign or a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ int kstrtoint(const char *s, unsigned int base, int *res) { long long tmp; From 462e471107624fe9bd8b6353ac13e06305c3f3fd Mon Sep 17 00:00:00 2001 From: Eldad Zack <eldad@fogrefinery.com> Date: Mon, 17 Dec 2012 16:03:05 -0800 Subject: [PATCH 116/180] simple_strto*: annotate function as obsolete Update the documentation for simple_strto* to reflect that it has been obsoleted and advise the usage of kstrto*. Signed-off-by: Eldad Zack <eldad@fogrefinery.com> Cc: J. Bruce Fields <bfields@fieldses.org> Cc: Joe Perches <joe@perches.com> Cc: Randy Dunlap <rdunlap@xenotime.net> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Rob Landley <rob@landley.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- lib/vsprintf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 292fcb174a32..fab33a9c5318 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -38,6 +38,8 @@ * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use + * + * This function is obsolete. Please use kstrtoull instead. */ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) { @@ -61,6 +63,8 @@ EXPORT_SYMBOL(simple_strtoull); * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use + * + * This function is obsolete. Please use kstrtoul instead. */ unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { @@ -73,6 +77,8 @@ EXPORT_SYMBOL(simple_strtoul); * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use + * + * This function is obsolete. Please use kstrtol instead. */ long simple_strtol(const char *cp, char **endp, unsigned int base) { @@ -88,6 +94,8 @@ EXPORT_SYMBOL(simple_strtol); * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use + * + * This function is obsolete. Please use kstrtoll instead. */ long long simple_strtoll(const char *cp, char **endp, unsigned int base) { From 992fb6e170639b0849bace8e49bf31bd37c4123c Mon Sep 17 00:00:00 2001 From: Oleg Nesterov <oleg@redhat.com> Date: Mon, 17 Dec 2012 16:03:07 -0800 Subject: [PATCH 117/180] ptrace: introduce PTRACE_O_EXITKILL Ptrace jailers want to be sure that the tracee can never escape from the control. However if the tracer dies unexpectedly the tracee continues to run in potentially unsafe mode. Add the new ptrace option PTRACE_O_EXITKILL. If the tracer exits it sends SIGKILL to every tracee which has this bit set. Note that the new option is not equal to the last-option << 1. Because currently all options have an event, and the new one starts the eventless group. It uses the random 20 bit, so we have the room for 12 more events, but we can also add the new eventless options below this one. Suggested by Amnon Shiloh. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Tested-by: Amnon Shiloh <u3557@miso.sublimeip.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Serge Hallyn <serge.hallyn@canonical.com> Cc: Chris Evans <scarybeasts@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/ptrace.h | 2 ++ include/uapi/linux/ptrace.h | 5 ++++- kernel/ptrace.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index a89ff04bddd9..addfbe7c180e 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -32,6 +32,8 @@ #define PT_TRACE_EXIT PT_EVENT_FLAG(PTRACE_EVENT_EXIT) #define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP) +#define PT_EXITKILL (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT) + /* single stepping state bits (used on ARM and PA-RISC) */ #define PT_SINGLESTEP_BIT 31 #define PT_SINGLESTEP (1<<PT_SINGLESTEP_BIT) diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h index 1ef6c056a9e4..022ab186a812 100644 --- a/include/uapi/linux/ptrace.h +++ b/include/uapi/linux/ptrace.h @@ -73,7 +73,10 @@ #define PTRACE_O_TRACEEXIT (1 << PTRACE_EVENT_EXIT) #define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP) -#define PTRACE_O_MASK 0x000000ff +/* eventless options */ +#define PTRACE_O_EXITKILL (1 << 20) + +#define PTRACE_O_MASK (0x000000ff | PTRACE_O_EXITKILL) #include <asm/ptrace.h> diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 1f5e55dda955..ec8118ab2a47 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -457,6 +457,9 @@ void exit_ptrace(struct task_struct *tracer) return; list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { + if (unlikely(p->ptrace & PT_EXITKILL)) + send_sig_info(SIGKILL, SEND_SIG_FORCED, p); + if (__ptrace_detach(tracer, p)) list_add(&p->ptrace_entry, &ptrace_dead); } From 7b9a7ec565505699f503b4fcf61500dceb36e744 Mon Sep 17 00:00:00 2001 From: Andrew Vagin <avagin@openvz.org> Date: Mon, 17 Dec 2012 16:03:10 -0800 Subject: [PATCH 118/180] proc: don't show nonexistent capabilities Without this patch it is really hard to interpret a bounding set, if CAP_LAST_CAP is unknown for a current kernel. Non-existant capabilities can not be deleted from a bounding set with help of prctl. E.g.: Here are two examples without/with this patch. CapBnd: ffffffe0fdecffff CapBnd: 00000000fdecffff I suggest to hide non-existent capabilities. Here is two reasons. * It's logically and easier for using. * It helps to checkpoint-restore capabilities of tasks, because tasks can be restored on another kernel, where CAP_LAST_CAP is bigger. Signed-off-by: Andrew Vagin <avagin@openvz.org> Cc: Andrew G. Morgan <morgan@kernel.org> Reviewed-by: Serge E. Hallyn <serge.hallyn@canonical.com> Cc: Pavel Emelyanov <xemul@parallels.com> Reviewed-by: Kees Cook <keescook@chromium.org> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/proc/array.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/proc/array.c b/fs/proc/array.c index d3696708fc1a..377a37366dde 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -308,6 +308,10 @@ static void render_cap_t(struct seq_file *m, const char *header, seq_putc(m, '\n'); } +/* Remove non-existent capabilities */ +#define NORM_CAPS(v) (v.cap[CAP_TO_INDEX(CAP_LAST_CAP)] &= \ + CAP_TO_MASK(CAP_LAST_CAP + 1) - 1) + static inline void task_cap(struct seq_file *m, struct task_struct *p) { const struct cred *cred; @@ -321,6 +325,11 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p) cap_bset = cred->cap_bset; rcu_read_unlock(); + NORM_CAPS(cap_inheritable); + NORM_CAPS(cap_permitted); + NORM_CAPS(cap_effective); + NORM_CAPS(cap_bset); + render_cap_t(m, "CapInh:\t", &cap_inheritable); render_cap_t(m, "CapPrm:\t", &cap_permitted); render_cap_t(m, "CapEff:\t", &cap_effective); From 834f82e2aa9a8ede94b17b656329f850c1471514 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:03:13 -0800 Subject: [PATCH 119/180] procfs: add VmFlags field in smaps output During c/r sessions we've found that there is no way at the moment to fetch some VMA associated flags, such as mlock() and madvise(). This leads us to a problem -- we don't know if we should call for mlock() and/or madvise() after restore on the vma area we're bringing back to life. This patch intorduces a new field into "smaps" output called VmFlags, where all set flags associated with the particular VMA is shown as two letter mnemonics. [ Strictly speaking for c/r we only need mlock/madvise bits but it has been said that providing just a few flags looks somehow inconsistent. So all flags are here now. ] This feature is made available on CONFIG_CHECKPOINT_RESTORE=n kernels, as other applications may start to use these fields. The data is encoded in a somewhat awkward two letters mnemonic form, to encourage userspace to be prepared for fields being added or removed in the future. [a.p.zijlstra@chello.nl: props to use for_each_set_bit] [sfr@canb.auug.org.au: props to use array instead of struct] [akpm@linux-foundation.org: overall redesign and simplification] [akpm@linux-foundation.org: remove unneeded braces per sfr, avoid using bloaty for_each_set_bit()] Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/filesystems/proc.txt | 40 ++++++++++++++++++++-- fs/proc/task_mmu.c | 53 ++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 3844d21d6ca3..74cb394e6888 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -142,7 +142,7 @@ Table 1-1: Process specific entries in /proc pagemap Page table stack Report full stack trace, enable via CONFIG_STACKTRACE smaps a extension based on maps, showing the memory consumption of - each mapping + each mapping and flags associated with it .............................................................................. For example, to get the status information of a process, all you have to do is @@ -415,8 +415,9 @@ Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 374 kB +VmFlags: rd ex mr mw me de -The first of these lines shows the same information as is displayed for the +the first of these lines shows the same information as is displayed for the mapping in /proc/PID/maps. The remaining lines show the size of the mapping (size), the amount of the mapping that is currently resident in RAM (RSS), the process' proportional share of this mapping (PSS), the number of clean and @@ -430,6 +431,41 @@ and a page is modified, the file page is replaced by a private anonymous copy. "Swap" shows how much would-be-anonymous memory is also used, but out on swap. +"VmFlags" field deserves a separate description. This member represents the kernel +flags associated with the particular virtual memory area in two letter encoded +manner. The codes are the following: + rd - readable + wr - writeable + ex - executable + sh - shared + mr - may read + mw - may write + me - may execute + ms - may share + gd - stack segment growns down + pf - pure PFN range + dw - disabled write to the mapped file + lo - pages are locked in memory + io - memory mapped I/O area + sr - sequential read advise provided + rr - random read advise provided + dc - do not copy area on fork + de - do not expand area on remapping + ac - area is accountable + nr - swap space is not reserved for the area + ht - area uses huge tlb pages + nl - non-linear mapping + ar - architecture specific flag + dd - do not include area into core dump + mm - mixed map area + hg - huge page advise flag + nh - no-huge page advise flag + mg - mergable advise flag + +Note that there is no guarantee that every flag and associated mnemonic will +be present in all further kernel releases. Things get changed, the flags may +be vanished or the reverse -- new added. + This file is only present if the CONFIG_MMU kernel configuration option is enabled. diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 48775628abbf..448455b7fd91 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -526,6 +526,57 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, return 0; } +static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) +{ + /* + * Don't forget to update Documentation/ on changes. + */ + static const char mnemonics[BITS_PER_LONG][2] = { + /* + * In case if we meet a flag we don't know about. + */ + [0 ... (BITS_PER_LONG-1)] = "??", + + [ilog2(VM_READ)] = "rd", + [ilog2(VM_WRITE)] = "wr", + [ilog2(VM_EXEC)] = "ex", + [ilog2(VM_SHARED)] = "sh", + [ilog2(VM_MAYREAD)] = "mr", + [ilog2(VM_MAYWRITE)] = "mw", + [ilog2(VM_MAYEXEC)] = "me", + [ilog2(VM_MAYSHARE)] = "ms", + [ilog2(VM_GROWSDOWN)] = "gd", + [ilog2(VM_PFNMAP)] = "pf", + [ilog2(VM_DENYWRITE)] = "dw", + [ilog2(VM_LOCKED)] = "lo", + [ilog2(VM_IO)] = "io", + [ilog2(VM_SEQ_READ)] = "sr", + [ilog2(VM_RAND_READ)] = "rr", + [ilog2(VM_DONTCOPY)] = "dc", + [ilog2(VM_DONTEXPAND)] = "de", + [ilog2(VM_ACCOUNT)] = "ac", + [ilog2(VM_NORESERVE)] = "nr", + [ilog2(VM_HUGETLB)] = "ht", + [ilog2(VM_NONLINEAR)] = "nl", + [ilog2(VM_ARCH_1)] = "ar", + [ilog2(VM_DONTDUMP)] = "dd", + [ilog2(VM_MIXEDMAP)] = "mm", + [ilog2(VM_HUGEPAGE)] = "hg", + [ilog2(VM_NOHUGEPAGE)] = "nh", + [ilog2(VM_MERGEABLE)] = "mg", + }; + size_t i; + + seq_puts(m, "VmFlags: "); + for (i = 0; i < BITS_PER_LONG; i++) { + if (vma->vm_flags & (1UL << i)) { + seq_printf(m, "%c%c ", + mnemonics[i][0], mnemonics[i][1]); + } + } + seq_putc(m, '\n'); +} + static int show_smap(struct seq_file *m, void *v, int is_pid) { struct proc_maps_private *priv = m->private; @@ -581,6 +632,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) seq_printf(m, "Nonlinear: %8lu kB\n", mss.nonlinear >> 10); + show_smap_vma_flags(m, vma); + if (m->count < m->size) /* vma is copied successfully */ m->version = (vma != get_gate_vma(task->mm)) ? vma->vm_start : 0; From 2f4b3bf6b2318cfaa177ec5a802f4d8d6afbd816 Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> Date: Mon, 17 Dec 2012 16:03:14 -0800 Subject: [PATCH 120/180] /proc/pid/status: add "Seccomp" field It is currently impossible to examine the state of seccomp for a given process. While attaching with gdb and attempting "call prctl(PR_GET_SECCOMP,...)" will work with some situations, it is not reliable. If the process is in seccomp mode 1, this query will kill the process (prctl not allowed), if the process is in mode 2 with prctl not allowed, it will similarly be killed, and in weird cases, if prctl is filtered to return errno 0, it can look like seccomp is disabled. When reviewing the state of running processes, there should be a way to externally examine the seccomp mode. ("Did this build of Chrome end up using seccomp?" "Did my distro ship ssh with seccomp enabled?") This adds the "Seccomp" line to /proc/$pid/status. Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: James Morris <jmorris@namei.org> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/filesystems/proc.txt | 2 ++ fs/proc/array.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 74cb394e6888..12665ee7094a 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -181,6 +181,7 @@ read the file /proc/PID/status: CapPrm: 0000000000000000 CapEff: 0000000000000000 CapBnd: ffffffffffffffff + Seccomp: 0 voluntary_ctxt_switches: 0 nonvoluntary_ctxt_switches: 1 @@ -237,6 +238,7 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7) CapPrm bitmap of permitted capabilities CapEff bitmap of effective capabilities CapBnd bitmap of capabilities bounding set + Seccomp seccomp mode, like prctl(PR_GET_SECCOMP, ...) Cpus_allowed mask of CPUs on which this process may run Cpus_allowed_list Same as previous, but in "list format" Mems_allowed mask of memory nodes allowed to this process diff --git a/fs/proc/array.c b/fs/proc/array.c index 377a37366dde..077235ffb38b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -336,6 +336,13 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p) render_cap_t(m, "CapBnd:\t", &cap_bset); } +static inline void task_seccomp(struct seq_file *m, struct task_struct *p) +{ +#ifdef CONFIG_SECCOMP + seq_printf(m, "Seccomp:\t%d\n", p->seccomp.mode); +#endif +} + static inline void task_context_switch_counts(struct seq_file *m, struct task_struct *p) { @@ -369,6 +376,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, } task_sig(m, task); task_cap(m, task); + task_seccomp(m, task); task_cpus_allowed(m, task); cpuset_task_status_allowed(m, task); task_context_switch_counts(m, task); From 8d238027b87e654be552eabdf492042a34c5c300 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Date: Mon, 17 Dec 2012 16:03:17 -0800 Subject: [PATCH 121/180] proc: pid/status: show all supplementary groups We display a list of supplementary group for each process in /proc/<pid>/status. However, we show only the first 32 groups, not all of them. Although this is rare, but sometimes processes do have more than 32 supplementary groups, and this kernel limitation breaks user-space apps that rely on the group list in /proc/<pid>/status. Number 32 comes from the internal NGROUPS_SMALL macro which defines the length for the internal kernel "small" groups buffer. There is no apparent reason to limit to this value. This patch removes the 32 groups printing limit. The Linux kernel limits the amount of supplementary groups by NGROUPS_MAX, which is currently set to 65536. And this is the maximum count of groups we may possibly print. Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com> Acked-by: Kees Cook <keescook@chromium.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/proc/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 077235ffb38b..439544fec388 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -212,7 +212,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, group_info = cred->group_info; task_unlock(p); - for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) + for (g = 0; g < group_info->ngroups; g++) seq_printf(m, "%d ", from_kgid_munged(user_ns, GROUP_AT(group_info, g))); put_cred(cred); From d740269867021faf4ce38a449353d2b986c34a67 Mon Sep 17 00:00:00 2001 From: Kees Cook <keescook@chromium.org> Date: Mon, 17 Dec 2012 16:03:20 -0800 Subject: [PATCH 122/180] exec: use -ELOOP for max recursion depth To avoid an explosion of request_module calls on a chain of abusive scripts, fail maximum recursion with -ELOOP instead of -ENOEXEC. As soon as maximum recursion depth is hit, the error will fail all the way back up the chain, aborting immediately. This also has the side-effect of stopping the user's shell from attempting to reexecute the top-level file as a shell script. As seen in the dash source: if (cmd != path_bshell && errno == ENOEXEC) { *argv-- = cmd; *argv = cmd = path_bshell; goto repeat; } The above logic was designed for running scripts automatically that lacked the "#!" header, not to re-try failed recursion. On a legitimate -ENOEXEC, things continue to behave as the shell expects. Additionally, when tracking recursion, the binfmt handlers should not be involved. The recursion being tracked is the depth of calls through search_binary_handler(), so that function should be exclusively responsible for tracking the depth. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: halfdog <me@halfdog.net> Cc: P J P <ppandit@redhat.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/binfmt_em86.c | 1 - fs/binfmt_misc.c | 6 ------ fs/binfmt_script.c | 4 +--- fs/exec.c | 10 +++++----- include/linux/binfmts.h | 2 -- 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index 4e6cce57d113..037a3e2b045b 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm) return -ENOEXEC; } - bprm->recursion_depth++; /* Well, the bang-shell is implicit... */ allow_write_access(bprm->file); fput(bprm->file); bprm->file = NULL; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index b0b70fbea06c..9be335fb8a7c 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm) if (!enabled) goto _ret; - retval = -ENOEXEC; - if (bprm->recursion_depth > BINPRM_MAX_RECURSION) - goto _ret; - /* to keep locking time low, we copy the interpreter string */ read_lock(&entries_lock); fmt = check_file(bprm); @@ -197,8 +193,6 @@ static int load_misc_binary(struct linux_binprm *bprm) if (retval < 0) goto _error; - bprm->recursion_depth++; - retval = search_binary_handler(bprm); if (retval < 0) goto _error; diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 8c954997e7f7..1610a91637e5 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm) char interp[BINPRM_BUF_SIZE]; int retval; - if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || - (bprm->recursion_depth > BINPRM_MAX_RECURSION)) + if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) return -ENOEXEC; /* * This section does the #! interpretation. * Sorta complicated, but hopefully it will work. -TYT */ - bprm->recursion_depth++; allow_write_access(bprm->file); fput(bprm->file); bprm->file = NULL; diff --git a/fs/exec.c b/fs/exec.c index 721a29929511..d5eb9e605ffd 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1356,6 +1356,10 @@ int search_binary_handler(struct linux_binprm *bprm) struct linux_binfmt *fmt; pid_t old_pid, old_vpid; + /* This allows 4 levels of binfmt rewrites before failing hard. */ + if (depth > 5) + return -ELOOP; + retval = security_bprm_check(bprm); if (retval) return retval; @@ -1380,12 +1384,8 @@ int search_binary_handler(struct linux_binprm *bprm) if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); + bprm->recursion_depth = depth + 1; retval = fn(bprm); - /* - * Restore the depth counter to its starting value - * in this call, so we don't have to rely on every - * load_binary function to restore it on return. - */ bprm->recursion_depth = depth; if (retval >= 0) { if (depth == 0) { diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 2630c9b41a86..a4c2b565c835 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -54,8 +54,6 @@ struct linux_binprm { #define BINPRM_FLAGS_EXECFD_BIT 1 #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) -#define BINPRM_MAX_RECURSION 4 - /* Function parameter for binfmt->coredump */ struct coredump_params { siginfo_t *siginfo; From a5ba911ec3792168530d35e16a8ec3b6fc60bcb5 Mon Sep 17 00:00:00 2001 From: Gao feng <gaofeng@cn.fujitsu.com> Date: Mon, 17 Dec 2012 16:03:22 -0800 Subject: [PATCH 123/180] pidns: remove unused is_container_init() Since commit 1cdcbec1a337 ("CRED: Neuter sys_capset()") is_container_init() has no callers. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Cc: David Howells <dhowells@redhat.com> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Cc: James Morris <jmorris@namei.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/sched.h | 6 ------ kernel/pid.c | 15 --------------- 2 files changed, 21 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index b089c92c609b..9914c662ed7b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1778,12 +1778,6 @@ static inline int is_global_init(struct task_struct *tsk) return tsk->pid == 1; } -/* - * is_container_init: - * check whether in the task is init in its own pid namespace. - */ -extern int is_container_init(struct task_struct *tsk); - extern struct pid *cad_pid; extern void free_task(struct task_struct *tsk); diff --git a/kernel/pid.c b/kernel/pid.c index fd996c1ed9f8..a54a1123c7cf 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -81,21 +81,6 @@ struct pid_namespace init_pid_ns = { }; EXPORT_SYMBOL_GPL(init_pid_ns); -int is_container_init(struct task_struct *tsk) -{ - int ret = 0; - struct pid *pid; - - rcu_read_lock(); - pid = task_pid(tsk); - if (pid != NULL && pid->numbers[pid->level].nr == 1) - ret = 1; - rcu_read_unlock(); - - return ret; -} -EXPORT_SYMBOL(is_container_init); - /* * Note: disable interrupts while the pidmap_lock is held as an * interrupt might come in and do read_lock(&tasklist_lock). From 8529091e8e2ae25e0f4003086f619765ff255e4b Mon Sep 17 00:00:00 2001 From: Josh Triplett <josh@joshtriplett.org> Date: Mon, 17 Dec 2012 16:03:24 -0800 Subject: [PATCH 124/180] linux/compiler.h: add __must_hold macro for functions called with a lock held linux/compiler.h has macros to denote functions that acquire or release locks, but not to denote functions called with a lock held that return with the lock still held. Add a __must_hold macro to cover that case. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Reported-by: Ed Cashin <ecashin@coraid.com> Tested-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/compiler.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index f430e4162f41..b121554f1fe2 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -10,6 +10,7 @@ # define __force __attribute__((force)) # define __nocast __attribute__((nocast)) # define __iomem __attribute__((noderef, address_space(2))) +# define __must_hold(x) __attribute__((context(x,1,1))) # define __acquires(x) __attribute__((context(x,0,1))) # define __releases(x) __attribute__((context(x,1,0))) # define __acquire(x) __context__(x,1) @@ -33,6 +34,7 @@ extern void __chk_io_ptr(const volatile void __iomem *); # define __chk_user_ptr(x) (void)0 # define __chk_io_ptr(x) (void)0 # define __builtin_warning(x, y...) (1) +# define __must_hold(x) # define __acquires(x) # define __releases(x) # define __acquire(x) (void)0 From 6e9766317fd51a33a32c65d2b76a6bde3227bbbd Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:25 -0800 Subject: [PATCH 125/180] Documentation/sparse.txt: document context annotations for lock checking The context feature of sparse is used with the Linux kernel sources to check for imbalanced uses of locks. Document the annotations defined in include/linux/compiler.h that tell sparse what to expect when a lock is held on function entry, exit, or both. Signed-off-by: Ed Cashin <ecashin@coraid.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Acked-by: Christopher Li <sparse@chrisli.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/sparse.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index 4909d4116356..eceab1308a8c 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -49,6 +49,24 @@ be generated without __CHECK_ENDIAN__. __bitwise - noisy stuff; in particular, __le*/__be* are that. We really don't want to drown in noise unless we'd explicitly asked for it. +Using sparse for lock checking +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following macros are undefined for gcc and defined during a sparse +run to use the "context" tracking feature of sparse, applied to +locking. These annotations tell sparse when a lock is held, with +regard to the annotated function's entry and exit. + +__must_hold - The specified lock is held on function entry and exit. + +__acquires - The specified lock is held on function exit, but not entry. + +__releases - The specified lock is held on function entry, but not exit. + +If the function enters and exits without the lock held, acquiring and +releasing the lock inside the function in a balanced way, no +annotation is needed. The tree annotations above are for cases where +sparse would otherwise report a context imbalance. Getting sparse ~~~~~~~~~~~~~~ From 662a889608dfabbb1b4954b172a6872a25dc8f90 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:26 -0800 Subject: [PATCH 126/180] aoe: describe the behavior of the "err" character device Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoechr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index ed57a890c643..2bf6273e6779 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -39,6 +39,11 @@ struct ErrMsg { }; static DEFINE_MUTEX(aoechr_mutex); + +/* A ring buffer of error messages, to be read through + * "/dev/etherd/err". When no messages are present, + * readers will block waiting for messages to appear. + */ static struct ErrMsg emsgs[NMSG]; static int emsgs_head_idx, emsgs_tail_idx; static struct completion emsgs_comp; From 4e78dd144b865162626f811d1097b6d181ec6a31 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:28 -0800 Subject: [PATCH 127/180] aoe: print warning regarding a common reason for dropped transmits Dropped transmits are not common, but when they do occur, increasing the transmit queue length often helps. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoenet.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 162c6471275c..24eca2bf9416 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -52,13 +52,18 @@ static struct sk_buff_head skbtxq; /* enters with txlock held */ static int -tx(void) +tx(void) __must_hold(&txlock) { struct sk_buff *skb; + struct net_device *ifp; while ((skb = skb_dequeue(&skbtxq))) { spin_unlock_irq(&txlock); - dev_queue_xmit(skb); + ifp = skb->dev; + if (dev_queue_xmit(skb) == NET_XMIT_DROP && net_ratelimit()) + pr_warn("aoe: packet could not be sent on %s. %s\n", + ifp ? ifp->name : "netif", + "consider increasing tx_queue_len"); spin_lock_irq(&txlock); } return 0; From 1b8a1636ceea573b1d452a1cccf01c990d8d628a Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:29 -0800 Subject: [PATCH 128/180] aoe: update cap on outstanding commands based on config query response The ATA over Ethernet config query response contains a "buffer count" field reflecting the AoE target's capacity to buffer incoming AoE commands. By taking the current value of this field into accound, we increase performance throughput or avoid network congestion, when the value has increased or decreased, respectively. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 6 +++--- drivers/block/aoe/aoecmd.c | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index d2ed7f18d1ac..52f75c097242 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -122,14 +122,14 @@ struct aoeif { struct aoetgt { unsigned char addr[6]; - ushort nframes; + ushort nframes; /* cap on frames to use */ struct aoedev *d; /* parent device I belong to */ struct list_head ffree; /* list of free frames */ struct aoeif ifs[NAOEIFS]; struct aoeif *ifp; /* current aoeif in use */ ushort nout; - ushort maxout; - ulong falloc; + ushort maxout; /* current value for max outstanding */ + ulong falloc; /* number of allocated frames */ ulong lastwadj; /* last window adjustment */ int minbcnt; int wpkts, rpkts; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 9fe4f1865558..a6e95e69296c 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -1373,7 +1373,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb) spin_lock_irqsave(&d->lock, flags); t = gettgt(d, h->src); - if (!t) { + if (t) { + t->nframes = n; + if (n < t->maxout) + t->maxout = n; + } else { t = addtgt(d, h->src, n); if (!t) goto bail; From 4ba9aa7f9819bafb304f09dee90bb1fa40627358 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:30 -0800 Subject: [PATCH 129/180] aoe: support the forgetting (flushing) of a user-specified AoE target Users sometimes want to cause the aoe driver to forget a particular previously discovered device when it is no longer online. The aoetools provide an "aoe-flush" command that users run to perform this administrative task. The changes below provide the support needed in the driver. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoedev.c | 44 ++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 90e5b537f94b..63b26609400f 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -241,6 +241,30 @@ aoedev_freedev(struct aoedev *d) kfree(d); } +/* return whether the user asked for this particular + * device to be flushed + */ +static int +user_req(char *s, size_t slen, struct aoedev *d) +{ + char *p; + size_t lim; + + if (!d->gd) + return 0; + p = strrchr(d->gd->disk_name, '/'); + if (!p) + p = d->gd->disk_name; + else + p += 1; + lim = sizeof(d->gd->disk_name); + lim -= p - d->gd->disk_name; + if (slen < lim) + lim = slen; + + return !strncmp(s, p, lim); +} + int aoedev_flush(const char __user *str, size_t cnt) { @@ -249,6 +273,7 @@ aoedev_flush(const char __user *str, size_t cnt) struct aoedev *rmd = NULL; char buf[16]; int all = 0; + int specified = 0; /* flush a specific device */ if (cnt >= 3) { if (cnt > sizeof buf) @@ -256,26 +281,33 @@ aoedev_flush(const char __user *str, size_t cnt) if (copy_from_user(buf, str, cnt)) return -EFAULT; all = !strncmp(buf, "all", 3); + if (!all) + specified = 1; } spin_lock_irqsave(&devlist_lock, flags); dd = &devlist; while ((d = *dd)) { spin_lock(&d->lock); - if ((!all && (d->flags & DEVFL_UP)) + if (specified) { + if (!user_req(buf, cnt, d)) + goto skip; + } else if ((!all && (d->flags & DEVFL_UP)) || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) || d->nopen - || d->ref) { - spin_unlock(&d->lock); - dd = &d->next; - continue; - } + || d->ref) + goto skip; + *dd = d->next; aoedev_downdev(d); d->flags |= DEVFL_TKILL; spin_unlock(&d->lock); d->next = rmd; rmd = d; + continue; +skip: + spin_unlock(&d->lock); + dd = &d->next; } spin_unlock_irqrestore(&devlist_lock, flags); while ((d = rmd)) { From aa304fdefa568d63c862df7abe55d39811845c7c Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:32 -0800 Subject: [PATCH 130/180] aoe: support larger I/O requests via aoe_maxsectors module param The GPFS filesystem is an example of an aoe user that requires the aoe driver to support I/O request sizes larger than the default. Most users will not need large I/O request sizes, because they would need to be split up into multiple AoE commands anyway. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoeblk.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 00dfc5008ad4..d5aa3b8c9f33 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -16,11 +16,18 @@ #include <linux/netdevice.h> #include <linux/mutex.h> #include <linux/export.h> +#include <linux/moduleparam.h> #include "aoe.h" static DEFINE_MUTEX(aoeblk_mutex); static struct kmem_cache *buf_pool_cache; +/* GPFS needs a larger value than the default. */ +static int aoe_maxsectors; +module_param(aoe_maxsectors, int, 0644); +MODULE_PARM_DESC(aoe_maxsectors, + "When nonzero, set the maximum number of sectors per I/O request"); + static ssize_t aoedisk_show_state(struct device *dev, struct device_attribute *attr, char *page) { @@ -248,6 +255,8 @@ aoeblk_gdalloc(void *vp) d->blkq = gd->queue = q; q->queuedata = d; d->gd = gd; + if (aoe_maxsectors) + blk_queue_max_hw_sectors(q, aoe_maxsectors); gd->major = AOE_MAJOR; gd->first_minor = d->sysminor; gd->fops = &aoe_bdops; From 90a2508d01845afbb3118615ce44d689cbb0e943 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:34 -0800 Subject: [PATCH 131/180] aoe: "payload" sysfs file exports per-AoE-command data transfer size The userland aoetools package includes an "aoe-stat" command that can display a "payload size" column when the aoe driver exports this information. Users can quickly see what amount of user data is transferred inside each AoE command on the network, network headers excluded. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoeblk.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index d5aa3b8c9f33..56736cd5f3fe 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -98,6 +98,14 @@ static ssize_t aoedisk_show_fwver(struct device *dev, return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver); } +static ssize_t aoedisk_show_payload(struct device *dev, + struct device_attribute *attr, char *page) +{ + struct gendisk *disk = dev_to_disk(dev); + struct aoedev *d = disk->private_data; + + return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt); +} static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL); static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL); @@ -106,12 +114,14 @@ static struct device_attribute dev_attr_firmware_version = { .attr = { .name = "firmware-version", .mode = S_IRUGO }, .show = aoedisk_show_fwver, }; +static DEVICE_ATTR(payload, S_IRUGO, aoedisk_show_payload, NULL); static struct attribute *aoe_attrs[] = { &dev_attr_state.attr, &dev_attr_mac.attr, &dev_attr_netif.attr, &dev_attr_firmware_version.attr, + &dev_attr_payload.attr, NULL, }; From d437962504462f31515344d58cdcaf0b73b389b5 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:37 -0800 Subject: [PATCH 132/180] aoe: cleanup: remove unused ata_scnt function Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index a6e95e69296c..df86a05067e8 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -552,16 +552,6 @@ sthtith(struct aoedev *d) return 1; } -static inline unsigned char -ata_scnt(unsigned char *packet) { - struct aoe_hdr *h; - struct aoe_atahdr *ah; - - h = (struct aoe_hdr *) packet; - ah = (struct aoe_atahdr *) (h+1); - return ah->scnt; -} - static void rexmit_timer(ulong vp) { From a04b41cd2c3ea39115a2d4f264773a5956a3318d Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:39 -0800 Subject: [PATCH 133/180] aoe: whitespace cleanup Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoechr.c | 2 +- drivers/block/aoe/aoecmd.c | 6 +++--- drivers/block/aoe/aoemain.c | 2 +- drivers/block/aoe/aoenet.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 52f75c097242..8e8da1cd204d 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -151,7 +151,7 @@ struct aoedev { struct work_struct work;/* disk create work struct */ struct gendisk *gd; struct request_queue *blkq; - struct hd_geometry geo; + struct hd_geometry geo; sector_t ssize; struct timer_list timer; spinlock_t lock; diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 2bf6273e6779..42e67ad6bd20 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -287,7 +287,7 @@ aoechr_init(void) int n, i; n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); - if (n < 0) { + if (n < 0) { printk(KERN_ERR "aoe: can't register char device\n"); return n; } diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index df86a05067e8..3ce01f6b3a5d 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -978,7 +978,7 @@ ktiocomplete(struct frame *f) pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", ahout->cmdstat, ahin->cmdstat, d->aoemajor, d->aoeminor); -noskb: if (buf) +noskb: if (buf) clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); goto badrsp; } @@ -1191,7 +1191,7 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) aoecmd_cfg_pkts(aoemajor, aoeminor, &queue); aoenet_xmit(&queue); } - + struct sk_buff * aoecmd_ata_id(struct aoedev *d) { @@ -1230,7 +1230,7 @@ aoecmd_ata_id(struct aoedev *d) return skb_clone(skb, GFP_ATOMIC); } - + static struct aoetgt * addtgt(struct aoedev *d, char *addr, ulong nframes) { diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 04793c2c701b..4b987c2fefbe 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -105,7 +105,7 @@ aoe_init(void) aoechr_exit(); chr_fail: aoedev_exit(); - + printk(KERN_INFO "aoe: initialisation failure.\n"); return ret; } diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 24eca2bf9416..2e47404ff008 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -124,8 +124,8 @@ aoenet_xmit(struct sk_buff_head *queue) } } -/* - * (1) len doesn't include the header by default. I want this. +/* + * (1) len doesn't include the header by default. I want this. */ static int aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) From cd220bf51f94e6b3f7678183b6ea911cefbf7d03 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:41 -0800 Subject: [PATCH 134/180] aoe: update driver-internal version number to 60 Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 8e8da1cd204d..536942b46ab6 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "50" +#define VERSION "60" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" From 667be1e757f5684576d01d7402907a2489b1402f Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:42 -0800 Subject: [PATCH 135/180] aoe: provide ATA identify device content to user on request Make the aoe driver follow expected behavior when the user uses ioctl to get the ATA device identify information, allowing access to model, serial number, etc. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 1 + drivers/block/aoe/aoeblk.c | 30 ++++++++++++++++++++++++++++++ drivers/block/aoe/aoecmd.c | 16 ++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 536942b46ab6..f6e0c03fe7b2 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -169,6 +169,7 @@ struct aoedev { struct aoetgt *htgt; /* target needing rexmit assistance */ ulong ntargets; ulong kicked; + char ident[512]; }; /* kthread tracking */ diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 56736cd5f3fe..7ba0fcf7b06b 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -17,6 +17,7 @@ #include <linux/mutex.h> #include <linux/export.h> #include <linux/moduleparam.h> +#include <scsi/sg.h> #include "aoe.h" static DEFINE_MUTEX(aoeblk_mutex); @@ -212,9 +213,38 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } +static int +aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg) +{ + struct aoedev *d; + + if (!arg) + return -EINVAL; + + d = bdev->bd_disk->private_data; + if ((d->flags & DEVFL_UP) == 0) { + pr_err("aoe: disk not up\n"); + return -ENODEV; + } + + if (cmd == HDIO_GET_IDENTITY) { + if (!copy_to_user((void __user *) arg, &d->ident, + sizeof(d->ident))) + return 0; + return -EFAULT; + } + + /* udev calls scsi_id, which uses SG_IO, resulting in noise */ + if (cmd != SG_IO) + pr_info("aoe: unknown ioctl 0x%x\n", cmd); + + return -ENOTTY; +} + static const struct block_device_operations aoe_bdops = { .open = aoeblk_open, .release = aoeblk_release, + .ioctl = aoeblk_ioctl, .getgeo = aoeblk_getgeo, .owner = THIS_MODULE, }; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 3ce01f6b3a5d..c4ff70b61e7e 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -798,6 +798,17 @@ aoecmd_sleepwork(struct work_struct *work) } } +static void +ata_ident_fixstring(u16 *id, int ns) +{ + u16 s; + + while (ns-- > 0) { + s = *id; + *id++ = s >> 8 | s << 8; + } +} + static void ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) { @@ -833,6 +844,11 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) d->geo.sectors = get_unaligned_le16(&id[56 << 1]); } + ata_ident_fixstring((u16 *) &id[10<<1], 10); /* serial */ + ata_ident_fixstring((u16 *) &id[23<<1], 4); /* firmware */ + ata_ident_fixstring((u16 *) &id[27<<1], 20); /* model */ + memcpy(d->ident, id, sizeof(d->ident)); + if (d->ssize != ssize) printk(KERN_INFO "aoe: %pm e%ld.%d v%04x has %llu sectors\n", From 3a0c40d2d29e476ece583540e4f11276e0f36d5f Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:43 -0800 Subject: [PATCH 136/180] aoe: improve network congestion handling The aoe driver already had some congestion handling, but it was limited in its ability to cope with the kind of congestion that can arise on more complex networks such as those involving paths through multiple ethernet switches. Some of the lessons from TCP's history of development can be applied to improving the congestion control and avoidance on AoE storage networks. These changes use familar concepts from Van Jacobson's "Congestion Avoidance and Control" paper from '88, without adding significant overhead. This patch depends on an upcoming patch that covers the failover case when AoE commands being retransmitted are transferred from one retransmit queue to another. Another upcoming patch increases the timing accuracy. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 16 ++-- drivers/block/aoe/aoecmd.c | 171 +++++++++++++++++++++++-------------- drivers/block/aoe/aoedev.c | 6 +- 3 files changed, 120 insertions(+), 73 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index f6e0c03fe7b2..9e884acd75fc 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -86,8 +86,11 @@ enum { NFACTIVE = 61, TIMERTICK = HZ / 10, - MINTIMER = HZ >> 2, + RTTSCALE = 8, + RTTDSCALE = 3, MAXTIMER = HZ << 1, + RTTAVG_INIT = HZ / 4 << RTTSCALE, + RTTDEV_INIT = RTTAVG_INIT / 4, }; struct buf { @@ -127,10 +130,11 @@ struct aoetgt { struct list_head ffree; /* list of free frames */ struct aoeif ifs[NAOEIFS]; struct aoeif *ifp; /* current aoeif in use */ - ushort nout; + ushort nout; /* value of nout when skb was sent */ ushort maxout; /* current value for max outstanding */ + ushort next_cwnd; /* incr maxout after decrementing to zero */ + ushort ssthresh; /* slow start threshold */ ulong falloc; /* number of allocated frames */ - ulong lastwadj; /* last window adjustment */ int minbcnt; int wpkts, rpkts; }; @@ -142,8 +146,8 @@ struct aoedev { u16 aoeminor; u16 flags; u16 nopen; /* (bd_openers isn't available without sleeping) */ - u16 rttavg; /* round trip average of requests/responses */ - u16 mintimer; + u16 rttavg; /* scaled AoE round trip time average */ + u16 rttdev; /* scaled round trip time mean deviation */ u16 fw_ver; /* version of blade's firmware */ u16 lasttag; /* last tag sent */ u16 useme; @@ -164,6 +168,7 @@ struct aoedev { } ip; ulong maxbcnt; struct list_head factive[NFACTIVE]; /* hash of active frames */ + struct list_head rexmitq; /* deferred retransmissions */ struct aoetgt *targets[NTARGETS]; struct aoetgt **tgt; /* target in use when working */ struct aoetgt *htgt; /* target needing rexmit assistance */ @@ -196,6 +201,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); void aoecmd_cfg_rsp(struct sk_buff *); void aoecmd_sleepwork(struct work_struct *); +void aoecmd_wreset(struct aoetgt *t); void aoecmd_cleanslate(struct aoedev *); void aoecmd_exit(void); int aoecmd_init(void); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index c4ff70b61e7e..f849fa2471ca 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -58,6 +58,23 @@ new_skb(ulong len) return skb; } +static struct frame * +getframe_deferred(struct aoedev *d, u32 tag) +{ + struct list_head *head, *pos, *nx; + struct frame *f; + + head = &d->rexmitq; + list_for_each_safe(pos, nx, head) { + f = list_entry(pos, struct frame, head); + if (f->tag == tag) { + list_del(pos); + return f; + } + } + return NULL; +} + static struct frame * getframe(struct aoedev *d, u32 tag) { @@ -552,11 +569,30 @@ sthtith(struct aoedev *d) return 1; } +static void +rexmit_deferred(struct aoedev *d) +{ + struct aoetgt *t; + struct frame *f; + struct list_head *pos, *nx, *head; + + head = &d->rexmitq; + list_for_each_safe(pos, nx, head) { + f = list_entry(pos, struct frame, head); + t = f->t; + if (t->nout >= t->maxout) + continue; + list_del(pos); + t->nout++; + resend(d, f); + } +} + static void rexmit_timer(ulong vp) { struct aoedev *d; - struct aoetgt *t, **tt, **te; + struct aoetgt *t; struct aoeif *ifp; struct frame *f; struct list_head *head, *pos, *nx; @@ -567,9 +603,11 @@ rexmit_timer(ulong vp) d = (struct aoedev *) vp; - /* timeout is always ~150% of the moving average */ - timeout = d->rttavg; - timeout += timeout >> 1; + /* timeout based on observed timings and variations */ + timeout = 2 * d->rttavg >> RTTSCALE; + timeout += 8 * d->rttdev >> RTTDSCALE; + if (timeout == 0) + timeout = 1; spin_lock_irqsave(&d->lock, flags); @@ -589,29 +627,12 @@ rexmit_timer(ulong vp) list_move_tail(pos, &flist); } } - /* window check */ - tt = d->targets; - te = tt + d->ntargets; - for (; tt < te && (t = *tt); tt++) { - if (t->nout == t->maxout - && t->maxout < t->nframes - && (jiffies - t->lastwadj)/HZ > 10) { - t->maxout++; - t->lastwadj = jiffies; - } - } - - if (!list_empty(&flist)) { /* retransmissions necessary */ - n = d->rttavg <<= 1; - if (n > MAXTIMER) - d->rttavg = MAXTIMER; - } /* process expired frames */ while (!list_empty(&flist)) { pos = flist.next; f = list_entry(pos, struct frame, head); - n = f->waited += timeout; + n = f->waited += tsince(f->tag); n /= HZ; if (n > aoe_deadsecs) { /* Waited too long. Device failure. @@ -620,18 +641,16 @@ rexmit_timer(ulong vp) */ list_splice(&flist, &d->factive[0]); aoedev_downdev(d); - break; + goto out; } - list_del(pos); t = f->t; if (n > aoe_deadsecs/2) d->htgt = t; /* see if another target can help */ - if (t->nout == t->maxout) { - if (t->maxout > 1) - t->maxout--; - t->lastwadj = jiffies; + if (t->maxout != 1) { + t->ssthresh = t->maxout / 2; + t->maxout = 1; } ifp = getif(t, f->skb->dev); @@ -640,9 +659,12 @@ rexmit_timer(ulong vp) ejectif(t, ifp); ifp = NULL; } - resend(d, f); + list_move_tail(pos, &d->rexmitq); + t->nout--; } + rexmit_deferred(d); +out: if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) { d->flags &= ~DEVFL_KICKME; d->blkq->request_fn(d->blkq); @@ -766,6 +788,7 @@ aoecmd_work(struct aoedev *d) { if (d->htgt && !sthtith(d)) return; + rexmit_deferred(d); while (aoecmd_ata_rw(d)) ; } @@ -868,26 +891,28 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) } static void -calc_rttavg(struct aoedev *d, int rtt) +calc_rttavg(struct aoedev *d, struct aoetgt *t, int rtt) { register long n; n = rtt; - if (n < 0) { - n = -rtt; - if (n < MINTIMER) - n = MINTIMER; - else if (n > MAXTIMER) - n = MAXTIMER; - d->mintimer += (n - d->mintimer) >> 1; - } else if (n < d->mintimer) - n = d->mintimer; - else if (n > MAXTIMER) - n = MAXTIMER; - /* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */ - n -= d->rttavg; - d->rttavg += n >> 2; + /* cf. Congestion Avoidance and Control, Jacobson & Karels, 1988 */ + n -= d->rttavg >> RTTSCALE; + d->rttavg += n; + if (n < 0) + n = -n; + n -= d->rttdev >> RTTDSCALE; + d->rttdev += n; + + if (!t || t->maxout >= t->nframes) + return; + if (t->maxout < t->ssthresh) + t->maxout += 1; + else if (t->nout == t->maxout && t->next_cwnd-- == 0) { + t->maxout += 1; + t->next_cwnd = t->maxout; + } } static struct aoetgt * @@ -1147,7 +1172,6 @@ aoecmd_ata_rsp(struct sk_buff *skb) struct aoedev *d; struct aoe_hdr *h; struct frame *f; - struct aoetgt *t; u32 n; ulong flags; char ebuf[128]; @@ -1168,23 +1192,28 @@ aoecmd_ata_rsp(struct sk_buff *skb) n = be32_to_cpu(get_unaligned(&h->tag)); f = getframe(d, n); - if (f == NULL) { - calc_rttavg(d, -tsince(n)); - spin_unlock_irqrestore(&d->lock, flags); - aoedev_put(d); - snprintf(ebuf, sizeof ebuf, - "%15s e%d.%d tag=%08x@%08lx\n", - "unexpected rsp", - get_unaligned_be16(&h->major), - h->minor, - get_unaligned_be32(&h->tag), - jiffies); - aoechr_error(ebuf); - return skb; + if (f) { + calc_rttavg(d, f->t, tsince(n)); + f->t->nout--; + } else { + f = getframe_deferred(d, n); + if (f) { + calc_rttavg(d, NULL, tsince(n)); + } else { + calc_rttavg(d, NULL, tsince(n)); + spin_unlock_irqrestore(&d->lock, flags); + aoedev_put(d); + snprintf(ebuf, sizeof(ebuf), + "%15s e%d.%d tag=%08x@%08lx\n", + "unexpected rsp", + get_unaligned_be16(&h->major), + h->minor, + get_unaligned_be32(&h->tag), + jiffies); + aoechr_error(ebuf); + return skb; + } } - t = f->t; - calc_rttavg(d, tsince(f->tag)); - t->nout--; aoecmd_work(d); spin_unlock_irqrestore(&d->lock, flags); @@ -1241,7 +1270,8 @@ aoecmd_ata_id(struct aoedev *d) skb->dev = t->ifp->nd; - d->rttavg = MAXTIMER; + d->rttavg = RTTAVG_INIT; + d->rttdev = RTTDEV_INIT; d->timer.function = rexmit_timer; return skb_clone(skb, GFP_ATOMIC); @@ -1273,7 +1303,7 @@ addtgt(struct aoedev *d, char *addr, ulong nframes) t->d = d; memcpy(t->addr, addr, sizeof t->addr); t->ifp = t->ifs; - t->maxout = t->nframes; + aoecmd_wreset(t); INIT_LIST_HEAD(&t->ffree); return *tt = t; } @@ -1382,7 +1412,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) if (t) { t->nframes = n; if (n < t->maxout) - t->maxout = n; + aoecmd_wreset(t); } else { t = addtgt(d, h->src, n); if (!t) @@ -1411,18 +1441,27 @@ bail: } } +void +aoecmd_wreset(struct aoetgt *t) +{ + t->maxout = 1; + t->ssthresh = t->nframes / 2; + t->next_cwnd = t->nframes; +} + void aoecmd_cleanslate(struct aoedev *d) { struct aoetgt **t, **te; - d->mintimer = MINTIMER; + d->rttavg = RTTAVG_INIT; + d->rttdev = RTTDEV_INIT; d->maxbcnt = 0; t = d->targets; te = t + NTARGETS; for (; t < te && *t; t++) - (*t)->maxout = (*t)->nframes; + aoecmd_wreset(*t); } void diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 63b26609400f..3c3aef208106 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -198,7 +198,7 @@ aoedev_downdev(struct aoedev *d) tt = d->targets; te = tt + NTARGETS; for (; tt < te && (t = *tt); tt++) { - t->maxout = t->nframes; + aoecmd_wreset(t); t->nout = 0; } @@ -391,10 +391,12 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) d->ref = 1; for (i = 0; i < NFACTIVE; i++) INIT_LIST_HEAD(&d->factive[i]); + INIT_LIST_HEAD(&d->rexmitq); d->sysminor = sysminor; d->aoemajor = maj; d->aoeminor = min; - d->mintimer = MINTIMER; + d->rttavg = RTTAVG_INIT; + d->rttdev = RTTDEV_INIT; d->next = devlist; devlist = d; out: From 2292a7e109d28ffd70ad060b241f9bd2a687dfa0 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:45 -0800 Subject: [PATCH 137/180] aoe: err device: include MAC addresses for unexpected responses The /dev/etherd/err character device provides low-level information about normal but sometimes interesting AoE command retransmits and "unexpected responses", i.e., responses for packets that have already been retransmitted. This change adds MAC addresses to the messages about unexpected responses, so that when they occur, it's more easy to determine the network paths to which they belong. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index f849fa2471ca..6ea27fd8954d 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -1204,12 +1204,14 @@ aoecmd_ata_rsp(struct sk_buff *skb) spin_unlock_irqrestore(&d->lock, flags); aoedev_put(d); snprintf(ebuf, sizeof(ebuf), - "%15s e%d.%d tag=%08x@%08lx\n", + "%15s e%d.%d tag=%08x@%08lx s=%pm d=%pm\n", "unexpected rsp", get_unaligned_be16(&h->major), h->minor, get_unaligned_be32(&h->tag), - jiffies); + jiffies, + h->src, + h->dst); aoechr_error(ebuf); return skb; } From 0d555ecfa468f6dc29697829844f2f79909e376f Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:47 -0800 Subject: [PATCH 138/180] aoe: manipulate aoedev network stats under lock With this bugfix in place the calculation of the criterion for "lateness" is performed under lock. Without the lock, there is a chance that one of the non-atomic operations performed on the round trip time statistics could be incomplete, such that an incorrect lateness criterion would be calculated. Without this change, the effect of the bug would be rare unecessary but benign retransmissions. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 6ea27fd8954d..9aefbe3957ca 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -603,14 +603,14 @@ rexmit_timer(ulong vp) d = (struct aoedev *) vp; + spin_lock_irqsave(&d->lock, flags); + /* timeout based on observed timings and variations */ timeout = 2 * d->rttavg >> RTTSCALE; timeout += 8 * d->rttdev >> RTTDSCALE; if (timeout == 0) timeout = 1; - spin_lock_irqsave(&d->lock, flags); - if (d->flags & DEVFL_TKILL) { spin_unlock_irqrestore(&d->lock, flags); return; From 5f0c9c48e7265039c3f945aaf44a1c6ae8adbd01 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:49 -0800 Subject: [PATCH 139/180] aoe: use high-resolution RTTs with fallback to low-res These changes improve the accuracy of the decision about whether it's time to retransmit an AoE command by using the microsecond-resolution gettimeofday instead of jiffies. Because the system time can jump suddenly, the decision reverts to using jiffies if the high-resolution time difference is relatively large. Otherwise the AoE targets could be considered failed inappropriately. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 9 +++--- drivers/block/aoe/aoecmd.c | 57 +++++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 9e884acd75fc..9fb68fc3b280 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -88,8 +88,7 @@ enum { TIMERTICK = HZ / 10, RTTSCALE = 8, RTTDSCALE = 3, - MAXTIMER = HZ << 1, - RTTAVG_INIT = HZ / 4 << RTTSCALE, + RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE, RTTDEV_INIT = RTTAVG_INIT / 4, }; @@ -106,6 +105,8 @@ struct buf { struct frame { struct list_head head; u32 tag; + struct timeval sent; /* high-res time packet was sent */ + u32 sent_jiffs; /* low-res jiffies-based sent time */ ulong waited; struct aoetgt *t; /* parent target I belong to */ sector_t lba; @@ -143,11 +144,11 @@ struct aoedev { struct aoedev *next; ulong sysminor; ulong aoemajor; + u32 rttavg; /* scaled AoE round trip time average */ + u32 rttdev; /* scaled round trip time mean deviation */ u16 aoeminor; u16 flags; u16 nopen; /* (bd_openers isn't available without sleeping) */ - u16 rttavg; /* scaled AoE round trip time average */ - u16 rttdev; /* scaled round trip time mean deviation */ u16 fw_ver; /* version of blade's firmware */ u16 lasttag; /* last tag sent */ u16 useme; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 9aefbe3957ca..a99220ad6262 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -387,6 +387,8 @@ aoecmd_ata_rw(struct aoedev *d) skb->dev = t->ifp->nd; skb = skb_clone(skb, GFP_ATOMIC); if (skb) { + do_gettimeofday(&f->sent); + f->sent_jiffs = (u32) jiffies; __skb_queue_head_init(&queue); __skb_queue_tail(&queue, skb); aoenet_xmit(&queue); @@ -475,11 +477,45 @@ resend(struct aoedev *d, struct frame *f) skb = skb_clone(skb, GFP_ATOMIC); if (skb == NULL) return; + do_gettimeofday(&f->sent); + f->sent_jiffs = (u32) jiffies; __skb_queue_head_init(&queue); __skb_queue_tail(&queue, skb); aoenet_xmit(&queue); } +static int +tsince_hr(struct frame *f) +{ + struct timeval now; + int n; + + do_gettimeofday(&now); + n = now.tv_usec - f->sent.tv_usec; + n += (now.tv_sec - f->sent.tv_sec) * USEC_PER_SEC; + + if (n < 0) + n = -n; + + /* For relatively long periods, use jiffies to avoid + * discrepancies caused by updates to the system time. + * + * On system with HZ of 1000, 32-bits is over 49 days + * worth of jiffies, or over 71 minutes worth of usecs. + * + * Jiffies overflow is handled by subtraction of unsigned ints: + * (gdb) print (unsigned) 2 - (unsigned) 0xfffffffe + * $3 = 4 + * (gdb) + */ + if (n > USEC_PER_SEC / 4) { + n = ((u32) jiffies) - f->sent_jiffs; + n *= USEC_PER_SEC / HZ; + } + + return n; +} + static int tsince(u32 tag) { @@ -489,7 +525,7 @@ tsince(u32 tag) n -= tag & 0xffff; if (n < 0) n += 1<<16; - return n; + return jiffies_to_usecs(n + 1); } static struct aoeif * @@ -552,6 +588,7 @@ sthtith(struct aoedev *d) nf->bv = f->bv; nf->bv_off = f->bv_off; nf->waited = 0; + nf->sent_jiffs = f->sent_jiffs; f->skb = skb; aoe_freetframe(f); ht->nout--; @@ -621,7 +658,7 @@ rexmit_timer(ulong vp) head = &d->factive[i]; list_for_each_safe(pos, nx, head) { f = list_entry(pos, struct frame, head); - if (tsince(f->tag) < timeout) + if (tsince_hr(f) < timeout) break; /* end of expired frames */ /* move to flist for later processing */ list_move_tail(pos, &flist); @@ -632,8 +669,8 @@ rexmit_timer(ulong vp) while (!list_empty(&flist)) { pos = flist.next; f = list_entry(pos, struct frame, head); - n = f->waited += tsince(f->tag); - n /= HZ; + n = f->waited += tsince_hr(f); + n /= USEC_PER_SEC; if (n > aoe_deadsecs) { /* Waited too long. Device failure. * Hang all frames on first hash bucket for downdev @@ -1193,12 +1230,12 @@ aoecmd_ata_rsp(struct sk_buff *skb) n = be32_to_cpu(get_unaligned(&h->tag)); f = getframe(d, n); if (f) { - calc_rttavg(d, f->t, tsince(n)); + calc_rttavg(d, f->t, tsince_hr(f)); f->t->nout--; } else { f = getframe_deferred(d, n); if (f) { - calc_rttavg(d, NULL, tsince(n)); + calc_rttavg(d, NULL, tsince_hr(f)); } else { calc_rttavg(d, NULL, tsince(n)); spin_unlock_irqrestore(&d->lock, flags); @@ -1276,7 +1313,13 @@ aoecmd_ata_id(struct aoedev *d) d->rttdev = RTTDEV_INIT; d->timer.function = rexmit_timer; - return skb_clone(skb, GFP_ATOMIC); + skb = skb_clone(skb, GFP_ATOMIC); + if (skb) { + do_gettimeofday(&f->sent); + f->sent_jiffs = (u32) jiffies; + } + + return skb; } static struct aoetgt * From 3fc9b032489d365957ce531d32e225b2d0b3ed11 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:51 -0800 Subject: [PATCH 140/180] aoe: commands in retransmit queue use new destination on failure When one remote MAC address isn't working as a destination for AoE commands, the frames used to track information associated with the AoE commands are moved to a new aoetgt (defined by the tuple of {AoE major, AoE minor, target MAC address}). This patch makes sure that the frames on the queue for retransmits that need to be done are updated to use the new destination, so that retransmits will be sent through a working network path. Without this change, packets on the retransmit queue will be needlessly retransmitted to the unresponsive destination MAC, possibly causing premature target failure before there's time for the retransmit timer to run again, decide to retransmit again, and finally update the destination to a working MAC address on the AoE target. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 1 + drivers/block/aoe/aoecmd.c | 75 +++++++++++++++++++++++++++----------- drivers/block/aoe/aoedev.c | 32 ++++++++++------ 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 9fb68fc3b280..c253cca4985b 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -108,6 +108,7 @@ struct frame { struct timeval sent; /* high-res time packet was sent */ u32 sent_jiffs; /* low-res jiffies-based sent time */ ulong waited; + ulong waited_total; struct aoetgt *t; /* parent target I belong to */ sector_t lba; struct sk_buff *skb; /* command skb freed on module exit */ diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index a99220ad6262..d9bc6ff56f49 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -352,6 +352,7 @@ aoecmd_ata_rw(struct aoedev *d) fhash(f); t->nout++; f->waited = 0; + f->waited_total = 0; f->buf = buf; f->bcnt = bcnt; f->lba = buf->sector; @@ -556,46 +557,69 @@ ejectif(struct aoetgt *t, struct aoeif *ifp) dev_put(nd); } +static struct frame * +reassign_frame(struct list_head *pos) +{ + struct frame *f; + struct frame *nf; + struct sk_buff *skb; + + f = list_entry(pos, struct frame, head); + nf = newframe(f->t->d); + if (!nf) + return NULL; + + list_del(pos); + + skb = nf->skb; + nf->skb = f->skb; + nf->buf = f->buf; + nf->bcnt = f->bcnt; + nf->lba = f->lba; + nf->bv = f->bv; + nf->bv_off = f->bv_off; + nf->waited = 0; + nf->waited_total = f->waited_total; + nf->sent = f->sent; + f->skb = skb; + aoe_freetframe(f); + f->t->nout--; + nf->t->nout++; + + return nf; +} + static int sthtith(struct aoedev *d) { struct frame *f, *nf; struct list_head *nx, *pos, *head; - struct sk_buff *skb; struct aoetgt *ht = d->htgt; int i; + /* look through the active and pending retransmit frames */ for (i = 0; i < NFACTIVE; i++) { head = &d->factive[i]; list_for_each_safe(pos, nx, head) { f = list_entry(pos, struct frame, head); if (f->t != ht) continue; - - nf = newframe(d); + nf = reassign_frame(pos); if (!nf) return 0; - - /* remove frame from active list */ - list_del(pos); - - /* reassign all pertinent bits to new outbound frame */ - skb = nf->skb; - nf->skb = f->skb; - nf->buf = f->buf; - nf->bcnt = f->bcnt; - nf->lba = f->lba; - nf->bv = f->bv; - nf->bv_off = f->bv_off; - nf->waited = 0; - nf->sent_jiffs = f->sent_jiffs; - f->skb = skb; - aoe_freetframe(f); - ht->nout--; - nf->t->nout++; resend(d, nf); } } + head = &d->rexmitq; + list_for_each_safe(pos, nx, head) { + f = list_entry(pos, struct frame, head); + if (f->t != ht) + continue; + nf = reassign_frame(pos); + if (!nf) + return 0; + resend(d, nf); + } /* We've cleaned up the outstanding so take away his * interfaces so he won't be used. We should remove him from * the target array here, but cleaning up a target is @@ -612,6 +636,7 @@ rexmit_deferred(struct aoedev *d) struct aoetgt *t; struct frame *f; struct list_head *pos, *nx, *head; + int since; head = &d->rexmitq; list_for_each_safe(pos, nx, head) { @@ -621,6 +646,9 @@ rexmit_deferred(struct aoedev *d) continue; list_del(pos); t->nout++; + since = tsince_hr(f); + f->waited += since; + f->waited_total += since; resend(d, f); } } @@ -637,6 +665,7 @@ rexmit_timer(ulong vp) register long timeout; ulong flags, n; int i; + int since; d = (struct aoedev *) vp; @@ -669,7 +698,8 @@ rexmit_timer(ulong vp) while (!list_empty(&flist)) { pos = flist.next; f = list_entry(pos, struct frame, head); - n = f->waited += tsince_hr(f); + since = tsince_hr(f); + n = f->waited_total + since; n /= USEC_PER_SEC; if (n > aoe_deadsecs) { /* Waited too long. Device failure. @@ -1301,6 +1331,7 @@ aoecmd_ata_id(struct aoedev *d) fhash(f); t->nout++; f->waited = 0; + f->waited_total = 0; /* set up ata header */ ah->scnt = 1; diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 3c3aef208106..91f7c99eb2a9 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -170,30 +170,40 @@ aoe_failip(struct aoedev *d) aoe_end_request(d, rq, 0); } +static void +downdev_frame(struct list_head *pos) +{ + struct frame *f; + + f = list_entry(pos, struct frame, head); + list_del(pos); + if (f->buf) { + f->buf->nframesout--; + aoe_failbuf(f->t->d, f->buf); + } + aoe_freetframe(f); +} + void aoedev_downdev(struct aoedev *d) { struct aoetgt *t, **tt, **te; - struct frame *f; struct list_head *head, *pos, *nx; struct request *rq; int i; d->flags &= ~DEVFL_UP; - /* clean out active buffers */ + /* clean out active and to-be-retransmitted buffers */ for (i = 0; i < NFACTIVE; i++) { head = &d->factive[i]; - list_for_each_safe(pos, nx, head) { - f = list_entry(pos, struct frame, head); - list_del(pos); - if (f->buf) { - f->buf->nframesout--; - aoe_failbuf(d, f->buf); - } - aoe_freetframe(f); - } + list_for_each_safe(pos, nx, head) + downdev_frame(pos); } + head = &d->rexmitq; + list_for_each_safe(pos, nx, head) + downdev_frame(pos); + /* reset window dressings */ tt = d->targets; te = tt + NTARGETS; From 519b77b0320fabb07fe54a300876dfff5f96d233 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:53 -0800 Subject: [PATCH 141/180] aoe: update driver-internal version to 64+ Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index c253cca4985b..9655ce38e6eb 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,6 @@ + /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "60" +#define VERSION "64+" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" From fe7252bf511d682a977dd096da140accce1b128b Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:55 -0800 Subject: [PATCH 142/180] aoe: copy fallback timing information on destination failover Commit f3b8e07af774 ("aoe: commands in retransmit queue use new destination on failure") omits the copying of the coarse-grained time when an AoE command was sent during the failover from one destination MAC address on the AoE target to another. The coarse-grained timing is only used when the system time changes or an unlikely length of time has passed since the sending of the AoE command. Users will not be impacted unless their system clock is very inaccurate or something unusual (e.g., 10 GbE link reset) happens during the period when the aoe driver is handling the failure of a port on the AoE target. Being effected will mean that an AoE target could be considered "down" too eagerly. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index d9bc6ff56f49..d609c47c599e 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -581,6 +581,7 @@ reassign_frame(struct list_head *pos) nf->waited = 0; nf->waited_total = f->waited_total; nf->sent = f->sent; + nf->sent_jiffs = f->sent_jiffs; f->skb = skb; aoe_freetframe(f); f->t->nout--; From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:03:58 -0800 Subject: [PATCH 143/180] aoe: remove vestigial request queue allocation Before the aoe driver was an I/O request handler, it was a make_request-style block driver. Even so, there was a problem where sysfs expected a request queue to exist, so one was provided in commit 7135a71b19be ("aoe: allocate unused request_queue for sysfs"). During the transition to the request-handler style, a patch was merged that was based on a driver without the noop queue, and the noop queue remained in place after the patch was merged, even though a new functional queue was introduced by the patch, allocated through blk_init_queue. The user impact is a memory leak proportional to the number of AoE targets discovered. This patch removes the memory leak and cleans up vestiges of the old do-nothing queue from the aoeblk_gdalloc function. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoeblk.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 7ba0fcf7b06b..57ac72c1715a 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -278,18 +278,12 @@ aoeblk_gdalloc(void *vp) if (q == NULL) { pr_err("aoe: cannot allocate block queue for %ld.%d\n", d->aoemajor, d->aoeminor); - mempool_destroy(mp); - goto err_disk; + goto err_mempool; } - d->blkq = blk_alloc_queue(GFP_KERNEL); - if (!d->blkq) - goto err_mempool; - d->blkq->backing_dev_info.name = "aoe"; - if (bdi_init(&d->blkq->backing_dev_info)) - goto err_blkq; spin_lock_irqsave(&d->lock, flags); - blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); + blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); + q->backing_dev_info.name = "aoe"; q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; d->bufpool = mp; d->blkq = gd->queue = q; @@ -314,11 +308,8 @@ aoeblk_gdalloc(void *vp) aoedisk_add_sysfs(d); return; -err_blkq: - blk_cleanup_queue(d->blkq); - d->blkq = NULL; err_mempool: - mempool_destroy(d->bufpool); + mempool_destroy(mp); err_disk: put_disk(gd); err: From 7b6ccc5f975f68d96f941c67eab001b390a7cd1a Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:00 -0800 Subject: [PATCH 144/180] aoe: increase default cap on outstanding AoE commands in the network The aoe driver will never be waiting for more than aoe_maxout AoE commands from a given remote network port on an AoE target. Increasing the cap increases performance. Users can tighten the setting to reduce the amount of memory used for handling AoE traffic or the network bandwidth used for AoE. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index d609c47c599e..53b98690d9b0 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -29,7 +29,7 @@ static int aoe_deadsecs = 60 * 3; module_param(aoe_deadsecs, int, 0644); MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); -static int aoe_maxout = 16; +static int aoe_maxout = 64; module_param(aoe_maxout, int, 0644); MODULE_PARM_DESC(aoe_maxout, "Only aoe_maxout outstanding packets for every MAC on eX.Y."); From 72837600ee8b0d09618f7fcbe36aab08c3ba8890 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:01 -0800 Subject: [PATCH 145/180] aoe: cleanup: correct comment for aoetgt nout A misplaced comment was attached to the nout member of the aoetgt. This change corrects the comment. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 9655ce38e6eb..bfd765cf0eb7 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -133,7 +133,7 @@ struct aoetgt { struct list_head ffree; /* list of free frames */ struct aoeif ifs[NAOEIFS]; struct aoeif *ifp; /* current aoeif in use */ - ushort nout; /* value of nout when skb was sent */ + ushort nout; /* number of AoE commands outstanding */ ushort maxout; /* current value for max outstanding */ ushort next_cwnd; /* incr maxout after decrementing to zero */ ushort ssthresh; /* slow start threshold */ From 60116cf77310c10b573552e4d700c270ddadba76 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:02 -0800 Subject: [PATCH 146/180] aoe: remove call to request handler from I/O completion There is no need to call the request handler function in the I/O completion routine. The user impact of not doing it is a more "nice" aoe driver that is less susceptible to causing soft lockups. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 53b98690d9b0..391dd8ee2009 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -1139,8 +1139,6 @@ badrsp: if (buf && --buf->nframesout == 0 && buf->resid == 0) aoe_end_buf(d, buf); - aoecmd_work(d); - spin_unlock_irq(&d->lock); aoedev_put(d); dev_kfree_skb(skb); From e0b2bbab0b569590e27161290f6ea549248356df Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:03 -0800 Subject: [PATCH 147/180] aoe: make error messages more specific in static minor allocation For some special-purpose systems where udev isn't present, static allocation of minor numbers is desirable. This update distinguishes different failure scenarios, to help the user understand what went wrong. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoedev.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 91f7c99eb2a9..88ccd6d83c39 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -69,25 +69,34 @@ minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin) NPERSHELF = 16, }; + if (aoemin >= NPERSHELF) { + pr_err("aoe: %s %d slots per shelf\n", + "static minor device numbers support only", + NPERSHELF); + error = -1; + goto out; + } + n = aoemaj * NPERSHELF + aoemin; - if (aoemin >= NPERSHELF || n >= N_DEVS) { + if (n >= N_DEVS) { pr_err("aoe: %s with e%ld.%d\n", "cannot use static minor device numbers", aoemaj, aoemin); error = -1; - } else { - spin_lock_irqsave(&used_minors_lock, flags); - if (test_bit(n, used_minors)) { - pr_err("aoe: %s %lu\n", - "existing device already has static minor number", - n); - error = -1; - } else - set_bit(n, used_minors); - spin_unlock_irqrestore(&used_minors_lock, flags); + goto out; } + spin_lock_irqsave(&used_minors_lock, flags); + if (test_bit(n, used_minors)) { + pr_err("aoe: %s %lu\n", + "existing device already has static minor number", + n); + error = -1; + } else + set_bit(n, used_minors); + spin_unlock_irqrestore(&used_minors_lock, flags); *sysminor = n; +out: return error; } From 10935d052eef9441a551571ff5853f84a00b2fd4 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:04 -0800 Subject: [PATCH 148/180] aoe: initialize sysminor to avoid compiler warning Because the minor_get and related functions use the return values for errors, the compiler doesn't know that sysminor will always either 1) be initialized in aoedev_by_aoeaddr by the call to minor_get, or 2) be unused as the "goto out" is executed. This patch avoids the compiler warning. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoedev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 88ccd6d83c39..80b3d3ea10c3 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -383,7 +383,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) struct aoedev *d; int i; ulong flags; - ulong sysminor; + ulong sysminor = 0; spin_lock_irqsave(&devlist_lock, flags); From b91316f2b7bc0b1d128a9890a2a4895f7e1c74fc Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:06 -0800 Subject: [PATCH 149/180] aoe: return real minor number for static minors The value returned by the static minor device number number allocator is the real minor number, so it must be multiplied by the supported number of partitions per aoedev. Without this fix the support for systems without udev is incomplete, and the few users of aoe on such systems will have surprising results when device nodes names do not match the AoE target. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoedev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 80b3d3ea10c3..aaaea662a72a 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -95,7 +95,7 @@ minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin) } else set_bit(n, used_minors); spin_unlock_irqrestore(&used_minors_lock, flags); - *sysminor = n; + *sysminor = n * AOE_PARTITIONS; out: return error; } From bbb44e30d07fdc111e34a5ec935b57521cea9499 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:08 -0800 Subject: [PATCH 150/180] aoe: improve handling of misbehaving network paths An AoE target can have multiple network ports used for AoE, and in the aoe driver, those are tracked by the aoetgt struct. These changes allow the aoe driver to handle network paths, or aoetgts, that are not working well, compared to the others. Paths that do not get responses despite the retransmission of AoE commands are marked as "tainted", and non-tainted paths are preferred. Meanwhile, the aoe driver attempts to "probe" the tainted path in the background by issuing reads of LBA 0 that are padded out to full (possibly jumbo-frame) size. If the probes get responses, then the path is "redeemed", and its taint is removed. This mechanism has been shown to be helpful in transparently handling and recovering from real-world network "brown outs" in ways that the earlier "shoot the help-needing target in the head" mechanism could not. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 11 +- drivers/block/aoe/aoecmd.c | 377 +++++++++++++++++++++++++------------ drivers/block/aoe/aoedev.c | 1 - 3 files changed, 268 insertions(+), 121 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index bfd765cf0eb7..b6d2b16358be 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -91,6 +91,9 @@ enum { RTTDSCALE = 3, RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE, RTTDEV_INIT = RTTAVG_INIT / 4, + + HARD_SCORN_SECS = 10, /* try another remote port after this */ + MAX_TAINT = 1000, /* cap on aoetgt taint */ }; struct buf { @@ -103,6 +106,10 @@ struct buf { struct request *rq; }; +enum frame_flags { + FFL_PROBE = 1, +}; + struct frame { struct list_head head; u32 tag; @@ -118,6 +125,7 @@ struct frame { struct bio_vec *bv; ulong bcnt; ulong bv_off; + char flags; }; struct aoeif { @@ -138,8 +146,10 @@ struct aoetgt { ushort next_cwnd; /* incr maxout after decrementing to zero */ ushort ssthresh; /* slow start threshold */ ulong falloc; /* number of allocated frames */ + int taint; /* how much we want to avoid this aoetgt */ int minbcnt; int wpkts, rpkts; + char nout_probes; }; struct aoedev { @@ -174,7 +184,6 @@ struct aoedev { struct list_head rexmitq; /* deferred retransmissions */ struct aoetgt *targets[NTARGETS]; struct aoetgt **tgt; /* target in use when working */ - struct aoetgt *htgt; /* target needing rexmit assistance */ ulong ntargets; ulong kicked; char ident[512]; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 391dd8ee2009..000f7fb48841 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -22,6 +22,7 @@ #define MAXIOC (8192) /* default meant to avoid most soft lockups */ static void ktcomplete(struct frame *, struct sk_buff *); +static int count_targets(struct aoedev *d, int *untainted); static struct buf *nextbuf(struct aoedev *); @@ -43,6 +44,8 @@ static struct { spinlock_t lock; } iocq; +static struct page *empty_page; + static struct sk_buff * new_skb(ulong len) { @@ -179,8 +182,10 @@ aoe_freetframe(struct frame *f) t = f->t; f->buf = NULL; + f->lba = 0; f->bv = NULL; f->r_skb = NULL; + f->flags = 0; list_add(&f->head, &t->ffree); } @@ -234,20 +239,25 @@ newframe(struct aoedev *d) struct frame *f; struct aoetgt *t, **tt; int totout = 0; + int use_tainted; + int has_untainted; if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ printk(KERN_ERR "aoe: NULL TARGETS!\n"); return NULL; } tt = d->tgt; /* last used target */ - for (;;) { + for (use_tainted = 0, has_untainted = 0;;) { tt++; if (tt >= &d->targets[NTARGETS] || !*tt) tt = d->targets; t = *tt; - totout += t->nout; + if (!t->taint) { + has_untainted = 1; + totout += t->nout; + } if (t->nout < t->maxout - && t != d->htgt + && (use_tainted || !t->taint) && t->ifp->nd) { f = newtframe(d, t); if (f) { @@ -256,8 +266,12 @@ newframe(struct aoedev *d) return f; } } - if (tt == d->tgt) /* we've looped and found nada */ - break; + if (tt == d->tgt) { /* we've looped and found nada */ + if (!use_tainted && !has_untainted) + use_tainted = 1; + else + break; + } } if (totout == 0) { d->kicked++; @@ -294,21 +308,68 @@ fhash(struct frame *f) list_add_tail(&f->head, &d->factive[n]); } +static void +ata_rw_frameinit(struct frame *f) +{ + struct aoetgt *t; + struct aoe_hdr *h; + struct aoe_atahdr *ah; + struct sk_buff *skb; + char writebit, extbit; + + skb = f->skb; + h = (struct aoe_hdr *) skb_mac_header(skb); + ah = (struct aoe_atahdr *) (h + 1); + skb_put(skb, sizeof(*h) + sizeof(*ah)); + memset(h, 0, skb->len); + + writebit = 0x10; + extbit = 0x4; + + t = f->t; + f->tag = aoehdr_atainit(t->d, t, h); + fhash(f); + t->nout++; + f->waited = 0; + f->waited_total = 0; + if (f->buf) + f->lba = f->buf->sector; + + /* set up ata header */ + ah->scnt = f->bcnt >> 9; + put_lba(ah, f->lba); + if (t->d->flags & DEVFL_EXT) { + ah->aflags |= AOEAFL_EXT; + } else { + extbit = 0; + ah->lba3 &= 0x0f; + ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ + } + if (f->buf && bio_data_dir(f->buf->bio) == WRITE) { + skb_fillup(skb, f->bv, f->bv_off, f->bcnt); + ah->aflags |= AOEAFL_WRITE; + skb->len += f->bcnt; + skb->data_len = f->bcnt; + skb->truesize += f->bcnt; + t->wpkts++; + } else { + t->rpkts++; + writebit = 0; + } + + ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; + skb->dev = t->ifp->nd; +} + static int aoecmd_ata_rw(struct aoedev *d) { struct frame *f; - struct aoe_hdr *h; - struct aoe_atahdr *ah; struct buf *buf; struct aoetgt *t; struct sk_buff *skb; struct sk_buff_head queue; ulong bcnt, fbcnt; - char writebit, extbit; - - writebit = 0x10; - extbit = 0x4; buf = nextbuf(d); if (buf == NULL) @@ -343,50 +404,15 @@ aoecmd_ata_rw(struct aoedev *d) } while (fbcnt); /* initialize the headers & frame */ - skb = f->skb; - h = (struct aoe_hdr *) skb_mac_header(skb); - ah = (struct aoe_atahdr *) (h+1); - skb_put(skb, sizeof *h + sizeof *ah); - memset(h, 0, skb->len); - f->tag = aoehdr_atainit(d, t, h); - fhash(f); - t->nout++; - f->waited = 0; - f->waited_total = 0; f->buf = buf; f->bcnt = bcnt; - f->lba = buf->sector; - - /* set up ata header */ - ah->scnt = bcnt >> 9; - put_lba(ah, buf->sector); - if (d->flags & DEVFL_EXT) { - ah->aflags |= AOEAFL_EXT; - } else { - extbit = 0; - ah->lba3 &= 0x0f; - ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ - } - if (bio_data_dir(buf->bio) == WRITE) { - skb_fillup(skb, f->bv, f->bv_off, bcnt); - ah->aflags |= AOEAFL_WRITE; - skb->len += bcnt; - skb->data_len = bcnt; - skb->truesize += bcnt; - t->wpkts++; - } else { - t->rpkts++; - writebit = 0; - } - - ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; + ata_rw_frameinit(f); /* mark all tracking fields and load out */ buf->nframesout += 1; buf->sector += bcnt >> 9; - skb->dev = t->ifp->nd; - skb = skb_clone(skb, GFP_ATOMIC); + skb = skb_clone(f->skb, GFP_ATOMIC); if (skb) { do_gettimeofday(&f->sent); f->sent_jiffs = (u32) jiffies; @@ -462,11 +488,14 @@ resend(struct aoedev *d, struct frame *f) h = (struct aoe_hdr *) skb_mac_header(skb); ah = (struct aoe_atahdr *) (h+1); - snprintf(buf, sizeof buf, - "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", - "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n, - h->src, h->dst, t->nout); - aoechr_error(buf); + if (!(f->flags & FFL_PROBE)) { + snprintf(buf, sizeof(buf), + "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", + "retransmit", d->aoemajor, d->aoeminor, + f->tag, jiffies, n, + h->src, h->dst, t->nout); + aoechr_error(buf); + } f->tag = n; fhash(f); @@ -558,18 +587,18 @@ ejectif(struct aoetgt *t, struct aoeif *ifp) } static struct frame * -reassign_frame(struct list_head *pos) +reassign_frame(struct frame *f) { - struct frame *f; struct frame *nf; struct sk_buff *skb; - f = list_entry(pos, struct frame, head); nf = newframe(f->t->d); if (!nf) return NULL; - - list_del(pos); + if (nf->t == f->t) { + aoe_freetframe(nf); + return NULL; + } skb = nf->skb; nf->skb = f->skb; @@ -583,52 +612,67 @@ reassign_frame(struct list_head *pos) nf->sent = f->sent; nf->sent_jiffs = f->sent_jiffs; f->skb = skb; - aoe_freetframe(f); - f->t->nout--; - nf->t->nout++; return nf; } -static int -sthtith(struct aoedev *d) +static void +probe(struct aoetgt *t) { - struct frame *f, *nf; - struct list_head *nx, *pos, *head; - struct aoetgt *ht = d->htgt; - int i; + struct aoedev *d; + struct frame *f; + struct sk_buff *skb; + struct sk_buff_head queue; + size_t n, m; + int frag; - /* look through the active and pending retransmit frames */ - for (i = 0; i < NFACTIVE; i++) { - head = &d->factive[i]; - list_for_each_safe(pos, nx, head) { - f = list_entry(pos, struct frame, head); - if (f->t != ht) - continue; - nf = reassign_frame(pos); - if (!nf) - return 0; - resend(d, nf); - } + d = t->d; + f = newtframe(d, t); + if (!f) { + pr_err("%s %pm for e%ld.%d: %s\n", + "aoe: cannot probe remote address", + t->addr, + (long) d->aoemajor, d->aoeminor, + "no frame available"); + return; } - head = &d->rexmitq; - list_for_each_safe(pos, nx, head) { - f = list_entry(pos, struct frame, head); - if (f->t != ht) - continue; - nf = reassign_frame(pos); - if (!nf) - return 0; - resend(d, nf); + f->flags |= FFL_PROBE; + ifrotate(t); + f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT; + ata_rw_frameinit(f); + skb = f->skb; + for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) { + if (n < PAGE_SIZE) + m = n; + else + m = PAGE_SIZE; + skb_fill_page_desc(skb, frag, empty_page, 0, m); } - /* We've cleaned up the outstanding so take away his - * interfaces so he won't be used. We should remove him from - * the target array here, but cleaning up a target is - * involved. PUNT! - */ - memset(ht->ifs, 0, sizeof ht->ifs); - d->htgt = NULL; - return 1; + skb->len += f->bcnt; + skb->data_len = f->bcnt; + skb->truesize += f->bcnt; + + skb = skb_clone(f->skb, GFP_ATOMIC); + if (skb) { + do_gettimeofday(&f->sent); + f->sent_jiffs = (u32) jiffies; + __skb_queue_head_init(&queue); + __skb_queue_tail(&queue, skb); + aoenet_xmit(&queue); + } +} + +static long +rto(struct aoedev *d) +{ + long t; + + t = 2 * d->rttavg >> RTTSCALE; + t += 8 * d->rttdev >> RTTDSCALE; + if (t == 0) + t = 1; + + return t; } static void @@ -636,17 +680,53 @@ rexmit_deferred(struct aoedev *d) { struct aoetgt *t; struct frame *f; + struct frame *nf; struct list_head *pos, *nx, *head; int since; + int untainted; + + count_targets(d, &untainted); head = &d->rexmitq; list_for_each_safe(pos, nx, head) { f = list_entry(pos, struct frame, head); t = f->t; + if (t->taint) { + if (!(f->flags & FFL_PROBE)) { + nf = reassign_frame(f); + if (nf) { + if (t->nout_probes == 0 + && untainted > 0) { + probe(t); + t->nout_probes++; + } + list_replace(&f->head, &nf->head); + pos = &nf->head; + aoe_freetframe(f); + f = nf; + t = f->t; + } + } else if (untainted < 1) { + /* don't probe w/o other untainted aoetgts */ + goto stop_probe; + } else if (tsince_hr(f) < t->taint * rto(d)) { + /* reprobe slowly when taint is high */ + continue; + } + } else if (f->flags & FFL_PROBE) { +stop_probe: /* don't probe untainted aoetgts */ + list_del(pos); + aoe_freetframe(f); + /* leaving d->kicked, because this is routine */ + f->t->d->flags |= DEVFL_KICKME; + continue; + } if (t->nout >= t->maxout) continue; list_del(pos); t->nout++; + if (f->flags & FFL_PROBE) + t->nout_probes++; since = tsince_hr(f); f->waited += since; f->waited_total += since; @@ -654,6 +734,36 @@ rexmit_deferred(struct aoedev *d) } } +/* An aoetgt accumulates demerits quickly, and successful + * probing redeems the aoetgt slowly. + */ +static void +scorn(struct aoetgt *t) +{ + int n; + + n = t->taint++; + t->taint += t->taint * 2; + if (n > t->taint) + t->taint = n; + if (t->taint > MAX_TAINT) + t->taint = MAX_TAINT; +} + +static int +count_targets(struct aoedev *d, int *untainted) +{ + int i, good; + + for (i = good = 0; i < d->ntargets && d->targets[i]; ++i) + if (d->targets[i]->taint == 0) + good++; + + if (untainted) + *untainted = good; + return i; +} + static void rexmit_timer(ulong vp) { @@ -666,6 +776,7 @@ rexmit_timer(ulong vp) register long timeout; ulong flags, n; int i; + int utgts; /* number of aoetgt descriptors (not slots) */ int since; d = (struct aoedev *) vp; @@ -673,10 +784,9 @@ rexmit_timer(ulong vp) spin_lock_irqsave(&d->lock, flags); /* timeout based on observed timings and variations */ - timeout = 2 * d->rttavg >> RTTSCALE; - timeout += 8 * d->rttdev >> RTTDSCALE; - if (timeout == 0) - timeout = 1; + timeout = rto(d); + + utgts = count_targets(d, NULL); if (d->flags & DEVFL_TKILL) { spin_unlock_irqrestore(&d->lock, flags); @@ -702,7 +812,7 @@ rexmit_timer(ulong vp) since = tsince_hr(f); n = f->waited_total + since; n /= USEC_PER_SEC; - if (n > aoe_deadsecs) { + if (n > aoe_deadsecs && !(f->flags & FFL_PROBE)) { /* Waited too long. Device failure. * Hang all frames on first hash bucket for downdev * to clean up. @@ -713,19 +823,26 @@ rexmit_timer(ulong vp) } t = f->t; - if (n > aoe_deadsecs/2) - d->htgt = t; /* see if another target can help */ + n = f->waited + since; + n /= USEC_PER_SEC; + if (aoe_deadsecs && utgts > 0 + && (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS)) + scorn(t); /* avoid this target */ if (t->maxout != 1) { t->ssthresh = t->maxout / 2; t->maxout = 1; } - ifp = getif(t, f->skb->dev); - if (ifp && ++ifp->lost > (t->nframes << 1) - && (ifp != t->ifs || t->ifs[1].nd)) { - ejectif(t, ifp); - ifp = NULL; + if (f->flags & FFL_PROBE) { + t->nout_probes--; + } else { + ifp = getif(t, f->skb->dev); + if (ifp && ++ifp->lost > (t->nframes << 1) + && (ifp != t->ifs || t->ifs[1].nd)) { + ejectif(t, ifp); + ifp = NULL; + } } list_move_tail(pos, &d->rexmitq); t->nout--; @@ -733,7 +850,7 @@ rexmit_timer(ulong vp) rexmit_deferred(d); out: - if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) { + if ((d->flags & DEVFL_KICKME) && d->blkq) { d->flags &= ~DEVFL_KICKME; d->blkq->request_fn(d->blkq); } @@ -854,8 +971,6 @@ nextbuf(struct aoedev *d) void aoecmd_work(struct aoedev *d) { - if (d->htgt && !sthtith(d)) - return; rexmit_deferred(d); while (aoecmd_ata_rw(d)) ; @@ -1065,19 +1180,22 @@ ktiocomplete(struct frame *f) struct aoeif *ifp; struct aoedev *d; long n; + int untainted; if (f == NULL) return; t = f->t; d = t->d; + skb = f->r_skb; + buf = f->buf; + if (f->flags & FFL_PROBE) + goto out; + if (!skb) /* just fail the buf. */ + goto noskb; hout = (struct aoe_hdr *) skb_mac_header(f->skb); ahout = (struct aoe_atahdr *) (hout+1); - buf = f->buf; - skb = f->r_skb; - if (skb == NULL) - goto noskb; /* just fail the buf. */ hin = (struct aoe_hdr *) skb->data; skb_pull(skb, sizeof(*hin)); @@ -1089,7 +1207,7 @@ ktiocomplete(struct frame *f) d->aoemajor, d->aoeminor); noskb: if (buf) clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); - goto badrsp; + goto out; } n = ahout->scnt << 9; @@ -1109,8 +1227,6 @@ noskb: if (buf) ifp = getif(t, skb->dev); if (ifp) ifp->lost = 0; - if (d->htgt == t) /* I'll help myself, thank you. */ - d->htgt = NULL; spin_unlock_irq(&d->lock); break; case ATA_CMD_ID_ATA: @@ -1131,8 +1247,17 @@ noskb: if (buf) be16_to_cpu(get_unaligned(&hin->major)), hin->minor); } -badrsp: +out: spin_lock_irq(&d->lock); + if (t->taint > 0 + && --t->taint > 0 + && t->nout_probes == 0) { + count_targets(d, &untainted); + if (untainted > 0) { + probe(t); + t->nout_probes++; + } + } aoe_freetframe(f); @@ -1261,6 +1386,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (f) { calc_rttavg(d, f->t, tsince_hr(f)); f->t->nout--; + if (f->flags & FFL_PROBE) + f->t->nout_probes--; } else { f = getframe_deferred(d, n); if (f) { @@ -1379,6 +1506,7 @@ addtgt(struct aoedev *d, char *addr, ulong nframes) memcpy(t->addr, addr, sizeof t->addr); t->ifp = t->ifs; aoecmd_wreset(t); + t->maxout = t->nframes / 2; INIT_LIST_HEAD(&t->ffree); return *tt = t; } @@ -1584,6 +1712,14 @@ aoe_flush_iocq(void) int __init aoecmd_init(void) { + void *p; + + /* get_zeroed_page returns page with ref count 1 */ + p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); + if (!p) + return -ENOMEM; + empty_page = virt_to_page(p); + INIT_LIST_HEAD(&iocq.head); spin_lock_init(&iocq.lock); init_waitqueue_head(&ktiowq); @@ -1599,4 +1735,7 @@ aoecmd_exit(void) { aoe_ktstop(&kts); aoe_flush_iocq(); + + free_page((unsigned long) page_address(empty_page)); + empty_page = NULL; } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index aaaea662a72a..f0c0c7416aed 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -223,7 +223,6 @@ aoedev_downdev(struct aoedev *d) /* clean out the in-process request (if any) */ aoe_failip(d); - d->htgt = NULL; /* fast fail all pending I/O */ if (d->blkq) { From e52a29326462badd9ceec90a9eb2ac2a8550e02e Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:09 -0800 Subject: [PATCH 151/180] aoe: avoid races between device destruction and discovery This change avoids a race that could result in a NULL pointer derference following a WARNing from kobject_add_internal, "don't try to register things with the same name in the same directory." The problem was found with a test that forgets and discovers an aoe device in a loop: while test ! -r /tmp/stop; do aoe-flush -a aoe-discover done The race was between aoedev_flush taking aoedevs out of the devlist, allowing a new discovery of the same AoE target to take place before the driver gets around to calling sysfs_remove_group. Fixing that one revealed another race between do_open and add_disk, and this patch avoids that, too. The fix required some care, because for flushing (forgetting) an aoedev, some of the steps must be performed under lock and some must be able to sleep. Also, for discovering a new aoedev, some steps might sleep. The check for a bad aoedev pointer remains from a time when about half of this patch was done, and it was possible for the bdev->bd_disk->private_data to become corrupted. The check should be removed eventually, but it is not expected to add significant overhead, occurring in the aoeblk_open routine. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 7 +- drivers/block/aoe/aoeblk.c | 36 +++++++- drivers/block/aoe/aoedev.c | 166 ++++++++++++++++++++++++------------- 3 files changed, 146 insertions(+), 63 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index b6d2b16358be..d50e9455b937 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -74,8 +74,11 @@ enum { DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */ DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */ - DEVFL_KICKME = (1<<4), /* slow polling network card catch */ - DEVFL_NEWSIZE = (1<<5), /* need to update dev size in block layer */ + DEVFL_GD_NOW = (1<<4), /* allocating gendisk */ + DEVFL_KICKME = (1<<5), /* slow polling network card catch */ + DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ + DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */ + DEVFL_FREED = (1<<8), /* device has been cleaned up */ }; enum { diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 57ac72c1715a..6b5b7876ecf3 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -147,9 +147,18 @@ aoeblk_open(struct block_device *bdev, fmode_t mode) struct aoedev *d = bdev->bd_disk->private_data; ulong flags; + if (!virt_addr_valid(d)) { + pr_crit("aoe: invalid device pointer in %s\n", + __func__); + WARN_ON(1); + return -ENODEV; + } + if (!(d->flags & DEVFL_UP) || d->flags & DEVFL_TKILL) + return -ENODEV; + mutex_lock(&aoeblk_mutex); spin_lock_irqsave(&d->lock, flags); - if (d->flags & DEVFL_UP) { + if (d->flags & DEVFL_UP && !(d->flags & DEVFL_TKILL)) { d->nopen++; spin_unlock_irqrestore(&d->lock, flags); mutex_unlock(&aoeblk_mutex); @@ -259,6 +268,18 @@ aoeblk_gdalloc(void *vp) struct request_queue *q; enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, }; ulong flags; + int late = 0; + + spin_lock_irqsave(&d->lock, flags); + if (d->flags & DEVFL_GDALLOC + && !(d->flags & DEVFL_TKILL) + && !(d->flags & DEVFL_GD_NOW)) + d->flags |= DEVFL_GD_NOW; + else + late = 1; + spin_unlock_irqrestore(&d->lock, flags); + if (late) + return; gd = alloc_disk(AOE_PARTITIONS); if (gd == NULL) { @@ -282,6 +303,11 @@ aoeblk_gdalloc(void *vp) } spin_lock_irqsave(&d->lock, flags); + WARN_ON(!(d->flags & DEVFL_GD_NOW)); + WARN_ON(!(d->flags & DEVFL_GDALLOC)); + WARN_ON(d->flags & DEVFL_TKILL); + WARN_ON(d->gd); + WARN_ON(d->flags & DEVFL_UP); blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); q->backing_dev_info.name = "aoe"; q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; @@ -306,6 +332,11 @@ aoeblk_gdalloc(void *vp) add_disk(gd); aoedisk_add_sysfs(d); + + spin_lock_irqsave(&d->lock, flags); + WARN_ON(!(d->flags & DEVFL_GD_NOW)); + d->flags &= ~DEVFL_GD_NOW; + spin_unlock_irqrestore(&d->lock, flags); return; err_mempool: @@ -314,7 +345,8 @@ err_disk: put_disk(gd); err: spin_lock_irqsave(&d->lock, flags); - d->flags &= ~DEVFL_GDALLOC; + d->flags &= ~DEVFL_GD_NOW; + schedule_work(&d->work); spin_unlock_irqrestore(&d->lock, flags); } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index f0c0c7416aed..3776715eb255 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -15,7 +15,6 @@ #include "aoe.h" static void dummy_timer(ulong); -static void aoedev_freedev(struct aoedev *); static void freetgt(struct aoedev *d, struct aoetgt *t); static void skbpoolfree(struct aoedev *d); @@ -236,29 +235,6 @@ aoedev_downdev(struct aoedev *d) set_capacity(d->gd, 0); } -static void -aoedev_freedev(struct aoedev *d) -{ - struct aoetgt **t, **e; - - cancel_work_sync(&d->work); - if (d->gd) { - aoedisk_rm_sysfs(d); - del_gendisk(d->gd); - put_disk(d->gd); - blk_cleanup_queue(d->blkq); - } - t = d->targets; - e = t + NTARGETS; - for (; t < e && *t; t++) - freetgt(d, *t); - if (d->bufpool) - mempool_destroy(d->bufpool); - skbpoolfree(d); - minor_free(d->sysminor); - kfree(d); -} - /* return whether the user asked for this particular * device to be flushed */ @@ -283,17 +259,62 @@ user_req(char *s, size_t slen, struct aoedev *d) return !strncmp(s, p, lim); } -int -aoedev_flush(const char __user *str, size_t cnt) +static void +freedev(struct aoedev *d) +{ + struct aoetgt **t, **e; + int freeing = 0; + unsigned long flags; + + spin_lock_irqsave(&d->lock, flags); + if (d->flags & DEVFL_TKILL + && !(d->flags & DEVFL_FREEING)) { + d->flags |= DEVFL_FREEING; + freeing = 1; + } + spin_unlock_irqrestore(&d->lock, flags); + if (!freeing) + return; + + del_timer_sync(&d->timer); + if (d->gd) { + aoedisk_rm_sysfs(d); + del_gendisk(d->gd); + put_disk(d->gd); + blk_cleanup_queue(d->blkq); + } + t = d->targets; + e = t + NTARGETS; + for (; t < e && *t; t++) + freetgt(d, *t); + if (d->bufpool) + mempool_destroy(d->bufpool); + skbpoolfree(d); + minor_free(d->sysminor); + + spin_lock_irqsave(&d->lock, flags); + d->flags |= DEVFL_FREED; + spin_unlock_irqrestore(&d->lock, flags); +} + +enum flush_parms { + NOT_EXITING = 0, + EXITING = 1, +}; + +static int +flush(const char __user *str, size_t cnt, int exiting) { ulong flags; struct aoedev *d, **dd; - struct aoedev *rmd = NULL; char buf[16]; int all = 0; int specified = 0; /* flush a specific device */ + unsigned int skipflags; - if (cnt >= 3) { + skipflags = DEVFL_GDALLOC | DEVFL_NEWSIZE | DEVFL_TKILL; + + if (!exiting && cnt >= 3) { if (cnt > sizeof buf) cnt = sizeof buf; if (copy_from_user(buf, str, cnt)) @@ -303,39 +324,71 @@ aoedev_flush(const char __user *str, size_t cnt) specified = 1; } + flush_scheduled_work(); + /* pass one: without sleeping, do aoedev_downdev */ spin_lock_irqsave(&devlist_lock, flags); - dd = &devlist; - while ((d = *dd)) { + for (d = devlist; d; d = d->next) { spin_lock(&d->lock); - if (specified) { + if (exiting) { + /* unconditionally take each device down */ + } else if (specified) { if (!user_req(buf, cnt, d)) - goto skip; + goto cont; } else if ((!all && (d->flags & DEVFL_UP)) - || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) + || d->flags & skipflags || d->nopen || d->ref) - goto skip; + goto cont; - *dd = d->next; aoedev_downdev(d); d->flags |= DEVFL_TKILL; +cont: spin_unlock(&d->lock); - d->next = rmd; - rmd = d; - continue; -skip: - spin_unlock(&d->lock); - dd = &d->next; } spin_unlock_irqrestore(&devlist_lock, flags); - while ((d = rmd)) { - rmd = d->next; - del_timer_sync(&d->timer); - aoedev_freedev(d); /* must be able to sleep */ + + /* pass two: call freedev, which might sleep, + * for aoedevs marked with DEVFL_TKILL + */ +restart: + spin_lock_irqsave(&devlist_lock, flags); + for (d = devlist; d; d = d->next) { + spin_lock(&d->lock); + if (d->flags & DEVFL_TKILL + && !(d->flags & DEVFL_FREEING)) { + spin_unlock(&d->lock); + spin_unlock_irqrestore(&devlist_lock, flags); + freedev(d); + goto restart; + } + spin_unlock(&d->lock); } + + /* pass three: remove aoedevs marked with DEVFL_FREED */ + for (dd = &devlist, d = *dd; d; d = *dd) { + struct aoedev *doomed = NULL; + + spin_lock(&d->lock); + if (d->flags & DEVFL_FREED) { + *dd = d->next; + doomed = d; + } else { + dd = &d->next; + } + spin_unlock(&d->lock); + kfree(doomed); + } + spin_unlock_irqrestore(&devlist_lock, flags); + return 0; } +int +aoedev_flush(const char __user *str, size_t cnt) +{ + return flush(str, cnt, NOT_EXITING); +} + /* This has been confirmed to occur once with Tms=3*1000 due to the * driver changing link and not processing its transmit ring. The * problem is hard enough to solve by returning an error that I'm @@ -388,7 +441,14 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) for (d=devlist; d; d=d->next) if (d->aoemajor == maj && d->aoeminor == min) { + spin_lock(&d->lock); + if (d->flags & DEVFL_TKILL) { + spin_unlock(&d->lock); + d = NULL; + goto out; + } d->ref++; + spin_unlock(&d->lock); break; } if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0) @@ -448,21 +508,9 @@ freetgt(struct aoedev *d, struct aoetgt *t) void aoedev_exit(void) { - struct aoedev *d; - ulong flags; - + flush_scheduled_work(); aoe_flush_iocq(); - while ((d = devlist)) { - devlist = d->next; - - spin_lock_irqsave(&d->lock, flags); - aoedev_downdev(d); - d->flags |= DEVFL_TKILL; - spin_unlock_irqrestore(&d->lock, flags); - - del_timer_sync(&d->timer); - aoedev_freedev(d); - } + flush(NULL, 0, EXITING); } int __init From 71114ec45f09eb6ef6f9d41c98d4ab6455086e58 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:11 -0800 Subject: [PATCH 152/180] aoe: use dynamic number of remote ports for AoE storage target Many AoE targets have four or fewer network ports, but some existing storage devices have many, and the AoE protocol sets no limit. This patch allows the use of more than eight remote MAC addresses per AoE target, while reducing the amount of memory used by the aoe driver in cases where there are many AoE targets with fewer than eight MAC addresses each. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 6 ++--- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/aoe/aoecmd.c | 50 ++++++++++++++++++++++++++------------ drivers/block/aoe/aoedev.c | 12 +++++++-- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index d50e9455b937..0f478dcfc199 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -84,7 +84,7 @@ enum { enum { DEFAULTBCNT = 2 * 512, /* 2 sectors */ MIN_BUFS = 16, - NTARGETS = 8, + NTARGETS = 4, NAOEIFS = 8, NSKBPOOLMAX = 256, NFACTIVE = 61, @@ -185,9 +185,9 @@ struct aoedev { ulong maxbcnt; struct list_head factive[NFACTIVE]; /* hash of active frames */ struct list_head rexmitq; /* deferred retransmissions */ - struct aoetgt *targets[NTARGETS]; + struct aoetgt **targets; + ulong ntargets; /* number of allocated aoetgt pointers */ struct aoetgt **tgt; /* target in use when working */ - ulong ntargets; ulong kicked; char ident[512]; }; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 6b5b7876ecf3..a129f8c8073d 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -67,7 +67,7 @@ static ssize_t aoedisk_show_netif(struct device *dev, nd = nds; ne = nd + ARRAY_SIZE(nds); t = d->targets; - te = t + NTARGETS; + te = t + d->ntargets; for (; t < te && *t; t++) { ifp = (*t)->ifs; e = ifp + NAOEIFS; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 000f7fb48841..da360f95c8ea 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -242,14 +242,14 @@ newframe(struct aoedev *d) int use_tainted; int has_untainted; - if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ + if (!d->targets || !d->targets[0]) { printk(KERN_ERR "aoe: NULL TARGETS!\n"); return NULL; } tt = d->tgt; /* last used target */ for (use_tainted = 0, has_untainted = 0;;) { tt++; - if (tt >= &d->targets[NTARGETS] || !*tt) + if (tt >= &d->targets[d->ntargets] || !*tt) tt = d->targets; t = *tt; if (!t->taint) { @@ -1104,7 +1104,7 @@ gettgt(struct aoedev *d, char *addr) struct aoetgt **t, **e; t = d->targets; - e = t + NTARGETS; + e = t + d->ntargets; for (; t < e && *t; t++) if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) return *t; @@ -1479,28 +1479,44 @@ aoecmd_ata_id(struct aoedev *d) return skb; } +static struct aoetgt ** +grow_targets(struct aoedev *d) +{ + ulong oldn, newn; + struct aoetgt **tt; + + oldn = d->ntargets; + newn = oldn * 2; + tt = kcalloc(newn, sizeof(*d->targets), GFP_ATOMIC); + if (!tt) + return NULL; + memmove(tt, d->targets, sizeof(*d->targets) * oldn); + d->tgt = tt + (d->tgt - d->targets); + kfree(d->targets); + d->targets = tt; + d->ntargets = newn; + + return &d->targets[oldn]; +} + static struct aoetgt * addtgt(struct aoedev *d, char *addr, ulong nframes) { struct aoetgt *t, **tt, **te; tt = d->targets; - te = tt + NTARGETS; + te = tt + d->ntargets; for (; tt < te && *tt; tt++) ; if (tt == te) { - printk(KERN_INFO - "aoe: device addtgt failure; too many targets\n"); - return NULL; + tt = grow_targets(d); + if (!tt) + goto nomem; } t = kzalloc(sizeof(*t), GFP_ATOMIC); - if (!t) { - printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); - return NULL; - } - - d->ntargets++; + if (!t) + goto nomem; t->nframes = nframes; t->d = d; memcpy(t->addr, addr, sizeof t->addr); @@ -1509,6 +1525,10 @@ addtgt(struct aoedev *d, char *addr, ulong nframes) t->maxout = t->nframes / 2; INIT_LIST_HEAD(&t->ffree); return *tt = t; + + nomem: + pr_info("aoe: cannot allocate memory to add target\n"); + return NULL; } static void @@ -1518,7 +1538,7 @@ setdbcnt(struct aoedev *d) int bcnt = 0; t = d->targets; - e = t + NTARGETS; + e = t + d->ntargets; for (; t < e && *t; t++) if (bcnt == 0 || bcnt > (*t)->minbcnt) bcnt = (*t)->minbcnt; @@ -1662,7 +1682,7 @@ aoecmd_cleanslate(struct aoedev *d) d->maxbcnt = 0; t = d->targets; - te = t + NTARGETS; + te = t + d->ntargets; for (; t < te && *t; t++) aoecmd_wreset(*t); } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 3776715eb255..e66ccbf41a50 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -214,7 +214,7 @@ aoedev_downdev(struct aoedev *d) /* reset window dressings */ tt = d->targets; - te = tt + NTARGETS; + te = tt + d->ntargets; for (; tt < te && (t = *tt); tt++) { aoecmd_wreset(t); t->nout = 0; @@ -284,7 +284,7 @@ freedev(struct aoedev *d) blk_cleanup_queue(d->blkq); } t = d->targets; - e = t + NTARGETS; + e = t + d->ntargets; for (; t < e && *t; t++) freetgt(d, *t); if (d->bufpool) @@ -376,6 +376,8 @@ restart: dd = &d->next; } spin_unlock(&d->lock); + if (doomed) + kfree(doomed->targets); kfree(doomed); } spin_unlock_irqrestore(&devlist_lock, flags); @@ -456,6 +458,12 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) d = kcalloc(1, sizeof *d, GFP_ATOMIC); if (!d) goto out; + d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC); + if (!d->targets) { + kfree(d); + goto out; + } + d->ntargets = NTARGETS; INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); skb_queue_head_init(&d->skbpool); From c450ba0fc12153cb5d3fd582b4ec82c75217a989 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:14 -0800 Subject: [PATCH 153/180] aoe: allow user to disable target failure timeout With this change, the aoe driver treats the value zero as special for the aoe_deadsecs module parameter. Normally, this value specifies the number of seconds during which the driver will continue to attempt retransmits to an unresponsive AoE target. After aoe_deadsecs has elapsed, the aoe driver marks the aoe device as "down" and fails all I/O. The new meaning of an aoe_deadsecs of zero is for the driver to retransmit commands indefinitely. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/aoe/aoe.txt | 4 +++- drivers/block/aoe/aoecmd.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/aoe/aoe.txt b/Documentation/aoe/aoe.txt index bfc9cb19abcd..c71487d399d1 100644 --- a/Documentation/aoe/aoe.txt +++ b/Documentation/aoe/aoe.txt @@ -125,7 +125,9 @@ DRIVER OPTIONS The aoe_deadsecs module parameter determines the maximum number of seconds that the driver will wait for an AoE device to provide a response to an AoE command. After aoe_deadsecs seconds have - elapsed, the AoE device will be marked as "down". + elapsed, the AoE device will be marked as "down". A value of zero + is supported for testing purposes and makes the aoe driver keep + trying AoE commands forever. The aoe_maxout module parameter has a default of 128. This is the maximum number of unresponded packets that will be sent to an AoE diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index da360f95c8ea..abf4ad2d3e18 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -812,7 +812,9 @@ rexmit_timer(ulong vp) since = tsince_hr(f); n = f->waited_total + since; n /= USEC_PER_SEC; - if (n > aoe_deadsecs && !(f->flags & FFL_PROBE)) { + if (aoe_deadsecs + && n > aoe_deadsecs + && !(f->flags & FFL_PROBE)) { /* Waited too long. Device failure. * Hang all frames on first hash bucket for downdev * to clean up. From 4a6c9ee93cd03604bd0e61066ce6aaf4bc0f1eb9 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:15 -0800 Subject: [PATCH 154/180] aoe: allow comma separator in aoe_iflist value By default, the aoe driver uses any ethernet interface for AoE, but the aoe_iflist module parameter provides a convenient way to limit AoE traffic to a specific list of local network interfaces. This change allows a list to be specified using the comma character as a separator. For example, modprobe aoe aoe_iflist=eth2,eth3 Before, it was inconvenient to get the quoting right in shell scripts when setting aoe_iflist to have more than one network interface. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoenet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 0f478dcfc199..f8d6c7e18a8b 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -11,7 +11,7 @@ #define AOE_PARTITIONS (16) #endif -#define WHITESPACE " \t\v\f\n" +#define WHITESPACE " \t\v\f\n," enum { AOECMD_ATA, diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 2e47404ff008..71d3ea8d3006 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -31,7 +31,7 @@ enum { static char aoe_iflist[IFLISTSZ]; module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600); -MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=\"dev1 [dev2 ...]\""); +MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=dev1[,dev2...]"); static wait_queue_head_t txwq; static struct ktstate kts; From bf29754ae8c1d611f43f0e25f1ba18e558455d8d Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:17 -0800 Subject: [PATCH 155/180] aoe: identify source of runt AoE packets This change only affects experimental AoE storage networks. It modifies the console message about runt packets detected so that the AoE major and minor addresses of the AoE target that generated the runt are mentioned. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoecmd.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index abf4ad2d3e18..25ef5c014fca 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -1217,8 +1217,10 @@ noskb: if (buf) case ATA_CMD_PIO_READ: case ATA_CMD_PIO_READ_EXT: if (skb->len < n) { - pr_err("aoe: runt data size in read. skb->len=%d need=%ld\n", - skb->len, n); + pr_err("%s e%ld.%d. skb->len=%d need=%ld\n", + "aoe: runt data size in read from", + (long) d->aoemajor, d->aoeminor, + skb->len, n); clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); break; } @@ -1233,7 +1235,9 @@ noskb: if (buf) break; case ATA_CMD_ID_ATA: if (skb->len < 512) { - pr_info("aoe: runt data size in ataid. skb->len=%d\n", + pr_info("%s e%ld.%d. skb->len=%d need=512\n", + "aoe: runt data size in ataid from", + (long) d->aoemajor, d->aoeminor, skb->len); break; } From 2b37c7d865121249f2dee9ae25d524333b07be63 Mon Sep 17 00:00:00 2001 From: Ed Cashin <ecashin@coraid.com> Date: Mon, 17 Dec 2012 16:04:19 -0800 Subject: [PATCH 156/180] aoe: update internal version number to 81 This version number is printed to the console on module initialization and is available in sysfs, which is where the userland aoe-version tool looks for it. Signed-off-by: Ed Cashin <ecashin@coraid.com> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoe.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index f8d6c7e18a8b..175649468c95 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,6 +1,5 @@ - /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "64+" +#define VERSION "81" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" From 31279b1457f992f24eee8d45ddd647f5fce42cf6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Mon, 17 Dec 2012 16:04:21 -0800 Subject: [PATCH 157/180] aoe: fix use after free in aoedev_by_aoeaddr() We should return NULL on failure instead of returning a freed pointer. Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Cc: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/aoe/aoedev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index e66ccbf41a50..98f2965778b9 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -461,6 +461,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC); if (!d->targets) { kfree(d); + d = NULL; goto out; } d->ntargets = NTARGETS; From 496f2f93b1cc286f5a4f4f9acdc1e5314978683f Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Mon, 17 Dec 2012 16:04:23 -0800 Subject: [PATCH 158/180] random32: rename random32 to prandom This renames all random32 functions to have 'prandom_' prefix as follows: void prandom_seed(u32 seed); /* rename from srandom32() */ u32 prandom_u32(void); /* rename from random32() */ void prandom_seed_state(struct rnd_state *state, u64 seed); /* rename from prandom32_seed() */ u32 prandom_u32_state(struct rnd_state *state); /* rename from prandom32() */ The purpose of this renaming is to prevent some kernel developers from assuming that prandom32() and random32() might imply that only prandom32() was the one using a pseudo-random number generator by prandom32's "p", and the result may be a very embarassing security exposure. This concern was expressed by Theodore Ts'o. And furthermore, I'm going to introduce new functions for getting the requested number of pseudo-random bytes. If I continue to use both prandom32 and random32 prefixes for these functions, the confusion is getting worse. As a result of this renaming, "prandom_" is the common prefix for pseudo-random number library. Currently, srandom32() and random32() are preserved because it is difficult to rename too many users at once. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Robert Love <robert.w.love@intel.com> Cc: Michel Lespinasse <walken@google.com> Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu> Cc: David Laight <david.laight@aculab.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Artem Bityutskiy <dedekind1@gmail.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/scsi/fcoe/fcoe_ctlr.c | 4 +-- include/linux/random.h | 17 +++++++++---- lib/interval_tree_test_main.c | 7 ++--- lib/random32.c | 48 +++++++++++++++++------------------ lib/rbtree_test.c | 6 ++--- 5 files changed, 45 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 2ebe03a4b51d..4a909d7cfde1 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2144,7 +2144,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) */ port_id = fip->port_id; if (fip->probe_tries) - port_id = prandom32(&fip->rnd_state) & 0xffff; + port_id = prandom_u32_state(&fip->rnd_state) & 0xffff; else if (!port_id) port_id = fip->lp->wwpn & 0xffff; if (!port_id || port_id == 0xffff) @@ -2169,7 +2169,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) { fip->probe_tries = 0; - prandom32_seed(&fip->rnd_state, fip->lp->wwpn); + prandom_seed_state(&fip->rnd_state, fip->lp->wwpn); fcoe_ctlr_vn_restart(fip); } diff --git a/include/linux/random.h b/include/linux/random.h index 6330ed47b38b..db6debc6649e 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -25,10 +25,17 @@ extern const struct file_operations random_fops, urandom_fops; unsigned int get_random_int(void); unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len); -u32 random32(void); -void srandom32(u32 seed); +u32 prandom_u32(void); +void prandom_seed(u32 seed); -u32 prandom32(struct rnd_state *); +/* + * These macros are preserved for backward compatibility and should be + * removed as soon as a transition is finished. + */ +#define random32() prandom_u32() +#define srandom32(seed) prandom_seed(seed) + +u32 prandom_u32_state(struct rnd_state *); /* * Handle minimum values for seeds @@ -39,11 +46,11 @@ static inline u32 __seed(u32 x, u32 m) } /** - * prandom32_seed - set seed for prandom32(). + * prandom_seed_state - set seed for prandom_u32_state(). * @state: pointer to state structure to receive the seed. * @seed: arbitrary 64-bit value to use as a seed. */ -static inline void prandom32_seed(struct rnd_state *state, u64 seed) +static inline void prandom_seed_state(struct rnd_state *state, u64 seed) { u32 i = (seed >> 32) ^ (seed << 10) ^ seed; diff --git a/lib/interval_tree_test_main.c b/lib/interval_tree_test_main.c index b25903987f7a..245900b98c8e 100644 --- a/lib/interval_tree_test_main.c +++ b/lib/interval_tree_test_main.c @@ -30,7 +30,8 @@ static void init(void) { int i; for (i = 0; i < NODES; i++) { - u32 a = prandom32(&rnd), b = prandom32(&rnd); + u32 a = prandom_u32_state(&rnd); + u32 b = prandom_u32_state(&rnd); if (a <= b) { nodes[i].start = a; nodes[i].last = b; @@ -40,7 +41,7 @@ static void init(void) } } for (i = 0; i < SEARCHES; i++) - queries[i] = prandom32(&rnd); + queries[i] = prandom_u32_state(&rnd); } static int interval_tree_test_init(void) @@ -51,7 +52,7 @@ static int interval_tree_test_init(void) printk(KERN_ALERT "interval tree insert/remove"); - prandom32_seed(&rnd, 3141592653589793238ULL); + prandom_seed_state(&rnd, 3141592653589793238ULL); init(); time1 = get_cycles(); diff --git a/lib/random32.c b/lib/random32.c index 938bde5876ac..d1830fade915 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -42,13 +42,13 @@ static DEFINE_PER_CPU(struct rnd_state, net_rand_state); /** - * prandom32 - seeded pseudo-random number generator. + * prandom_u32_state - seeded pseudo-random number generator. * @state: pointer to state structure holding seeded state. * * This is used for pseudo-randomness with no outside seeding. - * For more random results, use random32(). + * For more random results, use prandom_u32(). */ -u32 prandom32(struct rnd_state *state) +u32 prandom_u32_state(struct rnd_state *state) { #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b) @@ -58,32 +58,32 @@ u32 prandom32(struct rnd_state *state) return (state->s1 ^ state->s2 ^ state->s3); } -EXPORT_SYMBOL(prandom32); +EXPORT_SYMBOL(prandom_u32_state); /** - * random32 - pseudo random number generator + * prandom_u32 - pseudo random number generator * * A 32 bit pseudo-random number is generated using a fast * algorithm suitable for simulation. This algorithm is NOT * considered safe for cryptographic use. */ -u32 random32(void) +u32 prandom_u32(void) { unsigned long r; struct rnd_state *state = &get_cpu_var(net_rand_state); - r = prandom32(state); + r = prandom_u32_state(state); put_cpu_var(state); return r; } -EXPORT_SYMBOL(random32); +EXPORT_SYMBOL(prandom_u32); /** - * srandom32 - add entropy to pseudo random number generator + * prandom_seed - add entropy to pseudo random number generator * @seed: seed value * - * Add some additional seeding to the random32() pool. + * Add some additional seeding to the prandom pool. */ -void srandom32(u32 entropy) +void prandom_seed(u32 entropy) { int i; /* @@ -95,13 +95,13 @@ void srandom32(u32 entropy) state->s1 = __seed(state->s1 ^ entropy, 1); } } -EXPORT_SYMBOL(srandom32); +EXPORT_SYMBOL(prandom_seed); /* * Generate some initially weak seeding values to allow - * to start the random32() engine. + * to start the prandom_u32() engine. */ -static int __init random32_init(void) +static int __init prandom_init(void) { int i; @@ -114,22 +114,22 @@ static int __init random32_init(void) state->s3 = __seed(LCG(state->s2), 15); /* "warm it up" */ - prandom32(state); - prandom32(state); - prandom32(state); - prandom32(state); - prandom32(state); - prandom32(state); + prandom_u32_state(state); + prandom_u32_state(state); + prandom_u32_state(state); + prandom_u32_state(state); + prandom_u32_state(state); + prandom_u32_state(state); } return 0; } -core_initcall(random32_init); +core_initcall(prandom_init); /* * Generate better values after random number generator * is fully initialized. */ -static int __init random32_reseed(void) +static int __init prandom_reseed(void) { int i; @@ -143,8 +143,8 @@ static int __init random32_reseed(void) state->s3 = __seed(seeds[2], 15); /* mix it in */ - prandom32(state); + prandom_u32_state(state); } return 0; } -late_initcall(random32_reseed); +late_initcall(prandom_reseed); diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c index d7f491a54579..af38aedbd874 100644 --- a/lib/rbtree_test.c +++ b/lib/rbtree_test.c @@ -96,8 +96,8 @@ static void init(void) { int i; for (i = 0; i < NODES; i++) { - nodes[i].key = prandom32(&rnd); - nodes[i].val = prandom32(&rnd); + nodes[i].key = prandom_u32_state(&rnd); + nodes[i].val = prandom_u32_state(&rnd); } } @@ -155,7 +155,7 @@ static int rbtree_test_init(void) printk(KERN_ALERT "rbtree testing"); - prandom32_seed(&rnd, 3141592653589793238ULL); + prandom_seed_state(&rnd, 3141592653589793238ULL); init(); time1 = get_cycles(); From 6582c665d6b882dad8329e05749fbcf119f1ab88 Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Mon, 17 Dec 2012 16:04:25 -0800 Subject: [PATCH 159/180] prandom: introduce prandom_bytes() and prandom_bytes_state() Add functions to get the requested number of pseudo-random bytes. The difference from get_random_bytes() is that it generates pseudo-random numbers by prandom_u32(). It doesn't consume the entropy pool, and the sequence is reproducible if the same rnd_state is used. So it is suitable for generating random bytes for testing. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Artem Bityutskiy <dedekind1@gmail.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Eilon Greenstein <eilong@broadcom.com> Cc: David Laight <david.laight@aculab.com> Cc: Michel Lespinasse <walken@google.com> Cc: Robert Love <robert.w.love@intel.com> Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/random.h | 2 ++ lib/random32.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/linux/random.h b/include/linux/random.h index db6debc6649e..d9846088c2c5 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -26,6 +26,7 @@ unsigned int get_random_int(void); unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len); u32 prandom_u32(void); +void prandom_bytes(void *buf, int nbytes); void prandom_seed(u32 seed); /* @@ -36,6 +37,7 @@ void prandom_seed(u32 seed); #define srandom32(seed) prandom_seed(seed) u32 prandom_u32_state(struct rnd_state *); +void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes); /* * Handle minimum values for seeds diff --git a/lib/random32.c b/lib/random32.c index d1830fade915..52280d5526be 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -77,6 +77,55 @@ u32 prandom_u32(void) } EXPORT_SYMBOL(prandom_u32); +/* + * prandom_bytes_state - get the requested number of pseudo-random bytes + * + * @state: pointer to state structure holding seeded state. + * @buf: where to copy the pseudo-random bytes to + * @bytes: the requested number of bytes + * + * This is used for pseudo-randomness with no outside seeding. + * For more random results, use prandom_bytes(). + */ +void prandom_bytes_state(struct rnd_state *state, void *buf, int bytes) +{ + unsigned char *p = buf; + int i; + + for (i = 0; i < round_down(bytes, sizeof(u32)); i += sizeof(u32)) { + u32 random = prandom_u32_state(state); + int j; + + for (j = 0; j < sizeof(u32); j++) { + p[i + j] = random; + random >>= BITS_PER_BYTE; + } + } + if (i < bytes) { + u32 random = prandom_u32_state(state); + + for (; i < bytes; i++) { + p[i] = random; + random >>= BITS_PER_BYTE; + } + } +} +EXPORT_SYMBOL(prandom_bytes_state); + +/** + * prandom_bytes - get the requested number of pseudo-random bytes + * @buf: where to copy the pseudo-random bytes to + * @bytes: the requested number of bytes + */ +void prandom_bytes(void *buf, int bytes) +{ + struct rnd_state *state = &get_cpu_var(net_rand_state); + + prandom_bytes_state(state, buf, bytes); + put_cpu_var(state); +} +EXPORT_SYMBOL(prandom_bytes); + /** * prandom_seed - add entropy to pseudo random number generator * @seed: seed value From 8376d0bccde3cf739649ea8559f7bedb4b5583b7 Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Mon, 17 Dec 2012 16:04:28 -0800 Subject: [PATCH 160/180] bnx2x: use prandom_bytes() Use prandom_bytes() to fill rss key with pseudo-random bytes. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Eilon Greenstein <eilong@broadcom.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Artem Bityutskiy <dedekind1@gmail.com> Cc: David Laight <david.laight@aculab.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Michel Lespinasse <walken@google.com> Cc: Robert Love <robert.w.love@intel.com> Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index a2998bea5d4b..01588b66a38c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1832,7 +1832,6 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, bool config_hash) { struct bnx2x_config_rss_params params = {NULL}; - int i; /* Although RSS is meaningless when there is a single HW queue we * still need it enabled in order to have HW Rx hash generated. @@ -1864,9 +1863,7 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, if (config_hash) { /* RSS keys */ - for (i = 0; i < sizeof(params.rss_key) / 4; i++) - params.rss_key[i] = random32(); - + prandom_bytes(params.rss_key, sizeof(params.rss_key)); __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags); } From 7e45bf83f4cee68f0cfa9599007f8e089ea53365 Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Mon, 17 Dec 2012 16:04:32 -0800 Subject: [PATCH 161/180] mtd: nandsim: use prandom_bytes This also removes unnecessary memset call which is immediately overwritten with random bytes. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Artem Bityutskiy <dedekind1@gmail.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Laight <david.laight@aculab.com> Cc: Eilon Greenstein <eilong@broadcom.com> Cc: Michel Lespinasse <walken@google.com> Cc: Robert Love <robert.w.love@intel.com> Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/mtd/nand/nandsim.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a932c485eb04..c3c13e64a2f0 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -1397,10 +1397,7 @@ int do_read_error(struct nandsim *ns, int num) unsigned int page_no = ns->regs.row; if (read_error(page_no)) { - int i; - memset(ns->buf.byte, 0xFF, num); - for (i = 0; i < num; ++i) - ns->buf.byte[i] = random32(); + prandom_bytes(ns->buf.byte, num); NS_WARN("simulating read error in page %u\n", page_no); return 1; } From cdd9fa8de64bc5b33d8e943dde486b60d8468ec0 Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Mon, 17 Dec 2012 16:04:35 -0800 Subject: [PATCH 162/180] ubifs: use prandom_bytes This also converts filling memory loop to use memset. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Artem Bityutskiy <dedekind1@gmail.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: David Laight <david.laight@aculab.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Eilon Greenstein <eilong@broadcom.com> Cc: Michel Lespinasse <walken@google.com> Cc: Robert Love <robert.w.love@intel.com> Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/ubifs/debug.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 62911637e12f..12817ffc7345 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2560,7 +2560,7 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) static int corrupt_data(const struct ubifs_info *c, const void *buf, unsigned int len) { - unsigned int from, to, i, ffs = chance(1, 2); + unsigned int from, to, ffs = chance(1, 2); unsigned char *p = (void *)buf; from = random32() % (len + 1); @@ -2571,11 +2571,9 @@ static int corrupt_data(const struct ubifs_info *c, const void *buf, ffs ? "0xFFs" : "random data"); if (ffs) - for (i = from; i < to; i++) - p[i] = 0xFF; + memset(p + from, 0xFF, to - from); else - for (i = from; i < to; i++) - p[i] = random32() % 0x100; + prandom_bytes(p + from, to - from); return to; } From 000e06b01f7e1d615345815550306a0e0622433c Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:38 -0800 Subject: [PATCH 163/180] vm selftests: print failure status instead of cause make error Original behavior: bash-4.1$ make -C vm run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/vm' /bin/sh ./run_vmtests ./run_vmtests: line 24: /proc/sys/vm/nr_hugepages: Permission denied Please run this test as root make: *** [run_tests] Error 1 make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/vm' After applying the patch: bash-4.1$ make -C vm run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/vm' ./run_vmtests: line 24: /proc/sys/vm/nr_hugepages: Permission denied Please run this test as root vmtests: [FAIL] make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/vm' Signed-off-by: Dave Young <dyoung@redhat.com> Cc: Pekka Enberg <penberg@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/vm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 7300d0702efe..436d2e81868b 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile @@ -8,7 +8,7 @@ all: hugepage-mmap hugepage-shm map_hugetlb thuge-gen $(CC) $(CFLAGS) -o $@ $^ run_tests: all - /bin/sh ./run_vmtests + @/bin/sh ./run_vmtests || echo "vmtests: [FAIL]" clean: $(RM) hugepage-mmap hugepage-shm map_hugetlb From 9ed1d90ed1e0b5788e5b9148ed70adb1a017078c Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:39 -0800 Subject: [PATCH 164/180] mqueue selftests: print failure status instead of cause make error Original behavior: bash-4.1$ make -C mqueue run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/mqueue' ./mq_open_tests /test1 Not running as root, but almost all tests require root in order to modify system settings. Exiting. make: *** [run_tests] Error 1 make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/mqueue' After applying the patch: bash-4.1$ make -C mqueue run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/mqueue' Not running as root, but almost all tests require root in order to modify system settings. Exiting. mq_open_tests: [FAIL] Not running as root, but almost all tests require root in order to modify system settings. Exiting. mq_perf_tests: [FAIL] make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/mqueue' Signed-off-by: Dave Young <dyoung@redhat.com> Reviewed-by: Pekka Enberg <penberg@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/mqueue/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/mqueue/Makefile b/tools/testing/selftests/mqueue/Makefile index 54c0aad2b47c..218a122c7951 100644 --- a/tools/testing/selftests/mqueue/Makefile +++ b/tools/testing/selftests/mqueue/Makefile @@ -3,8 +3,8 @@ all: gcc -O2 -lrt -lpthread -lpopt -o mq_perf_tests mq_perf_tests.c run_tests: - ./mq_open_tests /test1 - ./mq_perf_tests + @./mq_open_tests /test1 || echo "mq_open_tests: [FAIL]" + @./mq_perf_tests || echo "mq_perf_tests: [FAIL]" clean: rm -f mq_open_tests mq_perf_tests From a58130ddc896e5a15e4de2bf50a1d89247118c23 Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:42 -0800 Subject: [PATCH 165/180] cpu-hotplug selftests: print failure status instead of cause make error Original behavior: bash-4.1$ make -C cpu-hotplug run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/cpu-hotplug' ./on-off-test.sh make: execvp: ./on-off-test.sh: Permission denied make: *** [run_tests] Error 127 make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/cpu-hotplug' After applying the patch: bash-4.1$ make -C cpu-hotplug run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/cpu-hotplug' /bin/sh: ./on-off-test.sh: Permission denied cpu-hotplug selftests: [FAIL] make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/cpu-hotplug' Signed-off-by: Dave Young <dyoung@redhat.com> Reviewed-by: Pekka Enberg <penberg@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/cpu-hotplug/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile index 7c9c20ff578a..12657a5e4bf9 100644 --- a/tools/testing/selftests/cpu-hotplug/Makefile +++ b/tools/testing/selftests/cpu-hotplug/Makefile @@ -1,6 +1,6 @@ all: run_tests: - ./on-off-test.sh + @./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]" clean: From aabccae6e9e2106e67a40d65eb423163cd69d2fb Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:45 -0800 Subject: [PATCH 166/180] mem-hotplug selftests: print failure status instead of cause make error Original behavior: bash-4.1$ make -C memory-hotplug run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/memory-hotplug' ./on-off-test.sh make: execvp: ./on-off-test.sh: Permission denied make: *** [run_tests] Error 127 make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/memory-hotplug' After applying the patch: bash-4.1$ make -C memory-hotplug run_tests make: Entering directory `/home/dave/git/linux-2.6/tools/testing/selftests/memory-hotplug' /bin/sh: ./on-off-test.sh: Permission denied memory-hotplug selftests: [FAIL] make: Leaving directory `/home/dave/git/linux-2.6/tools/testing/selftests/memory-hotplug' Signed-off-by: Dave Young <dyoung@redhat.com> Reviewed-by: Pekka Enberg <penberg@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/memory-hotplug/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile index 7c9c20ff578a..0f49c3f5f58d 100644 --- a/tools/testing/selftests/memory-hotplug/Makefile +++ b/tools/testing/selftests/memory-hotplug/Makefile @@ -1,6 +1,6 @@ all: run_tests: - ./on-off-test.sh + @./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]" clean: From 63d233673a9f6c524969e40e7012e3e461aafd32 Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:47 -0800 Subject: [PATCH 167/180] kcmp selftests: make run_tests fix make run_tests need the target is run_tests instead of run-tests Also gcc output should be kcmp_test. Fix these two issues. Signed-off-by: Dave Young <dyoung@redhat.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/kcmp/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile index dc79b86ea65c..c608945a0ef5 100644 --- a/tools/testing/selftests/kcmp/Makefile +++ b/tools/testing/selftests/kcmp/Makefile @@ -16,12 +16,12 @@ CFLAGS += -I../../../../arch/x86/include/ all: ifeq ($(ARCH),X86) - gcc $(CFLAGS) kcmp_test.c -o run_test + gcc $(CFLAGS) kcmp_test.c -o kcmp_test else echo "Not an x86 target, can't build kcmp selftest" endif -run-tests: all +run_tests: all ./kcmp_test clean: From ed8ad10c3b2fab18dd92d21afd4277a8a521ecfd Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:49 -0800 Subject: [PATCH 168/180] kcmp selftests: print fail status instead of cause make error In case kcmp_test exit non zero value it will cause make error. Better way is just print the test failure status. Signed-off-by: Dave Young <dyoung@redhat.com> Reviewed-by: Pekka Enberg <penberg@kernel.org> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/kcmp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile index c608945a0ef5..56eb5523dbb8 100644 --- a/tools/testing/selftests/kcmp/Makefile +++ b/tools/testing/selftests/kcmp/Makefile @@ -22,7 +22,7 @@ else endif run_tests: all - ./kcmp_test + @./kcmp_test || echo "kcmp_test: [FAIL]" clean: rm -fr ./run_test From 5a55f8bb2d0c4e5c05837b688ed1b2132a0ed0e7 Mon Sep 17 00:00:00 2001 From: Dave Young <dyoung@redhat.com> Date: Mon, 17 Dec 2012 16:04:50 -0800 Subject: [PATCH 169/180] breakpoint selftests: print failure status instead of cause make error In case breakpoint test exit non zero value it will cause make error. Better way is just print the test failure status. Signed-off-by: Dave Young <dyoung@redhat.com> Reviewed-by: Pekka Enberg <penberg@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/breakpoints/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile index 931278035f5c..e18b42b254af 100644 --- a/tools/testing/selftests/breakpoints/Makefile +++ b/tools/testing/selftests/breakpoints/Makefile @@ -17,7 +17,7 @@ else endif run_tests: - ./breakpoint_test + @./breakpoint_test || echo "breakpoints selftests: [FAIL]" clean: rm -fr breakpoint_test From 2bf1cbf1c616b4dd85a3a8a715af9c5701c16a91 Mon Sep 17 00:00:00 2001 From: Dave Jones <davej@redhat.com> Date: Mon, 17 Dec 2012 16:04:52 -0800 Subject: [PATCH 170/180] tools/testing/selftests/kcmp/kcmp_test.c: print reason for failure in kcmp_test I was curious why sys_kcmp wasn't working, which led me to the testcase. It turned out I hadn't enabled CHECKPOINT_RESTORE in the kernel I was testing. Add a decoding of errno to the testcase to make that obvious. Signed-off-by: Dave Jones <davej@redhat.com> Acked-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- tools/testing/selftests/kcmp/kcmp_test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c index 358cc6bfa35d..fa4f1b37e045 100644 --- a/tools/testing/selftests/kcmp/kcmp_test.c +++ b/tools/testing/selftests/kcmp/kcmp_test.c @@ -72,7 +72,8 @@ int main(int argc, char **argv) /* This one should return same fd */ ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1); if (ret) { - printf("FAIL: 0 expected but %d returned\n", ret); + printf("FAIL: 0 expected but %d returned (%s)\n", + ret, strerror(errno)); ret = -1; } else printf("PASS: 0 returned as expected\n"); @@ -80,7 +81,8 @@ int main(int argc, char **argv) /* Compare with self */ ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0); if (ret) { - printf("FAIL: 0 expected but %li returned\n", ret); + printf("FAIL: 0 expected but %li returned (%s)\n", + ret, strerror(errno)); ret = -1; } else printf("PASS: 0 returned as expected\n"); From 55985dd72ab27b47530dcc8bdddd28b69f4abe8b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:04:55 -0800 Subject: [PATCH 171/180] procfs: add ability to plug in auxiliary fdinfo providers This patch brings ability to print out auxiliary data associated with file in procfs interface /proc/pid/fdinfo/fd. In particular further patches make eventfd, evenpoll, signalfd and fsnotify to print additional information complete enough to restore these objects after checkpoint. To simplify the code we add show_fdinfo callback inside struct file_operations (as Al and Pavel are proposing). Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/proc/fd.c | 2 ++ include/linux/fs.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/proc/fd.c b/fs/proc/fd.c index f28a875f8779..d7a4a28ef630 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -50,6 +50,8 @@ static int seq_show(struct seq_file *m, void *v) if (!ret) { seq_printf(m, "pos:\t%lli\nflags:\t0%o\n", (long long)file->f_pos, f_flags); + if (file->f_op->show_fdinfo) + ret = file->f_op->show_fdinfo(m, file); fput(file); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 029552ff774c..5abf703d06ba 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -44,6 +44,7 @@ struct vm_area_struct; struct vfsmount; struct cred; struct swap_info_struct; +struct seq_file; extern void __init inode_init(void); extern void __init inode_init_early(void); @@ -1543,6 +1544,7 @@ struct file_operations { int (*setlease)(struct file *, long, struct file_lock **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); + int (*show_fdinfo)(struct seq_file *m, struct file *f); }; struct inode_operations { @@ -1578,8 +1580,6 @@ struct inode_operations { umode_t create_mode, int *opened); } ____cacheline_aligned; -struct seq_file; - ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, From cbac5542d48127b546a23d816380a7926eee1c25 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:04:57 -0800 Subject: [PATCH 172/180] fs, eventfd: add procfs fdinfo helper This allows us to print out raw counter value. The /proc/pid/fdinfo/fd output is | pos: 0 | flags: 04002 | eventfd-count: 5a Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/eventfd.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/eventfd.c b/fs/eventfd.c index d81b9f654086..35470d9b96e6 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -19,6 +19,8 @@ #include <linux/export.h> #include <linux/kref.h> #include <linux/eventfd.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> struct eventfd_ctx { struct kref kref; @@ -284,7 +286,25 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c return res; } +#ifdef CONFIG_PROC_FS +static int eventfd_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct eventfd_ctx *ctx = f->private_data; + int ret; + + spin_lock_irq(&ctx->wqh.lock); + ret = seq_printf(m, "eventfd-count: %16llx\n", + (unsigned long long)ctx->count); + spin_unlock_irq(&ctx->wqh.lock); + + return ret; +} +#endif + static const struct file_operations eventfd_fops = { +#ifdef CONFIG_PROC_FS + .show_fdinfo = eventfd_show_fdinfo, +#endif .release = eventfd_release, .poll = eventfd_poll, .read = eventfd_read, From 138d22b58696c506799f8de759804083ff9effae Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:02 -0800 Subject: [PATCH 173/180] fs, epoll: add procfs fdinfo helper This allows us to print out eventpoll target file descriptor, events and data, the /proc/pid/fdinfo/fd consists of | pos: 0 | flags: 02 | tfd: 5 events: 1d data: ffffffffffffffff enabled: 1 [avagin@: fix for unitialized ret variable] Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/eventpoll.c | 28 ++++++++++++++++++++++++++++ fs/proc/array.c | 2 +- fs/signalfd.c | 18 ++++++++++++++++++ include/linux/proc_fs.h | 3 +++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index cd96649bfe62..be56b21435f8 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -38,6 +38,8 @@ #include <asm/io.h> #include <asm/mman.h> #include <linux/atomic.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> /* * LOCKING: @@ -783,8 +785,34 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) return pollflags != -1 ? pollflags : 0; } +#ifdef CONFIG_PROC_FS +static int ep_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct eventpoll *ep = f->private_data; + struct rb_node *rbp; + int ret = 0; + + mutex_lock(&ep->mtx); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + struct epitem *epi = rb_entry(rbp, struct epitem, rbn); + + ret = seq_printf(m, "tfd: %8d events: %8x data: %16llx\n", + epi->ffd.fd, epi->event.events, + (long long)epi->event.data); + if (ret) + break; + } + mutex_unlock(&ep->mtx); + + return ret; +} +#endif + /* File callbacks that implement the eventpoll file behaviour */ static const struct file_operations eventpoll_fops = { +#ifdef CONFIG_PROC_FS + .show_fdinfo = ep_show_fdinfo, +#endif .release = ep_eventpoll_release, .poll = ep_eventpoll_poll, .llseek = noop_llseek, diff --git a/fs/proc/array.c b/fs/proc/array.c index 439544fec388..060a56a91278 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -220,7 +220,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, seq_putc(m, '\n'); } -static void render_sigset_t(struct seq_file *m, const char *header, +void render_sigset_t(struct seq_file *m, const char *header, sigset_t *set) { int i; diff --git a/fs/signalfd.c b/fs/signalfd.c index 8bee4e570911..b53486961735 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -29,6 +29,7 @@ #include <linux/anon_inodes.h> #include <linux/signalfd.h> #include <linux/syscalls.h> +#include <linux/proc_fs.h> void signalfd_cleanup(struct sighand_struct *sighand) { @@ -227,7 +228,24 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, return total ? total: ret; } +#ifdef CONFIG_PROC_FS +static int signalfd_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct signalfd_ctx *ctx = f->private_data; + sigset_t sigmask; + + sigmask = ctx->sigmask; + signotset(&sigmask); + render_sigset_t(m, "sigmask:\t", &sigmask); + + return 0; +} +#endif + static const struct file_operations signalfd_fops = { +#ifdef CONFIG_PROC_FS + .show_fdinfo = signalfd_show_fdinfo, +#endif .release = signalfd_release, .poll = signalfd_poll, .read = signalfd_read, diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 3fd2e871ff1b..b4f70f0a9a48 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -290,4 +290,7 @@ static inline struct net *PDE_NET(struct proc_dir_entry *pde) return pde->parent->data; } +#include <linux/signal.h> + +void render_sigset_t(struct seq_file *m, const char *header, sigset_t *set); #endif /* _LINUX_PROC_FS_H */ From ab49bdecc3ebb46ab661f5f05d5c5ea9606406c6 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:06 -0800 Subject: [PATCH 174/180] fs, exportfs: escape nil dereference if no s_export_op present This routine will be used to generate a file handle in fdinfo output for inotify subsystem, where if no s_export_op present the general export_encode_fh should be used. Thus add a test if s_export_op present inside exportfs_encode_fh itself. Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/exportfs/expfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 29ab099e3e08..10f137381ac7 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -357,7 +357,7 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, */ parent = p->d_inode; } - if (nop->encode_fh) + if (nop && nop->encode_fh) error = nop->encode_fh(inode, fid->raw, max_len, parent); else error = export_encode_fh(inode, fid, max_len, parent); From 711c7bf9914060d7aaf3c1a15f38094a5d5e748f Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:08 -0800 Subject: [PATCH 175/180] fs, exportfs: add exportfs_encode_inode_fh() helper We will need this helper in the next patch to provide a file handle for inotify marks in /proc/pid/fdinfo output. The patch is rather providing the way to use inodes directly when dentry is not available (like in case of inotify system). Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/exportfs/expfs.c | 19 ++++++++++++++----- include/linux/exportfs.h | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 10f137381ac7..606bb074c501 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -341,10 +341,21 @@ static int export_encode_fh(struct inode *inode, struct fid *fid, return type; } +int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, + int *max_len, struct inode *parent) +{ + const struct export_operations *nop = inode->i_sb->s_export_op; + + if (nop && nop->encode_fh) + return nop->encode_fh(inode, fid->raw, max_len, parent); + + return export_encode_fh(inode, fid, max_len, parent); +} +EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh); + int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, int connectable) { - const struct export_operations *nop = dentry->d_sb->s_export_op; int error; struct dentry *p = NULL; struct inode *inode = dentry->d_inode, *parent = NULL; @@ -357,10 +368,8 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, */ parent = p->d_inode; } - if (nop && nop->encode_fh) - error = nop->encode_fh(inode, fid->raw, max_len, parent); - else - error = export_encode_fh(inode, fid, max_len, parent); + + error = exportfs_encode_inode_fh(inode, fid, max_len, parent); dput(p); return error; diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 12291a7ee275..c7e6b6392ab8 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -177,6 +177,8 @@ struct export_operations { int (*commit_metadata)(struct inode *inode); }; +extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, + int *max_len, struct inode *parent); extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, int connectable); extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, From be77196b809cdce8603a5aadd5e3cfabd3cbef96 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:12 -0800 Subject: [PATCH 176/180] fs, notify: add procfs fdinfo helper This allow us to print out fsnotify details such as watchee inode, device, mask and optionally a file handle. For inotify objects if kernel compiled with exportfs support the output will be | pos: 0 | flags: 02000000 | inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:7e9e0000640d1b6d | inotify wd:2 ino:a111 sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:11a1000020542153 | inotify wd:1 ino:6b149 sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:49b1060023552153 If kernel compiled without exportfs support, the file handle won't be provided but inode and device only. | pos: 0 | flags: 02000000 | inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0 | inotify wd:2 ino:a111 sdev:800013 mask:800afce ignored_mask:0 | inotify wd:1 ino:6b149 sdev:800013 mask:800afce ignored_mask:0 For fanotify the output is like | pos: 0 | flags: 04002 | fanotify flags:10 event-flags:0 | fanotify mnt_id:12 mask:3b ignored_mask:0 | fanotify ino:50205 sdev:800013 mask:3b ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:05020500fb1d47e7 To minimize impact on general fsnotify code the new functionality is gathered in fs/notify/fdinfo.c file. Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/notify/Makefile | 2 +- fs/notify/fanotify/fanotify_user.c | 2 + fs/notify/fdinfo.c | 175 +++++++++++++++++++++++++++++ fs/notify/fdinfo.h | 27 +++++ fs/notify/inotify/inotify_user.c | 2 + 5 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 fs/notify/fdinfo.c create mode 100644 fs/notify/fdinfo.h diff --git a/fs/notify/Makefile b/fs/notify/Makefile index ae5f33a6d868..96d3420d0242 100644 --- a/fs/notify/Makefile +++ b/fs/notify/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o \ - mark.o vfsmount_mark.o + mark.o vfsmount_mark.o fdinfo.o obj-y += dnotify/ obj-y += inotify/ diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 6fcaeb8c902e..a5cd9bba022f 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -17,6 +17,7 @@ #include <asm/ioctls.h> #include "../../mount.h" +#include "../fdinfo.h" #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 #define FANOTIFY_DEFAULT_MAX_MARKS 8192 @@ -428,6 +429,7 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar } static const struct file_operations fanotify_fops = { + .show_fdinfo = fanotify_show_fdinfo, .poll = fanotify_poll, .read = fanotify_read, .write = fanotify_write, diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c new file mode 100644 index 000000000000..cb996179abfd --- /dev/null +++ b/fs/notify/fdinfo.c @@ -0,0 +1,175 @@ +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/fsnotify_backend.h> +#include <linux/idr.h> +#include <linux/init.h> +#include <linux/inotify.h> +#include <linux/fanotify.h> +#include <linux/kernel.h> +#include <linux/namei.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/seq_file.h> +#include <linux/proc_fs.h> +#include <linux/exportfs.h> + +#include "inotify/inotify.h" +#include "../fs/mount.h" + +#if defined(CONFIG_PROC_FS) + +#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY) + +static int show_fdinfo(struct seq_file *m, struct file *f, + int (*show)(struct seq_file *m, struct fsnotify_mark *mark)) +{ + struct fsnotify_group *group = f->private_data; + struct fsnotify_mark *mark; + int ret = 0; + + spin_lock(&group->mark_lock); + list_for_each_entry(mark, &group->marks_list, g_list) { + ret = show(m, mark); + if (ret) + break; + } + spin_unlock(&group->mark_lock); + return ret; +} + +#if defined(CONFIG_EXPORTFS) +static int show_mark_fhandle(struct seq_file *m, struct inode *inode) +{ + struct { + struct file_handle handle; + u8 pad[64]; + } f; + int size, ret, i; + + f.handle.handle_bytes = sizeof(f.pad); + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); + if ((ret == 255) || (ret == -ENOSPC)) { + WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); + return 0; + } + + f.handle.handle_type = ret; + f.handle.handle_bytes = size * sizeof(u32); + + ret = seq_printf(m, "fhandle-bytes:%x fhandle-type:%x f_handle:", + f.handle.handle_bytes, f.handle.handle_type); + + for (i = 0; i < f.handle.handle_bytes; i++) + ret |= seq_printf(m, "%02x", (int)f.handle.f_handle[i]); + + return ret; +} +#else +static int show_mark_fhandle(struct seq_file *m, struct inode *inode) +{ + return 0; +} +#endif + +#ifdef CONFIG_INOTIFY_USER + +static int inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) +{ + struct inotify_inode_mark *inode_mark; + struct inode *inode; + int ret = 0; + + if (!(mark->flags & (FSNOTIFY_MARK_FLAG_ALIVE | FSNOTIFY_MARK_FLAG_INODE))) + return 0; + + inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); + inode = igrab(mark->i.inode); + if (inode) { + ret = seq_printf(m, "inotify wd:%x ino:%lx sdev:%x " + "mask:%x ignored_mask:%x ", + inode_mark->wd, inode->i_ino, + inode->i_sb->s_dev, + mark->mask, mark->ignored_mask); + ret |= show_mark_fhandle(m, inode); + ret |= seq_putc(m, '\n'); + iput(inode); + } + + return ret; +} + +int inotify_show_fdinfo(struct seq_file *m, struct file *f) +{ + return show_fdinfo(m, f, inotify_fdinfo); +} + +#endif /* CONFIG_INOTIFY_USER */ + +#ifdef CONFIG_FANOTIFY + +static int fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) +{ + struct inode *inode; + int ret = 0; + + if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) + return 0; + + if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { + inode = igrab(mark->i.inode); + if (!inode) + goto out; + ret = seq_printf(m, "fanotify ino:%lx sdev:%x " + "mask:%x ignored_mask:%x ", + inode->i_ino, inode->i_sb->s_dev, + mark->mask, mark->ignored_mask); + ret |= show_mark_fhandle(m, inode); + ret |= seq_putc(m, '\n'); + iput(inode); + } else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) { + struct mount *mnt = real_mount(mark->m.mnt); + + ret = seq_printf(m, "fanotify mnt_id:%x mask:%x " + "ignored_mask:%x\n", + mnt->mnt_id, mark->mask, mark->ignored_mask); + } +out: + return ret; +} + +int fanotify_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct fsnotify_group *group = f->private_data; + unsigned int flags = 0; + + switch (group->priority) { + case FS_PRIO_0: + flags |= FAN_CLASS_NOTIF; + break; + case FS_PRIO_1: + flags |= FAN_CLASS_CONTENT; + break; + case FS_PRIO_2: + flags |= FAN_CLASS_PRE_CONTENT; + break; + } + + if (group->max_events == UINT_MAX) + flags |= FAN_UNLIMITED_QUEUE; + + if (group->fanotify_data.max_marks == UINT_MAX) + flags |= FAN_UNLIMITED_MARKS; + + seq_printf(m, "fanotify flags:%x event-flags:%x\n", + flags, group->fanotify_data.f_flags); + + return show_fdinfo(m, f, fanotify_fdinfo); +} + +#endif /* CONFIG_FANOTIFY */ + +#endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */ + +#endif /* CONFIG_PROC_FS */ diff --git a/fs/notify/fdinfo.h b/fs/notify/fdinfo.h new file mode 100644 index 000000000000..556afda990e9 --- /dev/null +++ b/fs/notify/fdinfo.h @@ -0,0 +1,27 @@ +#ifndef __FSNOTIFY_FDINFO_H__ +#define __FSNOTIFY_FDINFO_H__ + +#include <linux/errno.h> +#include <linux/proc_fs.h> + +struct seq_file; +struct file; + +#ifdef CONFIG_PROC_FS + +#ifdef CONFIG_INOTIFY_USER +extern int inotify_show_fdinfo(struct seq_file *m, struct file *f); +#endif + +#ifdef CONFIG_FANOTIFY +extern int fanotify_show_fdinfo(struct seq_file *m, struct file *f); +#endif + +#else /* CONFIG_PROC_FS */ + +#define inotify_show_fdinfo NULL +#define fanotify_show_fdinfo NULL + +#endif /* CONFIG_PROC_FS */ + +#endif /* __FSNOTIFY_FDINFO_H__ */ diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index c311dda054a3..36cb013c7c13 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -40,6 +40,7 @@ #include <linux/wait.h> #include "inotify.h" +#include "../fdinfo.h" #include <asm/ioctls.h> @@ -335,6 +336,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, } static const struct file_operations inotify_fops = { + .show_fdinfo = inotify_show_fdinfo, .poll = inotify_poll, .read = inotify_read, .fasync = inotify_fasync, From f1d8c16298d317dbdeb166a135e85dadd1782858 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:14 -0800 Subject: [PATCH 177/180] docs: add documentation about /proc/<pid>/fdinfo/<fd> output [akpm@linux-foundation.org: tweak documentation] Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/filesystems/proc.txt | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 12665ee7094a..bcc27c97efbb 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -41,6 +41,7 @@ Table of Contents 3.5 /proc/<pid>/mountinfo - Information about mounts 3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm 3.7 /proc/<pid>/task/<tid>/children - Information about task children + 3.8 /proc/<pid>/fdinfo/<fd> - Information about opened file 4 Configuring procfs 4.1 Mount options @@ -1633,6 +1634,87 @@ pids, so one need to either stop or freeze processes being inspected if precise results are needed. +3.7 /proc/<pid>/fdinfo/<fd> - Information about opened file +--------------------------------------------------------------- +This file provides information associated with an opened file. The regular +files have at least two fields -- 'pos' and 'flags'. The 'pos' represents +the current offset of the opened file in decimal form [see lseek(2) for +details] and 'flags' denotes the octal O_xxx mask the file has been +created with [see open(2) for details]. + +A typical output is + + pos: 0 + flags: 0100002 + +The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags +pair provide additional information particular to the objects they represent. + + Eventfd files + ~~~~~~~~~~~~~ + pos: 0 + flags: 04002 + eventfd-count: 5a + + where 'eventfd-count' is hex value of a counter. + + Signalfd files + ~~~~~~~~~~~~~~ + pos: 0 + flags: 04002 + sigmask: 0000000000000200 + + where 'sigmask' is hex value of the signal mask associated + with a file. + + Epoll files + ~~~~~~~~~~~ + pos: 0 + flags: 02 + tfd: 5 events: 1d data: ffffffffffffffff + + where 'tfd' is a target file descriptor number in decimal form, + 'events' is events mask being watched and the 'data' is data + associated with a target [see epoll(7) for more details]. + + Fsnotify files + ~~~~~~~~~~~~~~ + For inotify files the format is the following + + pos: 0 + flags: 02000000 + inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:7e9e0000640d1b6d + + where 'wd' is a watch descriptor in decimal form, ie a target file + descriptor number, 'ino' and 'sdev' are inode and device where the + target file resides and the 'mask' is the mask of events, all in hex + form [see inotify(7) for more details]. + + If the kernel was built with exportfs support, the path to the target + file is encoded as a file handle. The file handle is provided by three + fields 'fhandle-bytes', 'fhandle-type' and 'f_handle', all in hex + format. + + If the kernel is built without exportfs support the file handle won't be + printed out. + + For fanotify files the format is + + pos: 0 + flags: 02 + fanotify ino:2 sdev:800013 mask:1 ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:0200000000000000 + + or + + pos: 0 + flags: 02 + fanotify mnt_id:13 mask:1 ignored_mask:40000000 + + where 'ino', 'sdev' are target inode and device, 'mnt_id' is the mount + point identifier, 'mask' is the events mask used and 'ignored_mask' is + the mask of events which are to be ignored. All in hex format. + + ------------------------------------------------------------------------------ Configuring procfs ------------------------------------------------------------------------------ From e6dbcafb744ab94a94142a6e721e16330397fad8 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:16 -0800 Subject: [PATCH 178/180] fs, fanotify: add @mflags field to fanotify output The kernel keeps FAN_MARK_IGNORED_SURV_MODIFY bit separately from fsnotify_mark::mask|ignored_mask thus put it in @mflags (mark flags) field so the user-space reader will be able to detect if such bit were used on mark creation procedure. | pos: 0 | flags: 04002 | fanotify flags:10 event-flags:0 | fanotify mnt_id:12 mflags:40 mask:38 ignored_mask:40000003 | fanotify ino:4f969 sdev:800013 mflags:0 mask:3b ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:69f90400c275b5b4 Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/notify/fdinfo.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c index cb996179abfd..514c4b81483d 100644 --- a/fs/notify/fdinfo.c +++ b/fs/notify/fdinfo.c @@ -111,29 +111,33 @@ int inotify_show_fdinfo(struct seq_file *m, struct file *f) static int fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) { + unsigned int mflags = 0; struct inode *inode; int ret = 0; if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) return 0; + if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) + mflags |= FAN_MARK_IGNORED_SURV_MODIFY; + if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { inode = igrab(mark->i.inode); if (!inode) goto out; ret = seq_printf(m, "fanotify ino:%lx sdev:%x " - "mask:%x ignored_mask:%x ", + "mflags:%x mask:%x ignored_mask:%x ", inode->i_ino, inode->i_sb->s_dev, - mark->mask, mark->ignored_mask); + mflags, mark->mask, mark->ignored_mask); ret |= show_mark_fhandle(m, inode); ret |= seq_putc(m, '\n'); iput(inode); } else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) { struct mount *mnt = real_mount(mark->m.mnt); - ret = seq_printf(m, "fanotify mnt_id:%x mask:%x " - "ignored_mask:%x\n", - mnt->mnt_id, mark->mask, mark->ignored_mask); + ret = seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x " + "ignored_mask:%x\n", mnt->mnt_id, mflags, + mark->mask, mark->ignored_mask); } out: return ret; From e71ec593201e1b367b5f22955e3db49e3c562e67 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov <gorcunov@openvz.org> Date: Mon, 17 Dec 2012 16:05:18 -0800 Subject: [PATCH 179/180] docs: update documentation about /proc/<pid>/fdinfo/<fd> fanotify output Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: James Bottomley <jbottomley@parallels.com> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/filesystems/proc.txt | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index bcc27c97efbb..fd8d0d594fc7 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1698,21 +1698,27 @@ pair provide additional information particular to the objects they represent. If the kernel is built without exportfs support the file handle won't be printed out. + If there is no inotify mark attached yet the 'inotify' line will be omitted. + For fanotify files the format is pos: 0 flags: 02 - fanotify ino:2 sdev:800013 mask:1 ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:0200000000000000 + fanotify flags:10 event-flags:0 + fanotify mnt_id:12 mflags:40 mask:38 ignored_mask:40000003 + fanotify ino:4f969 sdev:800013 mflags:0 mask:3b ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:69f90400c275b5b4 - or + where fanotify 'flags' and 'event-flags' are values used in fanotify_init + call, 'mnt_id' is the mount point identifier, 'mflags' is the value of + flags associated with mark which are tracked separately from events + mask. 'ino', 'sdev' are target inode and device, 'mask' is the events + mask and 'ignored_mask' is the mask of events which are to be ignored. + All in hex format. Incorporation of 'mflags', 'mask' and 'ignored_mask' + does provide information about flags and mask used in fanotify_mark + call [see fsnotify manpage for details]. - pos: 0 - flags: 02 - fanotify mnt_id:13 mask:1 ignored_mask:40000000 - - where 'ino', 'sdev' are target inode and device, 'mnt_id' is the mount - point identifier, 'mask' is the events mask used and 'ignored_mask' is - the mask of events which are to be ignored. All in hex format. + While the first three lines are mandatory and always printed, the rest is + optional and may be omitted if no marks created yet. ------------------------------------------------------------------------------ From 6fd59a83b9261fa53eaf98fb5514abba504a3ea3 Mon Sep 17 00:00:00 2001 From: Nick Bowler <nbowler@elliptictech.com> Date: Mon, 17 Dec 2012 16:05:20 -0800 Subject: [PATCH 180/180] scatterlist: don't BUG when we can trivially return a proper error. There is absolutely no reason to crash the kernel when we have a perfectly good return value already available to use for conveying failure status. Let's return an error code instead of crashing the kernel: that sounds like a much better plan. [akpm@linux-foundation.org: s/E2BIG/EINVAL/] Signed-off-by: Nick Bowler <nbowler@elliptictech.com> Cc: Maxim Levitsky <maximlevitsky@gmail.com> Cc: Tejun Heo <tj@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- lib/scatterlist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 3675452b23ca..7874b01e816e 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -248,7 +248,8 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, unsigned int left; #ifndef ARCH_HAS_SG_CHAIN - BUG_ON(nents > max_ents); + if (WARN_ON_ONCE(nents > max_ents)) + return -EINVAL; #endif memset(table, 0, sizeof(*table));