mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Frank Binns <Frank.Binns@imgtec.com>
To: "dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	Matt Coster <Matt.Coster@imgtec.com>
Cc: Brendan King <Brendan.King@imgtec.com>,
	"daniel@ffwll.ch" <daniel@ffwll.ch>,
	"maarten.lankhorst@linux.intel.com"
	<maarten.lankhorst@linux.intel.com>,
	"mripard@kernel.org" <mripard@kernel.org>,
	"airlied@gmail.com" <airlied@gmail.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"tzimmermann@suse.de" <tzimmermann@suse.de>
Subject: Re: [PATCH v2 2/2] drm/imagination: Break an object reference loop
Date: Wed, 16 Oct 2024 13:31:59 +0000	[thread overview]
Message-ID: <b75e658cc5ce9ac24df2c31c1a6fd798a5f3a87f.camel@imgtec.com> (raw)
In-Reply-To: <48476abf-2def-4d83-87a3-8cbd8eb9db3b@imgtec.com>

On Mon, 2024-10-14 at 14:23 +0000, Matt Coster wrote:
> From: Brendan King <brendan.king@imgtec.com>
> 
> When remaining resources are being cleaned up on driver close,
> outstanding VM mappings may result in resources being leaked, due
> to an object reference loop, as shown below, with each object (or
> set of objects) referencing the object below it:
> 
>     PVR GEM Object
>     GPU scheduler "finished" fence
>     GPU scheduler “scheduled” fence
>     PVR driver “done” fence
>     PVR Context
>     PVR VM Context
>     PVR VM Mappings
>     PVR GEM Object
> 
> The reference that the PVR VM Context has on the VM mappings is a
> soft one, in the sense that the freeing of outstanding VM mappings
> is done as part of VM context destruction; no reference counts are
> involved, as is the case for all the other references in the loop.
> 
> To break the reference loop during cleanup, free the outstanding
> VM mappings before destroying the PVR Context associated with the
> VM context.
> 

Reviewed-by: Frank Binns <frank.binns@imgtec.com>

