diff options
Diffstat (limited to 'arch/powerpc/sysdev/msi_bitmap.c')
-rw-r--r-- | arch/powerpc/sysdev/msi_bitmap.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c index 2ff630267e9e..0c75214b6f92 100644 --- a/arch/powerpc/sysdev/msi_bitmap.c +++ b/arch/powerpc/sysdev/msi_bitmap.c | |||
@@ -20,32 +20,37 @@ int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num) | |||
20 | int offset, order = get_count_order(num); | 20 | int offset, order = get_count_order(num); |
21 | 21 | ||
22 | spin_lock_irqsave(&bmp->lock, flags); | 22 | spin_lock_irqsave(&bmp->lock, flags); |
23 | /* | 23 | |
24 | * This is fast, but stricter than we need. We might want to add | 24 | offset = bitmap_find_next_zero_area(bmp->bitmap, bmp->irq_count, 0, |
25 | * a fallback routine which does a linear search with no alignment. | 25 | num, (1 << order) - 1); |
26 | */ | 26 | if (offset > bmp->irq_count) |
27 | offset = bitmap_find_free_region(bmp->bitmap, bmp->irq_count, order); | 27 | goto err; |
28 | |||
29 | bitmap_set(bmp->bitmap, offset, num); | ||
28 | spin_unlock_irqrestore(&bmp->lock, flags); | 30 | spin_unlock_irqrestore(&bmp->lock, flags); |
29 | 31 | ||
30 | pr_debug("msi_bitmap: allocated 0x%x (2^%d) at offset 0x%x\n", | 32 | pr_debug("msi_bitmap: allocated 0x%x at offset 0x%x\n", num, offset); |
31 | num, order, offset); | ||
32 | 33 | ||
33 | return offset; | 34 | return offset; |
35 | err: | ||
36 | spin_unlock_irqrestore(&bmp->lock, flags); | ||
37 | return -ENOMEM; | ||
34 | } | 38 | } |
39 | EXPORT_SYMBOL(msi_bitmap_alloc_hwirqs); | ||
35 | 40 | ||
36 | void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset, | 41 | void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset, |
37 | unsigned int num) | 42 | unsigned int num) |
38 | { | 43 | { |
39 | unsigned long flags; | 44 | unsigned long flags; |
40 | int order = get_count_order(num); | ||
41 | 45 | ||
42 | pr_debug("msi_bitmap: freeing 0x%x (2^%d) at offset 0x%x\n", | 46 | pr_debug("msi_bitmap: freeing 0x%x at offset 0x%x\n", |
43 | num, order, offset); | 47 | num, offset); |
44 | 48 | ||
45 | spin_lock_irqsave(&bmp->lock, flags); | 49 | spin_lock_irqsave(&bmp->lock, flags); |
46 | bitmap_release_region(bmp->bitmap, offset, order); | 50 | bitmap_clear(bmp->bitmap, offset, num); |
47 | spin_unlock_irqrestore(&bmp->lock, flags); | 51 | spin_unlock_irqrestore(&bmp->lock, flags); |
48 | } | 52 | } |
53 | EXPORT_SYMBOL(msi_bitmap_free_hwirqs); | ||
49 | 54 | ||
50 | void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq) | 55 | void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq) |
51 | { | 56 | { |
@@ -143,7 +148,7 @@ void msi_bitmap_free(struct msi_bitmap *bmp) | |||
143 | #define check(x) \ | 148 | #define check(x) \ |
144 | if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__); | 149 | if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__); |
145 | 150 | ||
146 | void __init test_basics(void) | 151 | static void __init test_basics(void) |
147 | { | 152 | { |
148 | struct msi_bitmap bmp; | 153 | struct msi_bitmap bmp; |
149 | int i, size = 512; | 154 | int i, size = 512; |
@@ -180,6 +185,15 @@ void __init test_basics(void) | |||
180 | msi_bitmap_free_hwirqs(&bmp, size / 2, 1); | 185 | msi_bitmap_free_hwirqs(&bmp, size / 2, 1); |
181 | check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2); | 186 | check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2); |
182 | 187 | ||
188 | /* Check we get a naturally aligned offset */ | ||
189 | check(msi_bitmap_alloc_hwirqs(&bmp, 2) % 2 == 0); | ||
190 | check(msi_bitmap_alloc_hwirqs(&bmp, 4) % 4 == 0); | ||
191 | check(msi_bitmap_alloc_hwirqs(&bmp, 8) % 8 == 0); | ||
192 | check(msi_bitmap_alloc_hwirqs(&bmp, 9) % 16 == 0); | ||
193 | check(msi_bitmap_alloc_hwirqs(&bmp, 3) % 4 == 0); | ||
194 | check(msi_bitmap_alloc_hwirqs(&bmp, 7) % 8 == 0); | ||
195 | check(msi_bitmap_alloc_hwirqs(&bmp, 121) % 128 == 0); | ||
196 | |||
183 | msi_bitmap_free(&bmp); | 197 | msi_bitmap_free(&bmp); |
184 | 198 | ||
185 | /* Clients may check bitmap == NULL for "not-allocated" */ | 199 | /* Clients may check bitmap == NULL for "not-allocated" */ |
@@ -188,7 +202,7 @@ void __init test_basics(void) | |||
188 | kfree(bmp.bitmap); | 202 | kfree(bmp.bitmap); |
189 | } | 203 | } |
190 | 204 | ||
191 | void __init test_of_node(void) | 205 | static void __init test_of_node(void) |
192 | { | 206 | { |
193 | u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 }; | 207 | u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 }; |
194 | const char *expected_str = "0-9,20-24,28-39,41-99,220-255"; | 208 | const char *expected_str = "0-9,20-24,28-39,41-99,220-255"; |
@@ -236,7 +250,7 @@ void __init test_of_node(void) | |||
236 | kfree(bmp.bitmap); | 250 | kfree(bmp.bitmap); |
237 | } | 251 | } |
238 | 252 | ||
239 | int __init msi_bitmap_selftest(void) | 253 | static int __init msi_bitmap_selftest(void) |
240 | { | 254 | { |
241 | printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n"); | 255 | printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n"); |
242 | 256 | ||