[PATCH v2 08/10] powerpc: use for_each_sg()
This replaces the plain loop over the sglist array with for_each_sg() macro which consists of sg_next() function calls. Since powerpc does select ARCH_HAS_SG_CHAIN, it is necessary to use for_each_sg() in order to loop over each sg element. This also help find problems with drivers that do not properly initialize their sg tables when CONFIG_DEBUG_SG is enabled. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-a...@vger.kernel.org --- * New patch from v2 arch/powerpc/kernel/vio.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 5bfdab9..b7a6844 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -557,11 +557,11 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, struct vio_dev *viodev = to_vio_dev(dev); struct iommu_table *tbl; struct scatterlist *sgl; - int ret, count = 0; + int ret, count; size_t alloc_size = 0; tbl = get_iommu_table_base(dev); - for (sgl = sglist; count < nelems; count++, sgl++) + for_each_sg(sglist, sgl, nelems, count) alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE(tbl)); if (vio_cmo_alloc(viodev, alloc_size)) { @@ -577,7 +577,7 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, return ret; } - for (sgl = sglist, count = 0; count < ret; count++, sgl++) + for_each_sg(sglist, sgl, ret, count) alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl)); if (alloc_size) vio_cmo_dealloc(viodev, alloc_size); @@ -594,10 +594,10 @@ static void vio_dma_iommu_unmap_sg(struct device *dev, struct iommu_table *tbl; struct scatterlist *sgl; size_t alloc_size = 0; - int count = 0; + int count; tbl = get_iommu_table_base(dev); - for (sgl = sglist; count < nelems; count++, sgl++) + for_each_sg(sglist, sgl, nelems, count) alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl)); dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs); -- 1.9.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/2] mm: fix undefined reference to `.kernel_map_pages' on PPC builds
2015-01-23 5:41 GMT+09:00 Kim Phillips : > On Thu, 22 Jan 2015 10:45:51 +0900 > Joonsoo Kim wrote: > >> On Wed, Jan 21, 2015 at 09:57:59PM +0900, Akinobu Mita wrote: >> > 2015-01-21 9:07 GMT+09:00 Andrew Morton : >> > > On Tue, 20 Jan 2015 15:01:50 -0800 j...@joshtriplett.org wrote: >> > > >> > >> On Tue, Jan 20, 2015 at 02:02:00PM -0600, Kim Phillips wrote: >> > >> > It's possible to configure DEBUG_PAGEALLOC without PAGE_POISONING on >> > >> > ppc. Fix building the generic kernel_map_pages() implementation in >> > >> > this case: >> > >> > >> > >> > LD init/built-in.o >> > >> > mm/built-in.o: In function `free_pages_prepare': >> > >> > mm/page_alloc.c:770: undefined reference to `.kernel_map_pages' >> > >> > mm/built-in.o: In function `prep_new_page': >> > >> > mm/page_alloc.c:933: undefined reference to `.kernel_map_pages' >> > >> > mm/built-in.o: In function `map_pages': >> > >> > mm/compaction.c:61: undefined reference to `.kernel_map_pages' >> > >> > make: *** [vmlinux] Error 1 >> > >> > kernel_map_pages() is static inline function since commit 031bc5743f15 >> > ("mm/debug-pagealloc: make debug-pagealloc boottime configurable"). >> > >> > But there is old declaration in 'arch/powerpc/include/asm/cacheflush.h'. >> > Removing it or changing s/kernel_map_pages/__kernel_map_pages/ in this >> > header file or something can fix this problem? >> > >> > The architecture which has ARCH_SUPPORTS_DEBUG_PAGEALLOC >> > including PPC should not build mm/debug-pagealloc.o >> >> Yes, architecture with ARCH_SUPPORTS_DEBUG_PAGEALLOC should not build >> mm/debug-pagealloc.o. I attach the patch to remove old declaration. >> I hope it will fix Kim's problem. >> >> -->8-- >> From 7cb9d1ed8a785df152cb8934e187031c8ebd1bb2 Mon Sep 17 00:00:00 2001 >> From: Joonsoo Kim >> Date: Thu, 22 Jan 2015 10:28:58 +0900 >> Subject: [PATCH] mm/debug_pagealloc: fix build failure on ppc and some other >> archs >> >> Kim Phillips reported following build failure. >> >> LD init/built-in.o >> mm/built-in.o: In function `free_pages_prepare': >> mm/page_alloc.c:770: undefined reference to `.kernel_map_pages' >> mm/built-in.o: In function `prep_new_page': >> mm/page_alloc.c:933: undefined reference to `.kernel_map_pages' >> mm/built-in.o: In function `map_pages': >> mm/compaction.c:61: undefined reference to `.kernel_map_pages' >> make: *** [vmlinux] Error 1 >> >> Reason for this problem is that commit 031bc5743f15 >> ("mm/debug-pagealloc: make debug-pagealloc boottime configurable") forgot >> to remove old declaration of kernel_map_pages() in some architectures. >> This patch removes them to fix build failure. >> >> Reported-by: Kim Phillips >> Signed-off-by: Joonsoo Kim >> --- > > Thanks. Now I get this: > > LD init/built-in.o > mm/built-in.o: In function `kernel_map_pages': > include/linux/mm.h:2076: undefined reference to `.__kernel_map_pages' > include/linux/mm.h:2076: undefined reference to `.__kernel_map_pages' > include/linux/mm.h:2076: undefined reference to `.__kernel_map_pages' > Makefile:925: recipe for target 'vmlinux' failed > make: *** [vmlinux] Error 1 > > but, AFAICT, that's not because this patch is invalid: it's because > __kernel_map_pages() isn't implemented in > arch/powerpc/mm/pgtable_64.c, i.e., for non-PPC_STD_MMU_64 PPC64 > machines. Then, in order to use generic __kernel_map_pages() in mm/debug-pagealloc.c, CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC shouldn't be selected in arch/powerpc/Kconfig, when CONFIG_PPC_STD_MMU_64 isn't defined. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/2] mm: fix undefined reference to `.kernel_map_pages' on PPC builds
2015-01-21 9:07 GMT+09:00 Andrew Morton : > On Tue, 20 Jan 2015 15:01:50 -0800 j...@joshtriplett.org wrote: > >> On Tue, Jan 20, 2015 at 02:02:00PM -0600, Kim Phillips wrote: >> > It's possible to configure DEBUG_PAGEALLOC without PAGE_POISONING on >> > ppc. Fix building the generic kernel_map_pages() implementation in >> > this case: >> > >> > LD init/built-in.o >> > mm/built-in.o: In function `free_pages_prepare': >> > mm/page_alloc.c:770: undefined reference to `.kernel_map_pages' >> > mm/built-in.o: In function `prep_new_page': >> > mm/page_alloc.c:933: undefined reference to `.kernel_map_pages' >> > mm/built-in.o: In function `map_pages': >> > mm/compaction.c:61: undefined reference to `.kernel_map_pages' >> > make: *** [vmlinux] Error 1 kernel_map_pages() is static inline function since commit 031bc5743f15 ("mm/debug-pagealloc: make debug-pagealloc boottime configurable"). But there is old declaration in 'arch/powerpc/include/asm/cacheflush.h'. Removing it or changing s/kernel_map_pages/__kernel_map_pages/ in this header file or something can fix this problem? The architecture which has ARCH_SUPPORTS_DEBUG_PAGEALLOC including PPC should not build mm/debug-pagealloc.o ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: remove unused BITOP_LE_SWIZZLE macro
The BITOP_LE_SWIZZLE macro was used in the little-endian bitops functions for powerpc. But these functions were converted to generic bitops and the BITOP_LE_SWIZZLE is not used anymore. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/include/asm/bitops.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index ef918a2..08bd299 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -52,8 +52,6 @@ #define smp_mb__before_clear_bit() smp_mb() #define smp_mb__after_clear_bit() smp_mb() -#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) - /* Macro for generating the ***_bits() functions */ #define DEFINE_BITOP(fn, op, prefix, postfix) \ static __inline__ void fn(unsigned long mask, \ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] powerpc+of: Rename and fix OF reconfig notifier error inject module
2012/12/13 Benjamin Herrenschmidt : > This module used to inject errors in the pSeries specific dynamic > reconfiguration notifiers. Those are gone however, replaced by > generic notifiers for changes to the device-tree. So let's update > the module to deal with these instead and rename it along the way. > > Signed-off-by: Benjamin Herrenschmidt Looks good. Acked-by: Akinobu Mita ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: use asm-generic/bitops/le.h
The only difference between powerpc and asm-generic le-bitops is test_bit_le(). Usually all bitops require a long aligned bitmap. But powerpc test_bit_le() can take an unaligned address. There is no special callsite of test_bit_le() that needs unaligned access in powerpc as far as I can see. So convert to use asm-generic/bitops/le.h for powerpc. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/include/asm/bitops.h | 55 +-- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index 920596f..ef918a2 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -278,61 +278,8 @@ unsigned long __arch_hweight64(__u64 w); #include /* Little-endian versions */ +#include -static __inline__ int test_bit_le(unsigned long nr, - __const__ void *addr) -{ - __const__ unsigned char *tmp = (__const__ unsigned char *) addr; - return (tmp[nr >> 3] >> (nr & 7)) & 1; -} - -static inline void set_bit_le(int nr, void *addr) -{ - set_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline void clear_bit_le(int nr, void *addr) -{ - clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline void __set_bit_le(int nr, void *addr) -{ - __set_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline void __clear_bit_le(int nr, void *addr) -{ - __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline int test_and_set_bit_le(int nr, void *addr) -{ - return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline int test_and_clear_bit_le(int nr, void *addr) -{ - return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline int __test_and_set_bit_le(int nr, void *addr) -{ - return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline int __test_and_clear_bit_le(int nr, void *addr) -{ - return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -#define find_first_zero_bit_le(addr, size) \ - find_next_zero_bit_le((addr), (size), 0) -unsigned long find_next_zero_bit_le(const void *addr, - unsigned long size, unsigned long offset); - -unsigned long find_next_bit_le(const void *addr, - unsigned long size, unsigned long offset); /* Bitmap functions for the ext2 filesystem */ #include -- 1.7.11.7 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: remove BITOP_MASK and BITOP_WORD from asm/bitops.h
Replace BITOP_MASK and BITOP_WORD with BIT_MASK and BIT_WORD defined in linux/bitops.h and remove BITOP_* which are not used anymore. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/include/asm/bitops.h | 20 +--- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index dc2cf9c..920596f 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -52,8 +52,6 @@ #define smp_mb__before_clear_bit() smp_mb() #define smp_mb__after_clear_bit() smp_mb() -#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) /* Macro for generating the ***_bits() functions */ @@ -83,22 +81,22 @@ DEFINE_BITOP(change_bits, xor, "", "") static __inline__ void set_bit(int nr, volatile unsigned long *addr) { - set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)); + set_bits(BIT_MASK(nr), addr + BIT_WORD(nr)); } static __inline__ void clear_bit(int nr, volatile unsigned long *addr) { - clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)); + clear_bits(BIT_MASK(nr), addr + BIT_WORD(nr)); } static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr) { - clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr)); + clear_bits_unlock(BIT_MASK(nr), addr + BIT_WORD(nr)); } static __inline__ void change_bit(int nr, volatile unsigned long *addr) { - change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)); + change_bits(BIT_MASK(nr), addr + BIT_WORD(nr)); } /* Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output @@ -136,26 +134,26 @@ DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER, static __inline__ int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) { - return test_and_set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; + return test_and_set_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0; } static __inline__ int test_and_set_bit_lock(unsigned long nr, volatile unsigned long *addr) { - return test_and_set_bits_lock(BITOP_MASK(nr), - addr + BITOP_WORD(nr)) != 0; + return test_and_set_bits_lock(BIT_MASK(nr), + addr + BIT_WORD(nr)) != 0; } static __inline__ int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) { - return test_and_clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; + return test_and_clear_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0; } static __inline__ int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) { - return test_and_change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; + return test_and_change_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0; } #include -- 1.7.11.7 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: iommu: use bitmap library
- Caluculate the bitmap size with BITS_TO_LONGS() - Use bitmap_empty() to verify that all bits are cleared This also includes a printk to pr_warn() conversion. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/kernel/iommu.c | 16 +--- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 8226c6c..c862fd7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -656,7 +656,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) struct iommu_pool *p; /* number of bytes needed for the bitmap */ - sz = (tbl->it_size + 7) >> 3; + sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long); page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); if (!page) @@ -708,7 +708,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) void iommu_free_table(struct iommu_table *tbl, const char *node_name) { - unsigned long bitmap_sz, i; + unsigned long bitmap_sz; unsigned int order; if (!tbl || !tbl->it_map) { @@ -718,17 +718,11 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name) } /* verify that table contains no entries */ - /* it_size is in entries, and we're examining 64 at a time */ - for (i = 0; i < (tbl->it_size/64); i++) { - if (tbl->it_map[i] != 0) { - printk(KERN_WARNING "%s: Unexpected TCEs for %s\n", - __func__, node_name); - break; - } - } + if (!bitmap_empty(tbl->it_map, tbl->it_size)) + pr_warn("%s: Unexpected TCEs for %s\n", __func__, node_name); /* calculate bitmap size in bytes */ - bitmap_sz = (tbl->it_size + 7) / 8; + bitmap_sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long); /* free bitmap */ order = get_order(bitmap_sz); -- 1.7.11.7 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH -v5 0/6] notifier error injection
2012/7/4 Andrew Morton : > On Sat, 30 Jun 2012 14:59:24 +0900 > Akinobu Mita wrote: > >> This provides kernel modules that can be used to test the error handling >> of notifier call chain failures by injecting artifical errors to the >> following notifier chain callbacks. > > No updates to Documentation/fault-injection/? Thanks for the remainder. I'll prepare to add a document to it. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -v5 1/6] fault-injection: notifier error injection
The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Michael Ellerman --- No changes since v4 lib/Kconfig.debug | 11 + lib/Makefile|1 + lib/notifier-error-inject.c | 112 +++ lib/notifier-error-inject.h | 24 ++ 4 files changed, 148 insertions(+) create mode 100644 lib/notifier-error-inject.c create mode 100644 lib/notifier-error-inject.h diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ff5bdee..c848758 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1084,6 +1084,17 @@ config LKDTM Documentation on how to use the module can be found in Documentation/fault-injection/provoke-crashes.txt +config NOTIFIER_ERROR_INJECTION + tristate "Notifier error injection" + depends on DEBUG_KERNEL + select DEBUG_FS + help + This option provides the ability to inject artifical errors to + specified notifier chain callbacks. It is useful to test the error + handling of notifier call chain failures. + + Say N if unsure. + config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" depends on HOTPLUG_CPU && DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index 8c31a0c..23fba9e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o +obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c new file mode 100644 index 000..44b92cb --- /dev/null +++ b/lib/notifier-error-inject.c @@ -0,0 +1,112 @@ +#include + +#include "notifier-error-inject.h" + +static int debugfs_errno_set(void *data, u64 val) +{ + *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0); + return 0; +} + +static int debugfs_errno_get(void *data, u64 *val) +{ + *val = *(int *)data; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + +static struct dentry *debugfs_create_errno(const char *name, mode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_errno); +} + +static int notifier_err_inject_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct notifier_err_inject *err_inject = + container_of(nb, struct notifier_err_inject, nb); + struct notifier_err_inject_action *action; + + for (action = err_inject->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) + pr_info("Injecting error (%d) to %s\n", err, action->name); + + return notifier_from_errno(err); +} + +struct dentry *notifier_err_inject_dir; +EXPORT_SYMBOL_GPL(notifier_err_inject_dir); + +struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent, + struct notifier_err_inject *err_inject, int priority) +{ + struct notifier_err_inject_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + struct dentry *actions_dir; + + err_inject->nb.notifier_call = notifier_err_inject_callback; + err_inject->nb.priority = priority; + + dir = debugfs_create_dir(name, parent); + if (!dir) + return ERR_PTR(-ENOMEM); + + actions_dir = debugfs_create_dir("actions", dir); + if (!actions_dir) + goto fail; + + for (action = err_inject->actions; action->name; action++) { + struct dentry *action_dir; + + action_dir = debugfs_create_dir(action->name, actions_dir); + if (!action_dir) + goto fail; + + /* +* Create debugfs r/w file containing action->error. If +
[PATCH -v5 0/6] notifier error injection
This provides kernel modules that can be used to test the error handling of notifier call chain failures by injecting artifical errors to the following notifier chain callbacks. * CPU notifier * PM notifier * memory hotplug notifier * powerpc pSeries reconfig notifier Example: Inject CPU offline error (-1 == -EPERM) # cd /sys/kernel/debug/notifier-error-inject/cpu # echo -1 > actions/CPU_DOWN_PREPARE/error # echo 0 > /sys/devices/system/cpu/cpu1/online bash: echo: write error: Operation not permitted This also adds cpu and memory hotplug tests to tools/testing/selftests These tests first do simple online and offline test and then do fault injection tests if notifier error injection module is available. Changelog: * v5 (change only testing scripts) - make testing scripts a part of tools/testing/selftests - do simple on/offline tests even if no notifier error injection support * v4 (It is about 11 months since v3) - prefix all APIs with notifier_err_inject_* - rearrange debugfs interface (e.g. $DEBUGFS/cpu-notifier-error-inject/CPU_DOWN_PREPARE --> $DEBUGFS/notifier-error-inject/cpu/actions/CPU_DOWN_PREPARE/error) - update modules to follow new interface - add -r option for memory-notifier.sh to specify percent of offlining memory blocks * v3 - rewrite to be kernel modules instead of initializing at late_initcall()s (it makes the diffstat look different but most code remains unchanged) - export err_inject_notifier_block_{init,cleanup} for modules - export pSeries_reconfig_notifier_{,un}register symbols for a module - notifier priority can be specified as a module parameter - add testing scripts in tools/testing/fault-injection * v2 - "PM: Improve error code of pm_notifier_call_chain()" is now in -next - "debugfs: add debugfs_create_int" is dropped - put a comment in err_inject_notifier_block_init() - only allow valid errno to be injected (-MAX_ERRNO <= errno <= 0) - improve Kconfig help text - make CONFIG_PM_NOTIFIER_ERROR_INJECTION visible even if PM_DEBUG is disabled - make CONFIG_PM_NOTIFIER_ERROR_INJECTION default if PM_DEBUG is enabled Akinobu Mita (6): fault-injection: notifier error injection cpu: rewrite cpu-notifier-error-inject module PM: PM notifier error injection module memory: memory notifier error injection module powerpc: pSeries reconfig notifier error injection module fault-injection: add selftests for cpu and memory hotplug lib/Kconfig.debug | 91 +++- lib/Makefile |5 + lib/cpu-notifier-error-inject.c| 63 +++--- lib/memory-notifier-error-inject.c | 48 lib/notifier-error-inject.c| 112 ++ lib/notifier-error-inject.h| 24 ++ lib/pSeries-reconfig-notifier-error-inject.c | 51 + lib/pm-notifier-error-inject.c | 49 + tools/testing/selftests/Makefile |2 +- tools/testing/selftests/cpu-hotplug/Makefile |6 + tools/testing/selftests/cpu-hotplug/on-off-test.sh | 221 +++ tools/testing/selftests/memory-hotplug/Makefile|6 + .../selftests/memory-hotplug/on-off-test.sh| 230 13 files changed, 867 insertions(+), 41 deletions(-) create mode 100644 lib/memory-notifier-error-inject.c create mode 100644 lib/notifier-error-inject.c create mode 100644 lib/notifier-error-inject.h create mode 100644 lib/pSeries-reconfig-notifier-error-inject.c create mode 100644 lib/pm-notifier-error-inject.c create mode 100644 tools/testing/selftests/cpu-hotplug/Makefile create mode 100755 tools/testing/selftests/cpu-hotplug/on-off-test.sh create mode 100644 tools/testing/selftests/memory-hotplug/Makefile create mode 100755 tools/testing/selftests/memory-hotplug/on-off-test.sh Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Américo Wang Cc: Michael Ellerman Cc: Dave Jones -- 1.7.10.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -v5 6/6] fault-injection: add selftests for cpu and memory hotplug
This adds two selftests * tools/testing/selftests/cpu-hotplug/on-off-test.sh is testing script for CPU hotplug 1. Online all hot-pluggable CPUs 2. Offline all hot-pluggable CPUs 3. Online all hot-pluggable CPUs again 4. Exit if cpu-notifier-error-inject.ko is not available 5. Offline all hot-pluggable CPUs in preparation for testing 6. Test CPU hot-add error handling by injecting notifier errors 7. Online all hot-pluggable CPUs in preparation for testing 8. Test CPU hot-remove error handling by injecting notifier errors * tools/testing/selftests/memory-hotplug/on-off-test.sh is doing the similar thing for memory hotplug. 1. Online all hot-pluggable memory 2. Offline 10% of hot-pluggable memory 3. Online all hot-pluggable memory again 4. Exit if memory-notifier-error-inject.ko is not available 5. Offline 10% of hot-pluggable memory in preparation for testing 6. Test memory hot-add error handling by injecting notifier errors 7. Online all hot-pluggable memory in preparation for testing 8. Test memory hot-remove error handling by injecting notifier errors Signed-off-by: Akinobu Mita Suggested-by: Andrew Morton Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Américo Wang Cc: Dave Jones --- * v5 - make testing scripts a part of tools/testing/selftests - do simple on/offline tests even if no notifier error injection support tools/testing/selftests/Makefile |2 +- tools/testing/selftests/cpu-hotplug/Makefile |6 + tools/testing/selftests/cpu-hotplug/on-off-test.sh | 221 +++ tools/testing/selftests/memory-hotplug/Makefile|6 + .../selftests/memory-hotplug/on-off-test.sh| 230 5 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/cpu-hotplug/Makefile create mode 100755 tools/testing/selftests/cpu-hotplug/on-off-test.sh create mode 100644 tools/testing/selftests/memory-hotplug/Makefile create mode 100755 tools/testing/selftests/memory-hotplug/on-off-test.sh diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index a4162e1..85baf11 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -1,4 +1,4 @@ -TARGETS = breakpoints kcmp mqueue vm +TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug all: for TARGET in $(TARGETS); do \ diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile new file mode 100644 index 000..7c9c20f --- /dev/null +++ b/tools/testing/selftests/cpu-hotplug/Makefile @@ -0,0 +1,6 @@ +all: + +run_tests: + ./on-off-test.sh + +clean: diff --git a/tools/testing/selftests/cpu-hotplug/on-off-test.sh b/tools/testing/selftests/cpu-hotplug/on-off-test.sh new file mode 100755 index 000..bdde7cf --- /dev/null +++ b/tools/testing/selftests/cpu-hotplug/on-off-test.sh @@ -0,0 +1,221 @@ +#!/bin/bash + +SYSFS= + +prerequisite() +{ + msg="skip all tests:" + + if [ $UID != 0 ]; then + echo $msg must be run as root >&2 + exit 0 + fi + + SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` + + if [ ! -d "$SYSFS" ]; then + echo $msg sysfs is not mounted >&2 + exit 0 + fi + + if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then + echo $msg cpu hotplug is not supported >&2 + exit 0 + fi +} + +# +# list all hot-pluggable CPUs +# +hotpluggable_cpus() +{ + local state=${1:-.\*} + + for cpu in $SYSFS/devices/system/cpu/cpu*; do + if [ -f $cpu/online ] && grep -q $state $cpu/online; then + echo ${cpu##/*/cpu} + fi + done +} + +hotplaggable_offline_cpus() +{ + hotpluggable_cpus 0 +} + +hotpluggable_online_cpus() +{ + hotpluggable_cpus 1 +} + +cpu_is_online() +{ + grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online +} + +cpu_is_offline() +{ + grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online +} + +online_cpu() +{ + echo 1 > $SYSFS/devices/system/cpu/cpu$1/online +} + +offline_cpu() +{ + echo 0 > $SYSFS/devices/system/cpu/cpu$1/online +} + +online_cpu_expect_success() +{ + local cpu=$1 + + if ! online_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +online_cpu_expect_fail() +{ + local cpu=$1 + + if online_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected onl
[PATCH -v5 5/6] powerpc: pSeries reconfig notifier error injection module
This provides the ability to inject artifical errors to pSeries reconfig notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/notifier-error-inject/pSeries-reconfig If the notifier call chain should be failed with some events notified, write the error code to "actions//error". Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- No changes since v4 lib/Kconfig.debug| 17 + lib/Makefile |2 + lib/pSeries-reconfig-notifier-error-inject.c | 51 ++ 3 files changed, 70 insertions(+) create mode 100644 lib/pSeries-reconfig-notifier-error-inject.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 7cceddc..8f8e226 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1166,6 +1166,23 @@ config MEMORY_NOTIFIER_ERROR_INJECT If unsure, say N. +config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT + tristate "pSeries reconfig notifier error injection module" + depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + pSeries reconfig notifier chain callbacks. It is controlled + through debugfs interface under + /sys/kernel/debug/notifier-error-inject/pSeries-reconfig/ + + If the notifier call chain should be failed with some events + notified, write the error code to "actions//error". + + To compile this code as a module, choose M here: the module will + be called memory-notifier-error-inject. + + If unsure, say N. + config FAULT_INJECTION bool "Fault-injection framework" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index a867aa5..d055cb1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -94,6 +94,8 @@ obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o +obj-$(CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT) += \ + pSeries-reconfig-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/pSeries-reconfig-notifier-error-inject.c b/lib/pSeries-reconfig-notifier-error-inject.c new file mode 100644 index 000..7f7c98d --- /dev/null +++ b/lib/pSeries-reconfig-notifier-error-inject.c @@ -0,0 +1,51 @@ +#include +#include + +#include + +#include "notifier-error-inject.h" + +static int priority; +module_param(priority, int, 0); +MODULE_PARM_DESC(priority, "specify pSeries reconfig notifier priority"); + +static struct notifier_err_inject reconfig_err_inject = { + .actions = { + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_RECONFIG_ADD) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_RECONFIG_REMOVE) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_DRCONF_MEM_ADD) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_DRCONF_MEM_REMOVE) }, + {} + } +}; + +static struct dentry *dir; + +static int err_inject_init(void) +{ + int err; + + dir = notifier_err_inject_init("pSeries-reconfig", + notifier_err_inject_dir, &reconfig_err_inject, priority); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + err = pSeries_reconfig_notifier_register(&reconfig_err_inject.nb); + if (err) + debugfs_remove_recursive(dir); + + return err; +} + +static void err_inject_exit(void) +{ + pSeries_reconfig_notifier_unregister(&reconfig_err_inject.nb); + debugfs_remove_recursive(dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("pSeries reconfig notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); -- 1.7.10.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH -v4 6/6] fault-injection: add notifier error injection testing scripts
2012/6/27 Andrew Morton : > On Sat, 23 Jun 2012 23:58:22 +0900 > Akinobu Mita wrote: > >> This adds two testing scripts with notifier error injection > > Can we move these into tools/testing/selftests/, so that a "make > run_tests" runs these tests? > > Also, I don't think it's appropriate that "fault-injection" be in the > path - that's an implementation detail. What we're testing here is > memory hotplug, pm, cpu hotplug, etc. So each test would go into, say, > tools/testing/selftests/cpu-hotplug. > > Now, your cpu-hotplug test only tests a tiny part of the cpu-hotplug > code. But it is a start, and creates the place where additional tests > will be placed in the future. > > > If the kernel configuration means that the tests cannot be run, the > attempt should succeed so that other tests are not disrupted. I guess > that printing a warning in this case is useful. > > Probably the selftests will require root permissions - we haven't > really thought about that much. If these tests require root (I assume > they do?) then a sensible approach would be to check for that and to > emit a warning and return "success". Thanks for your advice. I'm going to make the following changes on these scripts 1. Change these paths to: tools/testing/selftests/{cpu,memory}-hotplug/on-off-test.sh 2. Skip tests and exit(0) with a warning if no root or no sysfs so that a "make run_tests" doesn't stop. 3. Add tests that simply online and offline cpus (or memory blocks) and then tests with this notifier error injection features if the kernel supports. > My overall take on the fault-injection code is that there has been a > disappointing amount of uptake: I don't see many developers using them > for whitebox testing their stuff. I guess this patchset addresses > that, in a way. I hope so. the impact of notifier error injection is restricted to the particular kernel functionarity and these scripts are easy to run. On the other hand, fault injection like failslab has a huge impact on any kernel components and it often results catastrophe to userspace even if no kernel bug. I am confident that I can find a certain amount of kernel bugs with failslab but it requires enough spare time. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -v4 6/6] fault-injection: add notifier error injection testing scripts
This adds two testing scripts with notifier error injection * tools/testing/fault-injection/cpu-notifier.sh is testing script for CPU notifier error handling by using cpu-notifier-error-inject.ko. 1. Offline all hot-pluggable CPUs in preparation for testing 2. Test CPU hot-add error handling by injecting notifier errors 3. Online all hot-pluggable CPUs in preparation for testing 4. Test CPU hot-remove error handling by injecting notifier errors * tools/testing/fault-injection/memory-notifier.sh is doing the similar thing for memory hotplug notifier. 1. Offline 10% of hot-pluggable memory in preparation for testing 2. Test memory hot-add error handling by injecting notifier errors 3. Online all hot-pluggable memory in preparation for testing 4. Test memory hot-remove error handling by injecting notifier errors Signed-off-by: Akinobu Mita Suggested-by: Andrew Morton Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Américo Wang --- * v4 - add -r option for memory-notifier.sh to specify percent of offlining memory blocks tools/testing/fault-injection/cpu-notifier.sh| 169 + tools/testing/fault-injection/memory-notifier.sh | 176 ++ 2 files changed, 345 insertions(+) create mode 100755 tools/testing/fault-injection/cpu-notifier.sh create mode 100755 tools/testing/fault-injection/memory-notifier.sh diff --git a/tools/testing/fault-injection/cpu-notifier.sh b/tools/testing/fault-injection/cpu-notifier.sh new file mode 100755 index 000..af93630 --- /dev/null +++ b/tools/testing/fault-injection/cpu-notifier.sh @@ -0,0 +1,169 @@ +#!/bin/bash + +# +# list all hot-pluggable CPUs +# +hotpluggable_cpus() +{ + local state=${1:-.\*} + + for cpu in /sys/devices/system/cpu/cpu*; do + if [ -f $cpu/online ] && grep -q $state $cpu/online; then + echo ${cpu##/*/cpu} + fi + done +} + +hotplaggable_offline_cpus() +{ + hotpluggable_cpus 0 +} + +hotpluggable_online_cpus() +{ + hotpluggable_cpus 1 +} + +cpu_is_online() +{ + grep -q 1 /sys/devices/system/cpu/cpu$1/online +} + +cpu_is_offline() +{ + grep -q 0 /sys/devices/system/cpu/cpu$1/online +} + +add_cpu() +{ + echo 1 > /sys/devices/system/cpu/cpu$1/online +} + +remove_cpu() +{ + echo 0 > /sys/devices/system/cpu/cpu$1/online +} + +add_cpu_expect_success() +{ + local cpu=$1 + + if ! add_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +add_cpu_expect_fail() +{ + local cpu=$1 + + if add_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected online >&2 + fi +} + +remove_cpu_expect_success() +{ + local cpu=$1 + + if ! remove_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +remove_cpu_expect_fail() +{ + local cpu=$1 + + if remove_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +if [ $UID != 0 ]; then + echo must be run as root >&2 + exit 1 +fi + +error=-12 +priority=0 + +while getopts e:hp: opt; do + case $opt in + e) + error=$OPTARG + ;; + h) + echo "Usage $0 [ -e errno ] [ -p notifier-priority ]" + exit + ;; + p) + priority=$OPTARG + ;; + esac +done + +if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then + echo "error code must be -4095 <= errno < 0" >&2 + exit 1 +fi + +DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` + +if [ ! -d "$DEBUGFS" ]; then + echo debugfs is not mounted >&2 + exit 1 +fi + +/sbin/modprobe -r cpu-notifier-error-inject +/sbin/modprobe -q cpu-notifier-error-inject priority=$priority + +NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu + +if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then + echo cpu-notifier-error-inject module is not available >&2 + exit 1 +fi + +# +# Offline all hot-pluggable CPUs +# +echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +for cpu in `hotpluggable_online_cpus`; do + remove_cpu_expect_success $cpu +done + +# +# Test CPU hot-add
[PATCH -v4 5/6] powerpc: pSeries reconfig notifier error injection module
This provides the ability to inject artifical errors to pSeries reconfig notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/notifier-error-inject/pSeries-reconfig If the notifier call chain should be failed with some events notified, write the error code to "actions//error". Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- * v4 - update modules to follow new interface lib/Kconfig.debug| 17 + lib/Makefile |2 + lib/pSeries-reconfig-notifier-error-inject.c | 51 ++ 3 files changed, 70 insertions(+) create mode 100644 lib/pSeries-reconfig-notifier-error-inject.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 7cceddc..8f8e226 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1166,6 +1166,23 @@ config MEMORY_NOTIFIER_ERROR_INJECT If unsure, say N. +config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT + tristate "pSeries reconfig notifier error injection module" + depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + pSeries reconfig notifier chain callbacks. It is controlled + through debugfs interface under + /sys/kernel/debug/notifier-error-inject/pSeries-reconfig/ + + If the notifier call chain should be failed with some events + notified, write the error code to "actions//error". + + To compile this code as a module, choose M here: the module will + be called memory-notifier-error-inject. + + If unsure, say N. + config FAULT_INJECTION bool "Fault-injection framework" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index a867aa5..d055cb1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -94,6 +94,8 @@ obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o +obj-$(CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT) += \ + pSeries-reconfig-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/pSeries-reconfig-notifier-error-inject.c b/lib/pSeries-reconfig-notifier-error-inject.c new file mode 100644 index 000..7f7c98d --- /dev/null +++ b/lib/pSeries-reconfig-notifier-error-inject.c @@ -0,0 +1,51 @@ +#include +#include + +#include + +#include "notifier-error-inject.h" + +static int priority; +module_param(priority, int, 0); +MODULE_PARM_DESC(priority, "specify pSeries reconfig notifier priority"); + +static struct notifier_err_inject reconfig_err_inject = { + .actions = { + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_RECONFIG_ADD) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_RECONFIG_REMOVE) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_DRCONF_MEM_ADD) }, + { NOTIFIER_ERR_INJECT_ACTION(PSERIES_DRCONF_MEM_REMOVE) }, + {} + } +}; + +static struct dentry *dir; + +static int err_inject_init(void) +{ + int err; + + dir = notifier_err_inject_init("pSeries-reconfig", + notifier_err_inject_dir, &reconfig_err_inject, priority); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + err = pSeries_reconfig_notifier_register(&reconfig_err_inject.nb); + if (err) + debugfs_remove_recursive(dir); + + return err; +} + +static void err_inject_exit(void) +{ + pSeries_reconfig_notifier_unregister(&reconfig_err_inject.nb); + debugfs_remove_recursive(dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("pSeries reconfig notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); -- 1.7.10.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -v4 1/6] fault-injection: notifier error injection
The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Michael Ellerman --- * v4 - prefix all APIs with notifier_err_inject_* - rearrange debugfs interface (e.g. $DEBUGFS/cpu-notifier-error-inject/CPU_DOWN_PREPARE --> $DEBUGFS/notifier-error-inject/cpu/actions/CPU_DOWN_PREPARE/error) lib/Kconfig.debug | 11 + lib/Makefile|1 + lib/notifier-error-inject.c | 112 +++ lib/notifier-error-inject.h | 24 ++ 4 files changed, 148 insertions(+) create mode 100644 lib/notifier-error-inject.c create mode 100644 lib/notifier-error-inject.h diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ff5bdee..c848758 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1084,6 +1084,17 @@ config LKDTM Documentation on how to use the module can be found in Documentation/fault-injection/provoke-crashes.txt +config NOTIFIER_ERROR_INJECTION + tristate "Notifier error injection" + depends on DEBUG_KERNEL + select DEBUG_FS + help + This option provides the ability to inject artifical errors to + specified notifier chain callbacks. It is useful to test the error + handling of notifier call chain failures. + + Say N if unsure. + config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" depends on HOTPLUG_CPU && DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index 8c31a0c..23fba9e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o +obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c new file mode 100644 index 000..44b92cb --- /dev/null +++ b/lib/notifier-error-inject.c @@ -0,0 +1,112 @@ +#include + +#include "notifier-error-inject.h" + +static int debugfs_errno_set(void *data, u64 val) +{ + *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0); + return 0; +} + +static int debugfs_errno_get(void *data, u64 *val) +{ + *val = *(int *)data; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + +static struct dentry *debugfs_create_errno(const char *name, mode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_errno); +} + +static int notifier_err_inject_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct notifier_err_inject *err_inject = + container_of(nb, struct notifier_err_inject, nb); + struct notifier_err_inject_action *action; + + for (action = err_inject->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) + pr_info("Injecting error (%d) to %s\n", err, action->name); + + return notifier_from_errno(err); +} + +struct dentry *notifier_err_inject_dir; +EXPORT_SYMBOL_GPL(notifier_err_inject_dir); + +struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent, + struct notifier_err_inject *err_inject, int priority) +{ + struct notifier_err_inject_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + struct dentry *actions_dir; + + err_inject->nb.notifier_call = notifier_err_inject_callback; + err_inject->nb.priority = priority; + + dir = debugfs_create_dir(name, parent); + if (!dir) + return ERR_PTR(-ENOMEM); + + actions_dir = debugfs_create_dir("actions", dir); + if (!actions_dir) + goto fail; + + for (action = err_inject->actions; action->name; action++) { + struct dentry *action_dir; + + action_dir = d
[PATCH -v4 0/6] notifier error injection
This provides kernel modules that can be used to test the error handling of notifier call chain failures by injecting artifical errors to the following notifier chain callbacks. * CPU notifier * PM notifier * memory hotplug notifier * powerpc pSeries reconfig notifier Example: Inject CPU offline error (-1 == -EPERM) # cd /sys/kernel/debug/notifier-error-inject/cpu # echo -1 > actions/CPU_DOWN_PREPARE/error # echo 0 > /sys/devices/system/cpu/cpu1/online bash: echo: write error: Operation not permitted There are also handy shell scripts to test CPU and memory hotplug notifier. Note that these tests didn't detect error handling bugs on my machine but I still think this feature is usefull to test the code path which is rarely executed. Changelog: * v4 (It is about 11 months since v3) - prefix all APIs with notifier_err_inject_* - rearrange debugfs interface (e.g. $DEBUGFS/cpu-notifier-error-inject/CPU_DOWN_PREPARE --> $DEBUGFS/notifier-error-inject/cpu/actions/CPU_DOWN_PREPARE/error) - update modules to follow new interface - add -r option for memory-notifier.sh to specify percent of offlining memory blocks * v3 - rewrite to be kernel modules instead of initializing at late_initcall()s (it makes the diffstat look different but most code remains unchanged) - export err_inject_notifier_block_{init,cleanup} for modules - export pSeries_reconfig_notifier_{,un}register symbols for a module - notifier priority can be specified as a module parameter - add testing scripts in tools/testing/fault-injection * v2 - "PM: Improve error code of pm_notifier_call_chain()" is now in -next - "debugfs: add debugfs_create_int" is dropped - put a comment in err_inject_notifier_block_init() - only allow valid errno to be injected (-MAX_ERRNO <= errno <= 0) - improve Kconfig help text - make CONFIG_PM_NOTIFIER_ERROR_INJECTION visible even if PM_DEBUG is disabled - make CONFIG_PM_NOTIFIER_ERROR_INJECTION default if PM_DEBUG is enabled Akinobu Mita (6): fault-injection: notifier error injection cpu: rewrite cpu-notifier-error-inject module PM: PM notifier error injection module memory: memory notifier error injection module powerpc: pSeries reconfig notifier error injection module fault-injection: add notifier error injection testing scripts lib/Kconfig.debug| 91 ++- lib/Makefile |5 + lib/cpu-notifier-error-inject.c | 63 +++- lib/memory-notifier-error-inject.c | 48 ++ lib/notifier-error-inject.c | 112 ++ lib/notifier-error-inject.h | 24 +++ lib/pSeries-reconfig-notifier-error-inject.c | 51 +++ lib/pm-notifier-error-inject.c | 49 ++ tools/testing/fault-injection/cpu-notifier.sh| 169 + tools/testing/fault-injection/memory-notifier.sh | 176 ++ 10 files changed, 748 insertions(+), 40 deletions(-) create mode 100644 lib/memory-notifier-error-inject.c create mode 100644 lib/notifier-error-inject.c create mode 100644 lib/notifier-error-inject.h create mode 100644 lib/pSeries-reconfig-notifier-error-inject.c create mode 100644 lib/pm-notifier-error-inject.c create mode 100755 tools/testing/fault-injection/cpu-notifier.sh create mode 100755 tools/testing/fault-injection/memory-notifier.sh Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Américo Wang Cc: Michael Ellerman -- 1.7.10.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: use string library
- Use memchr_inv to check if the data contains all 0xFF bytes. It is faster than looping for each byte. - Use memcmp to compare memory areas Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/powermac/nvram.c | 42 ++- 1 files changed, 19 insertions(+), 23 deletions(-) diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 54d2271..da18b26 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -279,7 +279,7 @@ static u32 core99_check(u8* datas) static int sm_erase_bank(int bank) { - int stat, i; + int stat; unsigned long timeout; u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; @@ -301,11 +301,10 @@ static int sm_erase_bank(int bank) out_8(base, SM_FLASH_CMD_CLEAR_STATUS); out_8(base, SM_FLASH_CMD_RESET); - for (i=0; ihttps://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 6/6] fault-injection: add notifier error injection testing scripts
* tools/testing/fault-injection/cpu-notifier.sh is testing script for CPU notifier error handling by using cpu-notifier-error-inject.ko. 1. Offline all hot-pluggable CPUs in preparation for testing 2. Test CPU hot-add error handling by injecting notifier errors 3. Online all hot-pluggable CPUs in preparation for testing 4. Test CPU hot-remove error handling by injecting notifier errors * tools/testing/fault-injection/memory-notifier.sh is doing the same thing for memory hotplug notifier. Signed-off-by: Akinobu Mita Suggested-by: Andrew Morton Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Américo Wang --- * v3 - new patch tools/testing/fault-injection/cpu-notifier.sh| 162 + tools/testing/fault-injection/memory-notifier.sh | 163 ++ 2 files changed, 325 insertions(+), 0 deletions(-) create mode 100755 tools/testing/fault-injection/cpu-notifier.sh create mode 100755 tools/testing/fault-injection/memory-notifier.sh diff --git a/tools/testing/fault-injection/cpu-notifier.sh b/tools/testing/fault-injection/cpu-notifier.sh new file mode 100755 index 000..be02a85 --- /dev/null +++ b/tools/testing/fault-injection/cpu-notifier.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +# +# list all hot-pluggable CPUs +# +hotpluggable_cpus() +{ + local state=${1:-.\*} + + for cpu in /sys/devices/system/cpu/cpu*; do + if [ -f $cpu/online ] && grep -q $state $cpu/online; then + echo ${cpu##/*/cpu} + fi + done +} + +hotplaggable_offline_cpus() +{ + hotpluggable_cpus 0 +} + +hotpluggable_online_cpus() +{ + hotpluggable_cpus 1 +} + +cpu_is_online() +{ + grep -q 1 /sys/devices/system/cpu/cpu$1/online +} + +cpu_is_offline() +{ + grep -q 0 /sys/devices/system/cpu/cpu$1/online +} + +add_cpu() +{ + echo 1 > /sys/devices/system/cpu/cpu$1/online +} + +remove_cpu() +{ + echo 0 > /sys/devices/system/cpu/cpu$1/online +} + +add_cpu_expect_success() +{ + local cpu=$1 + + if ! add_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +add_cpu_expect_fail() +{ + local cpu=$1 + + if add_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected online >&2 + fi +} + +remove_cpu_expect_success() +{ + local cpu=$1 + + if ! remove_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +remove_cpu_expect_fail() +{ + local cpu=$1 + + if remove_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 + fi +} + +if [ $UID != 0 ]; then + echo must be run as root >&2 + exit 1 +fi + +error=-12 +priority=0 + +while getopts e:p: opt; do + case $opt in + e) + error=$OPTARG + ;; + p) + priority=$OPTARG + ;; + esac +done + +if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then + echo "error code must be -4095 <= errno < 0" >&2 + exit 1 +fi + +DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` + +if [ ! -d "$DEBUGFS" ]; then + echo debugfs is not mounted >&2 + exit 1 +fi + +/sbin/modprobe -r cpu-notifier-error-inject +/sbin/modprobe -q cpu-notifier-error-inject priority=$priority + +if [ ! -d $DEBUGFS/cpu-notifier-error-inject ]; then + echo cpu-notifier-error-inject module is not available >&2 + exit 1 +fi + +# +# Offline all hot-pluggable CPUs +# +echo 0 > $DEBUGFS/cpu-notifier-error-inject/CPU_DOWN_PREPARE +for cpu in `hotpluggable_online_cpus`; do + remove_cpu_expect_success $cpu +done + +# +# Test CPU hot-add error handling (offline => online) +# +echo $error > $DEBUGFS/cpu-notifier-error-inject/CPU_UP_PREPARE +for cpu in `hotplaggable_offline_cpus`; do + add_cpu_expect_fail $cpu +done + +# +# Online all hot-pluggable CPUs +# +echo 0 > $DEBUGFS/cpu-notifier-error-inject/CPU_UP_PREPARE +for cpu in `hotplaggable_offline_cpus`; do + add_cpu_expect_success $cpu +done + +# +# Test CPU hot-remove error handling (online => offline) +# +echo $error > $DEBUGFS/cpu-notifier-error-inject/CPU_DOWN_PREPARE +for cpu in `hotpluggable_online_cpus`; do + remove
[PATCH v3 5/6] powerpc: pSeries reconfig notifier error injection module
This provides the ability to inject artifical errors to pSeries reconfig notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/pSeries-reconfig-notifier-error-inject/ Each of the files in the directory represents an event which can be failed and contains the error code. If the notifier call chain should be failed with some events notified, write the error code to the files. This module needs pSeries_reconfig_notifier_{,un}register symbols to be exported. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- * v3 - rewrite to be kernel modules instead of initializing at late_initcall()s - export pSeries_reconfig_notifier_{,un}register symbols for this module - notifier priority can be specified as a module parameter arch/powerpc/platforms/pseries/reconfig.c|2 + lib/Kconfig.debug| 14 +++ lib/Makefile |2 + lib/pSeries-reconfig-notifier-error-inject.c | 48 ++ 4 files changed, 66 insertions(+), 0 deletions(-) create mode 100644 lib/pSeries-reconfig-notifier-error-inject.c diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 168651a..b9808e9 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -103,11 +103,13 @@ int pSeries_reconfig_notifier_register(struct notifier_block *nb) { return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); } +EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register); void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); } +EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister); int pSeries_reconfig_notify(unsigned long action, void *p) { diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a2b0856..46298d7 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1099,6 +1099,20 @@ config MEMORY_NOTIFIER_ERROR_INJECT If unsure, say N. +config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT + tristate "pSeries reconfig notifier error injection module" + depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + pSeries reconfig notifier chain callbacks. It is controlled + through debugfs interface under + /sys/kernel/debug/pSeries-reconfig-notifier-error-inject/ + + To compile this code as a module, choose M here: the module will + be called memory-notifier-error-inject. + + If unsure, say N. + config FAULT_INJECTION bool "Fault-injection framework" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index f28914b..e68cea7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -92,6 +92,8 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o +obj-$(CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT) += \ + pSeries-reconfig-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/pSeries-reconfig-notifier-error-inject.c b/lib/pSeries-reconfig-notifier-error-inject.c new file mode 100644 index 000..f4ed2b3 --- /dev/null +++ b/lib/pSeries-reconfig-notifier-error-inject.c @@ -0,0 +1,48 @@ +#include +#include +#include + +#include + +static int priority; +module_param(priority, int, 0); +MODULE_PARM_DESC(priority, "specify pSeries reconfig notifier priority"); + +static struct err_inject_notifier_block err_inject_reconfig_nb = { + .actions = { + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_RECONFIG_ADD) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_RECONFIG_REMOVE) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_DRCONF_MEM_ADD) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_DRCONF_MEM_REMOVE) }, + {} + } +}; + +static int err_inject_init(void) +{ + int err; + + err = err_inject_notifier_block_init(&err_inject_reconfig_nb, + "pSeries-reconfig-notifier-error-inject", priority); + if (err) + return err; + + err = pSeries_reconfig_notifier_register(&err_inject_reconfig_nb.nb); + if (err) + err_inject_notifier_block_cleanup(&err_inject_reconfig_nb); + + return err; +} + +static void err_inject_exit(void) +{ + pSeries_reconfig_notifier_unregister(&err_inject_reconfig_nb.nb); + err_inject_notifier_block_cleanup(&err_inject_reconfig_nb); +} + +module_init(err_inject_init); +module_exit(err_inject_ex
[PATCH v3 1/6] fault-injection: notifier error injection
The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg KH Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- * v3 - export err_inject_notifier_block_{init,cleanup} for modules include/linux/notifier.h | 25 ++ kernel/notifier.c| 83 ++ lib/Kconfig.debug| 11 ++ 3 files changed, 119 insertions(+), 0 deletions(-) diff --git a/include/linux/notifier.h b/include/linux/notifier.h index c0688b0..51882d6 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -278,5 +278,30 @@ extern struct blocking_notifier_head reboot_notifier_list; #define VT_UPDATE 0x0004 /* A bigger update occurred */ #define VT_PREWRITE0x0005 /* A char is about to be written to the console */ +#ifdef CONFIG_NOTIFIER_ERROR_INJECTION + +struct err_inject_notifier_action { + unsigned long val; + int error; + const char *name; +}; + +#define ERR_INJECT_NOTIFIER_ACTION(action) \ + .name = #action, .val = (action), + +struct err_inject_notifier_block { + struct notifier_block nb; + struct dentry *dir; + struct err_inject_notifier_action actions[]; + /* The last slot must be terminated with zero sentinel */ +}; + +extern int err_inject_notifier_block_init(struct err_inject_notifier_block *enb, + const char *name, int priority); +extern void err_inject_notifier_block_cleanup( + struct err_inject_notifier_block *enb); + +#endif /* CONFIG_NOTIFIER_ERROR_INJECTION */ + #endif /* __KERNEL__ */ #endif /* _LINUX_NOTIFIER_H */ diff --git a/kernel/notifier.c b/kernel/notifier.c index 2488ba7..8dcb2cc 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -5,6 +5,7 @@ #include #include #include +#include /* * Notifier list for kernel code which wants to be called @@ -584,3 +585,85 @@ int unregister_die_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&die_chain, nb); } EXPORT_SYMBOL_GPL(unregister_die_notifier); + +#ifdef CONFIG_NOTIFIER_ERROR_INJECTION + +static int debugfs_errno_set(void *data, u64 val) +{ + *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0); + return 0; +} + +static int debugfs_errno_get(void *data, u64 *val) +{ + *val = *(int *)data; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + +static struct dentry *debugfs_create_errno(const char *name, mode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_errno); +} + +static int err_inject_notifier_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct err_inject_notifier_block *enb = + container_of(nb, struct err_inject_notifier_block, nb); + struct err_inject_notifier_action *action; + + for (action = enb->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) { + printk(KERN_INFO "Injecting error (%d) to %s\n", + err, action->name); + } + + return notifier_from_errno(err); +} + +int err_inject_notifier_block_init(struct err_inject_notifier_block *enb, + const char *name, int priority) +{ + struct err_inject_notifier_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + + enb->nb.notifier_call = err_inject_notifier_callback; + enb->nb.priority = priority; + + enb->dir = debugfs_create_dir(name, NULL); + if (!enb->dir) + return -ENOMEM; + + for (action = enb->actions; action->name; action++) { + /* +* Create debugfs r/w file containing action->error. If +* notifier call chain is called with action->val, it will +* fail with the error code +*/ + if (!debugfs_create_errno(action->name, mode, enb->dir, + &action->error)) { + debugfs_remove_recursive(enb->dir); +
[PATCH v2 5/5] powerpc: pSeries reconfig notifier error injection
This provides the ability to inject artifical errors to pSeries reconfig notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/pSeries-reconfig-notifier-error-inject/ Each of the files in the directory represents an event which can be failed and contains the error code. If the notifier call chain should be failed with some events notified, write the error code to the files. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- - Nothing changed from v1 arch/powerpc/platforms/pseries/reconfig.c | 31 + lib/Kconfig.debug |9 2 files changed, 40 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 168651a..31d9b0f 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -117,6 +117,37 @@ int pSeries_reconfig_notify(unsigned long action, void *p) return notifier_to_errno(err); } +#ifdef CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECTION + +static struct err_inject_notifier_block err_inject_reconfig_nb = { + .actions = { + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_RECONFIG_ADD) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_RECONFIG_REMOVE) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_DRCONF_MEM_ADD) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_DRCONF_MEM_REMOVE) }, + {} + } +}; + +static int __init err_inject_reconfig_notifier_init(void) +{ + int err; + + err = err_inject_notifier_block_init(&err_inject_reconfig_nb, + "pSeries-reconfig-notifier-error-inject", -1); + if (err) + return err; + + err = pSeries_reconfig_notifier_register(&err_inject_reconfig_nb.nb); + if (err) + err_inject_notifier_block_cleanup(&err_inject_reconfig_nb); + + return err; +} +late_initcall(err_inject_reconfig_notifier_init); + +#endif /* CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECTION */ + static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { struct device_node *np; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 8f5c380..d713000 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1080,6 +1080,15 @@ config MEMORY_NOTIFIER_ERROR_INJECTION # echo offline > /sys/devices/system/memory/memoryXXX/state bash: echo: write error: Cannot allocate memory +config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECTION + bool "pSeries reconfig notifier error injection" + depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + pSeries reconfig notifier chain callbacks. It is controlled + through debugfs interface under + /sys/kernel/debug/pSeries-reconfig-notifier-error-inject/ + config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" depends on HOTPLUG_CPU && DEBUG_KERNEL -- 1.7.4.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 1/5] fault-injection: notifier error injection
The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux...@lists.linux-foundation.org Cc: Greg Kroah-Hartman Cc: linux...@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- * v2 - put a comment in err_inject_notifier_block_init() - only allow valid errno to be injected (-MAX_ERRNO <= errno <= 0) include/linux/notifier.h | 25 ++ kernel/notifier.c| 81 ++ lib/Kconfig.debug| 11 ++ 3 files changed, 117 insertions(+), 0 deletions(-) diff --git a/include/linux/notifier.h b/include/linux/notifier.h index c0688b0..51882d6 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -278,5 +278,30 @@ extern struct blocking_notifier_head reboot_notifier_list; #define VT_UPDATE 0x0004 /* A bigger update occurred */ #define VT_PREWRITE0x0005 /* A char is about to be written to the console */ +#ifdef CONFIG_NOTIFIER_ERROR_INJECTION + +struct err_inject_notifier_action { + unsigned long val; + int error; + const char *name; +}; + +#define ERR_INJECT_NOTIFIER_ACTION(action) \ + .name = #action, .val = (action), + +struct err_inject_notifier_block { + struct notifier_block nb; + struct dentry *dir; + struct err_inject_notifier_action actions[]; + /* The last slot must be terminated with zero sentinel */ +}; + +extern int err_inject_notifier_block_init(struct err_inject_notifier_block *enb, + const char *name, int priority); +extern void err_inject_notifier_block_cleanup( + struct err_inject_notifier_block *enb); + +#endif /* CONFIG_NOTIFIER_ERROR_INJECTION */ + #endif /* __KERNEL__ */ #endif /* _LINUX_NOTIFIER_H */ diff --git a/kernel/notifier.c b/kernel/notifier.c index 2488ba7..8824ae3 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -5,6 +5,7 @@ #include #include #include +#include /* * Notifier list for kernel code which wants to be called @@ -584,3 +585,83 @@ int unregister_die_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&die_chain, nb); } EXPORT_SYMBOL_GPL(unregister_die_notifier); + +#ifdef CONFIG_NOTIFIER_ERROR_INJECTION + +static int debugfs_errno_set(void *data, u64 val) +{ + *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0); + return 0; +} + +static int debugfs_errno_get(void *data, u64 *val) +{ + *val = *(int *)data; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + +static struct dentry *debugfs_create_errno(const char *name, mode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_errno); +} + +static int err_inject_notifier_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct err_inject_notifier_block *enb = + container_of(nb, struct err_inject_notifier_block, nb); + struct err_inject_notifier_action *action; + + for (action = enb->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) { + printk(KERN_INFO "Injecting error (%d) to %s\n", + err, action->name); + } + + return notifier_from_errno(err); +} + +int err_inject_notifier_block_init(struct err_inject_notifier_block *enb, + const char *name, int priority) +{ + struct err_inject_notifier_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + + enb->nb.notifier_call = err_inject_notifier_callback; + enb->nb.priority = priority; + + enb->dir = debugfs_create_dir(name, NULL); + if (!enb->dir) + return -ENOMEM; + + for (action = enb->actions; action->name; action++) { + /* +* Create debugfs r/w file containing action->error. If +* notifier call chain is called with action->val, it will +* fail with the error code +*/ + if (!debugfs_create_errno(action->name, mode, enb->dir, + &action->error)) { +
Re: [PATCH 3/7] fault-injection: notifier error injection
2011/7/4 Pavel Machek : > >> + for (action = enb->actions; action->name; action++) { >> + struct dentry *file = debugfs_create_int(action->name, mode, >> + enb->dir, &action->error); >> + >> + if (!file) { >> + debugfs_remove_recursive(enb->dir); >> + return -ENOMEM; >> + } > > Few lines how this work would be welcome...? OK, I'll add a comment like below. /* * Create debugfs r/w file containing action->error. If notifier call * chain is called with action->val, it will fail with the error code */ ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 7/7] powerpc: pSeries reconfig notifier error injection
This provides the ability to inject artifical errors to pSeries reconfig notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/pSeries-reconfig-notifier-error-inject/ Each of the files in the directory represents an event which can be failed and contains the error code. If the notifier call chain should be failed with some events notified, write the error code to the files. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/pseries/reconfig.c | 31 + lib/Kconfig.debug |9 2 files changed, 40 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 168651a..31d9b0f 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -117,6 +117,37 @@ int pSeries_reconfig_notify(unsigned long action, void *p) return notifier_to_errno(err); } +#ifdef CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECTION + +static struct err_inject_notifier_block err_inject_reconfig_nb = { + .actions = { + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_RECONFIG_ADD) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_RECONFIG_REMOVE) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_DRCONF_MEM_ADD) }, + { ERR_INJECT_NOTIFIER_ACTION(PSERIES_DRCONF_MEM_REMOVE) }, + {} + } +}; + +static int __init err_inject_reconfig_notifier_init(void) +{ + int err; + + err = err_inject_notifier_block_init(&err_inject_reconfig_nb, + "pSeries-reconfig-notifier-error-inject", -1); + if (err) + return err; + + err = pSeries_reconfig_notifier_register(&err_inject_reconfig_nb.nb); + if (err) + err_inject_notifier_block_cleanup(&err_inject_reconfig_nb); + + return err; +} +late_initcall(err_inject_reconfig_notifier_init); + +#endif /* CONFIG_PSERIES_RECONFIG_NOTIFIER_ERROR_INJECTION */ + static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { struct device_node *np; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 52f0b0e..2becf8c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1059,6 +1059,15 @@ config MEMORY_NOTIFIER_ERROR_INJECTION memory hotplug notifier chain callbacks. It is controlled through debugfs interface under /sys/kernel/debug/memory-notifier-error-inject/ +config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECTION + bool "pSeries reconfig notifier error injection" + depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION + help + This option provides the ability to inject artifical errors to + pSeries reconfig notifier chain callbacks. It is controlled + through debugfs interface under + /sys/kernel/debug/pSeries-reconfig-notifier-error-inject/ + config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" depends on HOTPLUG_CPU && DEBUG_KERNEL -- 1.7.4.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/7] fault-injection: notifier error injection
The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Greg Kroah-Hartman Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linux...@lists.linux-foundation.org Cc: linux...@kvack.org Cc: linuxppc-dev@lists.ozlabs.org --- include/linux/notifier.h | 25 kernel/notifier.c| 57 ++ lib/Kconfig.debug| 11 + 3 files changed, 93 insertions(+), 0 deletions(-) diff --git a/include/linux/notifier.h b/include/linux/notifier.h index c0688b0..51882d6 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -278,5 +278,30 @@ extern struct blocking_notifier_head reboot_notifier_list; #define VT_UPDATE 0x0004 /* A bigger update occurred */ #define VT_PREWRITE0x0005 /* A char is about to be written to the console */ +#ifdef CONFIG_NOTIFIER_ERROR_INJECTION + +struct err_inject_notifier_action { + unsigned long val; + int error; + const char *name; +}; + +#define ERR_INJECT_NOTIFIER_ACTION(action) \ + .name = #action, .val = (action), + +struct err_inject_notifier_block { + struct notifier_block nb; + struct dentry *dir; + struct err_inject_notifier_action actions[]; + /* The last slot must be terminated with zero sentinel */ +}; + +extern int err_inject_notifier_block_init(struct err_inject_notifier_block *enb, + const char *name, int priority); +extern void err_inject_notifier_block_cleanup( + struct err_inject_notifier_block *enb); + +#endif /* CONFIG_NOTIFIER_ERROR_INJECTION */ + #endif /* __KERNEL__ */ #endif /* _LINUX_NOTIFIER_H */ diff --git a/kernel/notifier.c b/kernel/notifier.c index 2488ba7..8dcc485 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -5,6 +5,7 @@ #include #include #include +#include /* * Notifier list for kernel code which wants to be called @@ -584,3 +585,59 @@ int unregister_die_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&die_chain, nb); } EXPORT_SYMBOL_GPL(unregister_die_notifier); + +#ifdef CONFIG_NOTIFIER_ERROR_INJECTION + +static int err_inject_notifier_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct err_inject_notifier_block *enb = + container_of(nb, struct err_inject_notifier_block, nb); + struct err_inject_notifier_action *action; + + for (action = enb->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) { + printk(KERN_INFO "Injecting error (%d) to %s\n", + err, action->name); + } + + return notifier_from_errno(err); +} + +int err_inject_notifier_block_init(struct err_inject_notifier_block *enb, + const char *name, int priority) +{ + struct err_inject_notifier_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + + enb->nb.notifier_call = err_inject_notifier_callback; + enb->nb.priority = priority; + + enb->dir = debugfs_create_dir(name, NULL); + if (!enb->dir) + return -ENOMEM; + + for (action = enb->actions; action->name; action++) { + struct dentry *file = debugfs_create_int(action->name, mode, + enb->dir, &action->error); + + if (!file) { + debugfs_remove_recursive(enb->dir); + return -ENOMEM; + } + } + return 0; +} + +void err_inject_notifier_block_cleanup(struct err_inject_notifier_block *enb) +{ + debugfs_remove_recursive(enb->dir); +} + +#endif /* CONFIG_NOTIFIER_ERROR_INJECTION */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index dd373c8..8c6ce7e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1018,6 +1018,17 @@ config LKDTM Documentation on how to use the module can be found in Documentation/fault-injection/provoke-crashes.txt +config NOTIFIER_ERROR_INJECTION + bool "Notifier error injection" + depends on DEBUG_KERNEL + select DEBUG_FS + help + This option provides the ability to inject artifical errors to + specified notifier chain callbacks. It is useful t
[PATCH 2/2] powerpc: improve error code on reconfiguration notifier failure
Reconfiguration notifier call for device node may fail by several reasons, but it always assumes kmalloc failures. This enables reconfiguration notifier call chain to get the actual error code rather than -ENOMEM by converting all reconfiguration notifier calls to return encapsulate error code with notifier_from_errno(). Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/kernel/prom.c |8 +++- arch/powerpc/platforms/pseries/hotplug-cpu.c| 10 +++--- arch/powerpc/platforms/pseries/hotplug-memory.c | 16 +--- arch/powerpc/platforms/pseries/reconfig.c |4 +--- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 8c3112a..86677ba 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -862,16 +862,14 @@ static int prom_reconfig_notifier(struct notifier_block *nb, switch (action) { case PSERIES_RECONFIG_ADD: err = of_finish_dynamic_node(node); - if (err < 0) { + if (err < 0) printk(KERN_ERR "finish_node returned %d\n", err); - err = NOTIFY_BAD; - } break; default: - err = NOTIFY_DONE; + err = 0; break; } - return err; + return notifier_from_errno(err); } static struct notifier_block prom_reconfig_nb = { diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 46f13a3..bc02885 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -330,21 +330,17 @@ static void pseries_remove_processor(struct device_node *np) static int pseries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node) { - int err = NOTIFY_OK; + int err = 0; switch (action) { case PSERIES_RECONFIG_ADD: - if (pseries_add_processor(node)) - err = NOTIFY_BAD; + err = pseries_add_processor(node); break; case PSERIES_RECONFIG_REMOVE: pseries_remove_processor(node); break; - default: - err = NOTIFY_DONE; - break; } - return err; + return notifier_from_errno(err); } static struct notifier_block pseries_smp_nb = { diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 33867ec..1eaefd6 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -197,27 +197,21 @@ static int pseries_drconf_memory(unsigned long *base, unsigned int action) static int pseries_memory_notifier(struct notifier_block *nb, unsigned long action, void *node) { - int err = NOTIFY_OK; + int err = 0; switch (action) { case PSERIES_RECONFIG_ADD: - if (pseries_add_memory(node)) - err = NOTIFY_BAD; + err = pseries_add_memory(node); break; case PSERIES_RECONFIG_REMOVE: - if (pseries_remove_memory(node)) - err = NOTIFY_BAD; + err = pseries_remove_memory(node); break; case PSERIES_DRCONF_MEM_ADD: case PSERIES_DRCONF_MEM_REMOVE: - if (pseries_drconf_memory(node, action)) - err = NOTIFY_BAD; - break; - default: - err = NOTIFY_DONE; + err = pseries_drconf_memory(node, action); break; } - return err; + return notifier_from_errno(err); } static struct notifier_block pseries_mem_nb = { diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 286b6af..168651a 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -114,9 +114,7 @@ int pSeries_reconfig_notify(unsigned long action, void *p) int err = blocking_notifier_call_chain(&pSeries_reconfig_chain, action, p); - if (err == NOTIFY_BAD) - return -ENOMEM; /* For now, safe to assume kmalloc failure */ - return 0; + return notifier_to_errno(err); } static int pSeries_reconfig_add_node(const char *path, struct property *proplist) -- 1.7.4.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2] powerpc: introduce pSeries_reconfig_notify()
This introduces pSeries_reconfig_notify() as a just wrapper of blocking_notifier_call_chain() for pSeries_reconfig_chain. This is a preparation to improvement of error code on reconfiguration notifier failure. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/include/asm/pSeries_reconfig.h |2 +- arch/powerpc/platforms/pseries/dlpar.c | 10 +++- arch/powerpc/platforms/pseries/reconfig.c | 30 -- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h index 89d2f99..23cd6cc 100644 --- a/arch/powerpc/include/asm/pSeries_reconfig.h +++ b/arch/powerpc/include/asm/pSeries_reconfig.h @@ -17,7 +17,7 @@ #ifdef CONFIG_PPC_PSERIES extern int pSeries_reconfig_notifier_register(struct notifier_block *); extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); -extern struct blocking_notifier_head pSeries_reconfig_chain; +extern int pSeries_reconfig_notify(unsigned long action, void *p); /* Not the best place to put this, will be fixed when we move some * of the rtas suspend-me stuff to pseries */ extern void pSeries_coalesce_init(void); diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 57ceb92..e9be25b 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -262,12 +262,11 @@ int dlpar_attach_node(struct device_node *dn) if (!dn->parent) return -ENOMEM; - rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, - PSERIES_RECONFIG_ADD, dn); - if (rc == NOTIFY_BAD) { + rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn); + if (rc) { printk(KERN_ERR "Failed to add device node %s\n", dn->full_name); - return -ENOMEM; /* For now, safe to assume kmalloc failure */ + return rc; } of_attach_node(dn); @@ -297,8 +296,7 @@ int dlpar_detach_node(struct device_node *dn) remove_proc_entry(dn->pde->name, parent->pde); #endif - blocking_notifier_call_chain(&pSeries_reconfig_chain, - PSERIES_RECONFIG_REMOVE, dn); + pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn); of_detach_node(dn); of_node_put(dn); /* Must decrement the refcount */ diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 1de2cbb..286b6af 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -97,7 +97,7 @@ static struct device_node *derive_parent(const char *path) return parent; } -BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); +static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); int pSeries_reconfig_notifier_register(struct notifier_block *nb) { @@ -109,6 +109,16 @@ void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); } +int pSeries_reconfig_notify(unsigned long action, void *p) +{ + int err = blocking_notifier_call_chain(&pSeries_reconfig_chain, + action, p); + + if (err == NOTIFY_BAD) + return -ENOMEM; /* For now, safe to assume kmalloc failure */ + return 0; +} + static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { struct device_node *np; @@ -132,11 +142,9 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist goto out_err; } - err = blocking_notifier_call_chain(&pSeries_reconfig_chain, - PSERIES_RECONFIG_ADD, np); - if (err == NOTIFY_BAD) { + err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np); + if (err) { printk(KERN_ERR "Failed to add device node %s\n", path); - err = -ENOMEM; /* For now, safe to assume kmalloc failure */ goto out_err; } @@ -173,8 +181,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) remove_node_proc_entries(np); - blocking_notifier_call_chain(&pSeries_reconfig_chain, - PSERIES_RECONFIG_REMOVE, np); + pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np); of_detach_node(np); of_node_put(parent); @@ -472,11 +479,10 @@ static int do_update_property(char *buf, size_t bufsize) else action = PSERIES_DRCONF_MEM_REMOVE; - rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, - action, value); -
Re: [PATCH -mm 2/6] powerpc: convert little-endian bitops macros to static inline functions
2011/2/7 Benjamin Herrenschmidt : > On Thu, 2011-01-27 at 22:56 +0900, Akinobu Mita wrote: >> (This patch is intended to be folded into the patch in -mm: >> powerpc-introduce-little-endian-bitops.patch) >> >> The little-endian bitops on powerpc are written as preprocessor >> macros with the cast to "unsigned long *". >> This means that even non-pointers will be accepted without an error, and >> that is a Very Bad Thing. >> >> This converts the little-endian bitops macros to static inline functions >> with proper prototypes. > > No objection to the powerpc variant of the patches. What is the status > with the wholes series tho ? Does it looks like its going to be > accepted ? Do you expect my Ack and will merge the whole thing at once ? The whole series now seems acceptable since I fixed two issues that Linus found annoying. (the naming and the change of prototype) Please give your ack if it is OK. I should have fixed them quickly so that the series went upstream in the last merge windows. But I couldn't because I spent some time fixing and compile testing for a bisection hole. > Does it break bisection unless it's merged as one single giant patch ? I think there is no known problem that breaks bisectability by this patch series. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 2/6] powerpc: convert little-endian bitops macros to static inline functions
(This patch is intended to be folded into the patch in -mm: powerpc-introduce-little-endian-bitops.patch) The little-endian bitops on powerpc are written as preprocessor macros with the cast to "unsigned long *". This means that even non-pointers will be accepted without an error, and that is a Very Bad Thing. This converts the little-endian bitops macros to static inline functions with proper prototypes. Suggested-by: "H. Peter Anvin" Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/include/asm/bitops.h | 43 + 1 files changed, 29 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index fe67024..2e56187 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -288,20 +288,35 @@ static __inline__ int test_bit_le(unsigned long nr, return (tmp[nr >> 3] >> (nr & 7)) & 1; } -#define __set_bit_le(nr, addr) \ - __set_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) -#define __clear_bit_le(nr, addr) \ - __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) - -#define test_and_set_bit_le(nr, addr) \ - test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) -#define test_and_clear_bit_le(nr, addr) \ - test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) - -#define __test_and_set_bit_le(nr, addr) \ - __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) -#define __test_and_clear_bit_le(nr, addr) \ - __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) +static inline void __set_bit_le(int nr, void *addr) +{ + __set_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline void __clear_bit_le(int nr, void *addr) +{ + __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline int test_and_set_bit_le(int nr, void *addr) +{ + return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline int test_and_clear_bit_le(int nr, void *addr) +{ + return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline int __test_and_set_bit_le(int nr, void *addr) +{ + return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline int __test_and_clear_bit_le(int nr, void *addr) +{ + return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} #define find_first_zero_bit_le(addr, size) \ find_next_zero_bit_le((addr), (size), 0) -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v5 06/27] powerpc: introduce little-endian bitops
Introduce little-endian bit operations by renaming existing powerpc native little-endian bit operations and changing them to take any pointer types. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- Change from v4: - change the prototypes and add casts in the macro to take any pointer types The whole series is available in the git branch at: git://git.kernel.org/pub/scm/linux/kernel/git/mita/linux-2.6.git le-bitops-v5 arch/powerpc/include/asm/bitops.h | 46 ++-- 1 files changed, 23 insertions(+), 23 deletions(-) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index db567ed..a77f6be 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -281,27 +281,27 @@ unsigned long __arch_hweight64(__u64 w); /* Little-endian versions */ -static __inline__ int test_le_bit(unsigned long nr, - __const__ unsigned long *addr) +static __inline__ int test_bit_le(unsigned long nr, + __const__ void *addr) { __const__ unsigned char *tmp = (__const__ unsigned char *) addr; return (tmp[nr >> 3] >> (nr & 7)) & 1; } -#define __set_le_bit(nr, addr) \ - __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define __clear_le_bit(nr, addr) \ - __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define __set_bit_le(nr, addr) \ + __set_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) +#define __clear_bit_le(nr, addr) \ + __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) -#define test_and_set_le_bit(nr, addr) \ - test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define test_and_clear_le_bit(nr, addr) \ - test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define test_and_set_bit_le(nr, addr) \ + test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) +#define test_and_clear_bit_le(nr, addr) \ + test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) -#define __test_and_set_le_bit(nr, addr) \ - __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define __test_and_clear_le_bit(nr, addr) \ - __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define __test_and_set_bit_le(nr, addr) \ + __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) +#define __test_and_clear_bit_le(nr, addr) \ + __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (unsigned long *)(addr)) #define find_first_zero_bit_le(addr, size) \ find_next_zero_bit_le((addr), (size), 0) @@ -313,16 +313,16 @@ unsigned long find_next_bit_le(const void *addr, /* Bitmap functions for the ext2 filesystem */ #define ext2_set_bit(nr,addr) \ - __test_and_set_le_bit((nr), (unsigned long*)addr) + __test_and_set_bit_le((nr), (unsigned long*)addr) #define ext2_clear_bit(nr, addr) \ - __test_and_clear_le_bit((nr), (unsigned long*)addr) + __test_and_clear_bit_le((nr), (unsigned long*)addr) #define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_le_bit((nr), (unsigned long*)addr) + test_and_set_bit_le((nr), (unsigned long*)addr) #define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_le_bit((nr), (unsigned long*)addr) + test_and_clear_bit_le((nr), (unsigned long*)addr) -#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) +#define ext2_test_bit(nr, addr) test_bit_le((nr),(unsigned long*)addr) #define ext2_find_first_zero_bit(addr, size) \ find_first_zero_bit_le((unsigned long*)addr, size) @@ -334,13 +334,13 @@ unsigned long find_next_bit_le(const void *addr, /* Bitmap functions for the minix filesystem. */ #define minix_test_and_set_bit(nr,addr) \ - __test_and_set_le_bit(nr, (unsigned long *)addr) + __test_and_set_bit_le(nr, (unsigned long *)addr) #define minix_set_bit(nr,addr) \ - __set_le_bit(nr, (unsigned long *)addr) + __set_bit_le(nr, (unsigned long *)addr) #define minix_test_and_clear_bit(nr,addr) \ - __test_and_clear_le_bit(nr, (unsigned long *)addr) + __test_and_clear_bit_le(nr, (unsigned long *)addr) #define minix_test_bit(nr,addr) \ - test_le_bit(nr, (unsigned long *)addr) + test_bit_le(nr, (unsigned long *)addr) #define minix_find_first_zero_bit(addr,size) \ find_first_zero_bit_le((unsigned long *)addr, size) -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v4 03/24] powerpc: introduce little-endian bitops
Introduce little-endian bit operations by renaming existing powerpc native little-endian bit operations. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- The whole series is available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/mita/linux-2.6.git le-bitops-v4 arch/powerpc/include/asm/bitops.h | 38 ++-- 1 files changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index e903264..7b1c5a9 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -281,29 +281,29 @@ unsigned long __arch_hweight64(__u64 w); /* Little-endian versions */ -static __inline__ int test_le_bit(unsigned long nr, +static __inline__ int test_bit_le(unsigned long nr, __const__ unsigned long *addr) { __const__ unsigned char *tmp = (__const__ unsigned char *) addr; return (tmp[nr >> 3] >> (nr & 7)) & 1; } -#define __set_le_bit(nr, addr) \ +#define __set_bit_le(nr, addr) \ __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define __clear_le_bit(nr, addr) \ +#define __clear_bit_le(nr, addr) \ __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define test_and_set_le_bit(nr, addr) \ +#define test_and_set_bit_le(nr, addr) \ test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define test_and_clear_le_bit(nr, addr) \ +#define test_and_clear_bit_le(nr, addr) \ test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define __test_and_set_le_bit(nr, addr) \ +#define __test_and_set_bit_le(nr, addr) \ __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define __test_and_clear_le_bit(nr, addr) \ +#define __test_and_clear_bit_le(nr, addr) \ __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) -#define find_first_zero_le_bit(addr, size) \ +#define find_first_zero_bit_le(addr, size) \ find_next_zero_bit_le((addr), (size), 0) unsigned long find_next_zero_bit_le(const unsigned long *addr, unsigned long size, unsigned long offset); @@ -313,19 +313,19 @@ unsigned long find_next_bit_le(const unsigned long *addr, /* Bitmap functions for the ext2 filesystem */ #define ext2_set_bit(nr,addr) \ - __test_and_set_le_bit((nr), (unsigned long*)addr) + __test_and_set_bit_le((nr), (unsigned long*)addr) #define ext2_clear_bit(nr, addr) \ - __test_and_clear_le_bit((nr), (unsigned long*)addr) + __test_and_clear_bit_le((nr), (unsigned long*)addr) #define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_le_bit((nr), (unsigned long*)addr) + test_and_set_bit_le((nr), (unsigned long*)addr) #define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_le_bit((nr), (unsigned long*)addr) + test_and_clear_bit_le((nr), (unsigned long*)addr) -#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) +#define ext2_test_bit(nr, addr) test_bit_le((nr),(unsigned long*)addr) #define ext2_find_first_zero_bit(addr, size) \ - find_first_zero_le_bit((unsigned long*)addr, size) + find_first_zero_bit_le((unsigned long*)addr, size) #define ext2_find_next_zero_bit(addr, size, off) \ find_next_zero_bit_le((unsigned long *)addr, size, off) @@ -334,16 +334,16 @@ unsigned long find_next_bit_le(const unsigned long *addr, /* Bitmap functions for the minix filesystem. */ #define minix_test_and_set_bit(nr,addr) \ - __test_and_set_le_bit(nr, (unsigned long *)addr) + __test_and_set_bit_le(nr, (unsigned long *)addr) #define minix_set_bit(nr,addr) \ - __set_le_bit(nr, (unsigned long *)addr) + __set_bit_le(nr, (unsigned long *)addr) #define minix_test_and_clear_bit(nr,addr) \ - __test_and_clear_le_bit(nr, (unsigned long *)addr) + __test_and_clear_bit_le(nr, (unsigned long *)addr) #define minix_test_bit(nr,addr) \ - test_le_bit(nr, (unsigned long *)addr) + test_bit_le(nr, (unsigned long *)addr) #define minix_find_first_zero_bit(addr,size) \ - find_first_zero_le_bit((unsigned long *)addr, size) + find_first_zero_bit_le((unsigned long *)addr, size) #include -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: use simple_read_from_buffer
Simplify read file operation for /proc/powerpc/rtas/* interface by using simple_read_from_buffer. Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/kernel/rtas_flash.c | 53 - 1 files changed, 6 insertions(+), 47 deletions(-) diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 2b442e6..bf5f5ce 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -256,31 +256,16 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf, struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; char msg[RTAS_MSG_MAXLEN]; - int msglen; - uf = (struct rtas_update_flash_t *) dp->data; + uf = dp->data; if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) { get_flash_status_msg(uf->status, msg); } else { /* FIRMWARE_UPDATE_NAME */ sprintf(msg, "%d\n", uf->status); } - msglen = strlen(msg); - if (msglen > count) - msglen = count; - - if (ppos && *ppos != 0) - return 0; /* be cheap */ - - if (!access_ok(VERIFY_WRITE, buf, msglen)) - return -EINVAL; - if (copy_to_user(buf, msg, msglen)) - return -EFAULT; - - if (ppos) - *ppos = msglen; - return msglen; + return simple_read_from_buffer(buf, count, ppos, msg, strlen(msg)); } /* constructor for flash_block_cache */ @@ -394,26 +379,13 @@ static ssize_t manage_flash_read(struct file *file, char __user *buf, char msg[RTAS_MSG_MAXLEN]; int msglen; - args_buf = (struct rtas_manage_flash_t *) dp->data; + args_buf = dp->data; if (args_buf == NULL) return 0; msglen = sprintf(msg, "%d\n", args_buf->status); - if (msglen > count) - msglen = count; - if (ppos && *ppos != 0) - return 0; /* be cheap */ - - if (!access_ok(VERIFY_WRITE, buf, msglen)) - return -EINVAL; - - if (copy_to_user(buf, msg, msglen)) - return -EFAULT; - - if (ppos) - *ppos = msglen; - return msglen; + return simple_read_from_buffer(buf, count, ppos, msg, msglen); } static ssize_t manage_flash_write(struct file *file, const char __user *buf, @@ -495,24 +467,11 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf, char msg[RTAS_MSG_MAXLEN]; int msglen; - args_buf = (struct rtas_validate_flash_t *) dp->data; + args_buf = dp->data; - if (ppos && *ppos != 0) - return 0; /* be cheap */ - msglen = get_validate_flash_msg(args_buf, msg); - if (msglen > count) - msglen = count; - - if (!access_ok(VERIFY_WRITE, buf, msglen)) - return -EINVAL; - - if (copy_to_user(buf, msg, msglen)) - return -EFAULT; - if (ppos) - *ppos = msglen; - return msglen; + return simple_read_from_buffer(buf, count, ppos, msg, msglen); } static ssize_t validate_flash_write(struct file *file, const char __user *buf, -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] spufs: use simple_write_to_buffer
Simplify several write fileoperations for spufs by using simple_write_to_buffer(). Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jeremy Kerr Cc: linuxppc-dev@lists.ozlabs.org Cc: cbe-oss-...@lists.ozlabs.org --- arch/powerpc/platforms/cell/spufs/file.c | 27 +++ 1 files changed, 7 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 02f7b11..3c7c3f8 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -219,24 +219,17 @@ spufs_mem_write(struct file *file, const char __user *buffer, loff_t pos = *ppos; int ret; - if (pos < 0) - return -EINVAL; if (pos > LS_SIZE) return -EFBIG; - if (size > LS_SIZE - pos) - size = LS_SIZE - pos; ret = spu_acquire(ctx); if (ret) return ret; local_store = ctx->ops->get_ls(ctx); - ret = copy_from_user(local_store + pos, buffer, size); + size = simple_write_to_buffer(local_store, LS_SIZE, ppos, buffer, size); spu_release(ctx); - if (ret) - return -EFAULT; - *ppos = pos + size; return size; } @@ -574,18 +567,15 @@ spufs_regs_write(struct file *file, const char __user *buffer, if (*pos >= sizeof(lscsa->gprs)) return -EFBIG; - size = min_t(ssize_t, sizeof(lscsa->gprs) - *pos, size); - *pos += size; - ret = spu_acquire_saved(ctx); if (ret) return ret; - ret = copy_from_user((char *)lscsa->gprs + *pos - size, -buffer, size) ? -EFAULT : size; + size = simple_write_to_buffer(lscsa->gprs, sizeof(lscsa->gprs), pos, + buffer, size); spu_release_saved(ctx); - return ret; + return size; } static const struct file_operations spufs_regs_fops = { @@ -630,18 +620,15 @@ spufs_fpcr_write(struct file *file, const char __user * buffer, if (*pos >= sizeof(lscsa->fpcr)) return -EFBIG; - size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size); - ret = spu_acquire_saved(ctx); if (ret) return ret; - *pos += size; - ret = copy_from_user((char *)&lscsa->fpcr + *pos - size, -buffer, size) ? -EFAULT : size; + size = simple_write_to_buffer(&lscsa->fpcr, sizeof(lscsa->fpcr), pos, + buffer, size); spu_release_saved(ctx); - return ret; + return size; } static const struct file_operations spufs_fpcr_fops = { -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 02/22] bitops: rename generic little-endian bitops functions
As a preparation for providing little-endian bitops for all architectures, This removes generic_ prefix from little-endian bitops function names in asm-generic/bitops/le.h. s/generic_find_next_le_bit/find_next_le_bit/ s/generic_find_next_zero_le_bit/find_next_zero_le_bit/ s/generic_find_first_zero_le_bit/find_first_zero_le_bit/ s/generic___test_and_set_le_bit/__test_and_set_le_bit/ s/generic___test_and_clear_le_bit/__test_and_clear_le_bit/ s/generic_test_le_bit/test_le_bit/ s/generic___set_le_bit/__set_le_bit/ s/generic___clear_le_bit/__clear_le_bit/ s/generic_test_and_set_le_bit/test_and_set_le_bit/ s/generic_test_and_clear_le_bit/test_and_clear_le_bit/ Signed-off-by: Akinobu Mita Acked-by: Arnd Bergmann Acked-by: Hans-Christian Egtvedt Cc: Geert Uytterhoeven Cc: Roman Zippel Cc: Andreas Schwab Cc: linux-m...@lists.linux-m68k.org Cc: Greg Ungerer Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Andy Grover Cc: rds-de...@oss.oracle.com Cc: "David S. Miller" Cc: net...@vger.kernel.org Cc: Avi Kivity Cc: Marcelo Tosatti Cc: k...@vger.kernel.org --- No change from previous submission arch/avr32/kernel/avr32_ksyms.c |4 ++-- arch/avr32/lib/findbit.S |4 ++-- arch/m68k/include/asm/bitops_mm.h|8 arch/m68k/include/asm/bitops_no.h|2 +- arch/powerpc/include/asm/bitops.h| 11 ++- include/asm-generic/bitops/ext2-non-atomic.h | 12 ++-- include/asm-generic/bitops/le.h | 26 +- include/asm-generic/bitops/minix-le.h| 10 +- lib/find_next_bit.c |9 - net/rds/cong.c |6 +++--- virt/kvm/kvm_main.c |2 +- 11 files changed, 47 insertions(+), 47 deletions(-) diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 11e310c..c63b943 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -58,8 +58,8 @@ EXPORT_SYMBOL(find_first_zero_bit); EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_first_bit); EXPORT_SYMBOL(find_next_bit); -EXPORT_SYMBOL(generic_find_next_le_bit); -EXPORT_SYMBOL(generic_find_next_zero_le_bit); +EXPORT_SYMBOL(find_next_le_bit); +EXPORT_SYMBOL(find_next_zero_le_bit); /* I/O primitives (lib/io-*.S) */ EXPORT_SYMBOL(__raw_readsb); diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S index 997b33b..6880d85 100644 --- a/arch/avr32/lib/findbit.S +++ b/arch/avr32/lib/findbit.S @@ -123,7 +123,7 @@ ENTRY(find_next_bit) brgt1b retal r11 -ENTRY(generic_find_next_le_bit) +ENTRY(find_next_le_bit) lsr r8, r10, 5 sub r9, r11, r10 retle r11 @@ -153,7 +153,7 @@ ENTRY(generic_find_next_le_bit) brgt1b retal r11 -ENTRY(generic_find_next_zero_le_bit) +ENTRY(find_next_zero_le_bit) lsr r8, r10, 5 sub r9, r11, r10 retle r11 diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h index b4ecdaa..f1010ab 100644 --- a/arch/m68k/include/asm/bitops_mm.h +++ b/arch/m68k/include/asm/bitops_mm.h @@ -366,9 +366,9 @@ static inline int minix_test_bit(int nr, const void *vaddr) #define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) #define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) #define ext2_find_next_zero_bit(addr, size, offset) \ - generic_find_next_zero_le_bit((unsigned long *)addr, size, offset) + find_next_zero_le_bit((unsigned long *)addr, size, offset) #define ext2_find_next_bit(addr, size, offset) \ - generic_find_next_le_bit((unsigned long *)addr, size, offset) + find_next_le_bit((unsigned long *)addr, size, offset) static inline int ext2_test_bit(int nr, const void *vaddr) { @@ -398,7 +398,7 @@ static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size) return (p - addr) * 32 + res; } -static inline unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, +static inline unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + (offset >> 5); @@ -440,7 +440,7 @@ static inline int ext2_find_first_bit(const void *vaddr, unsigned size) return (p - addr) * 32 + res; } -static inline unsigned long generic_find_next_le_bit(const unsigned long *addr, +static inline unsigned long find_next_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + (offset >> 5); diff --git a/arch/m68k/include/asm/bitops_no.h b/arch/m68k/include/asm/bitops_no.h index 9d3cbe5..292e1ce 100644 --- a/arch/m68k/include/asm/bitop
[PATCH v2 02/22] bitops: rename generic little-endian bitops functions
As a preparation for providing little-endian bitops for all architectures, This removes generic_ prefix from little-endian bitops function names in asm-generic/bitops/le.h. s/generic_find_next_le_bit/find_next_le_bit/ s/generic_find_next_zero_le_bit/find_next_zero_le_bit/ s/generic_find_first_zero_le_bit/find_first_zero_le_bit/ s/generic___test_and_set_le_bit/__test_and_set_le_bit/ s/generic___test_and_clear_le_bit/__test_and_clear_le_bit/ s/generic_test_le_bit/test_le_bit/ s/generic___set_le_bit/__set_le_bit/ s/generic___clear_le_bit/__clear_le_bit/ s/generic_test_and_set_le_bit/test_and_set_le_bit/ s/generic_test_and_clear_le_bit/test_and_clear_le_bit/ Signed-off-by: Akinobu Mita Cc: Hans-Christian Egtvedt Cc: Geert Uytterhoeven Cc: Roman Zippel Cc: Andreas Schwab Cc: linux-m...@lists.linux-m68k.org Cc: Greg Ungerer Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Andy Grover Cc: rds-de...@oss.oracle.com Cc: "David S. Miller" Cc: net...@vger.kernel.org Cc: Avi Kivity Cc: Marcelo Tosatti Cc: k...@vger.kernel.org --- No change from previous submission arch/avr32/kernel/avr32_ksyms.c |4 ++-- arch/avr32/lib/findbit.S |4 ++-- arch/m68k/include/asm/bitops_mm.h|8 arch/m68k/include/asm/bitops_no.h|2 +- arch/powerpc/include/asm/bitops.h| 11 ++- include/asm-generic/bitops/ext2-non-atomic.h | 12 ++-- include/asm-generic/bitops/le.h | 26 +- include/asm-generic/bitops/minix-le.h| 10 +- lib/find_next_bit.c |9 - net/rds/cong.c |6 +++--- virt/kvm/kvm_main.c |2 +- 11 files changed, 47 insertions(+), 47 deletions(-) diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 11e310c..c63b943 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -58,8 +58,8 @@ EXPORT_SYMBOL(find_first_zero_bit); EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_first_bit); EXPORT_SYMBOL(find_next_bit); -EXPORT_SYMBOL(generic_find_next_le_bit); -EXPORT_SYMBOL(generic_find_next_zero_le_bit); +EXPORT_SYMBOL(find_next_le_bit); +EXPORT_SYMBOL(find_next_zero_le_bit); /* I/O primitives (lib/io-*.S) */ EXPORT_SYMBOL(__raw_readsb); diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S index 997b33b..6880d85 100644 --- a/arch/avr32/lib/findbit.S +++ b/arch/avr32/lib/findbit.S @@ -123,7 +123,7 @@ ENTRY(find_next_bit) brgt1b retal r11 -ENTRY(generic_find_next_le_bit) +ENTRY(find_next_le_bit) lsr r8, r10, 5 sub r9, r11, r10 retle r11 @@ -153,7 +153,7 @@ ENTRY(generic_find_next_le_bit) brgt1b retal r11 -ENTRY(generic_find_next_zero_le_bit) +ENTRY(find_next_zero_le_bit) lsr r8, r10, 5 sub r9, r11, r10 retle r11 diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h index b4ecdaa..f1010ab 100644 --- a/arch/m68k/include/asm/bitops_mm.h +++ b/arch/m68k/include/asm/bitops_mm.h @@ -366,9 +366,9 @@ static inline int minix_test_bit(int nr, const void *vaddr) #define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) #define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) #define ext2_find_next_zero_bit(addr, size, offset) \ - generic_find_next_zero_le_bit((unsigned long *)addr, size, offset) + find_next_zero_le_bit((unsigned long *)addr, size, offset) #define ext2_find_next_bit(addr, size, offset) \ - generic_find_next_le_bit((unsigned long *)addr, size, offset) + find_next_le_bit((unsigned long *)addr, size, offset) static inline int ext2_test_bit(int nr, const void *vaddr) { @@ -398,7 +398,7 @@ static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size) return (p - addr) * 32 + res; } -static inline unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, +static inline unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + (offset >> 5); @@ -440,7 +440,7 @@ static inline int ext2_find_first_bit(const void *vaddr, unsigned size) return (p - addr) * 32 + res; } -static inline unsigned long generic_find_next_le_bit(const unsigned long *addr, +static inline unsigned long find_next_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + (offset >> 5); diff --git a/arch/m68k/include/asm/bitops_no.h b/arch/m68k/include/asm/bitops_no.h index 9d3cbe5..292e1ce 100644 --- a/arch/m68k/include/asm/bitops_no.h +++ b/arch/m68k/include/asm
[PATCH] powerpc/512x: fix clk_get() return value
clk_get() should return an ERR_PTR value on error, not NULL. Signed-off-by: Akinobu Mita Cc: Grant Likely Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/512x/clock.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c index 5b243bd..3dc2a8d 100644 --- a/arch/powerpc/platforms/512x/clock.c +++ b/arch/powerpc/platforms/512x/clock.c @@ -57,7 +57,7 @@ static struct clk *mpc5121_clk_get(struct device *dev, const char *id) int id_match = 0; if (dev == NULL || id == NULL) - return NULL; + return clk; mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { -- 1.7.1.231.gd0b16 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: use __ratelimit
Replace open-coded rate limiting logic with __ratelimit(). Signed-off-by: Akinobu Mita Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-...@ozlabs.org --- arch/powerpc/platforms/iseries/pci.c | 10 +++--- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 175aac8..5873a47 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -583,14 +584,9 @@ static inline struct device_node *xlate_iomm_address( orig_addr = (unsigned long __force)addr; if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) { - static unsigned long last_jiffies; - static int num_printed; + static DEFINE_RATELIMIT_STATE(ratelimit, 60 * HZ, 10); - if (time_after(jiffies, last_jiffies + 60 * HZ)) { - last_jiffies = jiffies; - num_printed = 0; - } - if (num_printed++ < 10) + if (__ratelimit(&ratelimit)) printk(KERN_ERR "iSeries_%s: invalid access at IO address %p\n", func, addr); -- 1.6.0.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/7] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
2009/10/29 Andrew Morton : > > Why were these patches resent? What changed? > > Everybody who is going to review these patches has already reviewed > them and now they need to review them all again? I resent the patches because the iommu-helper change was not correct and I introduced serious bug in bitmap_find_next_zero_area() if align_mask != 0 in follow-up patch then those were dropped from the -mm tree. Only [PATCH 1/7] and [PATCH 2/7] have changes since the first submission of this patch set. * [PATCH 1/7] - Rewrite bitmap_set() and bitmap_clear() - Let bitmap_find_next_zero_area() check the last bit of the limit - Add kerneldoc for bitmap_find_next_zero_area() * [PATCH 2/7] - Convert find_next_zero_area() to use bitmap_find_next_zero_area() correctly iommu-helper doesn't want to search the last bit of the limist in bitmap * [PATCH 3/7] - [PATCH 7/7] - No changes ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/7] iommu-helper: Use bitmap library
Use bitmap library and kill some unused iommu helper functions. 1. s/iommu_area_free/bitmap_clear/ 2. s/iommu_area_reserve/bitmap_set/ 3. Use bitmap_find_next_zero_area instead of find_next_zero_area This cannot be simple substitution because find_next_zero_area doesn't check the last bit of the limit in bitmap 4. Remove iommu_area_free, iommu_area_reserve, and find_next_zero_area Signed-off-by: Akinobu Mita Cc: "David S. Miller" Cc: sparcli...@vger.kernel.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-...@ozlabs.org Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: FUJITA Tomonori Cc: Joerg Roedel --- arch/powerpc/kernel/iommu.c |4 +- arch/sparc/kernel/iommu.c|3 +- arch/x86/kernel/amd_iommu.c |4 +- arch/x86/kernel/pci-calgary_64.c |6 ++-- arch/x86/kernel/pci-gart_64.c|6 ++-- include/linux/iommu-helper.h |3 -- lib/iommu-helper.c | 59 ++ 7 files changed, 21 insertions(+), 64 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index fd51578..5547ae6 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -251,7 +251,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, } ppc_md.tce_free(tbl, entry, npages); - iommu_area_free(tbl->it_map, free_entry, npages); + bitmap_clear(tbl->it_map, free_entry, npages); } static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 7690cc2..5fad949 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_PCI #include @@ -169,7 +170,7 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT; - iommu_area_free(arena->map, entry, npages); + bitmap_clear(arena->map, entry, npages); } int iommu_table_init(struct iommu *iommu, int tsbsize, diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 98f230f..08b1d20 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -959,7 +959,7 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom, address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT; - iommu_area_free(range->bitmap, address, pages); + bitmap_clear(range->bitmap, address, pages); } diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 971a3be..c87bb20 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -211,7 +211,7 @@ static void iommu_range_reserve(struct iommu_table *tbl, spin_lock_irqsave(&tbl->it_lock, flags); - iommu_area_reserve(tbl->it_map, index, npages); + bitmap_set(tbl->it_map, index, npages); spin_unlock_irqrestore(&tbl->it_lock, flags); } @@ -305,7 +305,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, spin_lock_irqsave(&tbl->it_lock, flags); - iommu_area_free(tbl->it_map, entry, npages); + bitmap_clear(tbl->it_map, entry, npages); spin_unlock_irqrestore(&tbl->it_lock, flags); } diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index a7f1b64..156e362 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -123,7 +123,7 @@ static void free_iommu(unsigned long offset, int size) unsigned long flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); - iommu_area_free(iommu_gart_bitmap, offset, size); + bitmap_clear(iommu_gart_bitmap, offset, size); if (offset >= next_bit) next_bit = offset + size; spin_unlock_irqrestore(&iommu_bitmap_lock, flags); @@ -782,7 +782,7 @@ void __init gart_iommu_init(void) * Out of IOMMU space handling. * Reserve some invalid pages at the beginning of the GART. */ - iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES); + bitmap_set(iommu_gart_bitmap, 0, EMERGENCY_PAGES); agp_memory_reserved = iommu_size; printk(KERN_INFO diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h index 3b068e5..64d1b63 100644 --- a/in
[PATCH 1/7] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
This introduces new bitmap functions: bitmap_set: Set specified bit area bitmap_clear: Clear specified bit area bitmap_find_next_zero_area: Find free bit area These are mostly stolen from iommu helper. The differences are: - Use find_next_bit instead of doing test_bit for each bit - Rewrite bitmap_set and bitmap_clear Instead of setting or clearing for each bit. - Check the last bit of the limit iommu-helper doesn't want to find such area - The return value if there is no zero area find_next_zero_area in iommu helper: returns -1 bitmap_find_next_zero_area: return >= bitmap size Signed-off-by: Akinobu Mita Cc: FUJITA Tomonori Cc: "David S. Miller" Cc: sparcli...@vger.kernel.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-...@ozlabs.org Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: Greg Kroah-Hartman Cc: Lothar Wassmann Cc: linux-...@vger.kernel.org Cc: Roland Dreier Cc: Yevgeny Petrilin Cc: net...@vger.kernel.org Cc: Tony Luck Cc: Fenghua Yu Cc: linux-i...@vger.kernel.org Cc: linux-al...@sgi.com Cc: Joerg Roedel --- include/linux/bitmap.h | 11 ++ lib/bitmap.c | 81 2 files changed, 92 insertions(+), 0 deletions(-) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 756d78b..daf8c48 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -42,6 +42,9 @@ * bitmap_empty(src, nbits)Are all bits zero in *src? * bitmap_full(src, nbits) Are all bits set in *src? * bitmap_weight(src, nbits) Hamming Weight: number set bits + * bitmap_set(dst, pos, nbits) Set specified bit area + * bitmap_clear(dst, pos, nbits) Clear specified bit area + * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n * bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src) @@ -108,6 +111,14 @@ extern int __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2, int bits); extern int __bitmap_weight(const unsigned long *bitmap, int bits); +extern void bitmap_set(unsigned long *map, int i, int len); +extern void bitmap_clear(unsigned long *map, int start, int nr); +extern unsigned long bitmap_find_next_zero_area(unsigned long *map, +unsigned long size, +unsigned long start, +unsigned int nr, +unsigned long align_mask); + extern int bitmap_scnprintf(char *buf, unsigned int len, const unsigned long *src, int nbits); extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user, diff --git a/lib/bitmap.c b/lib/bitmap.c index 7025658..11bf497 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -271,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) } EXPORT_SYMBOL(__bitmap_weight); +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) + +void bitmap_set(unsigned long *map, int start, int nr) +{ + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_set >= 0) { + *p |= mask_to_set; + nr -= bits_to_set; + bits_to_set = BITS_PER_LONG; + mask_to_set = ~0UL; + p++; + } + if (nr) { + mask_to_set &= BITMAP_LAST_WORD_MASK(size); + *p |= mask_to_set; + } +} +EXPORT_SYMBOL(bitmap_set); + +void bitmap_clear(unsigned long *map, int start, int nr) +{ + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_clear >= 0) { + *p &= ~mask_to_clear; + nr -= bits_to_clear; + bits_to_clear = BITS_PER_LONG; + mask_to_clear = ~0UL; + p++; + } + if (nr) { + mask_to_clear &= BITMAP_LAST_WORD_MASK(size); + *p &= ~mask_to_clear; + } +} +EXPORT_SYMBOL(bitmap_clear); + +/* + * bitmap_find_next_zero_area - find a contiguous aligned zero area + * @map: The address to base the search on + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + * @nr: The number of zeroed bits we're looking for + * @align_mask: Alignment mask for zero area + * + * The @al
Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
>> >> --- a/lib/iommu-helper.c >> >> +++ b/lib/iommu-helper.c >> >> @@ -19,7 +19,7 @@ again: >> >> index = (index + align_mask) & ~align_mask; >> >> >> >> end = index + nr; >> >> - if (end >= size) >> >> + if (end > size) >> > >> > I think that this is intentional; the last byte of the limit doesn't >> > work. >> >> It looks ok to me. Without above change, find_next_zero_area cannot >> find a 64 bits zeroed area in next sample code. > > I meant that we don't want to find such area for IOMMUs (IIRC, it code > came from POWER IOMMU). OK, I see. I think we need the comment about it. So we cannot replace find_next_zero_area by bitmap_find_next_zero_area and current -mmotm has the bug introduced by this patch in iommu-helper and I also introduced the bug in bitmap_find_next_zero_area if align_mask != 0 in bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area-fix.patch Andrew, please drop lib-iommu-helperc-fix-off-by-one-error-in-find_next_zero_area.patch iommu-helper-simplify-find_next_zero_area.patch bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area-fix.patch iommu-helper-use-bitmap-library.patch isp1362-hcd-use-bitmap_find_next_zero_area.patch mlx4-use-bitmap_find_next_zero_area.patch sparc-use-bitmap_find_next_zero_area.patch ia64-use-bitmap_find_next_zero_area.patch genalloc-use-bitmap_find_next_zero_area.patch I'll overhaul the patchset and retry again. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
2009/10/17 FUJITA Tomonori : > On Tue, 13 Oct 2009 18:10:17 +0900 > Akinobu Mita wrote: > >> My user space testing exposed off-by-one error find_next_zero_area >> in iommu-helper. Some zero area cannot be found by this bug. >> >> Subject: [PATCH] Fix off-by-one error in find_next_zero_area >> >> Signed-off-by: Akinobu Mita >> --- >> lib/iommu-helper.c | 2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c >> index 75dbda0..afc58bc 100644 >> --- a/lib/iommu-helper.c >> +++ b/lib/iommu-helper.c >> @@ -19,7 +19,7 @@ again: >> index = (index + align_mask) & ~align_mask; >> >> end = index + nr; >> - if (end >= size) >> + if (end > size) > > I think that this is intentional; the last byte of the limit doesn't > work. It looks ok to me. Without above change, find_next_zero_area cannot find a 64 bits zeroed area in next sample code. unsigned long offset; DECLARE_BITMAP(map, 64); bitmap_clear(map, 0, 64); offset = find_next_zero_area(map, 64, 0, 64, 0); if (offset >= 64) printf("not found\n"); else printf("found\n"); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mmotm -v2] Fix bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area. patch
From: Akinobu Mita Subject: Fix bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch - Rewrite bitmap_set and bitmap_clear Instead of setting or clearing for each bit. - Fix off-by-one errors in bitmap_find_next_zero_area This bug was derived from find_next_zero_area in iommu-helper. - Add kerneldoc for bitmap_find_next_zero_area This patch is supposed to be folded into bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch * -v2 - Remove an extra test at the "index" value by find_next_bit Index was just returned by find_next_zero_bit, so we know it's zero. Noticed-by: Kyle Hubert Signed-off-by: Akinobu Mita --- lib/bitmap.c | 62 - 1 files changed, 48 insertions(+), 14 deletions(-) diff --git a/lib/bitmap.c b/lib/bitmap.c index 2415da4..962b863 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -271,28 +271,62 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) } EXPORT_SYMBOL(__bitmap_weight); -void bitmap_set(unsigned long *map, int i, int len) -{ - int end = i + len; +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) - while (i < end) { - __set_bit(i, map); - i++; +void bitmap_set(unsigned long *map, int start, int nr) +{ + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_set >= 0) { + *p |= mask_to_set; + nr -= bits_to_set; + bits_to_set = BITS_PER_LONG; + mask_to_set = ~0UL; + p++; + } + if (nr) { + mask_to_set &= BITMAP_LAST_WORD_MASK(size); + *p |= mask_to_set; } } EXPORT_SYMBOL(bitmap_set); void bitmap_clear(unsigned long *map, int start, int nr) { - int end = start + nr; - - while (start < end) { - __clear_bit(start, map); - start++; + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_clear >= 0) { + *p &= ~mask_to_clear; + nr -= bits_to_clear; + bits_to_clear = BITS_PER_LONG; + mask_to_clear = ~0UL; + p++; + } + if (nr) { + mask_to_clear &= BITMAP_LAST_WORD_MASK(size); + *p &= ~mask_to_clear; } } EXPORT_SYMBOL(bitmap_clear); +/* + * bitmap_find_next_zero_area - find a contiguous aligned zero area + * @map: The address to base the search on + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + * @nr: The number of zeroed bits we're looking for + * @align_mask: Alignment mask for zero area + * + * The @align_mask should be one less than a power of 2; the effect is that + * the bit offset of all zero areas this function finds is multiples of that + * power of 2. A @align_mask of 0 means no alignment is required. + */ unsigned long bitmap_find_next_zero_area(unsigned long *map, unsigned long size, unsigned long start, @@ -304,12 +338,12 @@ again: index = find_next_zero_bit(map, size, start); /* Align allocation */ - index = (index + align_mask) & ~align_mask; + index = __ALIGN_MASK(index, align_mask); end = index + nr; - if (end >= size) + if (end > size) return end; - i = find_next_bit(map, end, index); + i = find_next_bit(map, end, index + 1); if (i < end) { start = i + 1; goto again; -- 1.5.4.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
On Wed, Oct 14, 2009 at 08:54:47AM +1100, Michael Ellerman wrote: > On Tue, 2009-10-13 at 18:10 +0900, Akinobu Mita wrote: > > My user space testing exposed off-by-one error find_next_zero_area > > in iommu-helper. > > Why not merge those tests into the kernel as a configurable boot-time > self-test? I send the test program that I used. Obviously it needs better diagnostic messages and cleanup to be added into kernel tests. #include #include #include #include #if 1 /* Copy and paste from kernel source */ #define BITS_PER_BYTE 8 #define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE) #define BIT_WORD(nr)((nr) / BITS_PER_LONG) #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) #define BITMAP_LAST_WORD_MASK(nbits)\ ( \ ((nbits) % BITS_PER_LONG) ? \ (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ ) #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) void bitmap_set(unsigned long *map, int start, int nr) { unsigned long *p = map + BIT_WORD(start); const int size = start + nr; int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); while (nr - bits_to_set >= 0) { *p |= mask_to_set; nr -= bits_to_set; bits_to_set = BITS_PER_LONG; mask_to_set = ~0UL; p++; } if (nr) { mask_to_set &= BITMAP_LAST_WORD_MASK(size); *p |= mask_to_set; } } void bitmap_clear(unsigned long *map, int start, int nr) { unsigned long *p = map + BIT_WORD(start); const int size = start + nr; int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); while (nr - bits_to_clear >= 0) { *p &= ~mask_to_clear; nr -= bits_to_clear; bits_to_clear = BITS_PER_LONG; mask_to_clear = ~0UL; p++; } if (nr) { mask_to_clear &= BITMAP_LAST_WORD_MASK(size); *p &= ~mask_to_clear; } } static unsigned long __ffs(unsigned long word) { int num = 0; if ((word & 0x) == 0) { num += 16; word >>= 16; } if ((word & 0xff) == 0) { num += 8; word >>= 8; } if ((word & 0xf) == 0) { num += 4; word >>= 4; } if ((word & 0x3) == 0) { num += 2; word >>= 2; } if ((word & 0x1) == 0) num += 1; return num; } unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + BITOP_WORD(offset); unsigned long result = offset & ~(BITS_PER_LONG-1); unsigned long tmp; if (offset >= size) return size; size -= result; offset %= BITS_PER_LONG; if (offset) { tmp = *(p++); tmp &= (~0UL << offset); if (size < BITS_PER_LONG) goto found_first; if (tmp) goto found_middle; size -= BITS_PER_LONG; result += BITS_PER_LONG; } while (size & ~(BITS_PER_LONG-1)) { if ((tmp = *(p++))) goto found_middle; result += BITS_PER_LONG; size -= BITS_PER_LONG; } if (!size) return result; tmp = *p; found_first: tmp &= (~0UL >> (BITS_PER_LONG - size)); if (tmp == 0UL) /* Are any bits set? */ return result + size; /* Nope. */ found_middle: return result + __ffs(tmp); } #define ffz(x) __ffs(~(x)) unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + BITOP_WORD(offset); unsigned long result = offset & ~(BITS_PER_LONG-1); unsigned long tmp; if (offset >= size) return size; size -= result; offset %= BITS_PER_LONG; if (offset) { tmp = *(p++); tmp |= ~0UL >> (BITS_PER_LONG - offset); if (size < BITS_PER_LONG) goto found_first; if (~tmp) goto found_middle;
[PATCH -mmotm] Fix bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area. patch
Update PATCH 2/8 based on review comments by Andrew and bugfix exposed by user space testing. I didn't change argument of align_mask at this time because it turned out that it needs more changes in iommu-helper users. From: Akinobu Mita Subject: Fix bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch - Rewrite bitmap_set and bitmap_clear Instead of setting or clearing for each bit. - Fix off-by-one error in bitmap_find_next_zero_area This bug was derived from find_next_zero_area in iommu-helper. - Add kerneldoc for bitmap_find_next_zero_area This patch is supposed to be folded into bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch Signed-off-by: Akinobu Mita --- lib/bitmap.c | 60 + 1 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/bitmap.c b/lib/bitmap.c index 2415da4..84292c9 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -271,28 +271,62 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) } EXPORT_SYMBOL(__bitmap_weight); -void bitmap_set(unsigned long *map, int i, int len) -{ - int end = i + len; +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) - while (i < end) { - __set_bit(i, map); - i++; +void bitmap_set(unsigned long *map, int start, int nr) +{ + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_set >= 0) { + *p |= mask_to_set; + nr -= bits_to_set; + bits_to_set = BITS_PER_LONG; + mask_to_set = ~0UL; + p++; + } + if (nr) { + mask_to_set &= BITMAP_LAST_WORD_MASK(size); + *p |= mask_to_set; } } EXPORT_SYMBOL(bitmap_set); void bitmap_clear(unsigned long *map, int start, int nr) { - int end = start + nr; - - while (start < end) { - __clear_bit(start, map); - start++; + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_clear >= 0) { + *p &= ~mask_to_clear; + nr -= bits_to_clear; + bits_to_clear = BITS_PER_LONG; + mask_to_clear = ~0UL; + p++; + } + if (nr) { + mask_to_clear &= BITMAP_LAST_WORD_MASK(size); + *p &= ~mask_to_clear; } } EXPORT_SYMBOL(bitmap_clear); +/* + * bitmap_find_next_zero_area - find a contiguous aligned zero area + * @map: The address to base the search on + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + * @nr: The number of zeroed bits we're looking for + * @align_mask: Alignment mask for zero area + * + * The @align_mask should be one less than a power of 2; the effect is that + * the bit offset of all zero areas this function finds is multiples of that + * power of 2. A @align_mask of 0 means no alignment is required. + */ unsigned long bitmap_find_next_zero_area(unsigned long *map, unsigned long size, unsigned long start, @@ -304,10 +338,10 @@ again: index = find_next_zero_bit(map, size, start); /* Align allocation */ - index = (index + align_mask) & ~align_mask; + index = __ALIGN_MASK(index, align_mask); end = index + nr; - if (end >= size) + if (end > size) return end; i = find_next_bit(map, end, index); if (i < end) { -- 1.5.4.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
My user space testing exposed off-by-one error find_next_zero_area in iommu-helper. Some zero area cannot be found by this bug. Subject: [PATCH] Fix off-by-one error in find_next_zero_area Signed-off-by: Akinobu Mita --- lib/iommu-helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c index 75dbda0..afc58bc 100644 --- a/lib/iommu-helper.c +++ b/lib/iommu-helper.c @@ -19,7 +19,7 @@ again: index = (index + align_mask) & ~align_mask; end = index + nr; - if (end >= size) + if (end > size) return -1; for (i = index; i < end; i++) { if (test_bit(i, map)) { -- 1.5.4.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
On Fri, Oct 09, 2009 at 04:41:00PM -0700, Andrew Morton wrote: > On Fri, 9 Oct 2009 17:29:15 +0900 > Akinobu Mita wrote: > > > This introduces new bitmap functions: > > > > bitmap_set: Set specified bit area > > bitmap_clear: Clear specified bit area > > bitmap_find_next_zero_area: Find free bit area > > > > These are stolen from iommu helper. > > > > I changed the return value of bitmap_find_next_zero_area if there is > > no zero area. > > > > find_next_zero_area in iommu helper: returns -1 > > bitmap_find_next_zero_area: return >= bitmap size > > I'll plan to merge this patch into 2.6.32 so we can trickle all the > other patches into subsystems in an orderly fashion. Sounds good. > > +void bitmap_set(unsigned long *map, int i, int len) > > +{ > > + int end = i + len; > > + > > + while (i < end) { > > + __set_bit(i, map); > > + i++; > > + } > > +} > > This is really inefficient, isn't it? It's a pretty trivial matter to > romp through memory 32 or 64 bits at a time. OK. I'll do > > +unsigned long bitmap_find_next_zero_area(unsigned long *map, > > +unsigned long size, > > +unsigned long start, > > +unsigned int nr, > > +unsigned long align_mask) > > +{ > > + unsigned long index, end, i; > > +again: > > + index = find_next_zero_bit(map, size, start); > > + > > + /* Align allocation */ > > + index = (index + align_mask) & ~align_mask; > > + > > + end = index + nr; > > + if (end >= size) > > + return end; > > + i = find_next_bit(map, end, index); > > + if (i < end) { > > + start = i + 1; > > + goto again; > > + } > > + return index; > > +} > > +EXPORT_SYMBOL(bitmap_find_next_zero_area); > > This needs documentation, please. It appears that `size' is the size > of the bitmap and `nr' is the number of zeroed bits we're looking for, > but an inattentive programmer could get those reversed. > > Also the semantics of `align_mask' could benefit from spelling out. Is > the alignment with respect to memory boundaries or with respect to > `map' or with respect to map+start or what? OK. I will document it. And I plan to change bitmap_find_next_zero_area() to take the alignment instead of an align_mask as Roland said. > And why does align_mask exist at all? I was a bit surprised to see it > there. In which scenarios will it be non-zero? Because the users of iommu-helper and mlx4 need the alignment requirement for the zero area. arch/powerpc/kernel/iommu.c arch/x86/kernel/amd_iommu.c arch/x86/kernel/pci-gart_64.c drivers/net/mlx4/alloc.c ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/8] iommu-helper: Use bitmap library
Use bitmap library and kill some unused iommu helper functions. Cc: "David S. Miller" Cc: sparcli...@vger.kernel.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-...@ozlabs.org Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: FUJITA Tomonori Signed-off-by: Akinobu Mita --- arch/powerpc/kernel/iommu.c |4 +- arch/sparc/kernel/iommu.c|3 +- arch/x86/kernel/amd_iommu.c |4 +- arch/x86/kernel/pci-calgary_64.c |6 ++-- arch/x86/kernel/pci-gart_64.c|6 ++-- include/linux/iommu-helper.h |3 -- lib/iommu-helper.c | 55 - 7 files changed, 18 insertions(+), 63 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index fd51578..5547ae6 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -251,7 +251,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, } ppc_md.tce_free(tbl, entry, npages); - iommu_area_free(tbl->it_map, free_entry, npages); + bitmap_clear(tbl->it_map, free_entry, npages); } static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 7690cc2..5fad949 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_PCI #include @@ -169,7 +170,7 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT; - iommu_area_free(arena->map, entry, npages); + bitmap_clear(arena->map, entry, npages); } int iommu_table_init(struct iommu *iommu, int tsbsize, diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 98f230f..08b1d20 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -959,7 +959,7 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom, address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT; - iommu_area_free(range->bitmap, address, pages); + bitmap_clear(range->bitmap, address, pages); } diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 971a3be..c87bb20 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -211,7 +211,7 @@ static void iommu_range_reserve(struct iommu_table *tbl, spin_lock_irqsave(&tbl->it_lock, flags); - iommu_area_reserve(tbl->it_map, index, npages); + bitmap_set(tbl->it_map, index, npages); spin_unlock_irqrestore(&tbl->it_lock, flags); } @@ -305,7 +305,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, spin_lock_irqsave(&tbl->it_lock, flags); - iommu_area_free(tbl->it_map, entry, npages); + bitmap_clear(tbl->it_map, entry, npages); spin_unlock_irqrestore(&tbl->it_lock, flags); } diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 98a827e..3010cd1 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -122,7 +122,7 @@ static void free_iommu(unsigned long offset, int size) unsigned long flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); - iommu_area_free(iommu_gart_bitmap, offset, size); + bitmap_clear(iommu_gart_bitmap, offset, size); if (offset >= next_bit) next_bit = offset + size; spin_unlock_irqrestore(&iommu_bitmap_lock, flags); @@ -781,7 +781,7 @@ void __init gart_iommu_init(void) * Out of IOMMU space handling. * Reserve some invalid pages at the beginning of the GART. */ - iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES); + bitmap_set(iommu_gart_bitmap, 0, EMERGENCY_PAGES); agp_memory_reserved = iommu_size; printk(KERN_INFO diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h index 3b068e5..64d1b63 100644 --- a/include/linux/iommu-helper.h +++ b/include/linux/iommu-helper.h @@ -14,14 +14,11 @@ static inline unsigned long iommu_device_max_index(unsigned long size, extern int iommu_is_span_boundary(unsigned int index, unsigned int nr, unsigned long shift, unsigned long boundary_size); -extern void
[PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
This introduces new bitmap functions: bitmap_set: Set specified bit area bitmap_clear: Clear specified bit area bitmap_find_next_zero_area: Find free bit area These are stolen from iommu helper. I changed the return value of bitmap_find_next_zero_area if there is no zero area. find_next_zero_area in iommu helper: returns -1 bitmap_find_next_zero_area: return >= bitmap size Cc: FUJITA Tomonori Cc: "David S. Miller" Cc: sparcli...@vger.kernel.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-...@ozlabs.org Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: Greg Kroah-Hartman Cc: Lothar Wassmann Cc: linux-...@vger.kernel.org Cc: Roland Dreier Cc: Yevgeny Petrilin Cc: net...@vger.kernel.org Cc: Tony Luck Cc: Fenghua Yu Cc: linux-i...@vger.kernel.org Cc: linux-al...@sgi.com Signed-off-by: Akinobu Mita --- include/linux/bitmap.h | 11 +++ lib/bitmap.c | 47 +++ 2 files changed, 58 insertions(+), 0 deletions(-) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 756d78b..daf8c48 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -42,6 +42,9 @@ * bitmap_empty(src, nbits)Are all bits zero in *src? * bitmap_full(src, nbits) Are all bits set in *src? * bitmap_weight(src, nbits) Hamming Weight: number set bits + * bitmap_set(dst, pos, nbits) Set specified bit area + * bitmap_clear(dst, pos, nbits) Clear specified bit area + * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n * bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src) @@ -108,6 +111,14 @@ extern int __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2, int bits); extern int __bitmap_weight(const unsigned long *bitmap, int bits); +extern void bitmap_set(unsigned long *map, int i, int len); +extern void bitmap_clear(unsigned long *map, int start, int nr); +extern unsigned long bitmap_find_next_zero_area(unsigned long *map, +unsigned long size, +unsigned long start, +unsigned int nr, +unsigned long align_mask); + extern int bitmap_scnprintf(char *buf, unsigned int len, const unsigned long *src, int nbits); extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user, diff --git a/lib/bitmap.c b/lib/bitmap.c index 7025658..95070fa 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -271,6 +271,53 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) } EXPORT_SYMBOL(__bitmap_weight); +void bitmap_set(unsigned long *map, int i, int len) +{ + int end = i + len; + + while (i < end) { + __set_bit(i, map); + i++; + } +} +EXPORT_SYMBOL(bitmap_set); + +void bitmap_clear(unsigned long *map, int start, int nr) +{ + int end = start + nr; + + while (start < end) { + __clear_bit(start, map); + start++; + } +} +EXPORT_SYMBOL(bitmap_clear); + +unsigned long bitmap_find_next_zero_area(unsigned long *map, +unsigned long size, +unsigned long start, +unsigned int nr, +unsigned long align_mask) +{ + unsigned long index, end, i; +again: + index = find_next_zero_bit(map, size, start); + + /* Align allocation */ + index = (index + align_mask) & ~align_mask; + + end = index + nr; + if (end >= size) + return end; + i = find_next_bit(map, end, index); + if (i < end) { + start = i + 1; + goto again; + } + return index; +} +EXPORT_SYMBOL(bitmap_find_next_zero_area); + /* * Bitmap printing & parsing functions: first version by Bill Irwin, * second version by Paul Jackson, third by Joe Korty. -- 1.5.4.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] Fix highmem build failure
Looks good. I tested it on x86_32. ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH] Fix highmem build failure
On Wed, Apr 01, 2009 at 04:33:31PM -0500, Kumar Gala wrote: > The following commit breaks PPC builds with CONFIG_HIGHMEM=y > > commit f4112de6b679d84bd9b9681c7504be7bdfb7c7d5 > Author: Akinobu Mita > Date: Tue Mar 31 15:23:25 2009 -0700 > > mm: introduce debug_kmap_atomic > Thanks. But the definition of debug_kmap_atomic() needs to be outside of ifdef CONFIG_HIGHMEM. Because debug_kmap_atomic() is used without CONFIG_HIGHMEM by kmap_atomic_prot_pfn() in arch/x86/mm/iomap_32.c > --- a/include/linux/highmem.h > +++ b/include/linux/highmem.h > @@ -20,6 +20,19 @@ static inline void flush_kernel_dcache_page(struct page > *page) > #endif > > #ifdef CONFIG_HIGHMEM > +#include > + > +#if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_TRACE_IRQFLAGS_SUPPORT) > + > +void debug_kmap_atomic(enum km_type type); > + > +#else > + > +static inline void debug_kmap_atomic(enum km_type type) > +{ > +} > + > +#endif > > #include > ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH 1/2] eHEA: Capability flag for DLPAR support
2007/7/4, Jan-Bernd Themann <[EMAIL PROTECTED]>: > diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c > index bdb5241..f8c0908 100644 > --- a/drivers/net/ehea/ehea_main.c > +++ b/drivers/net/ehea/ehea_main.c > @@ -2923,6 +2923,15 @@ static int check_module_parm(void) > return ret; > } > > +static ssize_t ehea_show_capabilities(struct device_driver *drv, > + char *buf) > +{ > + return sprintf(buf, "%d", EHEA_CAPABILITIES); > +} > + > +static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH, > + ehea_show_capabilities, NULL); > + > int __init ehea_module_init(void) > { > int ret; > @@ -2937,12 +2946,20 @@ int __init ehea_module_init(void) > if (ret) > ehea_error("failed registering eHEA device driver on ebus"); > You forgot to put: return ret; or goto out; > + ret = driver_create_file(&ehea_driver.driver, > &driver_attr_capabilities); > + if (ret) { > + ehea_error("failed to register capabilities attribute, > ret=%d", ret); > + ibmebus_unregister_driver(&ehea_driver); > + goto out; > + } > + > out: > return ret; > } > ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev