summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/mm/gmmu.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-09-20 15:21:33 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-10-04 05:29:55 -0400
commite400475a915f73abb823b00945179eec470f73e0 (patch)
treeaa655eea59f2180f47f97d7ce325810cfa83cc10 /drivers/gpu/nvgpu/common/mm/gmmu.c
parent7a3dbdd43f142f7f94a19ff6a320e589f0b23324 (diff)
gpu: nvgpu: Combine VIDMEM and SYSMEM map paths
Combine the VIDMEM and SYSMEM GMMU mapping paths into one single function. With the proper nvgpu_sgt abstraction in place the high level mapping code can treat these two types of maps identically. The benefits of this are immediate: a change to the mapping code will have much more testing coverage - the same code runs on both vidmem and sysmem. This also makes it easier to make changes to mapping code since the changes will be testable no matter what type of mem is being mapped. JIRA NVGPU-68 Change-Id: I308eda03d426966ba8e1d4892c99cf97b45c5993 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1566706 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/mm/gmmu.c')
-rw-r--r--drivers/gpu/nvgpu/common/mm/gmmu.c114
1 files changed, 21 insertions, 93 deletions
diff --git a/drivers/gpu/nvgpu/common/mm/gmmu.c b/drivers/gpu/nvgpu/common/mm/gmmu.c
index cad53fa1..b802cb53 100644
--- a/drivers/gpu/nvgpu/common/mm/gmmu.c
+++ b/drivers/gpu/nvgpu/common/mm/gmmu.c
@@ -466,79 +466,12 @@ static int __set_pd_level(struct vm_gk20a *vm,
466 return 0; 466 return 0;
467} 467}
468 468
469/* 469static int __nvgpu_gmmu_do_update_page_table(struct vm_gk20a *vm,
470 * VIDMEM version of the update_ptes logic. 470 struct nvgpu_sgt *sgt,
471 */ 471 u64 space_to_skip,
472static int __nvgpu_gmmu_update_page_table_vidmem(struct vm_gk20a *vm, 472 u64 virt_addr,
473 struct nvgpu_sgt *sgt, 473 u64 length,
474 u64 space_to_skip, 474 struct nvgpu_gmmu_attrs *attrs)
475 u64 virt_addr,
476 u64 length,
477 struct nvgpu_gmmu_attrs *attrs)
478{
479 u64 phys_addr, chunk_length;
480 int err = 0;
481 void *sgl;
482
483 if (!sgt) {
484 /*
485 * This is considered an unmap. Just pass in 0 as the physical
486 * address for the entire GPU range.
487 */
488 err = __set_pd_level(vm, &vm->pdb,
489 0,
490 0,
491 virt_addr, length,
492 attrs);
493 return err;
494 }
495
496 /*
497 * Otherwise iterate across all the chunks in this allocation and
498 * map them.
499 */
500 nvgpu_sgt_for_each_sgl(sgl, sgt) {
501 if (space_to_skip &&
502 space_to_skip >= nvgpu_sgt_get_length(sgt, sgl)) {
503 space_to_skip -= nvgpu_sgt_get_length(sgt, sgl);
504 sgl = nvgpu_sgt_get_next(sgt, sgl);
505 continue;
506 }
507
508 phys_addr = nvgpu_sgt_get_phys(sgt, sgl) + space_to_skip;
509 chunk_length = min(length, (nvgpu_sgt_get_length(sgt, sgl) -
510 space_to_skip));
511
512 err = __set_pd_level(vm, &vm->pdb,
513 0,
514 phys_addr,
515 virt_addr, chunk_length,
516 attrs);
517 if (err)
518 break;
519
520 /* Space has been skipped so zero this for future chunks. */
521 space_to_skip = 0;
522
523 /*
524 * Update the map pointer and the remaining length.
525 */
526 virt_addr += chunk_length;
527 length -= chunk_length;
528
529 if (length == 0)
530 break;
531 }
532
533 return err;
534}
535
536static int __nvgpu_gmmu_update_page_table_sysmem(struct vm_gk20a *vm,
537 struct nvgpu_sgt *sgt,
538 u64 space_to_skip,
539 u64 virt_addr,
540 u64 length,
541 struct nvgpu_gmmu_attrs *attrs)
542{ 475{
543 struct gk20a *g = gk20a_from_vm(vm); 476 struct gk20a *g = gk20a_from_vm(vm);
544 void *sgl; 477 void *sgl;
@@ -565,7 +498,7 @@ static int __nvgpu_gmmu_update_page_table_sysmem(struct vm_gk20a *vm,
565 * mapping is simple since the "physical" address is actually a virtual 498 * mapping is simple since the "physical" address is actually a virtual
566 * IO address and will be contiguous. 499 * IO address and will be contiguous.
567 */ 500 */
568 if (!g->mm.bypass_smmu) { 501 if (attrs->aperture == APERTURE_SYSMEM && !g->mm.bypass_smmu) {
569 u64 io_addr = nvgpu_sgt_get_gpu_addr(sgt, g, sgt->sgl, attrs); 502 u64 io_addr = nvgpu_sgt_get_gpu_addr(sgt, g, sgt->sgl, attrs);
570 503
571 io_addr += space_to_skip; 504 io_addr += space_to_skip;
@@ -608,8 +541,15 @@ static int __nvgpu_gmmu_update_page_table_sysmem(struct vm_gk20a *vm,
608 virt_addr, 541 virt_addr,
609 chunk_length, 542 chunk_length,
610 attrs); 543 attrs);
544 if (err)
545 break;
611 546
547 /* Space has been skipped so zero this for future chunks. */
612 space_to_skip = 0; 548 space_to_skip = 0;
549
550 /*
551 * Update the map pointer and the remaining length.
552 */
613 virt_addr += chunk_length; 553 virt_addr += chunk_length;
614 length -= chunk_length; 554 length -= chunk_length;
615 555
@@ -617,7 +557,7 @@ static int __nvgpu_gmmu_update_page_table_sysmem(struct vm_gk20a *vm,
617 break; 557 break;
618 } 558 }
619 559
620 return 0; 560 return err;
621} 561}
622 562
623/* 563/*
@@ -689,24 +629,12 @@ static int __nvgpu_gmmu_update_page_table(struct vm_gk20a *vm,
689 attrs->coherent ? 'c' : '-', 629 attrs->coherent ? 'c' : '-',
690 attrs->valid ? 'V' : '-'); 630 attrs->valid ? 'V' : '-');
691 631
692 /* 632 err = __nvgpu_gmmu_do_update_page_table(vm,
693 * For historical reasons these are separate, but soon these will be 633 sgt,
694 * unified. 634 space_to_skip,
695 */ 635 virt_addr,
696 if (attrs->aperture == APERTURE_VIDMEM) 636 length,
697 err = __nvgpu_gmmu_update_page_table_vidmem(vm, 637 attrs);
698 sgt,
699 space_to_skip,
700 virt_addr,
701 length,
702 attrs);
703 else
704 err = __nvgpu_gmmu_update_page_table_sysmem(vm,
705 sgt,
706 space_to_skip,
707 virt_addr,
708 length,
709 attrs);
710 638
711 unmap_gmmu_pages(g, &vm->pdb); 639 unmap_gmmu_pages(g, &vm->pdb);
712 nvgpu_smp_mb(); 640 nvgpu_smp_mb();