Skip to contentSkip to conversation

RFC: drm/msm: separate iova allocation and mapping

PATCH Superseded Jordan Crouse 1 participant 7 messages Oct 31, 2018 1 message not in the archive

Subsystems (4)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover RFC: drm/msm: separate iova allocation and mapping

Currently in the msm driver iova addresses are mapped in the IOMMU at allocation time and stay there for the life of the buffer. This may not be desirable for long lived user space buffers that could be temporarily swapped or moved.

This first set of patches breaks up the allocation and mapping into distinct steps and adds reference counting for pinning and unpinning the memory. Future code can use this information to manipulate the memory when it isn't in use.

Jordan Crouse (6):
drm/msm: Add a common function to free kernel buffer objects drm/msm: Remove sgt from the mmu unmap function drm/msm: Split msm_gem_get_iova into two steps
drm/msm: Clean up and enhance the output of the 'gem' debugfs node drm/msm: Add msm_gem_get_and_pin_iova()
drm/msm: Count how many times iova memory is pinned

 drivers/gpu/drm/msm/adreno/a5xx_debugfs.c |   6 +-
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c     |  22 +--
 drivers/gpu/drm/msm/adreno/a5xx_power.c   |  13 +-
 drivers/gpu/drm/msm/adreno/a5xx_preempt.c |  14 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c     |   3 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c   |   3 +-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c |   6 +-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c  |   4 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c |   4 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c        |   4 +-
 drivers/gpu/drm/msm/msm_drv.c             |   4 +
 drivers/gpu/drm/msm/msm_drv.h             |  16 ++-
 drivers/gpu/drm/msm/msm_fb.c              |   4 +-
 drivers/gpu/drm/msm/msm_fbdev.c           |   2 +-
 drivers/gpu/drm/msm/msm_gem.c             | 162 ++++++++++++++++------
 drivers/gpu/drm/msm/msm_gem.h             |   2 +
 drivers/gpu/drm/msm/msm_gem_submit.c      |   4 +-
 drivers/gpu/drm/msm/msm_gem_vma.c         |  95 +++++++++----
 drivers/gpu/drm/msm/msm_gpu.c             |  16 +--
 drivers/gpu/drm/msm/msm_iommu.c           |   3 +-
 drivers/gpu/drm/msm/msm_mmu.h             |   3 +-
 drivers/gpu/drm/msm/msm_ringbuffer.c      |   7 +-
 22 files changed, 242 insertions(+), 155 deletions(-)
Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno

A message that is not in the archive (sent off-list or not yet received): 20181031170552.32542-1-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org

#2 lore raw

PATCH 1/6 drm/msm: Add a common function to free kernel buffer objects

Buffer objects allocated with msm_gem_kernel_new() are mostly freed the same way so we can save a few lines of code with a common function.

---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c     | 13 ++-----------
 drivers/gpu/drm/msm/adreno/a5xx_power.c   | 13 +------------
 drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 14 ++------------
 drivers/gpu/drm/msm/msm_drv.h             |  2 ++
 drivers/gpu/drm/msm/msm_gem.c             | 15 +++++++++++++++
 drivers/gpu/drm/msm/msm_gpu.c             | 12 ++----------
 drivers/gpu/drm/msm/msm_ringbuffer.c      |  7 ++-----
 7 files changed, 26 insertions(+), 50 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +2 -11
index 2d34643ef2e2..d6f8dedc028a 100644
@@ -1228,15 +1228,6 @@ static int a5xx_crashdumper_init(struct msm_gpu *gpu,
 	return 0;
 }
 
-static void a5xx_crashdumper_free(struct msm_gpu *gpu,
-		struct a5xx_crashdumper *dumper)
-{
-	msm_gem_put_iova(dumper->bo, gpu->aspace);
-	msm_gem_put_vaddr(dumper->bo);
-
-	drm_gem_object_put(dumper->bo);
-}
-
 static int a5xx_crashdumper_run(struct msm_gpu *gpu,
 		struct a5xx_crashdumper *dumper)
 {
@@ -1329,7 +1320,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu *gpu,
 
 	if (a5xx_crashdumper_run(gpu, &dumper)) {
 		kfree(a5xx_state->hlsqregs);
-		a5xx_crashdumper_free(gpu, &dumper);
+		msm_gem_kernel_put(dumper.bo, gpu->aspace, true);
 		return;
 	}
 
@@ -1337,7 +1328,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu *gpu,
 	memcpy(a5xx_state->hlsqregs, dumper.ptr + (256 * SZ_1K),
 		count * sizeof(u32));
 
-	a5xx_crashdumper_free(gpu, &dumper);
+	msm_gem_kernel_put(dumper.bo, gpu->aspace, true);
 }
 
 static struct msm_gpu_state *a5xx_gpu_state_get(struct msm_gpu *gpu)
