diff options
author | Denis Kirjanov <kda@linux-powerpc.org> | 2015-09-16 15:26:14 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-10-05 06:32:50 -0400 |
commit | cb2d3883c6033831e2a93b396fcc43033108409c (patch) | |
tree | 2324cf13c2716efb64cd2c9f4ce518f44a224fb4 | |
parent | 06bacefcbd5f91efb7ffedc17615fa188d6ce406 (diff) |
powerpc/msi: Free the bitmap if it was slab allocated
During the MSI bitmap test on boot kmemleak spews the following trace:
unreferenced object 0xc00000016e86c900 (size 64):
comm "swapper/0", pid 1, jiffies 4294893173 (age 518.024s)
hex dump (first 32 bytes):
00 00 01 ff 7f ff 7f 37 00 00 00 00 00 00 00 00
.......7........
ff ff ff ff ff ff ff ff 01 ff ff ff ff
ff ff ff
................
backtrace:
[<c00000000003eebc>] .zalloc_maybe_bootmem+0x3c/0x380
[<c000000000042d6c>] .msi_bitmap_alloc+0x3c/0xb0
[<c000000000a9aff8>] .msi_bitmap_selftest+0x30/0x2b4
[<c0000000000090f4>] .do_one_initcall+0xd4/0x270
[<c000000000a8e250>] .kernel_init_freeable+0x1a0/0x280
[<c000000000009b5c>] .kernel_init+0x1c/0x120
[<c000000000007fbc>] .ret_from_kernel_thread+0x58/0x9c
Add a flag to msi_bitmap for tracking allocations from slab and memblock
so we can properly free/handle memory in msi_bitmap_free().
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
[mpe: Reword changelog & use bitmap_from_slab in the if]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | arch/powerpc/include/asm/msi_bitmap.h | 1 | ||||
-rw-r--r-- | arch/powerpc/sysdev/msi_bitmap.c | 16 |
2 files changed, 13 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/msi_bitmap.h b/arch/powerpc/include/asm/msi_bitmap.h index 97ac3f46ae0d..1ec7125551f1 100644 --- a/arch/powerpc/include/asm/msi_bitmap.h +++ b/arch/powerpc/include/asm/msi_bitmap.h | |||
@@ -19,6 +19,7 @@ struct msi_bitmap { | |||
19 | unsigned long *bitmap; | 19 | unsigned long *bitmap; |
20 | spinlock_t lock; | 20 | spinlock_t lock; |
21 | unsigned int irq_count; | 21 | unsigned int irq_count; |
22 | bool bitmap_from_slab; | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num); | 25 | int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num); |
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c index 73b64c73505b..1a826f3b4424 100644 --- a/arch/powerpc/sysdev/msi_bitmap.c +++ b/arch/powerpc/sysdev/msi_bitmap.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/bitmap.h> | 13 | #include <linux/bitmap.h> |
14 | #include <linux/bootmem.h> | ||
14 | #include <asm/msi_bitmap.h> | 15 | #include <asm/msi_bitmap.h> |
15 | #include <asm/setup.h> | 16 | #include <asm/setup.h> |
16 | 17 | ||
@@ -122,7 +123,15 @@ int msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count, | |||
122 | size = BITS_TO_LONGS(irq_count) * sizeof(long); | 123 | size = BITS_TO_LONGS(irq_count) * sizeof(long); |
123 | pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size); | 124 | pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size); |
124 | 125 | ||
125 | bmp->bitmap = zalloc_maybe_bootmem(size, GFP_KERNEL); | 126 | bmp->bitmap_from_slab = slab_is_available(); |
127 | if (bmp->bitmap_from_slab) | ||
128 | bmp->bitmap = kzalloc(size, GFP_KERNEL); | ||
129 | else { | ||
130 | bmp->bitmap = memblock_virt_alloc(size, 0); | ||
131 | /* the bitmap won't be freed from memblock allocator */ | ||
132 | kmemleak_not_leak(bmp->bitmap); | ||
133 | } | ||
134 | |||
126 | if (!bmp->bitmap) { | 135 | if (!bmp->bitmap) { |
127 | pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n"); | 136 | pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n"); |
128 | return -ENOMEM; | 137 | return -ENOMEM; |
@@ -138,7 +147,8 @@ int msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count, | |||
138 | 147 | ||
139 | void msi_bitmap_free(struct msi_bitmap *bmp) | 148 | void msi_bitmap_free(struct msi_bitmap *bmp) |
140 | { | 149 | { |
141 | /* we can't free the bitmap we don't know if it's bootmem etc. */ | 150 | if (bmp->bitmap_from_slab) |
151 | kfree(bmp->bitmap); | ||
142 | of_node_put(bmp->of_node); | 152 | of_node_put(bmp->of_node); |
143 | bmp->bitmap = NULL; | 153 | bmp->bitmap = NULL; |
144 | } | 154 | } |
@@ -203,8 +213,6 @@ static void __init test_basics(void) | |||
203 | 213 | ||
204 | /* Clients may WARN_ON bitmap == NULL for "not-allocated" */ | 214 | /* Clients may WARN_ON bitmap == NULL for "not-allocated" */ |
205 | WARN_ON(bmp.bitmap != NULL); | 215 | WARN_ON(bmp.bitmap != NULL); |
206 | |||
207 | kfree(bmp.bitmap); | ||
208 | } | 216 | } |
209 | 217 | ||
210 | static void __init test_of_node(void) | 218 | static void __init test_of_node(void) |