diff options
author | Gary King <gking@nvidia.com> | 2010-05-17 23:04:54 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-17 23:08:31 -0700 |
commit | 94af0b4ea79b5b633632c342fd7011b7c8cd88fd (patch) | |
tree | f1bf6e4a40bc262622b125caa194bca4fa7458b4 /drivers | |
parent | 90c2e642c9ab27dfffe141d9f8f4840cef1c5a89 (diff) |
[nvmap] restructure allocations to avoid allocation inside spinlocks
statically allocate a maximally-sized block array at heap init time,
rather than dynamically doubling the array size when spare blocks are
unavailable.
allocate new handle ref objects prior to locking the file's ref lock
Change-Id: I193210e059ed38c67287650fc4b578e85097ec12
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/nvmap.c | 43 |
1 files changed, 9 insertions, 34 deletions
diff --git a/drivers/char/nvmap.c b/drivers/char/nvmap.c index e58f18fee955..f85dfc2bf7ef 100644 --- a/drivers/char/nvmap.c +++ b/drivers/char/nvmap.c @@ -20,6 +20,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define NV_DEBUG 0 + #include <linux/vmalloc.h> #include <linux/module.h> #include <linux/bitmap.h> @@ -262,17 +264,18 @@ static unsigned long _nvmap_carveout_blockstat(struct nvmap_carveout *co, static int _nvmap_init_carveout(struct nvmap_carveout *co, const char *name, unsigned long base_address, size_t len) { - const unsigned int min_blocks = 16; + unsigned int num_blocks; struct nvmap_mem_block *blocks = NULL; int i; - blocks = kzalloc(sizeof(*blocks)*min_blocks, GFP_KERNEL); + num_blocks = min_t(unsigned int, len/1024, 1024); + blocks = vmalloc(sizeof(*blocks)*num_blocks); if (!blocks) goto fail; co->name = kstrdup(name, GFP_KERNEL); if (!co->name) goto fail; - for (i=1; i<min_blocks; i++) { + for (i=1; i<num_blocks; i++) { blocks[i].next = i+1; blocks[i].prev = i-1; blocks[i].next_free = -1; @@ -286,7 +289,7 @@ static int _nvmap_init_carveout(struct nvmap_carveout *co, blocks[0].base = base_address; blocks[0].size = len; co->blocks = blocks; - co->num_blocks = min_blocks; + co->num_blocks = num_blocks; spin_lock_init(&co->lock); co->block_index = 0; co->spare_index = 1; @@ -298,39 +301,12 @@ fail: return -ENOMEM; } -static int nvmap_grow_blocks(struct nvmap_carveout *co) -{ - struct nvmap_mem_block *blocks; - unsigned int i; - - if (co->num_blocks >= 1<<(8*sizeof(co->free_index)-1)) return -ENOMEM; - blocks = kzalloc(sizeof(*blocks)*(co->num_blocks*2), GFP_KERNEL); - if (!blocks) return -ENOMEM; - - memcpy(blocks, co->blocks, sizeof(*blocks)*(co->num_blocks)); - kfree(co->blocks); - co->blocks = blocks; - for (i=co->num_blocks; i<co->num_blocks*2; i++) { - blocks[i].next = i+1; - blocks[i].prev = i-1; - blocks[i].next_free = -1; - blocks[i].prev_free = -1; - } - blocks[co->num_blocks].prev = -1; - blocks[i-1].next = -1; - co->spare_index = co->num_blocks; - co->num_blocks *= 2; - return 0; -} - static int nvmap_get_spare(struct nvmap_carveout *co) { int idx; if (co->spare_index == -1) - if (nvmap_grow_blocks(co)) - return -1; + return -1; - BUG_ON(co->spare_index == -1); idx = co->spare_index; co->spare_index = co->blocks[idx].next; co->blocks[idx].next = -1; @@ -2039,10 +2015,8 @@ static int _nvmap_do_create(struct nvmap_file_priv *priv, BUG_ON(!h); - spin_lock(&priv->ref_lock); r = kzalloc(sizeof(*r), GFP_KERNEL); if (!r) { - spin_unlock(&priv->ref_lock); if (h) _nvmap_handle_put(h); return -ENOMEM; } @@ -2051,6 +2025,7 @@ static int _nvmap_do_create(struct nvmap_file_priv *priv, r->h = h; atomic_set(&r->pin, 0); + spin_lock(&priv->ref_lock); p = &priv->handle_refs.rb_node; while (*p) { struct nvmap_handle_ref *l; |