drivers/gpu/drm/msm/adreno/a5xx_power.c +1 -12
index 7a41e1c147e4..66bcd88dd8c0 100644
@@ -298,7 +298,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
 		MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace,
 		&a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova);
 	if (IS_ERR(ptr))
-		goto err;
+		return;
 
 	while (cmds_size > 0) {
 		int i;
@@ -317,15 +317,4 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
 
 	msm_gem_put_vaddr(a5xx_gpu->gpmu_bo);
 	a5xx_gpu->gpmu_dwords = dwords;
-
-	return;
-err:
-	if (a5xx_gpu->gpmu_iova)
-		msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
-	if (a5xx_gpu->gpmu_bo)
-		drm_gem_object_put(a5xx_gpu->gpmu_bo);
-
-	a5xx_gpu->gpmu_bo = NULL;
-	a5xx_gpu->gpmu_iova = 0;
-	a5xx_gpu->gpmu_dwords = 0;
 }
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +2 -12
index fdb08fc68c2c..48481e663685 100644
@@ -267,18 +267,8 @@ void a5xx_preempt_fini(struct msm_gpu *gpu)
 	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
 	int i;
 
-	for (i = 0; i < gpu->nr_rings; i++) {
-		if (!a5xx_gpu->preempt_bo[i])
-			continue;
-
-		msm_gem_put_vaddr(a5xx_gpu->preempt_bo[i]);
-
-		if (a5xx_gpu->preempt_iova[i])
-			msm_gem_put_iova(a5xx_gpu->preempt_bo[i], gpu->aspace);
-
-		drm_gem_object_put(a5xx_gpu->preempt_bo[i]);
-		a5xx_gpu->preempt_bo[i] = NULL;
-	}
+	for (i = 0; i < gpu->nr_rings; i++)
+		msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace, true);
 }
 
 void a5xx_preempt_init(struct msm_gpu *gpu)
drivers/gpu/drm/msm/msm_drv.h +2 -0
index 9d11f321f5a9..3225f8fbd8c9 100644
@@ -312,6 +312,8 @@ void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
 void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size,
 		uint32_t flags, struct msm_gem_address_space *aspace,
 		struct drm_gem_object **bo, uint64_t *iova);
+void msm_gem_kernel_put(struct drm_gem_object *bo,
+		struct msm_gem_address_space *aspace, bool locked);
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
 		struct dma_buf *dmabuf, struct sg_table *sgt);
 
drivers/gpu/drm/msm/msm_gem.c +15 -0
index 00c795ced02c..855f5721a14e 100644
@@ -1073,3 +1073,18 @@ void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size,
 {
 	return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, true);
 }
+
+void msm_gem_kernel_put(struct drm_gem_object *bo,
+		struct msm_gem_address_space *aspace, bool locked)
+{
+	if (IS_ERR_OR_NULL(bo))
+		return;
+
+	msm_gem_put_vaddr(bo);
+	msm_gem_put_iova(bo, aspace);
+
+	if (locked)
+		drm_gem_object_put(bo);
+	else
+		drm_gem_object_put_unlocked(bo);
+}
drivers/gpu/drm/msm/msm_gpu.c +2 -10
index ff958486819b..71a2d431663f 100644
@@ -961,11 +961,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 		gpu->rb[i] = NULL;
 	}
 
-	if (gpu->memptrs_bo) {
-		msm_gem_put_vaddr(gpu->memptrs_bo);
-		msm_gem_put_iova(gpu->memptrs_bo, gpu->aspace);
-		drm_gem_object_put_unlocked(gpu->memptrs_bo);
-	}
+	msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace, false);
 
 	platform_set_drvdata(pdev, NULL);
 	return ret;
@@ -984,11 +980,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
 		gpu->rb[i] = NULL;
 	}
 
