diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_allocator_bitmap.c | 24 |
1 files changed, 20 insertions, 4 deletions
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, | |||
211 | static u64 gk20a_bitmap_alloc(struct gk20a_allocator *__a, u64 len) | 211 | static 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) | |||
255 | fail_reset_bitmap: | 270 | fail_reset_bitmap: |
256 | bitmap_clear(a->bitmap, offs, blks); | 271 | bitmap_clear(a->bitmap, offs, blks); |
257 | fail: | 272 | fail: |
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; |