summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-10-17 13:55:00 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-11-01 22:06:23 -0400
commitd13c256d5ee11da1664377481543005142d9bd30 (patch)
treee00ef697d05a20428619c8920ddfcb645fc095d8 /drivers/gpu/nvgpu/common/linux
parenta37cec19f0cf5212cbd472cd8d94acaa1e1cff6d (diff)
gpu: nvgpu: VM unmap refactoring
Re-organize the unmap code to be better split between OS specific requirements and common core requirements. The new code flow works as follows: nvgpu_vm_unmap() Is the primary entrance to the unmap path. It takes a VM and a GPU virtual address to unmap. There's also an optional batch mapping struct. This function is responsible for making sure there is a real buffer and that if it's being called on a fixed mapping then the mapping will definitely be freed (since buffers are ref-counted). Then this function decrements the ref-count and returns. If the ref-count hits zero then __nvgpu_vm_unmap_ref() is called which just calls __nvgpu_vm_unmap() with the relevant batch struct if present. This is where the real work is done. __nvgpu_vm_unmap() clears the GMMU mapping, removes the mapped buffer from the various lists and trees it may be in and then calls the nvgpu_vm_unmap_system() function. This function handles any OS specific stuff and must be defined by all VM OS implementations. There's a a short cut used by some other core VM code to free mappings without going through nvgpu_vm_map(). Mostly they just directly decrement the mapping ref-count which can then call __nvgpu_vm_unmap_ref() if the ref-count hits zero. JIRA NVGPU-30 JIRA NVGPU-71 Change-Id: Ic626d37ab936819841bab45214f027b40ffa4e5a Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1583982 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux')
-rw-r--r--drivers/gpu/nvgpu/common/linux/cde.c4
-rw-r--r--drivers/gpu/nvgpu/common/linux/ioctl_as.c10
-rw-r--r--drivers/gpu/nvgpu/common/linux/ioctl_dbg.c4
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm.c84
4 files changed, 17 insertions, 85 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/cde.c b/drivers/gpu/nvgpu/common/linux/cde.c
index 65c50726..2f2e886f 100644
--- a/drivers/gpu/nvgpu/common/linux/cde.c
+++ b/drivers/gpu/nvgpu/common/linux/cde.c
@@ -1167,7 +1167,7 @@ __releases(&l->cde_app->mutex)
1167 cde_ctx->init_cmd_executed = true; 1167 cde_ctx->init_cmd_executed = true;
1168 1168
1169 /* unmap the buffers - channel holds references to them now */ 1169 /* unmap the buffers - channel holds references to them now */
1170 nvgpu_vm_unmap(cde_ctx->vm, map_vaddr); 1170 nvgpu_vm_unmap(cde_ctx->vm, map_vaddr, NULL);
1171 1171
1172 return err; 1172 return err;
1173 1173
@@ -1175,7 +1175,7 @@ exit_unmap_surface:
1175 if (surface) 1175 if (surface)
1176 dma_buf_vunmap(compbits_scatter_buf, surface); 1176 dma_buf_vunmap(compbits_scatter_buf, surface);
1177exit_unmap_vaddr: 1177exit_unmap_vaddr:
1178 nvgpu_vm_unmap(cde_ctx->vm, map_vaddr); 1178 nvgpu_vm_unmap(cde_ctx->vm, map_vaddr, NULL);
1179exit_idle: 1179exit_idle:
1180 gk20a_idle(g); 1180 gk20a_idle(g);
1181 return err; 1181 return err;
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_as.c b/drivers/gpu/nvgpu/common/linux/ioctl_as.c
index 08064370..18d0dd07 100644
--- a/drivers/gpu/nvgpu/common/linux/ioctl_as.c
+++ b/drivers/gpu/nvgpu/common/linux/ioctl_as.c
@@ -118,7 +118,10 @@ static int gk20a_as_ioctl_unmap_buffer(
118 struct nvgpu_as_unmap_buffer_args *args) 118 struct nvgpu_as_unmap_buffer_args *args)
119{ 119{
120 gk20a_dbg_fn(""); 120 gk20a_dbg_fn("");
121 return nvgpu_vm_unmap_buffer(as_share->vm, args->offset, NULL); 121
122 nvgpu_vm_unmap(as_share->vm, args->offset, NULL);
123
124 return 0;
122} 125}
123 126
124static int gk20a_as_ioctl_map_buffer_batch( 127static int gk20a_as_ioctl_map_buffer_batch(
@@ -155,10 +158,7 @@ static int gk20a_as_ioctl_map_buffer_batch(
155 break; 158 break;
156 } 159 }
157 160
158 err = nvgpu_vm_unmap_buffer(as_share->vm, unmap_args.offset, 161 nvgpu_vm_unmap(as_share->vm, unmap_args.offset, &batch);
159 &batch);
160 if (err)
161 break;
162 } 162 }
163 163
164 if (err) { 164 if (err) {
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_dbg.c b/drivers/gpu/nvgpu/common/linux/ioctl_dbg.c
index 403d9261..24bf813a 100644
--- a/drivers/gpu/nvgpu/common/linux/ioctl_dbg.c
+++ b/drivers/gpu/nvgpu/common/linux/ioctl_dbg.c
@@ -1142,7 +1142,7 @@ static int gk20a_perfbuf_map(struct dbg_session_gk20a *dbg_s,
1142 return 0; 1142 return 0;
1143 1143
1144err_unmap: 1144err_unmap:
1145 nvgpu_vm_unmap_buffer(mm->perfbuf.vm, args->offset, NULL); 1145 nvgpu_vm_unmap(mm->perfbuf.vm, args->offset, NULL);
1146err_remove_vm: 1146err_remove_vm:
1147 nvgpu_vm_put(mm->perfbuf.vm); 1147 nvgpu_vm_put(mm->perfbuf.vm);
1148 nvgpu_mutex_release(&g->dbg_sessions_lock); 1148 nvgpu_mutex_release(&g->dbg_sessions_lock);
@@ -1386,7 +1386,7 @@ static int gk20a_perfbuf_release_locked(struct gk20a *g, u64 offset)
1386 1386
1387 err = g->ops.dbg_session_ops.perfbuffer_disable(g); 1387 err = g->ops.dbg_session_ops.perfbuffer_disable(g);
1388 1388
1389 nvgpu_vm_unmap_buffer(vm, offset, NULL); 1389 nvgpu_vm_unmap(vm, offset, NULL);
1390 nvgpu_free_inst_block(g, &mm->perfbuf.inst_block); 1390 nvgpu_free_inst_block(g, &mm->perfbuf.inst_block);
1391 nvgpu_vm_put(vm); 1391 nvgpu_vm_put(vm);
1392 1392
diff --git a/drivers/gpu/nvgpu/common/linux/vm.c b/drivers/gpu/nvgpu/common/linux/vm.c
index 984c2015..feb124f8 100644
--- a/drivers/gpu/nvgpu/common/linux/vm.c
+++ b/drivers/gpu/nvgpu/common/linux/vm.c
@@ -641,88 +641,20 @@ int nvgpu_vm_map_buffer(struct vm_gk20a *vm,
641 return err; 641 return err;
642} 642}
643 643
644int nvgpu_vm_unmap_buffer(struct vm_gk20a *vm, u64 offset, 644/*
645 struct vm_gk20a_mapping_batch *batch) 645 * This is the function call-back for freeing OS specific components of an
646{ 646 * nvgpu_mapped_buf. This should most likely never be called outside of the
647 struct gk20a *g = vm->mm->g; 647 * core MM framework!
648 struct nvgpu_mapped_buf *mapped_buffer; 648 *
649 649 * Note: the VM lock will be held.
650 nvgpu_mutex_acquire(&vm->update_gmmu_lock); 650 */
651 651void nvgpu_vm_unmap_system(struct nvgpu_mapped_buf *mapped_buffer)
652 mapped_buffer = __nvgpu_vm_find_mapped_buf(vm, offset);
653 if (!mapped_buffer) {
654 nvgpu_mutex_release(&vm->update_gmmu_lock);
655 nvgpu_err(g, "invalid addr to unmap 0x%llx", offset);
656 return 0;
657 }
658
659 if (mapped_buffer->flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) {
660 struct nvgpu_timeout timeout;
661
662 nvgpu_mutex_release(&vm->update_gmmu_lock);
663
664 nvgpu_timeout_init(vm->mm->g, &timeout, 10000,
665 NVGPU_TIMER_RETRY_TIMER);
666 do {
667 if (nvgpu_atomic_read(
668 &mapped_buffer->ref.refcount) == 1)
669 break;
670 nvgpu_udelay(5);
671 } while (!nvgpu_timeout_expired_msg(&timeout,
672 "sync-unmap failed on 0x%llx"));
673
674 nvgpu_mutex_acquire(&vm->update_gmmu_lock);
675 }
676
677 if (mapped_buffer->user_mapped == 0) {
678 nvgpu_mutex_release(&vm->update_gmmu_lock);
679 nvgpu_err(g, "addr already unmapped from user 0x%llx", offset);
680 return 0;
681 }
682
683 mapped_buffer->user_mapped--;
684 if (mapped_buffer->user_mapped == 0)
685 vm->num_user_mapped_buffers--;
686
687 vm->kref_put_batch = batch;
688 nvgpu_ref_put(&mapped_buffer->ref, nvgpu_vm_unmap_locked_ref);
689 vm->kref_put_batch = NULL;
690
691 nvgpu_mutex_release(&vm->update_gmmu_lock);
692 return 0;
693}
694
695/* NOTE! mapped_buffers lock must be held */
696void nvgpu_vm_unmap_locked(struct nvgpu_mapped_buf *mapped_buffer,
697 struct vm_gk20a_mapping_batch *batch)
698{ 652{
699 struct vm_gk20a *vm = mapped_buffer->vm; 653 struct vm_gk20a *vm = mapped_buffer->vm;
700 struct gk20a *g = vm->mm->g;
701
702 g->ops.mm.gmmu_unmap(vm,
703 mapped_buffer->addr,
704 mapped_buffer->size,
705 mapped_buffer->pgsz_idx,
706 mapped_buffer->va_allocated,
707 gk20a_mem_flag_none,
708 mapped_buffer->vm_area ?
709 mapped_buffer->vm_area->sparse : false,
710 batch);
711 654
712 gk20a_mm_unpin(dev_from_vm(vm), mapped_buffer->dmabuf, 655 gk20a_mm_unpin(dev_from_vm(vm), mapped_buffer->dmabuf,
713 mapped_buffer->sgt); 656 mapped_buffer->sgt);
714 657
715 /* remove from mapped buffer tree and remove list, free */
716 nvgpu_remove_mapped_buf(vm, mapped_buffer);
717 if (!nvgpu_list_empty(&mapped_buffer->buffer_list))
718 nvgpu_list_del(&mapped_buffer->buffer_list);
719
720 /* keep track of mapped buffers */
721 if (mapped_buffer->user_mapped)
722 vm->num_user_mapped_buffers--;
723
724 if (mapped_buffer->own_mem_ref) 658 if (mapped_buffer->own_mem_ref)
725 dma_buf_put(mapped_buffer->dmabuf); 659 dma_buf_put(mapped_buffer->dmabuf);
726
727 nvgpu_kfree(g, mapped_buffer);
728} 660}