-	if (gpu->memptrs_bo) {
-		msm_gem_put_vaddr(gpu->memptrs_bo);
-		msm_gem_put_iova(gpu->memptrs_bo, gpu->aspace);
-		drm_gem_object_put_unlocked(gpu->memptrs_bo);
-	}
+	msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace, false);
 
 	if (!IS_ERR_OR_NULL(gpu->aspace)) {
 		gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu,
drivers/gpu/drm/msm/msm_ringbuffer.c +2 -5
index 6f5295b3f2f6..9fa9525c5293 100644
@@ -73,10 +73,7 @@ void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
 
 	msm_fence_context_free(ring->fctx);
 
-	if (ring->bo) {
-		msm_gem_put_iova(ring->bo, ring->gpu->aspace);
-		msm_gem_put_vaddr(ring->bo);
-		drm_gem_object_put_unlocked(ring->bo);
-	}
+	msm_gem_kernel_put(ring->bo, ring->gpu->aspace, false);
+
 	kfree(ring);
 }
Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
#3 lore raw

PATCH 2/6 drm/msm: Remove sgt from the mmu unmap function

In reply to a message not in the archive

The scatter gather table doesn't need to be passed in for the MMU unmap function.

---
 drivers/gpu/drm/msm/msm_drv.h     | 2 +-
 drivers/gpu/drm/msm/msm_gem.c     | 2 +-
 drivers/gpu/drm/msm/msm_gem_vma.c | 4 ++--
 drivers/gpu/drm/msm/msm_iommu.c   | 3 +--
 drivers/gpu/drm/msm/msm_mmu.h     | 3 +--
 5 files changed, 6 insertions(+), 8 deletions(-)
drivers/gpu/drm/msm/msm_drv.h +1 -1
index 3225f8fbd8c9..3a0f2119127b 100644
@@ -242,7 +242,7 @@ void msm_atomic_state_clear(struct drm_atomic_state *state);
 void msm_atomic_state_free(struct drm_atomic_state *state);
 
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
-		struct msm_gem_vma *vma, struct sg_table *sgt);
+		struct msm_gem_vma *vma);
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
 
drivers/gpu/drm/msm/msm_gem.c +1 -1
index 855f5721a14e..ff75e557b708 100644
@@ -352,7 +352,7 @@ put_iova(struct drm_gem_object *obj)
 	WARN_ON(!mutex_is_locked(&msm_obj->lock));
 
 	list_for_each_entry_safe(vma, tmp, &msm_obj->vmas, list) {
-		msm_gem_unmap_vma(vma->aspace, vma, msm_obj->sgt);
+		msm_gem_unmap_vma(vma->aspace, vma);
 		del_vma(vma);
 	}
 }
drivers/gpu/drm/msm/msm_gem_vma.c +2 -2
index ffbec224551b..704ae7e69500 100644
@@ -40,14 +40,14 @@ void msm_gem_address_space_put(struct msm_gem_address_space *aspace)
 
 void
 msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
-		struct msm_gem_vma *vma, struct sg_table *sgt)
+		struct msm_gem_vma *vma)
 {
 	if (!aspace || !vma->iova)
 		return;
 
 	if (aspace->mmu) {
 		unsigned size = vma->node.size << PAGE_SHIFT;
-		aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, sgt, size);
+		aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, size);
 	}
 
 	spin_lock(&aspace->lock);
drivers/gpu/drm/msm/msm_iommu.c +1 -2
index b23d33622f37..9c313cb129ee 100644
@@ -71,8 +71,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
 	return (ret == len) ? 0 : -EINVAL;
 }
 
-static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova,
-		struct sg_table *sgt, unsigned len)
+static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len)
 {
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
 
drivers/gpu/drm/msm/msm_mmu.h +1 -2
index aa2c5d4580c8..94c0b83d8026 100644
@@ -25,8 +25,7 @@ struct msm_mmu_funcs {
 	void (*detach)(struct msm_mmu *mmu, const char * const *names, int cnt);
 	int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
 			unsigned len, int prot);
-	int (*unmap)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
-			unsigned len);
+	int (*unmap)(struct msm_mmu *mmu, uint64_t iova, unsigned len);
 	void (*destroy)(struct msm_mmu *mmu);
 };
 
Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
#4 lore raw

PATCH 3/6 drm/msm: Split msm_gem_get_iova into two steps

In reply to a message not in the archive

Split the operation of msm_gem_get_iova into two operations:
1) allocate an iova and 2) map (pin) the backing memory int the iommu. This is the first step toward allowing memory pinning to occur independently of the iova management.

