summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/bitmap_allocator_priv.h9
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c24
2 files changed, 29 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/bitmap_allocator_priv.h b/drivers/gpu/nvgpu/gk20a/bitmap_allocator_priv.h
index 053a6425..a686b704 100644
--- a/drivers/gpu/nvgpu/gk20a/bitmap_allocator_priv.h
+++ b/drivers/gpu/nvgpu/gk20a/bitmap_allocator_priv.h
@@ -31,6 +31,15 @@ struct gk20a_bitmap_allocator {
31 u64 num_bits; /* Number of allocatable bits. */ 31 u64 num_bits; /* Number of allocatable bits. */
32 u64 bit_offs; /* Offset of bitmap. */ 32 u64 bit_offs; /* Offset of bitmap. */
33 33
34 /*
35 * Optimization for making repeated allocations faster. Keep track of
36 * the next bit after the most recent allocation. This is where the next
37 * search will start from. This should make allocation faster in cases
38 * where lots of allocations get made one after another. It shouldn't
39 * have a negative impact on the case where the allocator is fragmented.
40 */
41 u64 next_blk;
42
34 unsigned long *bitmap; /* The actual bitmap! */ 43 unsigned long *bitmap; /* The actual bitmap! */
35 struct rb_root allocs; /* Tree of outstanding allocations. */ 44 struct rb_root allocs; /* Tree of outstanding allocations. */
36 45
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c b/drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c
index a2aa85fa..03ccbe85 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c
@@ -211,7 +211,7 @@ static int __gk20a_bitmap_store_alloc(struct gk20a_bitmap_allocator *a,
211static u64 gk20a_bitmap_alloc(struct gk20a_allocator *__a, u64 len) 211static u64 gk20a_bitmap_alloc(struct gk20a_allocator *__a, u64 len)
212{ 212{
213 u64 blks, addr; 213 u64 blks, addr;
214 unsigned long offs, adjusted_offs; 214 unsigned long offs, adjusted_offs, limit;
215 struct gk20a_bitmap_allocator *a = bitmap_allocator(__a); 215 struct gk20a_bitmap_allocator *a = bitmap_allocator(__a);
216 216
217 blks = len >> a->blk_shift; 217 blks = len >> a->blk_shift;
@@ -221,11 +221,26 @@ static u64 gk20a_bitmap_alloc(struct gk20a_allocator *__a, u64 len)
221 221
222 alloc_lock(__a); 222 alloc_lock(__a);
223 223
224 offs = bitmap_find_next_zero_area(a->bitmap, a->num_bits, 0, blks, 0); 224 /*
225 if (offs >= a->num_bits) 225 * First look from next_blk and onwards...
226 goto fail; 226 */
227 offs = bitmap_find_next_zero_area(a->bitmap, a->num_bits,
228 a->next_blk, blks, 0);
229 if (offs >= a->num_bits) {
230 /*
231 * If that didn't work try the remaining area. Since there can
232 * be available space that spans across a->next_blk we need to
233 * search up to the first set bit after that.
234 */
235 limit = find_next_bit(a->bitmap, a->num_bits, a->next_blk);
236 offs = bitmap_find_next_zero_area(a->bitmap, limit,
237 0, blks, 0);
238 if (offs >= a->next_blk)
239 goto fail;
240 }
227 241
228 bitmap_set(a->bitmap, offs, blks); 242 bitmap_set(a->bitmap, offs, blks);
243 a->next_blk = offs + blks;
229 244
230 adjusted_offs = offs + a->bit_offs; 245 adjusted_offs = offs + a->bit_offs;
231 addr = ((u64)adjusted_offs) * a->blk_size; 246 addr = ((u64)adjusted_offs) * a->blk_size;
@@ -255,6 +270,7 @@ static u64 gk20a_bitmap_alloc(struct gk20a_allocator *__a, u64 len)
255fail_reset_bitmap: 270fail_reset_bitmap:
256 bitmap_clear(a->bitmap, offs, blks); 271 bitmap_clear(a->bitmap, offs, blks);
257fail: 272fail:
273 a->next_blk = 0;
258 alloc_unlock(__a); 274 alloc_unlock(__a);
259 alloc_dbg(__a, "Alloc failed!\n"); 275 alloc_dbg(__a, "Alloc failed!\n");
260 return 0; 276 return 0;