Am Freitag, dem 10.07.2026 um 14:03 +0200 schrieb Christian Gmeiner: > From: Christian Gmeiner <[email protected]> > > The next commit updates per-context data from the GPU reset path, which > runs in the scheduler timeout worker. This can race with closing the DRM > file: drm_sched_entity_flush() only waits until the entity queue is > empty, it does not wait for jobs still running on the hardware. So the > context can already be freed while the reset path still needs it. > > Reference count the context and let every submit hold a reference, the > same way a submit already keeps its mmu context and pid alive. No > functional change. > > Signed-off-by: Christian Gmeiner <[email protected]>
Reviewed-by: Lucas Stach <[email protected]> > --- > drivers/gpu/drm/etnaviv/etnaviv_drv.c | 17 ++++++++++++++++- > drivers/gpu/drm/etnaviv/etnaviv_drv.h | 11 +++++++++++ > drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 5 ++++- > 3 files changed, 31 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c > b/drivers/gpu/drm/etnaviv/etnaviv_drv.c > index 08aca9035fc1..a27ed014fb4e 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c > @@ -60,6 +60,19 @@ static void load_gpu(struct drm_device *dev) > } > } > > +static void etnaviv_file_private_release(struct kref *kref) > +{ > + struct etnaviv_file_private *ctx = > + container_of(kref, struct etnaviv_file_private, refcount); > + > + kfree(ctx); > +} > + > +void etnaviv_file_private_put(struct etnaviv_file_private *ctx) > +{ > + kref_put(&ctx->refcount, etnaviv_file_private_release); > +} > + > static int etnaviv_open(struct drm_device *dev, struct drm_file *file) > { > struct etnaviv_drm_private *priv = dev->dev_private; > @@ -70,6 +83,8 @@ static int etnaviv_open(struct drm_device *dev, struct > drm_file *file) > if (!ctx) > return -ENOMEM; > > + kref_init(&ctx->refcount); > + > ret = xa_alloc_cyclic(&priv->active_contexts, &ctx->id, ctx, > xa_limit_32b, &priv->next_context_id, GFP_KERNEL); > if (ret < 0) > @@ -120,7 +135,7 @@ static void etnaviv_postclose(struct drm_device *dev, > struct drm_file *file) > > xa_erase(&priv->active_contexts, ctx->id); > > - kfree(ctx); > + etnaviv_file_private_put(ctx); > } > > /* > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h > b/drivers/gpu/drm/etnaviv/etnaviv_drv.h > index 55a9e745604d..cba4323ae589 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h > +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h > @@ -7,6 +7,7 @@ > #define __ETNAVIV_DRV_H__ > > #include <linux/io.h> > +#include <linux/kref.h> > #include <linux/list.h> > #include <linux/mm_types.h> > #include <linux/sizes.h> > @@ -29,6 +30,7 @@ struct etnaviv_iommu_global; > #define ETNAVIV_SOFTPIN_START_ADDRESS SZ_4M /* must be >= > SUBALLOC_SIZE */ > > struct etnaviv_file_private { > + struct kref refcount; > int id; > struct etnaviv_iommu_context *mmu; > struct drm_sched_entity sched_entity[ETNA_MAX_PIPES]; > @@ -53,6 +55,15 @@ struct etnaviv_drm_private { > struct etnaviv_cmdbuf *flop_reset_data_ppu; > }; > > +void etnaviv_file_private_put(struct etnaviv_file_private *ctx); > + > +static inline struct etnaviv_file_private * > +etnaviv_file_private_get(struct etnaviv_file_private *ctx) > +{ > + kref_get(&ctx->refcount); > + return ctx; > +} > + > int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, > struct drm_file *file); > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > index 1a77a09b3377..98f1f59a8b05 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > @@ -398,6 +398,9 @@ static void submit_cleanup(struct kref *kref) > > put_pid(submit->pid); > > + if (submit->ctx) > + etnaviv_file_private_put(submit->ctx); > + > kfree(submit->pmrs); > kfree(submit); > } > @@ -526,7 +529,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void > *data, > if (ret) > goto err_submit_put; > > - submit->ctx = file->driver_priv; > + submit->ctx = etnaviv_file_private_get(file->driver_priv); > submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu); > submit->exec_state = args->exec_state; > submit->flags = args->flags;