---
 drivers/gpu/drm/msm/msm_drv.h     |  2 +
 drivers/gpu/drm/msm/msm_gem.c     | 80 ++++++++++++++++++++-----------
 drivers/gpu/drm/msm/msm_gem.h     |  1 +
 drivers/gpu/drm/msm/msm_gem_vma.c | 44 ++++++++++++-----
 4 files changed, 86 insertions(+), 41 deletions(-)
drivers/gpu/drm/msm/msm_drv.h +2 -0
index 3a0f2119127b..63b28b69b2ab 100644
@@ -241,6 +241,8 @@ struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
 void msm_atomic_state_clear(struct drm_atomic_state *state);
 void msm_atomic_state_free(struct drm_atomic_state *state);
 
+int msm_gem_init_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma, int npages);
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma);
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
drivers/gpu/drm/msm/msm_gem.c +52 -28

104 lines not on this page · raw message

drivers/gpu/drm/msm/msm_gem.h +1 -0
index c5d9bd3e47a8..32c13e6559b5 100644
@@ -41,6 +41,7 @@ struct msm_gem_vma {
 	uint64_t iova;
 	struct msm_gem_address_space *aspace;
 	struct list_head list;    /* node in msm_gem_object::vmas */
+	bool mapped;
 };
 
 struct msm_gem_object {
drivers/gpu/drm/msm/msm_gem_vma.c +31 -13

68 lines not on this page · raw message

Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
#5 lore raw

PATCH 4/6 drm/msm: Clean up and enhance the output of the 'gem' debugfs node

In reply to a message not in the archive

Add headers for the 'gem' debugfs file to make it easier to remember what all the values mean and move the list of virtual address regions to the next line and add the name and map status to make it clearer what we are looking at.

---
 drivers/gpu/drm/msm/msm_gem.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/msm_gem.c +14 -6
index 189d7f0f1aad..805a300f8663 100644
@@ -763,16 +763,23 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 		break;
 	}
 
-	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p\t",
+	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p",
 			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
 			obj->name, kref_read(&obj->refcount),
 			off, msm_obj->vaddr);
 
-	/* FIXME: we need to print the address space here too */
-	list_for_each_entry(vma, &msm_obj->vmas, list)
-		seq_printf(m, " %08llx", vma->iova);
+	seq_printf(m, " %08zu%9s\n", obj->size, madv);
 
-	seq_printf(m, " %zu%s\n", obj->size, madv);
+	if (!list_empty(&msm_obj->vmas)) {
+
+		seq_puts(m, "   vmas:");
+
+		list_for_each_entry(vma, &msm_obj->vmas, list)
+			seq_printf(m, " [%s: %08llx,%s]", vma->aspace->name,
+				vma->iova, vma->mapped ? "mapped" : "unmapped");
+
+		seq_puts(m, "\n");
+	}
 
 	rcu_read_lock();
 	fobj = rcu_dereference(robj->fence);
@@ -799,9 +806,10 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
 	int count = 0;
 	size_t size = 0;
 
