Both patches are: Reviewed-by: Iago Toral Quiroga <[email protected]>
El jue, 15-01-2026 a las 12:05 -0300, Maíra Canal escribió: > The IDR interface is deprecated and the XArray API is the recommended > replacement. Replace the per-file IDR used to track perfmons with an > XArray. This allows us to remove the external mutex that protects the > IDR. > > While here, introduce the v3d_perfmon_delete() helper to consolidate > the perfmon cleanup logic used by both v3d_perfmon_close_file() and > v3d_perfmon_destroy_ioctl(). > > Signed-off-by: Maíra Canal <[email protected]> > --- > drivers/gpu/drm/v3d/v3d_drv.h | 5 +-- > drivers/gpu/drm/v3d/v3d_perfmon.c | 55 +++++++++++------------------ > -- > 2 files changed, 21 insertions(+), 39 deletions(-) > > diff --git a/drivers/gpu/drm/v3d/v3d_drv.h > b/drivers/gpu/drm/v3d/v3d_drv.h > index 99a39329bb85..314213c26710 100644 > --- a/drivers/gpu/drm/v3d/v3d_drv.h > +++ b/drivers/gpu/drm/v3d/v3d_drv.h > @@ -220,10 +220,7 @@ v3d_has_csd(struct v3d_dev *v3d) > struct v3d_file_priv { > struct v3d_dev *v3d; > > - struct { > - struct idr idr; > - struct mutex lock; > - } perfmon; > + struct xarray perfmons; > > struct drm_sched_entity sched_entity[V3D_MAX_QUEUES]; > > diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c > b/drivers/gpu/drm/v3d/v3d_perfmon.c > index 9a3fe5255874..41325ffc7f43 100644 > --- a/drivers/gpu/drm/v3d/v3d_perfmon.c > +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c > @@ -290,24 +290,23 @@ struct v3d_perfmon *v3d_perfmon_find(struct > v3d_file_priv *v3d_priv, int id) > { > struct v3d_perfmon *perfmon; > > - mutex_lock(&v3d_priv->perfmon.lock); > - perfmon = idr_find(&v3d_priv->perfmon.idr, id); > + xa_lock(&v3d_priv->perfmons); > + perfmon = xa_load(&v3d_priv->perfmons, id); > v3d_perfmon_get(perfmon); > - mutex_unlock(&v3d_priv->perfmon.lock); > + xa_unlock(&v3d_priv->perfmons); > > return perfmon; > } > > void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv) > { > - mutex_init(&v3d_priv->perfmon.lock); > - idr_init_base(&v3d_priv->perfmon.idr, 1); > + xa_init_flags(&v3d_priv->perfmons, XA_FLAGS_ALLOC1); > } > > -static int v3d_perfmon_idr_del(int id, void *elem, void *data) > +static void v3d_perfmon_delete(struct v3d_file_priv *v3d_priv, > + struct v3d_perfmon *perfmon) > { > - struct v3d_perfmon *perfmon = elem; > - struct v3d_dev *v3d = (struct v3d_dev *)data; > + struct v3d_dev *v3d = v3d_priv->v3d; > > /* If the active perfmon is being destroyed, stop it first > */ > if (perfmon == v3d->active_perfmon) > @@ -317,19 +316,17 @@ static int v3d_perfmon_idr_del(int id, void > *elem, void *data) > cmpxchg(&v3d->global_perfmon, perfmon, NULL); > > v3d_perfmon_put(perfmon); > - > - return 0; > } > > void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv) > { > - struct v3d_dev *v3d = v3d_priv->v3d; > + struct v3d_perfmon *perfmon; > + unsigned long id; > > - mutex_lock(&v3d_priv->perfmon.lock); > - idr_for_each(&v3d_priv->perfmon.idr, v3d_perfmon_idr_del, > v3d); > - idr_destroy(&v3d_priv->perfmon.idr); > - mutex_unlock(&v3d_priv->perfmon.lock); > - mutex_destroy(&v3d_priv->perfmon.lock); > + xa_for_each(&v3d_priv->perfmons, id, perfmon) > + v3d_perfmon_delete(v3d_priv, perfmon); > + > + xa_destroy(&v3d_priv->perfmons); > } > > int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data, > @@ -341,6 +338,7 @@ int v3d_perfmon_create_ioctl(struct drm_device > *dev, void *data, > struct v3d_perfmon *perfmon; > unsigned int i; > int ret; > + u32 id; > > /* Number of monitored counters cannot exceed HW limits. */ > if (req->ncounters > DRM_V3D_MAX_PERF_COUNTERS || > @@ -366,18 +364,16 @@ int v3d_perfmon_create_ioctl(struct drm_device > *dev, void *data, > refcount_set(&perfmon->refcnt, 1); > mutex_init(&perfmon->lock); > > - mutex_lock(&v3d_priv->perfmon.lock); > - ret = idr_alloc(&v3d_priv->perfmon.idr, perfmon, > V3D_PERFMONID_MIN, > - V3D_PERFMONID_MAX, GFP_KERNEL); > - mutex_unlock(&v3d_priv->perfmon.lock); > - > + ret = xa_alloc(&v3d_priv->perfmons, &id, perfmon, > + XA_LIMIT(V3D_PERFMONID_MIN, > V3D_PERFMONID_MAX), > + GFP_KERNEL); > if (ret < 0) { > mutex_destroy(&perfmon->lock); > kfree(perfmon); > return ret; > } > > - req->id = ret; > + req->id = id; > > return 0; > } > @@ -387,24 +383,13 @@ int v3d_perfmon_destroy_ioctl(struct drm_device > *dev, void *data, > { > struct v3d_file_priv *v3d_priv = file_priv->driver_priv; > struct drm_v3d_perfmon_destroy *req = data; > - struct v3d_dev *v3d = v3d_priv->v3d; > struct v3d_perfmon *perfmon; > > - mutex_lock(&v3d_priv->perfmon.lock); > - perfmon = idr_remove(&v3d_priv->perfmon.idr, req->id); > - mutex_unlock(&v3d_priv->perfmon.lock); > - > + perfmon = xa_erase(&v3d_priv->perfmons, req->id); > if (!perfmon) > return -EINVAL; > > - /* If the active perfmon is being destroyed, stop it first > */ > - if (perfmon == v3d->active_perfmon) > - v3d_perfmon_stop(v3d, perfmon, false); > - > - /* If the global perfmon is being destroyed, set it to NULL > */ > - cmpxchg(&v3d->global_perfmon, perfmon, NULL); > - > - v3d_perfmon_put(perfmon); > + v3d_perfmon_delete(v3d_priv, perfmon); > > return 0; > }
