2023-11-29 22:08:54

by Danilo Krummrich

[permalink] [raw]
Subject: [PATCH drm-misc-next v2 0/2] PowerVR VM fixes

Hi,

Some major GPUVM changes landed just before v8 of the PowerVR series. Since v8
went in rather quickly (review process was finished otherwise) I haven't had the
chance to review the subsequent code changes.

Hence, this series with a few fixes in this context. Plus a minor GPUVM patch to
make the drm_gpuvm_prepare_* helpers useful for PowerVR.

- Danilo

Changes in V2
=============
- GPUVM: update function DOC comment to indicate the passing zero fences to
drm_gpuvm_prepare_* functions results into drm_exec_lock_obj() calls rather
than drm_exec_prepare_obj() calls.
- pvr/vm: use drm_gpuvm_exec wrappers
- drop 3 patches which were applied already

Danilo Krummrich (2):
drm/gpuvm: fall back to drm_exec_lock_obj()
drm/imagination: vm: make use of GPUVM's drm_exec helper

drivers/gpu/drm/drm_gpuvm.c | 43 +++++++++++--
drivers/gpu/drm/imagination/pvr_vm.c | 91 +++++++++++-----------------
include/drm/drm_gpuvm.h | 23 +------
3 files changed, 77 insertions(+), 80 deletions(-)


base-commit: 83dc1029dcf50b5b849b26679a1b3f860b85d79c
--
2.43.0


2023-11-29 22:09:09

by Danilo Krummrich

[permalink] [raw]
Subject: [PATCH drm-misc-next v2 1/2] drm/gpuvm: fall back to drm_exec_lock_obj()

Fall back to drm_exec_lock_obj() if num_fences is zero for the
drm_gpuvm_prepare_* function family.

Otherwise dma_resv_reserve_fences() would actually allocate slots even
though num_fences is zero.

Cc: Christian König <[email protected]>
Signed-off-by: Danilo Krummrich <[email protected]>
---
drivers/gpu/drm/drm_gpuvm.c | 43 ++++++++++++++++++++++++++++++++-----
include/drm/drm_gpuvm.h | 23 +++-----------------
2 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c
index 54f5e8851de5..07a6676bc4f9 100644
--- a/drivers/gpu/drm/drm_gpuvm.c
+++ b/drivers/gpu/drm/drm_gpuvm.c
@@ -1085,6 +1085,37 @@ drm_gpuvm_put(struct drm_gpuvm *gpuvm)
}
EXPORT_SYMBOL_GPL(drm_gpuvm_put);