+	seq_puts(m, "   flags       id ref offset   kaddr           size    madv\n");
 	list_for_each_entry(msm_obj, list, mm_list) {
 		struct drm_gem_object *obj = &msm_obj->base;
-		seq_printf(m, "   ");
+		seq_puts(m, "   ");
 		msm_gem_describe(obj, m);
 		count++;
 		size += obj->size;
Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
#6 lore raw

PATCH 5/6 drm/msm: Add msm_gem_get_and_pin_iova()

In reply to a message not in the archive

Add a new function to get and pin the iova memory in one step (basically renaming the old msm_gem_get_iova function) and switch msm_gem_get_iova() to only allocate an iova but not map it in the IOMMU. This is only currently used by msm_ioctl_gem_info() since all other users of of the iova expect that the memory be immediately available.

---
 drivers/gpu/drm/msm/adreno/adreno_gpu.c   |  3 ++-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c |  4 ++--
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c  |  2 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c |  2 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c        |  2 +-
 drivers/gpu/drm/msm/msm_drv.c             |  4 ++++
 drivers/gpu/drm/msm/msm_drv.h             |  2 ++
 drivers/gpu/drm/msm/msm_fb.c              |  2 +-
 drivers/gpu/drm/msm/msm_fbdev.c           |  2 +-
 drivers/gpu/drm/msm/msm_gem.c             | 24 ++++++++++++++++++-----
 drivers/gpu/drm/msm/msm_gem_submit.c      |  2 +-
 drivers/gpu/drm/msm/msm_gpu.c             |  2 +-
 12 files changed, 36 insertions(+), 15 deletions(-)
drivers/gpu/drm/msm/adreno/adreno_gpu.c +2 -1
index 141062fbb4c8..3c2988514fc5 100644
@@ -209,7 +209,8 @@ int adreno_hw_init(struct msm_gpu *gpu)
 		if (!ring)
 			continue;
 
-		ret = msm_gem_get_iova(ring->bo, gpu->aspace, &ring->iova);
+		ret = msm_gem_get_and_pin_iova(ring->bo, gpu->aspace,
+			&ring->iova);
 		if (ret) {
 			ring->iova = 0;
 			DRM_DEV_ERROR(gpu->dev->dev,
drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c +2 -2
index b91706cee2b8..ef6884f1fc34 100644
@@ -384,7 +384,7 @@ static void update_cursor(struct drm_crtc *crtc)
 		if (next_bo) {
 			/* take a obj ref + iova ref when we start scanning out: */
 			drm_gem_object_get(next_bo);
-			msm_gem_get_iova(next_bo, kms->aspace, &iova);
+			msm_gem_get_and_pin_iova(next_bo, kms->aspace, &iova);
 
 			/* enable cursor: */
 			mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_SIZE(dma),
@@ -442,7 +442,7 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
 	}
 
 	if (cursor_bo) {
-		ret = msm_gem_get_iova(cursor_bo, kms->aspace, &iova);
+		ret = msm_gem_get_and_pin_iova(cursor_bo, kms->aspace, &iova);
 		if (ret)
 			goto fail;
 	} else {
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +1 -1
index 481c0d231149..9fd6b9b2dbcb 100644
@@ -538,7 +538,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
 		goto fail;
 	}
 
-	ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, kms->aspace,
+	ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->aspace,
 			&mdp4_kms->blank_cursor_iova);
 	if (ret) {
 		DRM_DEV_ERROR(dev->dev, "could not pin blank-cursor bo: %d\n", ret);
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +1 -1
index 413b52211017..c7cc276575fb 100644
@@ -903,7 +903,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
 	if (!cursor_bo)
 		return -ENOENT;
 
-	ret = msm_gem_get_iova(cursor_bo, kms->aspace,
+	ret = msm_gem_get_and_pin_iova(cursor_bo, kms->aspace,
 			&mdp5_crtc->cursor.iova);
 	if (ret)
 		return -EINVAL;
drivers/gpu/drm/msm/dsi/dsi_host.c +1 -1
index eba901584035..99122767abf4 100644
@@ -1248,7 +1248,7 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *dma_base)
 	if (!dma_base)
 		return -EINVAL;
 
-	return msm_gem_get_iova(msm_host->tx_gem_obj,
+	return msm_gem_get_and_pin_iova(msm_host->tx_gem_obj,
 				priv->kms->aspace, dma_base);
 }
 
drivers/gpu/drm/msm/msm_drv.c +4 -0
index 9c9f7ff6960b..f2ebfb9ba0e4 100644
@@ -849,6 +849,10 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev,
 	if (!priv->gpu)
 		return -EINVAL;
 
+	/*
+	 * Don't pin the memory here - just get an address so that userspace can
+	 * be productive
+	 */
 	return msm_gem_get_iova(obj, priv->gpu->aspace, iova);
 }
 
drivers/gpu/drm/msm/msm_drv.h +2 -0
index 63b28b69b2ab..4372505a0bda 100644
@@ -271,6 +271,8 @@ vm_fault_t msm_gem_fault(struct vm_fault *vmf);
 uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
 int msm_gem_get_iova(struct drm_gem_object *obj,
 		struct msm_gem_address_space *aspace, uint64_t *iova);
+int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,
+		struct msm_gem_address_space *aspace, uint64_t *iova);
 uint64_t msm_gem_iova(struct drm_gem_object *obj,
 		struct msm_gem_address_space *aspace);
 struct page **msm_gem_get_pages(struct drm_gem_object *obj);
drivers/gpu/drm/msm/msm_fb.c +1 -1
index 475191fcf412..4e1e435db5a6 100644
@@ -66,7 +66,7 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb,
 	uint64_t iova;
 
 	for (i = 0; i < n; i++) {
-		ret = msm_gem_get_iova(fb->obj[i], aspace, &iova);
+		ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &iova);
 		DBG("FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret);
 		if (ret)
 			return ret;
drivers/gpu/drm/msm/msm_fbdev.c +1 -1
index f94cbbbf3834..c03e860ba737 100644
@@ -104,7 +104,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
 	 * in panic (ie. lock-safe, etc) we could avoid pinning the
 	 * buffer now:
 	 */
-	ret = msm_gem_get_iova(bo, priv->kms->aspace, &paddr);
+	ret = msm_gem_get_and_pin_iova(bo, priv->kms->aspace, &paddr);
 	if (ret) {
 		DRM_DEV_ERROR(dev->dev, "failed to get buffer obj iova: %d\n", ret);
 		goto fail_unlock;
drivers/gpu/drm/msm/msm_gem.c +19 -5
index 805a300f8663..a7e51001879b 100644
@@ -408,9 +408,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
 			obj->size >> PAGE_SHIFT);
 }
 
-
-/* get iova, taking a reference.  Should have a matching put */
-int msm_gem_get_iova(struct drm_gem_object *obj,
+/* get iova and pin it. Should have a matching put */
+int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,
 		struct msm_gem_address_space *aspace, uint64_t *iova)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -431,8 +430,23 @@ int msm_gem_get_iova(struct drm_gem_object *obj,
 	return ret;
 }
 
+/* Get an iova but don't pin the memory behind it */
+int msm_gem_get_iova(struct drm_gem_object *obj,
+		struct msm_gem_address_space *aspace, uint64_t *iova)
+{
+	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+	int ret;
+
+	mutex_lock(&msm_obj->lock);
+	ret = msm_gem_get_iova_locked(obj, aspace, iova);
+	mutex_unlock(&msm_obj->lock);
+
+	return ret;
+}
+
+
 /* get iova without taking a reference, used in places where you have
- * already done a 'msm_gem_get_iova()'.
+ * already done a 'msm_gem_get_and_pin_iova' or 'msm_gem_get_iova'
  */
 uint64_t msm_gem_iova(struct drm_gem_object *obj,
 		struct msm_gem_address_space *aspace)
@@ -1072,7 +1086,7 @@ static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
 		return ERR_CAST(obj);
 
 	if (iova) {
-		ret = msm_gem_get_iova(obj, aspace, iova);
+		ret = msm_gem_get_and_pin_iova(obj, aspace, iova);
 		if (ret) {
 			drm_gem_object_put(obj);
 			return ERR_PTR(ret);
drivers/gpu/drm/msm/msm_gem_submit.c +1 -1
index 66673ea9bf6f..da907260660c 100644
@@ -269,7 +269,7 @@ static int submit_pin_objects(struct msm_gem_submit *submit)
 		uint64_t iova;
 
 		/* if locking succeeded, pin bo: */
-		ret = msm_gem_get_iova(&msm_obj->base,
+		ret = msm_gem_get_and_pin_iova(&msm_obj->base,
 				submit->gpu->aspace, &iova);
 
 		if (ret)
drivers/gpu/drm/msm/msm_gpu.c +1 -1
index 71a2d431663f..13dab9527bda 100644
@@ -754,7 +754,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 
 		/* submit takes a reference to the bo and iova until retired: */
 		drm_gem_object_get(&msm_obj->base);
-		msm_gem_get_iova(&msm_obj->base,
+		msm_gem_get_and_pin_iova(&msm_obj->base,
 				submit->gpu->aspace, &iova);
 
 		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
#7 lore raw

PATCH 6/6 drm/msm: Count how many times iova memory is pinned

In reply to a message not in the archive

Add a reference count to track how many times a particular chunk of iova memory is pinned (mapped) in the iomu and add msm_gem_unpin_iova to give up references.

It is important to note that msm_gem_unpin_iova replaces msm_gem_put_iova because the new implicit behavior that an assigned iova in a given vma is now valid for the life of the buffer and what we are really focusing on is the use of that iova.

For now the unmappings are lazy; once the reference counts go to zero they *COULD* be unmapped dynamically but that will require an outside force such as a shrinker or mm_notifiers. For now, we're just focusing on getting the counting right and setting ourselves up to be ready for the future.

---
 drivers/gpu/drm/msm/adreno/a5xx_debugfs.c |  6 +--
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c     |  9 ++--
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c     |  3 +-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c |  2 +-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c  |  2 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c |  2 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c        |  2 +-
 drivers/gpu/drm/msm/msm_drv.h             |  8 +++-
 drivers/gpu/drm/msm/msm_fb.c              |  2 +-
 drivers/gpu/drm/msm/msm_gem.c             | 43 ++++++++++++-------
 drivers/gpu/drm/msm/msm_gem.h             |  1 +
 drivers/gpu/drm/msm/msm_gem_submit.c      |  2 +-
 drivers/gpu/drm/msm/msm_gem_vma.c         | 51 +++++++++++++++++------
 drivers/gpu/drm/msm/msm_gpu.c             |  2 +-
 14 files changed, 87 insertions(+), 48 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_debugfs.c +2 -4
index 6983cd9102bd..d9af3aff690f 100644
@@ -130,15 +130,13 @@ reset_set(void *data, u64 val)
 	adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
 
 	if (a5xx_gpu->pm4_bo) {
-		if (a5xx_gpu->pm4_iova)
-			msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
+		msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace);
 		drm_gem_object_put(a5xx_gpu->pm4_bo);
 		a5xx_gpu->pm4_bo = NULL;
 	}
 
 	if (a5xx_gpu->pfp_bo) {
-		if (a5xx_gpu->pfp_iova)
-			msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
+		msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace);
 		drm_gem_object_put(a5xx_gpu->pfp_bo);
 		a5xx_gpu->pfp_bo = NULL;
 	}
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +3 -6
index d6f8dedc028a..135496393cf3 100644
@@ -841,20 +841,17 @@ static void a5xx_destroy(struct msm_gpu *gpu)
 	a5xx_preempt_fini(gpu);
 
 	if (a5xx_gpu->pm4_bo) {
-		if (a5xx_gpu->pm4_iova)
-			msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
+		msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace);
 		drm_gem_object_put_unlocked(a5xx_gpu->pm4_bo);
 	}
 
 	if (a5xx_gpu->pfp_bo) {
-		if (a5xx_gpu->pfp_iova)
-			msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
+		msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace);
 		drm_gem_object_put_unlocked(a5xx_gpu->pfp_bo);
 	}
 
 	if (a5xx_gpu->gpmu_bo) {
-		if (a5xx_gpu->gpmu_iova)
-			msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
+		msm_gem_unpin_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
 		drm_gem_object_put_unlocked(a5xx_gpu->gpmu_bo);
 	}
 
drivers/gpu/drm/msm/adreno/a6xx_gpu.c +1 -2
index 38b7a5a92bfb..9acf12c21b23 100644
@@ -746,8 +746,7 @@ static void a6xx_destroy(struct msm_gpu *gpu)
 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
 
 	if (a6xx_gpu->sqe_bo) {
-		if (a6xx_gpu->sqe_iova)
-			msm_gem_put_iova(a6xx_gpu->sqe_bo, gpu->aspace);
+		msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace);
 		drm_gem_object_put_unlocked(a6xx_gpu->sqe_bo);
 	}
 
drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c +1 -1
index ef6884f1fc34..8f2359dc87b4 100644
@@ -128,7 +128,7 @@ static void unref_cursor_worker(struct drm_flip_work *work, void *val)
 	struct mdp4_kms *mdp4_kms = get_kms(&mdp4_crtc->base);
 	struct msm_kms *kms = &mdp4_kms->base.base;
 
-	msm_gem_put_iova(val, kms->aspace);
+	msm_gem_unpin_iova(val, kms->aspace);
 	drm_gem_object_put_unlocked(val);
 }
 
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +1 -1
index 9fd6b9b2dbcb..934a49818ea4 100644
@@ -165,7 +165,7 @@ static void mdp4_destroy(struct msm_kms *kms)
 	struct msm_gem_address_space *aspace = kms->aspace;
 
 	if (mdp4_kms->blank_cursor_iova)
-		msm_gem_put_iova(mdp4_kms->blank_cursor_bo, kms->aspace);
+		msm_gem_unpin_iova(mdp4_kms->blank_cursor_bo, kms->aspace);
 	drm_gem_object_put_unlocked(mdp4_kms->blank_cursor_bo);
 
 	if (aspace) {
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +1 -1
index c7cc276575fb..c5fde1a4191a 100644
@@ -173,7 +173,7 @@ static void unref_cursor_worker(struct drm_flip_work *work, void *val)
 	struct mdp5_kms *mdp5_kms = get_kms(&mdp5_crtc->base);
 	struct msm_kms *kms = &mdp5_kms->base.base;
 
-	msm_gem_put_iova(val, kms->aspace);
+	msm_gem_unpin_iova(val, kms->aspace);
 	drm_gem_object_put_unlocked(val);
 }
 