> Signed-off-by: Brendan King <brendan.king@imgtec.com>
> Signed-off-by: Matt Coster <matt.coster@imgtec.com>
> ---
> Changes in v1 -> v2:
>  - None
> ---
>  drivers/gpu/drm/imagination/pvr_context.c | 19 +++++++++++++++++++
>  drivers/gpu/drm/imagination/pvr_context.h | 18 ++++++++++++++++++
>  drivers/gpu/drm/imagination/pvr_vm.c      | 22 ++++++++++++++++++----
>  drivers/gpu/drm/imagination/pvr_vm.h      |  1 +
>  4 files changed, 56 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/imagination/pvr_context.c b/drivers/gpu/drm/imagination/pvr_context.c
> index 255c93582734..4cb3494c0bb2 100644
> --- a/drivers/gpu/drm/imagination/pvr_context.c
> +++ b/drivers/gpu/drm/imagination/pvr_context.c
> @@ -450,11 +450,30 @@ pvr_context_destroy(struct pvr_file *pvr_file, u32 handle)
>   */
>  void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
>  {
> +	struct pvr_device *pvr_dev = pvr_file->pvr_dev;
>  	struct pvr_context *ctx;
>  	unsigned long handle;
>  
>  	xa_for_each(&pvr_file->ctx_handles, handle, ctx)
>  		pvr_context_destroy(pvr_file, handle);
> +
> +	spin_lock(&pvr_dev->ctx_list_lock);
> +	ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
> +
> +	while (!list_entry_is_head(ctx, &pvr_file->contexts, file_link)) {
> +		list_del_init(&ctx->file_link);
> +
> +		if (pvr_context_get_if_referenced(ctx)) {
> +			spin_unlock(&pvr_dev->ctx_list_lock);
> +
> +			pvr_vm_unmap_all(ctx->vm_ctx);
> +
> +			pvr_context_put(ctx);
> +			spin_lock(&pvr_dev->ctx_list_lock);
> +		}
> +		ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
> +	}
> +	spin_unlock(&pvr_dev->ctx_list_lock);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/imagination/pvr_context.h b/drivers/gpu/drm/imagination/pvr_context.h
> index a5b0a82a54a1..07afa179cdf4 100644
> --- a/drivers/gpu/drm/imagination/pvr_context.h
> +++ b/drivers/gpu/drm/imagination/pvr_context.h
> @@ -126,6 +126,24 @@ pvr_context_get(struct pvr_context *ctx)
>  	return ctx;
>  }
>  
> +/**
> + * pvr_context_get_if_referenced() - Take an additional reference on a still
> + * referenced context.
> + * @ctx: Context pointer.
> + *
> + * Call pvr_context_put() to release.
> + *
> + * Returns:
> + *  * True on success, or
> + *  * false if no context pointer passed, or the context wasn't still
> + *  * referenced.
> + */
> +static __always_inline bool
> +pvr_context_get_if_referenced(struct pvr_context *ctx)
> +{
> +	return ctx != NULL && kref_get_unless_zero(&ctx->ref_count) != 0;
> +}
> +
>  /**
>   * pvr_context_lookup() - Lookup context pointer from handle and file.
>   * @pvr_file: Pointer to pvr_file structure.
> diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c
> index 97c0f772ed65..7bd6ba4c6e8a 100644
> --- a/drivers/gpu/drm/imagination/pvr_vm.c
> +++ b/drivers/gpu/drm/imagination/pvr_vm.c
> @@ -14,6 +14,7 @@
>  #include <drm/drm_gem.h>
>  #include <drm/drm_gpuvm.h>
>  
> +#include <linux/bug.h>
>  #include <linux/container_of.h>
>  #include <linux/err.h>
>  #include <linux/errno.h>
> @@ -597,12 +598,26 @@ pvr_vm_create_context(struct pvr_device *pvr_dev, bool is_userspace_context)
>  }
>  
>  /**
> - * pvr_vm_context_release() - Teardown a VM context.
> - * @ref_count: Pointer to reference counter of the VM context.
> + * pvr_vm_unmap_all() - Unmap all mappings associated with a VM context.
> + * @vm_ctx: Target VM context.
>   *
>   * This function ensures that no mappings are left dangling by unmapping them
>   * all in order of ascending device-virtual address.
>   */
> +void
> +pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx)
> +{
> +	WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
> +			     vm_ctx->gpuvm_mgr.mm_range));
> +}
> +
> +/**
> + * pvr_vm_context_release() - Teardown a VM context.
> + * @ref_count: Pointer to reference counter of the VM context.
> + *
> + * This function also ensures that no mappings are left dangling by calling
> + * pvr_vm_unmap_all.
> + */
>  static void
>  pvr_vm_context_release(struct kref *ref_count)
>  {
> @@ -612,8 +627,7 @@ pvr_vm_context_release(struct kref *ref_count)
>  	if (vm_ctx->fw_mem_ctx_obj)
>  		pvr_fw_object_destroy(vm_ctx->fw_mem_ctx_obj);
>  
> -	WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
> -			     vm_ctx->gpuvm_mgr.mm_range));
> +	pvr_vm_unmap_all(vm_ctx);
>  
>  	pvr_mmu_context_destroy(vm_ctx->mmu_ctx);
>  	drm_gem_private_object_fini(&vm_ctx->dummy_gem);
> diff --git a/drivers/gpu/drm/imagination/pvr_vm.h b/drivers/gpu/drm/imagination/pvr_vm.h
> index f2a6463f2b05..79406243617c 100644
> --- a/drivers/gpu/drm/imagination/pvr_vm.h
> +++ b/drivers/gpu/drm/imagination/pvr_vm.h
> @@ -39,6 +39,7 @@ int pvr_vm_map(struct pvr_vm_context *vm_ctx,
>  	       struct pvr_gem_object *pvr_obj, u64 pvr_obj_offset,
>  	       u64 device_addr, u64 size);
>  int pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size);
> +void pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx);
>  
>  dma_addr_t pvr_vm_get_page_table_root_addr(struct pvr_vm_context *vm_ctx);
>  struct dma_resv *pvr_vm_get_dma_resv(struct pvr_vm_context *vm_ctx);

      reply	other threads:[~2024-10-16 13:32 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-14 14:20 [PATCH v2 0/2] " Matt Coster
2024-10-14 14:22 ` [PATCH v2 1/2] drm/imagination: Add a per-file PVR context list Matt Coster
2024-10-16 13:31   ` Frank Binns
2024-10-14 14:23 ` [PATCH v2 2/2] drm/imagination: Break an object reference loop Matt Coster
2024-10-16 13:31   ` Frank Binns [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b75e658cc5ce9ac24df2c31c1a6fd798a5f3a87f.camel@imgtec.com \
    --to=frank.binns@imgtec.com \
    --cc=Brendan.King@imgtec.com \
    --cc=Matt.Coster@imgtec.com \
    --cc=airlied@gmail.com \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®