From 4c021b1dfbb5e422d82370087f0813997e864f00 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Fri, 27 Jun 2014 15:23:40 +0300 Subject: gpu: nvgpu: Replace allocator with bitmap alloc Replace gk20a allocator with Linux bitmap allocator. Change-Id: Iba5e28f68ab5cf19e2c033005efd7f9da6e4a5b6 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/554184 --- drivers/gpu/nvgpu/gk20a/gk20a_allocator.c | 732 +----------------------------- drivers/gpu/nvgpu/gk20a/gk20a_allocator.h | 25 +- 2 files changed, 23 insertions(+), 734 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c index 8ad3c63f..b404799f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c @@ -18,627 +18,6 @@ #include "gk20a_allocator.h" -static inline void link_block_list(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev, - struct rb_node *rb_parent); -static inline void link_block_rb(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct rb_node **rb_link, - struct rb_node *rb_parent); -static void link_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev, struct rb_node **rb_link, - struct rb_node *rb_parent); -static void insert_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block); - -static void unlink_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev); -static struct gk20a_alloc_block *unlink_blocks( - struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev, u32 end); - -static struct gk20a_alloc_block *find_block( - struct gk20a_allocator *allocator, u32 addr); -static struct gk20a_alloc_block *find_block_prev( - struct gk20a_allocator *allocator, u32 addr, - struct gk20a_alloc_block **pprev); -static struct gk20a_alloc_block *find_block_prepare( - struct gk20a_allocator *allocator, u32 addr, - struct gk20a_alloc_block **pprev, struct rb_node ***rb_link, - struct rb_node **rb_parent); - -static void update_free_addr_cache(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - u32 addr, u32 len, bool free); -static int find_free_area(struct gk20a_allocator *allocator, - u32 *addr, u32 len); - -static void adjust_block(struct gk20a_alloc_block *block, - u32 start, u32 end, - struct gk20a_alloc_block *insert); -static struct gk20a_alloc_block *merge_block( - struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, u32 addr, u32 end); -static int split_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - u32 addr, int new_below); - -static int block_alloc_single_locked(struct gk20a_allocator *allocator, - u32 *addr, u32 len); -static int block_free_locked(struct gk20a_allocator *allocator, - u32 addr, u32 len); - -/* link a block into allocator block list */ -static inline void link_block_list(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev, - struct rb_node *rb_parent) -{ - struct gk20a_alloc_block *next; - - block->prev = prev; - if (prev) { - next = prev->next; - prev->next = block; - } else { - allocator->block_first = block; - if (rb_parent) - next = rb_entry(rb_parent, - struct gk20a_alloc_block, rb); - else - next = NULL; - } - block->next = next; - if (next) - next->prev = block; -} - -/* link a block into allocator rb tree */ -static inline void link_block_rb(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, struct rb_node **rb_link, - struct rb_node *rb_parent) -{ - rb_link_node(&block->rb, rb_parent, rb_link); - rb_insert_color(&block->rb, &allocator->rb_root); -} - -/* add a block to allocator with known location */ -static void link_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev, struct rb_node **rb_link, - struct rb_node *rb_parent) -{ - struct gk20a_alloc_block *next; - - link_block_list(allocator, block, prev, rb_parent); - link_block_rb(allocator, block, rb_link, rb_parent); - allocator->block_count++; - - next = block->next; - allocator_dbg(allocator, "link new block %d:%d between block %d:%d and block %d:%d", - block->start, block->end, - prev ? prev->start : -1, prev ? prev->end : -1, - next ? next->start : -1, next ? next->end : -1); -} - -/* add a block to allocator */ -static void insert_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block) -{ - struct gk20a_alloc_block *prev; - struct rb_node **rb_link, *rb_parent; - - find_block_prepare(allocator, block->start, - &prev, &rb_link, &rb_parent); - link_block(allocator, block, prev, rb_link, rb_parent); -} - -/* remove a block from allocator */ -static void unlink_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev) -{ - struct gk20a_alloc_block *next = block->next; - - allocator_dbg(allocator, "unlink block %d:%d between block %d:%d and block %d:%d", - block->start, block->end, - prev ? prev->start : -1, prev ? prev->end : -1, - next ? next->start : -1, next ? next->end : -1); - - BUG_ON(block->start < allocator->base); - BUG_ON(block->end > allocator->limit); - - if (prev) - prev->next = next; - else - allocator->block_first = next; - - if (next) - next->prev = prev; - rb_erase(&block->rb, &allocator->rb_root); - if (allocator->block_recent == block) - allocator->block_recent = prev; - - allocator->block_count--; -} - -/* remove a list of blocks from allocator. the list can contain both - regular blocks and non-contiguous blocks. skip all non-contiguous - blocks, remove regular blocks into a separate list, return list head */ -static struct gk20a_alloc_block * -unlink_blocks(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, - struct gk20a_alloc_block *prev, - u32 end) -{ - struct gk20a_alloc_block **insertion_point; - struct gk20a_alloc_block *last_unfreed_block = prev; - struct gk20a_alloc_block *last_freed_block = NULL; - struct gk20a_alloc_block *first_freed_block = NULL; - - insertion_point = (prev ? &prev->next : &allocator->block_first); - *insertion_point = NULL; - - do { - if (!block->nc_block) { - allocator_dbg(allocator, "unlink block %d:%d", - block->start, block->end); - if (last_freed_block) - last_freed_block->next = block; - block->prev = last_freed_block; - rb_erase(&block->rb, &allocator->rb_root); - last_freed_block = block; - allocator->block_count--; - if (!first_freed_block) - first_freed_block = block; - } else { - allocator_dbg(allocator, "skip nc block %d:%d", - block->start, block->end); - if (!*insertion_point) - *insertion_point = block; - if (last_unfreed_block) - last_unfreed_block->next = block; - block->prev = last_unfreed_block; - last_unfreed_block = block; - } - block = block->next; - } while (block && block->start < end); - - if (!*insertion_point) - *insertion_point = block; - - if (block) - block->prev = last_unfreed_block; - if (last_unfreed_block) - last_unfreed_block->next = block; - if (last_freed_block) - last_freed_block->next = NULL; - - allocator->block_recent = NULL; - - return first_freed_block; -} - -/* Look up the first block which satisfies addr < block->end, - NULL if none */ -static struct gk20a_alloc_block * -find_block(struct gk20a_allocator *allocator, u32 addr) -{ - struct gk20a_alloc_block *block = allocator->block_recent; - - if (!(block && block->end > addr && block->start <= addr)) { - struct rb_node *rb_node; - - rb_node = allocator->rb_root.rb_node; - block = NULL; - - while (rb_node) { - struct gk20a_alloc_block *block_tmp; - - block_tmp = rb_entry(rb_node, - struct gk20a_alloc_block, rb); - - if (block_tmp->end > addr) { - block = block_tmp; - if (block_tmp->start <= addr) - break; - rb_node = rb_node->rb_left; - } else - rb_node = rb_node->rb_right; - if (block) - allocator->block_recent = block; - } - } - return block; -} - -/* Same as find_block, but also return a pointer to the previous block */ -static struct gk20a_alloc_block * -find_block_prev(struct gk20a_allocator *allocator, u32 addr, - struct gk20a_alloc_block **pprev) -{ - struct gk20a_alloc_block *block = NULL, *prev = NULL; - struct rb_node *rb_node; - if (!allocator) - goto out; - - block = allocator->block_first; - - rb_node = allocator->rb_root.rb_node; - - while (rb_node) { - struct gk20a_alloc_block *block_tmp; - block_tmp = rb_entry(rb_node, struct gk20a_alloc_block, rb); - - if (addr < block_tmp->end) - rb_node = rb_node->rb_left; - else { - prev = block_tmp; - if (!prev->next || addr < prev->next->end) - break; - rb_node = rb_node->rb_right; - } - } - -out: - *pprev = prev; - return prev ? prev->next : block; -} - -/* Same as find_block, but also return a pointer to the previous block - and return rb_node to prepare for rbtree insertion */ -static struct gk20a_alloc_block * -find_block_prepare(struct gk20a_allocator *allocator, u32 addr, - struct gk20a_alloc_block **pprev, struct rb_node ***rb_link, - struct rb_node **rb_parent) -{ - struct gk20a_alloc_block *block; - struct rb_node **__rb_link, *__rb_parent, *rb_prev; - - __rb_link = &allocator->rb_root.rb_node; - rb_prev = __rb_parent = NULL; - block = NULL; - - while (*__rb_link) { - struct gk20a_alloc_block *block_tmp; - - __rb_parent = *__rb_link; - block_tmp = rb_entry(__rb_parent, - struct gk20a_alloc_block, rb); - - if (block_tmp->end > addr) { - block = block_tmp; - if (block_tmp->start <= addr) - break; - __rb_link = &__rb_parent->rb_left; - } else { - rb_prev = __rb_parent; - __rb_link = &__rb_parent->rb_right; - } - } - - *pprev = NULL; - if (rb_prev) - *pprev = rb_entry(rb_prev, struct gk20a_alloc_block, rb); - *rb_link = __rb_link; - *rb_parent = __rb_parent; - return block; -} - -/* update first_free_addr/last_free_addr based on new free addr - called when free block(s) and allocate block(s) */ -static void update_free_addr_cache(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *next, - u32 addr, u32 len, bool free) -{ - /* update from block free */ - if (free) { - if (allocator->first_free_addr > addr) - allocator->first_free_addr = addr; - } else { /* update from block alloc */ - if (allocator->last_free_addr < addr + len) - allocator->last_free_addr = addr + len; - if (allocator->first_free_addr == addr) { - if (!next || next->start > addr + len) - allocator->first_free_addr = addr + len; - else - allocator->first_free_addr = next->end; - } - } - - if (allocator->first_free_addr > allocator->last_free_addr) - allocator->first_free_addr = allocator->last_free_addr; -} - -/* find a free address range for a fixed len */ -static int find_free_area(struct gk20a_allocator *allocator, - u32 *addr, u32 len) -{ - struct gk20a_alloc_block *block; - u32 start_addr, search_base, search_limit; - - /* fixed addr allocation */ - /* note: constraints for fixed are handled by caller */ - if (*addr) { - block = find_block(allocator, *addr); - if (allocator->limit - len >= *addr && - (!block || *addr + len <= block->start)) { - update_free_addr_cache(allocator, block, - *addr, len, false); - return 0; - } else - return -ENOMEM; - } - - if (!allocator->constraint.enable) { - search_base = allocator->base; - search_limit = allocator->limit; - } else { - start_addr = *addr = allocator->constraint.base; - search_base = allocator->constraint.base; - search_limit = allocator->constraint.limit; - } - - /* cached_hole_size has max free space up to last_free_addr */ - if (len > allocator->cached_hole_size) - start_addr = *addr = allocator->last_free_addr; - else { - start_addr = *addr = allocator->base; - allocator->cached_hole_size = 0; - } - - allocator_dbg(allocator, "start search addr : %d", start_addr); - -full_search: - for (block = find_block(allocator, *addr);; block = block->next) { - if (search_limit - len < *addr) { - /* start a new search in case we missed any hole */ - if (start_addr != search_base) { - start_addr = *addr = search_base; - allocator->cached_hole_size = 0; - allocator_dbg(allocator, "start a new search from base"); - goto full_search; - } - return -ENOMEM; - } - if (!block || *addr + len <= block->start) { - update_free_addr_cache(allocator, block, - *addr, len, false); - allocator_dbg(allocator, "free space from %d, len %d", - *addr, len); - allocator_dbg(allocator, "next free addr: %d", - allocator->last_free_addr); - return 0; - } - if (*addr + allocator->cached_hole_size < block->start) - allocator->cached_hole_size = block->start - *addr; - *addr = block->end; - } -} - -/* expand/shrink a block with new start and new end - split_block function provides insert block for shrink */ -static void adjust_block(struct gk20a_alloc_block *block, - u32 start, u32 end, struct gk20a_alloc_block *insert) -{ - struct gk20a_allocator *allocator = block->allocator; - - allocator_dbg(allocator, "curr block %d:%d, new start %d, new end %d", - block->start, block->end, start, end); - - /* expand */ - if (!insert) { - if (start == block->end) { - struct gk20a_alloc_block *next = block->next; - - if (next && end == next->start) { - /* ....AAAA.... */ - /* PPPP....NNNN */ - /* PPPPPPPPPPPP */ - unlink_block(allocator, next, block); - block->end = next->end; - kmem_cache_free(allocator->block_cache, next); - } else { - /* ....AAAA.... */ - /* PPPP........ */ - /* PPPPPPPP.... */ - block->end = end; - } - } - - if (end == block->start) { - /* ....AAAA.... */ - /* ........NNNN */ - /* PP..NNNNNNNN ....NNNNNNNN */ - block->start = start; - } - } else { /* shrink */ - /* BBBBBBBB -> BBBBIIII OR BBBBBBBB -> IIIIBBBB */ - block->start = start; - block->end = end; - insert_block(allocator, insert); - } -} - -/* given a range [addr, end], merge it with blocks before or after or both - if they can be combined into a contiguous block */ -static struct gk20a_alloc_block * -merge_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *prev, u32 addr, u32 end) -{ - struct gk20a_alloc_block *next; - - if (prev) - next = prev->next; - else - next = allocator->block_first; - - allocator_dbg(allocator, "curr block %d:%d", addr, end); - if (prev) - allocator_dbg(allocator, "prev block %d:%d", - prev->start, prev->end); - if (next) - allocator_dbg(allocator, "next block %d:%d", - next->start, next->end); - - /* don't merge with non-contiguous allocation block */ - if (prev && prev->end == addr && !prev->nc_block) { - adjust_block(prev, addr, end, NULL); - return prev; - } - - /* don't merge with non-contiguous allocation block */ - if (next && end == next->start && !next->nc_block) { - adjust_block(next, addr, end, NULL); - return next; - } - - return NULL; -} - -/* split a block based on addr. addr must be within (start, end). - if new_below == 1, link new block before adjusted current block */ -static int split_block(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block, u32 addr, int new_below) -{ - struct gk20a_alloc_block *new_block; - - allocator_dbg(allocator, "start %d, split %d, end %d, new_below %d", - block->start, addr, block->end, new_below); - - BUG_ON(!(addr > block->start && addr < block->end)); - - new_block = kmem_cache_alloc(allocator->block_cache, GFP_KERNEL); - if (!new_block) - return -ENOMEM; - - *new_block = *block; - - if (new_below) - new_block->end = addr; - else - new_block->start = addr; - - if (new_below) - adjust_block(block, addr, block->end, new_block); - else - adjust_block(block, block->start, addr, new_block); - - return 0; -} - -/* free a list of blocks */ -static void free_blocks(struct gk20a_allocator *allocator, - struct gk20a_alloc_block *block) -{ - struct gk20a_alloc_block *curr_block; - while (block) { - curr_block = block; - block = block->next; - kmem_cache_free(allocator->block_cache, curr_block); - } -} - -/* called with rw_sema acquired */ -static int block_alloc_single_locked(struct gk20a_allocator *allocator, - u32 *addr_req, u32 len) -{ - struct gk20a_alloc_block *block, *prev; - struct rb_node **rb_link, *rb_parent; - u32 addr = *addr_req; - int err; - - *addr_req = ~0; - - err = find_free_area(allocator, &addr, len); - if (err) - return err; - - find_block_prepare(allocator, addr, &prev, &rb_link, &rb_parent); - - /* merge requested free space with existing block(s) - if they can be combined into one contiguous block */ - block = merge_block(allocator, prev, addr, addr + len); - if (block) { - *addr_req = addr; - return 0; - } - - /* create a new block if cannot merge */ - block = kmem_cache_zalloc(allocator->block_cache, GFP_KERNEL); - if (!block) - return -ENOMEM; - - block->allocator = allocator; - block->start = addr; - block->end = addr + len; - - link_block(allocator, block, prev, rb_link, rb_parent); - - *addr_req = addr; - - return 0; -} - -/* called with rw_sema acquired */ -static int block_free_locked(struct gk20a_allocator *allocator, - u32 addr, u32 len) -{ - struct gk20a_alloc_block *block, *prev, *last; - u32 end; - int err; - - /* no block has block->end > addr, already free */ - block = find_block_prev(allocator, addr, &prev); - if (!block) - return 0; - - allocator_dbg(allocator, "first block in free range %d:%d", - block->start, block->end); - - end = addr + len; - /* not in any block, already free */ - if (block->start >= end) - return 0; - - /* don't touch nc_block in range free */ - if (addr > block->start && !block->nc_block) { - int err = split_block(allocator, block, addr, 0); - if (err) - return err; - prev = block; - } - - last = find_block(allocator, end); - if (last && end > last->start && !last->nc_block) { - - allocator_dbg(allocator, "last block in free range %d:%d", - last->start, last->end); - - err = split_block(allocator, last, end, 1); - if (err) - return err; - } - - block = prev ? prev->next : allocator->block_first; - - allocator_dbg(allocator, "first block for free %d:%d", - block->start, block->end); - - /* remove blocks between [addr, addr + len) from rb tree - and put them in a list */ - block = unlink_blocks(allocator, block, prev, end); - free_blocks(allocator, block); - - update_free_addr_cache(allocator, NULL, addr, len, true); - - return 0; -} - /* init allocator struct */ int gk20a_allocator_init(struct gk20a_allocator *allocator, const char *name, u32 start, u32 len, u32 align) @@ -647,26 +26,19 @@ int gk20a_allocator_init(struct gk20a_allocator *allocator, strncpy(allocator->name, name, 32); - allocator->block_cache = - kmem_cache_create(allocator->name, - sizeof(struct gk20a_alloc_block), 0, - SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); - if (!allocator->block_cache) - return -ENOMEM; - - allocator->rb_root = RB_ROOT; - allocator->base = start; allocator->limit = start + len - 1; allocator->align = align; + allocator->bitmap = kzalloc(BITS_TO_LONGS(len) * sizeof(long), + GFP_KERNEL); + if (!allocator->bitmap) + return -ENOMEM; + allocator_dbg(allocator, "%s : base %d, limit %d, align %d", allocator->name, allocator->base, allocator->limit, allocator->align); - allocator->first_free_addr = allocator->last_free_addr = start; - allocator->cached_hole_size = len; - init_rwsem(&allocator->rw_sema); allocator->alloc = gk20a_allocator_block_alloc; @@ -678,26 +50,9 @@ int gk20a_allocator_init(struct gk20a_allocator *allocator, /* destroy allocator, free all remaining blocks if any */ void gk20a_allocator_destroy(struct gk20a_allocator *allocator) { - struct gk20a_alloc_block *block, *next; - u32 free_count = 0; - down_write(&allocator->rw_sema); - for (block = allocator->block_first; block; ) { - allocator_dbg(allocator, "free remaining block %d:%d", - block->start, block->end); - next = block->next; - kmem_cache_free(allocator->block_cache, block); - free_count++; - block = next; - } - - up_write(&allocator->rw_sema); - - /* block_count doesn't match real number of blocks */ - BUG_ON(free_count != allocator->block_count); - - kmem_cache_destroy(allocator->block_cache); + kfree(allocator->bitmap); memset(allocator, 0, sizeof(struct gk20a_allocator)); } @@ -712,23 +67,14 @@ void gk20a_allocator_destroy(struct gk20a_allocator *allocator) int gk20a_allocator_block_alloc(struct gk20a_allocator *allocator, u32 *addr, u32 len) { - int ret; -#if defined(ALLOCATOR_DEBUG) - struct gk20a_alloc_block *block; - bool should_fail = false; -#endif + unsigned long _addr; allocator_dbg(allocator, "[in] addr %d, len %d", *addr, len); if ((*addr != 0 && *addr < allocator->base) || /* check addr range */ *addr + len > allocator->limit || /* check addr range */ *addr & (allocator->align - 1) || /* check addr alignment */ - len == 0) /* check len */ - return -EINVAL; - - if (allocator->constraint.enable && - (*addr + len > allocator->constraint.limit || - *addr > allocator->constraint.base)) + len == 0) /* check len */ return -EINVAL; len = ALIGN(len, allocator->align); @@ -737,52 +83,29 @@ int gk20a_allocator_block_alloc(struct gk20a_allocator *allocator, down_write(&allocator->rw_sema); -#if defined(ALLOCATOR_DEBUG) - if (*addr) { - for (block = allocator->block_first; - block; block = block->next) { - if (block->end > *addr && block->start < *addr + len) { - should_fail = true; - break; - } - } - } -#endif - - ret = block_alloc_single_locked(allocator, addr, len); + _addr = bitmap_find_next_zero_area(allocator->bitmap, + allocator->limit - allocator->base + 1, + *addr ? (*addr - allocator->base) : 0, + len, + allocator->align - 1); + if ((_addr > allocator->limit - allocator->base + 1) || + (*addr && *addr != (_addr + allocator->base))) + return -ENOMEM; -#if defined(ALLOCATOR_DEBUG) - if (!ret) { - bool allocated = false; - BUG_ON(should_fail); - BUG_ON(*addr < allocator->base); - BUG_ON(*addr + len > allocator->limit); - for (block = allocator->block_first; - block; block = block->next) { - if (!block->nc_block && - block->start <= *addr && - block->end >= *addr + len) { - allocated = true; - break; - } - } - BUG_ON(!allocated); - } -#endif + bitmap_set(allocator->bitmap, _addr, len); + *addr = allocator->base + _addr; up_write(&allocator->rw_sema); allocator_dbg(allocator, "[out] addr %d, len %d", *addr, len); - return ret; + return 0; } /* free all blocks between start and end */ int gk20a_allocator_block_free(struct gk20a_allocator *allocator, u32 addr, u32 len) { - int ret; - allocator_dbg(allocator, "[in] addr %d, len %d", addr, len); if (addr + len > allocator->limit || /* check addr range */ @@ -795,23 +118,10 @@ int gk20a_allocator_block_free(struct gk20a_allocator *allocator, return -EINVAL; down_write(&allocator->rw_sema); - - ret = block_free_locked(allocator, addr, len); - -#if defined(ALLOCATOR_DEBUG) - if (!ret) { - struct gk20a_alloc_block *block; - for (block = allocator->block_first; - block; block = block->next) { - if (!block->nc_block) - BUG_ON(block->start >= addr && - block->end <= addr + len); - } - } -#endif + bitmap_clear(allocator->bitmap, addr - allocator->base, len); up_write(&allocator->rw_sema); allocator_dbg(allocator, "[out] addr %d, len %d", addr, len); - return ret; + return 0; } diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h index 5621800e..154f953a 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h @@ -33,6 +33,8 @@ struct gk20a_allocator { u32 limit; /* max value = limit - 1 */ u32 align; /* alignment size, power of 2 */ + unsigned long *bitmap; /* bitmap */ + struct gk20a_alloc_block *block_first; /* first block in list */ struct gk20a_alloc_block *block_recent; /* last visited block */ @@ -62,29 +64,6 @@ struct gk20a_allocator { }; -/* a block of linear space range [start, end) */ -struct gk20a_alloc_block { - struct gk20a_allocator *allocator; /* parent allocator */ - struct rb_node rb; /* rb tree node */ - - u32 start; /* linear space range - [start, end) */ - u32 end; - - void *priv; /* backing structure for this - linear space block - page table, comp tag, etc */ - - struct gk20a_alloc_block *prev; /* prev block with lower address */ - struct gk20a_alloc_block *next; /* next block with higher address */ - - bool nc_block; - struct gk20a_alloc_block *nc_prev; /* prev block for - non-contiguous allocation */ - struct gk20a_alloc_block *nc_next; /* next block for - non-contiguous allocation */ -}; - int gk20a_allocator_init(struct gk20a_allocator *allocator, const char *name, u32 base, u32 size, u32 align); void gk20a_allocator_destroy(struct gk20a_allocator *allocator); -- cgit v1.2.2