drivers/gpu/drm/msm/dsi/dsi_host.c +1 -1
index 99122767abf4..3b7092e1dcc7 100644
@@ -1118,7 +1118,7 @@ static void dsi_tx_buf_free(struct msm_dsi_host *msm_host)
 
 	priv = dev->dev_private;
 	if (msm_host->tx_gem_obj) {
-		msm_gem_put_iova(msm_host->tx_gem_obj, priv->kms->aspace);
+		msm_gem_unpin_iova(msm_host->tx_gem_obj, priv->kms->aspace);
 		drm_gem_object_put_unlocked(msm_host->tx_gem_obj);
 		msm_host->tx_gem_obj = NULL;
 	}
drivers/gpu/drm/msm/msm_drv.h +6 -2
index 4372505a0bda..955c2f522db6 100644
@@ -243,10 +243,14 @@ void msm_atomic_state_free(struct drm_atomic_state *state);
 
 int msm_gem_init_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma, int npages);
+void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma);
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma);
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
+void msm_gem_close_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma);
 
 void msm_gem_address_space_put(struct msm_gem_address_space *aspace);
 
@@ -275,10 +279,10 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj,
 		struct msm_gem_address_space *aspace, uint64_t *iova);
 uint64_t msm_gem_iova(struct drm_gem_object *obj,
 		struct msm_gem_address_space *aspace);
