summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/mm/page_allocator.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/mm/page_allocator.c')
-rw-r--r--drivers/gpu/nvgpu/common/mm/page_allocator.c142
1 files changed, 76 insertions, 66 deletions
diff --git a/drivers/gpu/nvgpu/common/mm/page_allocator.c b/drivers/gpu/nvgpu/common/mm/page_allocator.c
index 72ff8f2d..6d92b457 100644
--- a/drivers/gpu/nvgpu/common/mm/page_allocator.c
+++ b/drivers/gpu/nvgpu/common/mm/page_allocator.c
@@ -147,19 +147,16 @@ static void __nvgpu_free_pages(struct nvgpu_page_allocator *a,
147 struct nvgpu_page_alloc *alloc, 147 struct nvgpu_page_alloc *alloc,
148 bool free_buddy_alloc) 148 bool free_buddy_alloc)
149{ 149{
150 struct page_alloc_chunk *chunk; 150 struct nvgpu_mem_sgl *sgl = alloc->sgl;
151 151
152 while (!nvgpu_list_empty(&alloc->alloc_chunks)) { 152 if (free_buddy_alloc) {
153 chunk = nvgpu_list_first_entry(&alloc->alloc_chunks, 153 while (sgl) {
154 page_alloc_chunk, 154 nvgpu_free(&a->source_allocator, sgl->phys);
155 list_entry); 155 sgl = nvgpu_mem_sgl_next(sgl);
156 nvgpu_list_del(&chunk->list_entry); 156 }
157
158 if (free_buddy_alloc)
159 nvgpu_free(&a->source_allocator, chunk->base);
160 nvgpu_kmem_cache_free(a->chunk_cache, chunk);
161 } 157 }
162 158
159 nvgpu_mem_sgl_free(a->owner->g, alloc->sgl);
163 nvgpu_kmem_cache_free(a->alloc_cache, alloc); 160 nvgpu_kmem_cache_free(a->alloc_cache, alloc);
164} 161}
165 162
@@ -243,15 +240,14 @@ static void free_slab_page(struct nvgpu_page_allocator *a,
243} 240}
244 241
245/* 242/*
246 * This expects @alloc to have 1 empty page_alloc_chunk already added to the 243 * This expects @alloc to have 1 empty sgl_entry ready for usage.
247 * alloc_chunks list.
248 */ 244 */
249static int __do_slab_alloc(struct nvgpu_page_allocator *a, 245static int __do_slab_alloc(struct nvgpu_page_allocator *a,
250 struct page_alloc_slab *slab, 246 struct page_alloc_slab *slab,
251 struct nvgpu_page_alloc *alloc) 247 struct nvgpu_page_alloc *alloc)
252{ 248{
253 struct page_alloc_slab_page *slab_page = NULL; 249 struct page_alloc_slab_page *slab_page = NULL;
254 struct page_alloc_chunk *chunk; 250 struct nvgpu_mem_sgl *sgl;
255 unsigned long offs; 251 unsigned long offs;
256 252
257 /* 253 /*
@@ -302,18 +298,19 @@ static int __do_slab_alloc(struct nvgpu_page_allocator *a,
302 BUG(); /* Should be impossible to hit this. */ 298 BUG(); /* Should be impossible to hit this. */
303 299
304 /* 300 /*
305 * Handle building the nvgpu_page_alloc struct. We expect one 301 * Handle building the nvgpu_page_alloc struct. We expect one sgl
306 * page_alloc_chunk to be present. 302 * to be present.
307 */ 303 */
308 alloc->slab_page = slab_page; 304 alloc->slab_page = slab_page;
309 alloc->nr_chunks = 1; 305 alloc->nr_chunks = 1;
310 alloc->length = slab_page->slab_size; 306 alloc->length = slab_page->slab_size;
311 alloc->base = slab_page->page_addr + (offs * slab_page->slab_size); 307 alloc->base = slab_page->page_addr + (offs * slab_page->slab_size);
312 308
313 chunk = nvgpu_list_first_entry(&alloc->alloc_chunks, 309 sgl = alloc->sgl;
314 page_alloc_chunk, list_entry); 310 sgl->phys = alloc->base;
315 chunk->base = alloc->base; 311 sgl->dma = alloc->base;
316 chunk->length = alloc->length; 312 sgl->length = alloc->length;
313 sgl->next = NULL;
317 314
318 return 0; 315 return 0;
319} 316}
@@ -327,7 +324,7 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_slab(
327 int err, slab_nr; 324 int err, slab_nr;
328 struct page_alloc_slab *slab; 325 struct page_alloc_slab *slab;
329 struct nvgpu_page_alloc *alloc = NULL; 326 struct nvgpu_page_alloc *alloc = NULL;
330 struct page_alloc_chunk *chunk = NULL; 327 struct nvgpu_mem_sgl *sgl = NULL;
331 328
332 /* 329 /*
333 * Align the length to a page and then divide by the page size (4k for 330 * Align the length to a page and then divide by the page size (4k for
@@ -341,15 +338,13 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_slab(
341 palloc_dbg(a, "OOM: could not alloc page_alloc struct!\n"); 338 palloc_dbg(a, "OOM: could not alloc page_alloc struct!\n");
342 goto fail; 339 goto fail;
343 } 340 }
344 chunk = nvgpu_kmem_cache_alloc(a->chunk_cache); 341 sgl = nvgpu_kzalloc(a->owner->g, sizeof(*sgl));
345 if (!chunk) { 342 if (!sgl) {
346 palloc_dbg(a, "OOM: could not alloc alloc_chunk struct!\n"); 343 palloc_dbg(a, "OOM: could not alloc sgl struct!\n");
347 goto fail; 344 goto fail;
348 } 345 }
349 346
350 nvgpu_init_list_node(&alloc->alloc_chunks); 347 alloc->sgl = sgl;
351 nvgpu_list_add(&chunk->list_entry, &alloc->alloc_chunks);
352
353 err = __do_slab_alloc(a, slab, alloc); 348 err = __do_slab_alloc(a, slab, alloc);
354 if (err) 349 if (err)
355 goto fail; 350 goto fail;
@@ -363,8 +358,8 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_slab(
363fail: 358fail:
364 if (alloc) 359 if (alloc)
365 nvgpu_kmem_cache_free(a->alloc_cache, alloc); 360 nvgpu_kmem_cache_free(a->alloc_cache, alloc);
366 if (chunk) 361 if (sgl)
367 nvgpu_kmem_cache_free(a->chunk_cache, chunk); 362 nvgpu_kfree(a->owner->g, sgl);
368 return NULL; 363 return NULL;
369} 364}
370 365
@@ -426,7 +421,7 @@ static struct nvgpu_page_alloc *__do_nvgpu_alloc_pages(
426 struct nvgpu_page_allocator *a, u64 pages) 421 struct nvgpu_page_allocator *a, u64 pages)
427{ 422{
428 struct nvgpu_page_alloc *alloc; 423 struct nvgpu_page_alloc *alloc;
429 struct page_alloc_chunk *c; 424 struct nvgpu_mem_sgl *sgl, *prev_sgl = NULL;
430 u64 max_chunk_len = pages << a->page_shift; 425 u64 max_chunk_len = pages << a->page_shift;
431 int i = 0; 426 int i = 0;
432 427
@@ -436,7 +431,6 @@ static struct nvgpu_page_alloc *__do_nvgpu_alloc_pages(
436 431
437 memset(alloc, 0, sizeof(*alloc)); 432 memset(alloc, 0, sizeof(*alloc));
438 433
439 nvgpu_init_list_node(&alloc->alloc_chunks);
440 alloc->length = pages << a->page_shift; 434 alloc->length = pages << a->page_shift;
441 435
442 while (pages) { 436 while (pages) {
@@ -482,36 +476,48 @@ static struct nvgpu_page_alloc *__do_nvgpu_alloc_pages(
482 goto fail_cleanup; 476 goto fail_cleanup;
483 } 477 }
484 478
485 c = nvgpu_kmem_cache_alloc(a->chunk_cache); 479 sgl = nvgpu_kzalloc(a->owner->g, sizeof(*sgl));
486 if (!c) { 480 if (!sgl) {
487 nvgpu_free(&a->source_allocator, chunk_addr); 481 nvgpu_free(&a->source_allocator, chunk_addr);
488 goto fail_cleanup; 482 goto fail_cleanup;
489 } 483 }
490 484
491 pages -= chunk_pages; 485 pages -= chunk_pages;
492 486
493 c->base = chunk_addr; 487 sgl->phys = chunk_addr;
494 c->length = chunk_len; 488 sgl->dma = chunk_addr;
495 nvgpu_list_add(&c->list_entry, &alloc->alloc_chunks); 489 sgl->length = chunk_len;
490
491 /*
492 * Build the singly linked list with a head node that is part of
493 * the list.
494 */
495 if (prev_sgl)
496 prev_sgl->next = sgl;
497 else
498 alloc->sgl = sgl;
499
500 prev_sgl = sgl;
496 501
497 i++; 502 i++;
498 } 503 }
499 504
500 alloc->nr_chunks = i; 505 alloc->nr_chunks = i;
501 c = nvgpu_list_first_entry(&alloc->alloc_chunks, 506 alloc->base = alloc->sgl->phys;
502 page_alloc_chunk, list_entry);
503 alloc->base = c->base;
504 507
505 return alloc; 508 return alloc;
506 509
507fail_cleanup: 510fail_cleanup:
508 while (!nvgpu_list_empty(&alloc->alloc_chunks)) { 511 sgl = alloc->sgl;
509 c = nvgpu_list_first_entry(&alloc->alloc_chunks, 512 while (sgl) {
510 page_alloc_chunk, list_entry); 513 struct nvgpu_mem_sgl *next = sgl->next;
511 nvgpu_list_del(&c->list_entry); 514
512 nvgpu_free(&a->source_allocator, c->base); 515 nvgpu_free(&a->source_allocator, sgl->phys);
513 nvgpu_kmem_cache_free(a->chunk_cache, c); 516 nvgpu_kfree(a->owner->g, sgl);
517
518 sgl = next;
514 } 519 }
520
515 nvgpu_kmem_cache_free(a->alloc_cache, alloc); 521 nvgpu_kmem_cache_free(a->alloc_cache, alloc);
516fail: 522fail:
517 return NULL; 523 return NULL;
@@ -521,7 +527,7 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages(
521 struct nvgpu_page_allocator *a, u64 len) 527 struct nvgpu_page_allocator *a, u64 len)
522{ 528{
523 struct nvgpu_page_alloc *alloc = NULL; 529 struct nvgpu_page_alloc *alloc = NULL;
524 struct page_alloc_chunk *c; 530 struct nvgpu_mem_sgl *sgl;
525 u64 pages; 531 u64 pages;
526 int i = 0; 532 int i = 0;
527 533
@@ -536,11 +542,15 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages(
536 542
537 palloc_dbg(a, "Alloc 0x%llx (%llu) id=0x%010llx\n", 543 palloc_dbg(a, "Alloc 0x%llx (%llu) id=0x%010llx\n",
538 pages << a->page_shift, pages, alloc->base); 544 pages << a->page_shift, pages, alloc->base);
539 nvgpu_list_for_each_entry(c, &alloc->alloc_chunks, 545 sgl = alloc->sgl;
540 page_alloc_chunk, list_entry) { 546 while (sgl) {
541 palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n", 547 palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n",
542 i++, c->base, c->length); 548 i++,
549 nvgpu_mem_sgl_phys(sgl),
550 nvgpu_mem_sgl_length(sgl));
551 sgl = sgl->next;
543 } 552 }
553 palloc_dbg(a, "Alloc done\n");
544 554
545 return alloc; 555 return alloc;
546} 556}
@@ -638,11 +648,11 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages_fixed(
638 struct nvgpu_page_allocator *a, u64 base, u64 length, u32 unused) 648 struct nvgpu_page_allocator *a, u64 base, u64 length, u32 unused)
639{ 649{
640 struct nvgpu_page_alloc *alloc; 650 struct nvgpu_page_alloc *alloc;
641 struct page_alloc_chunk *c; 651 struct nvgpu_mem_sgl *sgl;
642 652
643 alloc = nvgpu_kmem_cache_alloc(a->alloc_cache); 653 alloc = nvgpu_kmem_cache_alloc(a->alloc_cache);
644 c = nvgpu_kmem_cache_alloc(a->chunk_cache); 654 sgl = nvgpu_kzalloc(a->owner->g, sizeof(*sgl));
645 if (!alloc || !c) 655 if (!alloc || !sgl)
646 goto fail; 656 goto fail;
647 657
648 alloc->base = nvgpu_alloc_fixed(&a->source_allocator, base, length, 0); 658 alloc->base = nvgpu_alloc_fixed(&a->source_allocator, base, length, 0);
@@ -653,17 +663,18 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages_fixed(
653 663
654 alloc->nr_chunks = 1; 664 alloc->nr_chunks = 1;
655 alloc->length = length; 665 alloc->length = length;
656 nvgpu_init_list_node(&alloc->alloc_chunks); 666 alloc->sgl = sgl;
657 667
658 c->base = alloc->base; 668 sgl->phys = alloc->base;
659 c->length = length; 669 sgl->dma = alloc->base;
660 nvgpu_list_add(&c->list_entry, &alloc->alloc_chunks); 670 sgl->length = length;
671 sgl->next = NULL;
661 672
662 return alloc; 673 return alloc;
663 674
664fail: 675fail:
665 if (c) 676 if (sgl)
666 nvgpu_kmem_cache_free(a->chunk_cache, c); 677 nvgpu_kfree(a->owner->g, sgl);
667 if (alloc) 678 if (alloc)
668 nvgpu_kmem_cache_free(a->alloc_cache, alloc); 679 nvgpu_kmem_cache_free(a->alloc_cache, alloc);
669 return NULL; 680 return NULL;
@@ -677,7 +688,7 @@ static u64 nvgpu_page_alloc_fixed(struct nvgpu_allocator *__a,
677{ 688{
678 struct nvgpu_page_allocator *a = page_allocator(__a); 689 struct nvgpu_page_allocator *a = page_allocator(__a);
679 struct nvgpu_page_alloc *alloc = NULL; 690 struct nvgpu_page_alloc *alloc = NULL;
680 struct page_alloc_chunk *c; 691 struct nvgpu_mem_sgl *sgl;
681 u64 aligned_len, pages; 692 u64 aligned_len, pages;
682 int i = 0; 693 int i = 0;
683 694
@@ -697,10 +708,13 @@ static u64 nvgpu_page_alloc_fixed(struct nvgpu_allocator *__a,
697 708
698 palloc_dbg(a, "Alloc [fixed] @ 0x%010llx + 0x%llx (%llu)\n", 709 palloc_dbg(a, "Alloc [fixed] @ 0x%010llx + 0x%llx (%llu)\n",
699 alloc->base, aligned_len, pages); 710 alloc->base, aligned_len, pages);
700 nvgpu_list_for_each_entry(c, &alloc->alloc_chunks, 711 sgl = alloc->sgl;
701 page_alloc_chunk, list_entry) { 712 while (sgl) {
702 palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n", 713 palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n",
703 i++, c->base, c->length); 714 i++,
715 nvgpu_mem_sgl_phys(sgl),
716 nvgpu_mem_sgl_length(sgl));
717 sgl = sgl->next;
704 } 718 }
705 719
706 a->nr_fixed_allocs++; 720 a->nr_fixed_allocs++;
@@ -896,11 +910,9 @@ int nvgpu_page_allocator_init(struct gk20a *g, struct nvgpu_allocator *__a,
896 910
897 a->alloc_cache = nvgpu_kmem_cache_create(g, 911 a->alloc_cache = nvgpu_kmem_cache_create(g,
898 sizeof(struct nvgpu_page_alloc)); 912 sizeof(struct nvgpu_page_alloc));
899 a->chunk_cache = nvgpu_kmem_cache_create(g,
900 sizeof(struct page_alloc_chunk));
901 a->slab_page_cache = nvgpu_kmem_cache_create(g, 913 a->slab_page_cache = nvgpu_kmem_cache_create(g,
902 sizeof(struct page_alloc_slab_page)); 914 sizeof(struct page_alloc_slab_page));
903 if (!a->alloc_cache || !a->chunk_cache || !a->slab_page_cache) { 915 if (!a->alloc_cache || !a->slab_page_cache) {
904 err = -ENOMEM; 916 err = -ENOMEM;
905 goto fail; 917 goto fail;
906 } 918 }
@@ -941,8 +953,6 @@ int nvgpu_page_allocator_init(struct gk20a *g, struct nvgpu_allocator *__a,
941fail: 953fail:
942 if (a->alloc_cache) 954 if (a->alloc_cache)
943 nvgpu_kmem_cache_destroy(a->alloc_cache); 955 nvgpu_kmem_cache_destroy(a->alloc_cache);
944 if (a->chunk_cache)
945 nvgpu_kmem_cache_destroy(a->chunk_cache);
946 if (a->slab_page_cache) 956 if (a->slab_page_cache)
947 nvgpu_kmem_cache_destroy(a->slab_page_cache); 957 nvgpu_kmem_cache_destroy(a->slab_page_cache);
948 nvgpu_kfree(g, a); 958 nvgpu_kfree(g, a);