+static int
+exec_prepare_obj(struct drm_exec *exec, struct drm_gem_object *obj,
+ unsigned int num_fences)
+{
+ return num_fences ? drm_exec_prepare_obj(exec, obj, num_fences) :
+ drm_exec_lock_obj(exec, obj);
+}
+
+/**
+ * drm_gpuvm_prepare_vm() - prepare the GPUVMs common dma-resv
+ * @gpuvm: the &drm_gpuvm
+ * @exec: the &drm_exec context
+ * @num_fences: the amount of &dma_fences to reserve
+ *
+ * Calls drm_exec_prepare_obj() for the GPUVMs dummy &drm_gem_object; if
+ * @num_fences is zero drm_exec_lock_obj() is called instead.
+ *
+ * Using this function directly, it is the drivers responsibility to call
+ * drm_exec_init() and drm_exec_fini() accordingly.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int
+drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm,
+ struct drm_exec *exec,
+ unsigned int num_fences)
+{
+ return exec_prepare_obj(exec, gpuvm->r_obj, num_fences);
+}
+EXPORT_SYMBOL_GPL(drm_gpuvm_prepare_vm);
+
static int
__drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm,
struct drm_exec *exec,
@@ -1095,7 +1126,7 @@ __drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm,
int ret = 0;

for_each_vm_bo_in_list(gpuvm, extobj, &extobjs, vm_bo) {
- ret = drm_exec_prepare_obj(exec, vm_bo->obj, num_fences);
+ ret = exec_prepare_obj(exec, vm_bo->obj, num_fences);
if (ret)
break;
}
@@ -1116,7 +1147,7 @@ drm_gpuvm_prepare_objects_locked(struct drm_gpuvm *gpuvm,

drm_gpuvm_resv_assert_held(gpuvm);
list_for_each_entry(vm_bo, &gpuvm->extobj.list, list.entry.extobj) {
- ret = drm_exec_prepare_obj(exec, vm_bo->obj, num_fences);
+ ret = exec_prepare_obj(exec, vm_bo->obj, num_fences);
if (ret)
break;

@@ -1134,7 +1165,8 @@ drm_gpuvm_prepare_objects_locked(struct drm_gpuvm *gpuvm,
* @num_fences: the amount of &dma_fences to reserve
*
* Calls drm_exec_prepare_obj() for all &drm_gem_objects the given
- * &drm_gpuvm contains mappings of.
+ * &drm_gpuvm contains mappings of; if @num_fences is zero drm_exec_lock_obj()
+ * is called instead.
*
* Using this function directly, it is the drivers responsibility to call
* drm_exec_init() and drm_exec_fini() accordingly.
@@ -1171,7 +1203,8 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_prepare_objects);
* @num_fences: the amount of &dma_fences to reserve
*
* Calls drm_exec_prepare_obj() for all &drm_gem_objects mapped between @addr
- * and @addr + @range.
+ * and @addr + @range; if @num_fences is zero drm_exec_lock_obj() is called
+ * instead.
*
* Returns: 0 on success, negative error code on failure.
*/
@@ -1186,7 +1219,7 @@ drm_gpuvm_prepare_range(struct drm_gpuvm *gpuvm, struct drm_exec *exec,
drm_gpuvm_for_each_va_range(va, gpuvm, addr, end) {
struct drm_gem_object *obj = va->gem.obj;

- ret = drm_exec_prepare_obj(exec, obj, num_fences);
+ ret = exec_prepare_obj(exec, obj, num_fences);
if (ret)
return ret;
}
diff --git a/include/drm/drm_gpuvm.h b/include/drm/drm_gpuvm.h
index f94fec9a8517..b3f82ec7fb17 100644
--- a/include/drm/drm_gpuvm.h
+++ b/include/drm/drm_gpuvm.h
@@ -544,26 +544,9 @@ struct drm_gpuvm_exec {
} extra;
};

-/**
- * drm_gpuvm_prepare_vm() - prepare the GPUVMs common dma-resv
- * @gpuvm: the &drm_gpuvm
- * @exec: the &drm_exec context
- * @num_fences: the amount of &dma_fences to reserve
- *
- * Calls drm_exec_prepare_obj() for the GPUVMs dummy &drm_gem_object.
- *
- * Using this function directly, it is the drivers responsibility to call
- * drm_exec_init() and drm_exec_fini() accordingly.
- *
- * Returns: 0 on success, negative error code on failure.
- */
-static inline int
-drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm,
- struct drm_exec *exec,
- unsigned int num_fences)
-{
- return drm_exec_prepare_obj(exec, gpuvm->r_obj, num_fences);
-}
+int drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm,
+ struct drm_exec *exec,
+ unsigned int num_fences);

int drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm,
struct drm_exec *exec,
--
2.43.0

2023-11-29 22:09:29

by Danilo Krummrich

[permalink] [raw]
Subject: [PATCH drm-misc-next v2 2/2] drm/imagination: vm: make use of GPUVM's drm_exec helper

Make use of GPUVM's drm_exec helper functions preventing direct access
to GPUVM internal data structures, such as the external object list.

This is especially important to ensure following the locking rules
around the GPUVM external object list.

Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code")
Signed-off-by: Danilo Krummrich <[email protected]>
---
drivers/gpu/drm/imagination/pvr_vm.c | 91 +++++++++++-----------------
1 file changed, 36 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c
index e0d74d9a6190..c6ab1581d509 100644
--- a/drivers/gpu/drm/imagination/pvr_vm.c
+++ b/drivers/gpu/drm/imagination/pvr_vm.c
@@ -333,48 +333,6 @@ pvr_vm_bind_op_unmap_init(struct pvr_vm_bind_op *bind_op,
return err;
}

