diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/mm/gmmu.c | 114 |
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 | /* | 469 | static 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, |
472 | static 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 | |||
536 | static 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(); |