diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/mm/page_allocator.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/mm/page_allocator.c | 114 |
1 files changed, 96 insertions, 18 deletions
diff --git a/drivers/gpu/nvgpu/common/mm/page_allocator.c b/drivers/gpu/nvgpu/common/mm/page_allocator.c index 6d92b457..9c35f528 100644 --- a/drivers/gpu/nvgpu/common/mm/page_allocator.c +++ b/drivers/gpu/nvgpu/common/mm/page_allocator.c | |||
@@ -143,20 +143,93 @@ static void nvgpu_page_release_co(struct nvgpu_allocator *a, | |||
143 | nvgpu_alloc_release_carveout(&va->source_allocator, co); | 143 | nvgpu_alloc_release_carveout(&va->source_allocator, co); |
144 | } | 144 | } |
145 | 145 | ||
146 | static void *nvgpu_page_alloc_sgl_next(void *sgl) | ||
147 | { | ||
148 | struct nvgpu_mem_sgl *nvgpu_sgl = sgl; | ||
149 | |||
150 | return nvgpu_sgl->next; | ||
151 | } | ||
152 | |||
153 | static u64 nvgpu_page_alloc_sgl_phys(void *sgl) | ||
154 | { | ||
155 | struct nvgpu_mem_sgl *nvgpu_sgl = sgl; | ||
156 | |||
157 | return nvgpu_sgl->phys; | ||
158 | } | ||
159 | |||
160 | static u64 nvgpu_page_alloc_sgl_dma(void *sgl) | ||
161 | { | ||
162 | struct nvgpu_mem_sgl *nvgpu_sgl = sgl; | ||
163 | |||
164 | return nvgpu_sgl->dma; | ||
165 | } | ||
166 | |||
167 | static u64 nvgpu_page_alloc_sgl_length(void *sgl) | ||
168 | { | ||
169 | struct nvgpu_mem_sgl *nvgpu_sgl = sgl; | ||
170 | |||
171 | return nvgpu_sgl->length; | ||
172 | } | ||
173 | |||
174 | static u64 nvgpu_page_alloc_sgl_gpu_addr(struct gk20a *g, void *sgl, | ||
175 | struct nvgpu_gmmu_attrs *attrs) | ||
176 | { | ||
177 | struct nvgpu_mem_sgl *nvgpu_sgl = sgl; | ||
178 | |||
179 | return nvgpu_sgl->phys; | ||
180 | } | ||
181 | |||
182 | static void nvgpu_page_alloc_sgt_free(struct gk20a *g, struct nvgpu_sgt *sgt) | ||
183 | { | ||
184 | /* | ||
185 | * No-op here. The free is handled by the page_alloc free() functions. | ||
186 | */ | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * These implement the generic scatter gather ops for pages allocated | ||
191 | * by the page allocator. however, the primary aim for this, is of course, | ||
192 | * vidmem. | ||
193 | */ | ||
194 | static const struct nvgpu_sgt_ops page_alloc_sgl_ops = { | ||
195 | .sgl_next = nvgpu_page_alloc_sgl_next, | ||
196 | .sgl_phys = nvgpu_page_alloc_sgl_phys, | ||
197 | .sgl_dma = nvgpu_page_alloc_sgl_dma, | ||
198 | .sgl_length = nvgpu_page_alloc_sgl_length, | ||
199 | .sgl_gpu_addr = nvgpu_page_alloc_sgl_gpu_addr, | ||
200 | .sgt_free = nvgpu_page_alloc_sgt_free, | ||
201 | }; | ||
202 | |||
203 | /* | ||
204 | * This actually frees the sgl memory. Used by the page_alloc free() functions. | ||
205 | */ | ||
206 | static void nvgpu_page_alloc_sgl_proper_free(struct gk20a *g, | ||
207 | struct nvgpu_mem_sgl *sgl) | ||
208 | { | ||
209 | struct nvgpu_mem_sgl *next; | ||
210 | |||
211 | while (sgl) { | ||
212 | next = sgl->next; | ||
213 | nvgpu_kfree(g, sgl); | ||
214 | sgl = next; | ||
215 | } | ||
216 | } | ||
217 | |||
146 | static void __nvgpu_free_pages(struct nvgpu_page_allocator *a, | 218 | static void __nvgpu_free_pages(struct nvgpu_page_allocator *a, |
147 | struct nvgpu_page_alloc *alloc, | 219 | struct nvgpu_page_alloc *alloc, |
148 | bool free_buddy_alloc) | 220 | bool free_buddy_alloc) |
149 | { | 221 | { |
150 | struct nvgpu_mem_sgl *sgl = alloc->sgl; | 222 | struct nvgpu_mem_sgl *sgl = alloc->sgt.sgl; |
151 | 223 | ||
152 | if (free_buddy_alloc) { | 224 | if (free_buddy_alloc) { |
153 | while (sgl) { | 225 | while (sgl) { |
154 | nvgpu_free(&a->source_allocator, sgl->phys); | 226 | nvgpu_free(&a->source_allocator, |
155 | sgl = nvgpu_mem_sgl_next(sgl); | 227 | nvgpu_sgt_get_phys(&alloc->sgt, sgl)); |
228 | sgl = nvgpu_sgt_get_next(&alloc->sgt, sgl); | ||
156 | } | 229 | } |
157 | } | 230 | } |
158 | 231 | ||
159 | nvgpu_mem_sgl_free(a->owner->g, alloc->sgl); | 232 | nvgpu_page_alloc_sgl_proper_free(a->owner->g, sgl); |
160 | nvgpu_kmem_cache_free(a->alloc_cache, alloc); | 233 | nvgpu_kmem_cache_free(a->alloc_cache, alloc); |
161 | } | 234 | } |
162 | 235 | ||
@@ -306,7 +379,7 @@ static int __do_slab_alloc(struct nvgpu_page_allocator *a, | |||
306 | alloc->length = slab_page->slab_size; | 379 | alloc->length = slab_page->slab_size; |
307 | alloc->base = slab_page->page_addr + (offs * slab_page->slab_size); | 380 | alloc->base = slab_page->page_addr + (offs * slab_page->slab_size); |
308 | 381 | ||
309 | sgl = alloc->sgl; | 382 | sgl = alloc->sgt.sgl; |
310 | sgl->phys = alloc->base; | 383 | sgl->phys = alloc->base; |
311 | sgl->dma = alloc->base; | 384 | sgl->dma = alloc->base; |
312 | sgl->length = alloc->length; | 385 | sgl->length = alloc->length; |
@@ -338,13 +411,16 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_slab( | |||
338 | palloc_dbg(a, "OOM: could not alloc page_alloc struct!\n"); | 411 | palloc_dbg(a, "OOM: could not alloc page_alloc struct!\n"); |
339 | goto fail; | 412 | goto fail; |
340 | } | 413 | } |
414 | |||
415 | alloc->sgt.ops = &page_alloc_sgl_ops; | ||
416 | |||
341 | sgl = nvgpu_kzalloc(a->owner->g, sizeof(*sgl)); | 417 | sgl = nvgpu_kzalloc(a->owner->g, sizeof(*sgl)); |
342 | if (!sgl) { | 418 | if (!sgl) { |
343 | palloc_dbg(a, "OOM: could not alloc sgl struct!\n"); | 419 | palloc_dbg(a, "OOM: could not alloc sgl struct!\n"); |
344 | goto fail; | 420 | goto fail; |
345 | } | 421 | } |
346 | 422 | ||
347 | alloc->sgl = sgl; | 423 | alloc->sgt.sgl = sgl; |
348 | err = __do_slab_alloc(a, slab, alloc); | 424 | err = __do_slab_alloc(a, slab, alloc); |
349 | if (err) | 425 | if (err) |
350 | goto fail; | 426 | goto fail; |
@@ -432,6 +508,7 @@ static struct nvgpu_page_alloc *__do_nvgpu_alloc_pages( | |||
432 | memset(alloc, 0, sizeof(*alloc)); | 508 | memset(alloc, 0, sizeof(*alloc)); |
433 | 509 | ||
434 | alloc->length = pages << a->page_shift; | 510 | alloc->length = pages << a->page_shift; |
511 | alloc->sgt.ops = &page_alloc_sgl_ops; | ||
435 | 512 | ||
436 | while (pages) { | 513 | while (pages) { |
437 | u64 chunk_addr = 0; | 514 | u64 chunk_addr = 0; |
@@ -495,7 +572,7 @@ static struct nvgpu_page_alloc *__do_nvgpu_alloc_pages( | |||
495 | if (prev_sgl) | 572 | if (prev_sgl) |
496 | prev_sgl->next = sgl; | 573 | prev_sgl->next = sgl; |
497 | else | 574 | else |
498 | alloc->sgl = sgl; | 575 | alloc->sgt.sgl = sgl; |
499 | 576 | ||
500 | prev_sgl = sgl; | 577 | prev_sgl = sgl; |
501 | 578 | ||
@@ -503,12 +580,12 @@ static struct nvgpu_page_alloc *__do_nvgpu_alloc_pages( | |||
503 | } | 580 | } |
504 | 581 | ||
505 | alloc->nr_chunks = i; | 582 | alloc->nr_chunks = i; |
506 | alloc->base = alloc->sgl->phys; | 583 | alloc->base = ((struct nvgpu_mem_sgl *)alloc->sgt.sgl)->phys; |
507 | 584 | ||
508 | return alloc; | 585 | return alloc; |
509 | 586 | ||
510 | fail_cleanup: | 587 | fail_cleanup: |
511 | sgl = alloc->sgl; | 588 | sgl = alloc->sgt.sgl; |
512 | while (sgl) { | 589 | while (sgl) { |
513 | struct nvgpu_mem_sgl *next = sgl->next; | 590 | struct nvgpu_mem_sgl *next = sgl->next; |
514 | 591 | ||
@@ -542,13 +619,13 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages( | |||
542 | 619 | ||
543 | palloc_dbg(a, "Alloc 0x%llx (%llu) id=0x%010llx\n", | 620 | palloc_dbg(a, "Alloc 0x%llx (%llu) id=0x%010llx\n", |
544 | pages << a->page_shift, pages, alloc->base); | 621 | pages << a->page_shift, pages, alloc->base); |
545 | sgl = alloc->sgl; | 622 | sgl = alloc->sgt.sgl; |
546 | while (sgl) { | 623 | while (sgl) { |
547 | palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n", | 624 | palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n", |
548 | i++, | 625 | i++, |
549 | nvgpu_mem_sgl_phys(sgl), | 626 | nvgpu_sgt_get_phys(&alloc->sgt, sgl), |
550 | nvgpu_mem_sgl_length(sgl)); | 627 | nvgpu_sgt_get_length(&alloc->sgt, sgl)); |
551 | sgl = sgl->next; | 628 | sgl = nvgpu_sgt_get_next(&alloc->sgt, sgl); |
552 | } | 629 | } |
553 | palloc_dbg(a, "Alloc done\n"); | 630 | palloc_dbg(a, "Alloc done\n"); |
554 | 631 | ||
@@ -655,6 +732,7 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages_fixed( | |||
655 | if (!alloc || !sgl) | 732 | if (!alloc || !sgl) |
656 | goto fail; | 733 | goto fail; |
657 | 734 | ||
735 | alloc->sgt.ops = &page_alloc_sgl_ops; | ||
658 | alloc->base = nvgpu_alloc_fixed(&a->source_allocator, base, length, 0); | 736 | alloc->base = nvgpu_alloc_fixed(&a->source_allocator, base, length, 0); |
659 | if (!alloc->base) { | 737 | if (!alloc->base) { |
660 | WARN(1, "nvgpu: failed to fixed alloc pages @ 0x%010llx", base); | 738 | WARN(1, "nvgpu: failed to fixed alloc pages @ 0x%010llx", base); |
@@ -663,7 +741,7 @@ static struct nvgpu_page_alloc *__nvgpu_alloc_pages_fixed( | |||
663 | 741 | ||
664 | alloc->nr_chunks = 1; | 742 | alloc->nr_chunks = 1; |
665 | alloc->length = length; | 743 | alloc->length = length; |
666 | alloc->sgl = sgl; | 744 | alloc->sgt.sgl = sgl; |
667 | 745 | ||
668 | sgl->phys = alloc->base; | 746 | sgl->phys = alloc->base; |
669 | sgl->dma = alloc->base; | 747 | sgl->dma = alloc->base; |
@@ -708,13 +786,13 @@ static u64 nvgpu_page_alloc_fixed(struct nvgpu_allocator *__a, | |||
708 | 786 | ||
709 | palloc_dbg(a, "Alloc [fixed] @ 0x%010llx + 0x%llx (%llu)\n", | 787 | palloc_dbg(a, "Alloc [fixed] @ 0x%010llx + 0x%llx (%llu)\n", |
710 | alloc->base, aligned_len, pages); | 788 | alloc->base, aligned_len, pages); |
711 | sgl = alloc->sgl; | 789 | sgl = alloc->sgt.sgl; |
712 | while (sgl) { | 790 | while (sgl) { |
713 | palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n", | 791 | palloc_dbg(a, " Chunk %2d: 0x%010llx + 0x%llx\n", |
714 | i++, | 792 | i++, |
715 | nvgpu_mem_sgl_phys(sgl), | 793 | nvgpu_sgt_get_phys(&alloc->sgt, sgl), |
716 | nvgpu_mem_sgl_length(sgl)); | 794 | nvgpu_sgt_get_length(&alloc->sgt, sgl)); |
717 | sgl = sgl->next; | 795 | sgl = nvgpu_sgt_get_next(&alloc->sgt, sgl); |
718 | } | 796 | } |
719 | 797 | ||
720 | a->nr_fixed_allocs++; | 798 | a->nr_fixed_allocs++; |