-static int
-pvr_vm_bind_op_lock_resvs(struct drm_exec *exec, struct pvr_vm_bind_op *bind_op)
-{
- drm_exec_until_all_locked(exec) {
- struct drm_gem_object *r_obj = &bind_op->vm_ctx->dummy_gem;
- struct drm_gpuvm *gpuvm = &bind_op->vm_ctx->gpuvm_mgr;
- struct pvr_gem_object *pvr_obj = bind_op->pvr_obj;
- struct drm_gpuvm_bo *gpuvm_bo;
-
- /* Acquire lock on the vm_context's reserve object. */
- int err = drm_exec_lock_obj(exec, r_obj);
-
- drm_exec_retry_on_contention(exec);
- if (err)
- return err;
-
- /* Acquire lock on all BOs in the context. */
- list_for_each_entry(gpuvm_bo, &gpuvm->extobj.list,
- list.entry.extobj) {
- err = drm_exec_lock_obj(exec, gpuvm_bo->obj);
-
- drm_exec_retry_on_contention(exec);
- if (err)
- return err;
- }
-
- /* Unmap operations don't have an object to lock. */
- if (!pvr_obj)
- break;
-
- /* Acquire lock on the GEM being mapped. */
- err = drm_exec_lock_obj(exec,
- gem_from_pvr_gem(bind_op->pvr_obj));
-
- drm_exec_retry_on_contention(exec);
- if (err)
- return err;
- }
-
- return 0;
-}
-
/**
* pvr_vm_gpuva_map() - Insert a mapping into a memory context.
* @op: gpuva op containing the remap details.
@@ -731,6 +689,20 @@ void pvr_destroy_vm_contexts_for_file(struct pvr_file *pvr_file)
}
}

+static int
+pvr_vm_lock_extra(struct drm_gpuvm_exec *vm_exec)
+{
+ struct pvr_vm_bind_op *bind_op = vm_exec->extra.priv;
+ struct pvr_gem_object *pvr_obj = bind_op->pvr_obj;
+
+ /* Unmap operations don't have an object to lock. */
+ if (!pvr_obj)
+ return 0;
+
+ /* Acquire lock on the GEM being mapped. */
+ return drm_exec_lock_obj(&vm_exec->exec, gem_from_pvr_gem(pvr_obj));
+}
+
/**
* pvr_vm_map() - Map a section of physical memory into a section of
* device-virtual memory.
@@ -758,7 +730,15 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
u64 pvr_obj_offset, u64 device_addr, u64 size)
{
struct pvr_vm_bind_op bind_op = {0};
- struct drm_exec exec;
+ struct drm_gpuvm_exec vm_exec = {
+ .vm = &vm_ctx->gpuvm_mgr,
+ .flags = DRM_EXEC_INTERRUPTIBLE_WAIT |
+ DRM_EXEC_IGNORE_DUPLICATES,
+ .extra = {
+ .fn = pvr_vm_lock_extra,
+ .priv = &bind_op,
+ },
+ };

int err = pvr_vm_bind_op_map_init(&bind_op, vm_ctx, pvr_obj,
pvr_obj_offset, device_addr,
@@ -767,18 +747,15 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
if (err)
return err;

- drm_exec_init(&exec,
- DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES);
-
pvr_gem_object_get(pvr_obj);

- err = pvr_vm_bind_op_lock_resvs(&exec, &bind_op);
+ err = drm_gpuvm_exec_lock(&vm_exec);
if (err)
goto err_cleanup;

err = pvr_vm_bind_op_exec(&bind_op);

- drm_exec_fini(&exec);
+ drm_gpuvm_exec_unlock(&vm_exec);

err_cleanup:
pvr_vm_bind_op_fini(&bind_op);
@@ -804,24 +781,28 @@ int
pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size)
{
struct pvr_vm_bind_op bind_op = {0};
- struct drm_exec exec;
+ struct drm_gpuvm_exec vm_exec = {
+ .vm = &vm_ctx->gpuvm_mgr,
+ .flags = DRM_EXEC_INTERRUPTIBLE_WAIT |
+ DRM_EXEC_IGNORE_DUPLICATES,
+ .extra = {
+ .fn = pvr_vm_lock_extra,
+ .priv = &bind_op,
+ },
+ };

int err = pvr_vm_bind_op_unmap_init(&bind_op, vm_ctx, device_addr,
size);
-
if (err)
return err;

- drm_exec_init(&exec,
- DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES);
-
- err = pvr_vm_bind_op_lock_resvs(&exec, &bind_op);
+ err = drm_gpuvm_exec_lock(&vm_exec);
if (err)
goto err_cleanup;

err = pvr_vm_bind_op_exec(&bind_op);

- drm_exec_fini(&exec);
+ drm_gpuvm_exec_unlock(&vm_exec);

err_cleanup:
pvr_vm_bind_op_fini(&bind_op);
--
2.43.0

2023-12-05 14:55:07

by Donald Robson

[permalink] [raw]
Subject: Re: [EXTERNAL] [PATCH drm-misc-next v2 0/2] PowerVR VM fixes

Apologies, I didn't reply all last time.

Thanks Danilo!

Reviewed-by: Donald Robson <[email protected]>

On Wed, 2023-11-29 at 23:07 +0100, Danilo Krummrich wrote:
> *** CAUTION: This email originates from a source not known to Imagination Technologies. Think before you click a link or open an attachment ***
>
> Hi,
>
> Some major GPUVM changes landed just before v8 of the PowerVR series. Since v8
> went in rather quickly (review process was finished otherwise) I haven't had the
> chance to review the subsequent code changes.
>
> Hence, this series with a few fixes in this context. Plus a minor GPUVM patch to
> make the drm_gpuvm_prepare_* helpers useful for PowerVR.
>
> - Danilo
>
> Changes in V2
> =============
> - GPUVM: update function DOC comment to indicate the passing zero fences to
> drm_gpuvm_prepare_* functions results into drm_exec_lock_obj() calls rather
> than drm_exec_prepare_obj() calls.
> - pvr/vm: use drm_gpuvm_exec wrappers
> - drop 3 patches which were applied already
>
> Danilo Krummrich (2):
> drm/gpuvm: fall back to drm_exec_lock_obj()
> drm/imagination: vm: make use of GPUVM's drm_exec helper
>
> drivers/gpu/drm/drm_gpuvm.c | 43 +++++++++++--
> drivers/gpu/drm/imagination/pvr_vm.c | 91 +++++++++++-----------------
> include/drm/drm_gpuvm.h | 23 +------
> 3 files changed, 77 insertions(+), 80 deletions(-)
>
>
> base-commit: 83dc1029dcf50b5b849b26679a1b3f860b85d79c

2023-12-05 15:35:09

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH drm-misc-next v2 0/2] PowerVR VM fixes

Hi,

On Wed, Nov 29, 2023 at 11:07:59PM +0100, Danilo Krummrich wrote:
> Some major GPUVM changes landed just before v8 of the PowerVR series. Since v8
> went in rather quickly (review process was finished otherwise) I haven't had the
> chance to review the subsequent code changes.
>
> Hence, this series with a few fixes in this context. Plus a minor GPUVM patch to
> make the drm_gpuvm_prepare_* helpers useful for PowerVR.

This doesn't apply on drm-misc-next anymore, could you rebase and
resend?

Thanks!
Maxime


Attachments:
(No filename) (534.00 B)
signature.asc (235.00 B)
Download all attachments

2023-12-05 15:41:52

by Danilo Krummrich

[permalink] [raw]
Subject: Re: [PATCH drm-misc-next v2 0/2] PowerVR VM fixes

On Tue, Dec 05, 2023 at 04:35:00PM +0100, Maxime Ripard wrote:
> Hi,
>
> On Wed, Nov 29, 2023 at 11:07:59PM +0100, Danilo Krummrich wrote:
> > Some major GPUVM changes landed just before v8 of the PowerVR series. Since v8
> > went in rather quickly (review process was finished otherwise) I haven't had the
> > chance to review the subsequent code changes.
> >
> > Hence, this series with a few fixes in this context. Plus a minor GPUVM patch to
> > make the drm_gpuvm_prepare_* helpers useful for PowerVR.
>
> This doesn't apply on drm-misc-next anymore, could you rebase and
> resend?

I already applied the two patches to drm-misc-next.

- Danilo

>
> Thanks!
> Maxime


2023-12-06 08:28:24

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH drm-misc-next v2 0/2] PowerVR VM fixes

On Tue, Dec 05, 2023 at 04:40:40PM +0100, Danilo Krummrich wrote:
> On Tue, Dec 05, 2023 at 04:35:00PM +0100, Maxime Ripard wrote:
> > Hi,
> >
> > On Wed, Nov 29, 2023 at 11:07:59PM +0100, Danilo Krummrich wrote:
> > > Some major GPUVM changes landed just before v8 of the PowerVR series. Since v8
> > > went in rather quickly (review process was finished otherwise) I haven't had the
> > > chance to review the subsequent code changes.
> > >
> > > Hence, this series with a few fixes in this context. Plus a minor GPUVM patch to
> > > make the drm_gpuvm_prepare_* helpers useful for PowerVR.
> >
> > This doesn't apply on drm-misc-next anymore, could you rebase and
> > resend?
>
> I already applied the two patches to drm-misc-next.

Uh, sorry I didn't notice it.

Maxime


Attachments:
(No filename) (798.00 B)
signature.asc (235.00 B)
Download all attachments