+void msm_gem_unpin_iova(struct drm_gem_object *obj,
+		struct msm_gem_address_space *aspace);
 struct page **msm_gem_get_pages(struct drm_gem_object *obj);
 void msm_gem_put_pages(struct drm_gem_object *obj);
-void msm_gem_put_iova(struct drm_gem_object *obj,
-		struct msm_gem_address_space *aspace);
 int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 		struct drm_mode_create_dumb *args);
 int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
drivers/gpu/drm/msm/msm_fb.c +1 -1
index 4e1e435db5a6..1224739094f2 100644
@@ -81,7 +81,7 @@ void msm_framebuffer_cleanup(struct drm_framebuffer *fb,
 	int i, n = fb->format->num_planes;
 
 	for (i = 0; i < n; i++)
-		msm_gem_put_iova(fb->obj[i], aspace);
+		msm_gem_unpin_iova(fb->obj[i], aspace);
 }
 
 uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb,
drivers/gpu/drm/msm/msm_gem.c +28 -15

89 lines not on this page · raw message

drivers/gpu/drm/msm/msm_gem.h +1 -0
index 32c13e6559b5..53d3bf49a9fa 100644
@@ -42,6 +42,7 @@ struct msm_gem_vma {
 	struct msm_gem_address_space *aspace;
 	struct list_head list;    /* node in msm_gem_object::vmas */
 	bool mapped;
+	int inuse;
 };
 
 struct msm_gem_object {
drivers/gpu/drm/msm/msm_gem_submit.c +1 -1
index da907260660c..9c78521ee08a 100644
@@ -167,7 +167,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit,
 	struct msm_gem_object *msm_obj = submit->bos[i].obj;
 
 	if (submit->bos[i].flags & BO_PINNED)
-		msm_gem_put_iova(&msm_obj->base, submit->gpu->aspace);
+		msm_gem_unpin_iova(&msm_obj->base, submit->gpu->aspace);
 
 	if (submit->bos[i].flags & BO_LOCKED)
 		ww_mutex_unlock(&msm_obj->resv->lock);
drivers/gpu/drm/msm/msm_gem_vma.c +39 -12

83 lines not on this page · raw message

drivers/gpu/drm/msm/msm_gpu.c +1 -1
index 13dab9527bda..e6ce24bfb9b1 100644
@@ -670,7 +670,7 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
 		/* move to inactive: */
 		msm_gem_move_to_inactive(&msm_obj->base);
-		msm_gem_put_iova(&msm_obj->base, gpu->aspace);
+		msm_gem_unpin_iova(&msm_obj->base, gpu->aspace);
 		drm_gem_object_put(&msm_obj->base);
 	}
 
Signature · 6 lines
2.18.0

_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno