diff options
author | Paul Mundt <lethal@linux-sh.org> | 2006-11-30 22:01:43 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-12-05 20:45:39 -0500 |
commit | 9f650cf2b811cfb605f10483eeb1dc86f43cdbcb (patch) | |
tree | db9506994a49ecdd9151776fe5fb3ed7f3343c92 | |
parent | 6fc21b82ef74911887ced1aff8d37ce079bb8b36 (diff) |
sh: Fix store queue bitmap end.
The end of the store queue bitmap is miscalculated when searching
for a free range in sq_remap(), missing the PAGE_SHIFT shift that's
done in sq_api_init(). This runs in to workloads where we can scan
beyond the end of the bitmap.
Spotted by Paul Jackson:
http://marc.theaimsgroup.com/?l=linux-kernel&m=116493191224097&w
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/kernel/cpu/sh4/sq.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 7bcc73f9b8df..55f43506995a 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <asm/page.h> | 23 | #include <asm/page.h> |
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
25 | #include <asm/cpu/sq.h> | 25 | #include <asm/cpu/sq.h> |
@@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len) | |||
67 | /* Wait for completion */ | 67 | /* Wait for completion */ |
68 | store_queue_barrier(); | 68 | store_queue_barrier(); |
69 | } | 69 | } |
70 | EXPORT_SYMBOL(sq_flush_range); | ||
70 | 71 | ||
71 | static inline void sq_mapping_list_add(struct sq_mapping *map) | 72 | static inline void sq_mapping_list_add(struct sq_mapping *map) |
72 | { | 73 | { |
@@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, | |||
166 | map->size = size; | 167 | map->size = size; |
167 | map->name = name; | 168 | map->name = name; |
168 | 169 | ||
169 | page = bitmap_find_free_region(sq_bitmap, 0x04000000, | 170 | page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT, |
170 | get_order(map->size)); | 171 | get_order(map->size)); |
171 | if (unlikely(page < 0)) { | 172 | if (unlikely(page < 0)) { |
172 | ret = -ENOSPC; | 173 | ret = -ENOSPC; |
@@ -193,6 +194,7 @@ out: | |||
193 | kmem_cache_free(sq_cache, map); | 194 | kmem_cache_free(sq_cache, map); |
194 | return ret; | 195 | return ret; |
195 | } | 196 | } |
197 | EXPORT_SYMBOL(sq_remap); | ||
196 | 198 | ||
197 | /** | 199 | /** |
198 | * sq_unmap - Unmap a Store Queue allocation | 200 | * sq_unmap - Unmap a Store Queue allocation |
@@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr) | |||
234 | 236 | ||
235 | kmem_cache_free(sq_cache, map); | 237 | kmem_cache_free(sq_cache, map); |
236 | } | 238 | } |
239 | EXPORT_SYMBOL(sq_unmap); | ||
237 | 240 | ||
238 | /* | 241 | /* |
239 | * Needlessly complex sysfs interface. Unfortunately it doesn't seem like | 242 | * Needlessly complex sysfs interface. Unfortunately it doesn't seem like |
@@ -402,7 +405,3 @@ module_exit(sq_api_exit); | |||
402 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); | 405 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); |
403 | MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); | 406 | MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); |
404 | MODULE_LICENSE("GPL"); | 407 | MODULE_LICENSE("GPL"); |
405 | |||
406 | EXPORT_SYMBOL(sq_remap); | ||
407 | EXPORT_SYMBOL(sq_unmap); | ||
408 | EXPORT_SYMBOL(sq_flush_range); | ||