Message ID | 20190221184226.2149-4-willy@infradead.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Convert DRM to XArray | expand |
On Thu, Feb 21, 2019 at 10:41:23AM -0800, Matthew Wilcox wrote: > Signed-off-by: Matthew Wilcox <willy@infradead.org> > --- > drivers/gpu/drm/drm_dp_aux_dev.c | 41 +++++++++++++------------------- > 1 file changed, 17 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c > index 0e4f25d63fd2..393a32976900 100644 > --- a/drivers/gpu/drm/drm_dp_aux_dev.c > +++ b/drivers/gpu/drm/drm_dp_aux_dev.c > @@ -49,8 +49,7 @@ struct drm_dp_aux_dev { > > #define DRM_AUX_MINORS 256 > #define AUX_MAX_OFFSET (1 << 20) > -static DEFINE_IDR(aux_idr); > -static DEFINE_MUTEX(aux_idr_mutex); > +static DEFINE_XARRAY_ALLOC(aux_xa); > static struct class *drm_dp_aux_dev_class; > static int drm_dev_major = -1; > > @@ -58,19 +57,21 @@ static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index) > { > struct drm_dp_aux_dev *aux_dev = NULL; > > - mutex_lock(&aux_idr_mutex); > - aux_dev = idr_find(&aux_idr, index); > + xa_lock(&aux_xa); > + aux_dev = xa_load(&aux_xa, index); > if (!kref_get_unless_zero(&aux_dev->refcount)) > aux_dev = NULL; > - mutex_unlock(&aux_idr_mutex); > + xa_unlock(&aux_xa); > > return aux_dev; > } > > static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) > { > + static u32 next; Is there a particular reason for that being static? > + > struct drm_dp_aux_dev *aux_dev; > - int index; > + int err; > > aux_dev = kzalloc(sizeof(*aux_dev), GFP_KERNEL); > if (!aux_dev) > @@ -79,15 +80,12 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) > atomic_set(&aux_dev->usecount, 1); > kref_init(&aux_dev->refcount); > > - mutex_lock(&aux_idr_mutex); > - index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, > - GFP_KERNEL); > - mutex_unlock(&aux_idr_mutex); > - if (index < 0) { > + err = xa_alloc_cyclic(&aux_xa, &aux_dev->index, aux_dev, > + XA_LIMIT(0, DRM_AUX_MINORS), &next, GFP_KERNEL); > + if (err < 0) { > kfree(aux_dev); > - return ERR_PTR(index); > + return ERR_PTR(err); > } > - aux_dev->index = index; > > return aux_dev; > } > @@ -246,22 +244,19 @@ static const struct file_operations auxdev_fops = { > > static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_aux(struct drm_dp_aux *aux) > { > - struct drm_dp_aux_dev *iter, *aux_dev = NULL; > - int id; > + struct drm_dp_aux_dev *aux_dev; > + unsigned long id; > > /* don't increase kref count here because this function should only be > * used by drm_dp_aux_unregister_devnode. Thus, it will always have at > * least one reference - the one that drm_dp_aux_register_devnode > * created > */ > - mutex_lock(&aux_idr_mutex); > - idr_for_each_entry(&aux_idr, iter, id) { > - if (iter->aux == aux) { > - aux_dev = iter; > + xa_for_each(&aux_xa, id, aux_dev) { > + if (aux_dev->aux == aux) > break; > - } > } > - mutex_unlock(&aux_idr_mutex); > + > return aux_dev; > } > > @@ -274,9 +269,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) > if (!aux_dev) /* attach must have failed */ > return; > > - mutex_lock(&aux_idr_mutex); > - idr_remove(&aux_idr, aux_dev->index); > - mutex_unlock(&aux_idr_mutex); > + xa_erase(&aux_xa, aux_dev->index); > > atomic_dec(&aux_dev->usecount); > wait_var_event(&aux_dev->usecount, !atomic_read(&aux_dev->usecount)); > -- > 2.20.1 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel
On Mon, Feb 25, 2019 at 07:57:33PM +0200, Ville Syrjälä wrote: > On Thu, Feb 21, 2019 at 10:41:23AM -0800, Matthew Wilcox wrote: > > @@ -49,8 +49,7 @@ struct drm_dp_aux_dev { > > > > #define DRM_AUX_MINORS 256 > > #define AUX_MAX_OFFSET (1 << 20) > > -static DEFINE_IDR(aux_idr); > > -static DEFINE_MUTEX(aux_idr_mutex); > > +static DEFINE_XARRAY_ALLOC(aux_xa); > > static struct class *drm_dp_aux_dev_class; > > static int drm_dev_major = -1; [...] > > static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) > > { > > + static u32 next; > > Is there a particular reason for that being static? It needs to maintain its value between function calls so that we know where to start allocating from the next time we call xa_alloc_cyclic(). It can either live here with a short name, or we could put it at file scope with a descriptive name (probably aux_xa_next). It's up to you which you think is better; it's your driver. The IDR embedded the 'next' value in the struct idr, but that was overhead paid by all users of the IDR rather than the very few that called idr_alloc_cyclic(). > > + err = xa_alloc_cyclic(&aux_xa, &aux_dev->index, aux_dev, > > + XA_LIMIT(0, DRM_AUX_MINORS), &next, GFP_KERNEL); > > + if (err < 0) { > > kfree(aux_dev);
On Mon, Feb 25, 2019 at 10:42:46AM -0800, Matthew Wilcox wrote: > On Mon, Feb 25, 2019 at 07:57:33PM +0200, Ville Syrjälä wrote: > > On Thu, Feb 21, 2019 at 10:41:23AM -0800, Matthew Wilcox wrote: > > > @@ -49,8 +49,7 @@ struct drm_dp_aux_dev { > > > > > > #define DRM_AUX_MINORS 256 > > > #define AUX_MAX_OFFSET (1 << 20) > > > -static DEFINE_IDR(aux_idr); > > > -static DEFINE_MUTEX(aux_idr_mutex); > > > +static DEFINE_XARRAY_ALLOC(aux_xa); > > > static struct class *drm_dp_aux_dev_class; > > > static int drm_dev_major = -1; > [...] > > > static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) > > > { > > > + static u32 next; > > > > Is there a particular reason for that being static? > > It needs to maintain its value between function calls so that we know > where to start allocating from the next time we call xa_alloc_cyclic(). > It can either live here with a short name, or we could put it at file > scope with a descriptive name (probably aux_xa_next). It's up to you > which you think is better; it's your driver. File scope would seem a bit more clear to me. I'm slightly worried someone might do some cleanup here and drop the static without thinking. Alterntively a short comment would probably suffice. > > The IDR embedded the 'next' value in the struct idr, but that was > overhead paid by all users of the IDR rather than the very few that > called idr_alloc_cyclic(). > > > > + err = xa_alloc_cyclic(&aux_xa, &aux_dev->index, aux_dev, > > > + XA_LIMIT(0, DRM_AUX_MINORS), &next, GFP_KERNEL); > > > + if (err < 0) { > > > kfree(aux_dev);
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c index 0e4f25d63fd2..393a32976900 100644 --- a/drivers/gpu/drm/drm_dp_aux_dev.c +++ b/drivers/gpu/drm/drm_dp_aux_dev.c @@ -49,8 +49,7 @@ struct drm_dp_aux_dev { #define DRM_AUX_MINORS 256 #define AUX_MAX_OFFSET (1 << 20) -static DEFINE_IDR(aux_idr); -static DEFINE_MUTEX(aux_idr_mutex); +static DEFINE_XARRAY_ALLOC(aux_xa); static struct class *drm_dp_aux_dev_class; static int drm_dev_major = -1; @@ -58,19 +57,21 @@ static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index) { struct drm_dp_aux_dev *aux_dev = NULL; - mutex_lock(&aux_idr_mutex); - aux_dev = idr_find(&aux_idr, index); + xa_lock(&aux_xa); + aux_dev = xa_load(&aux_xa, index); if (!kref_get_unless_zero(&aux_dev->refcount)) aux_dev = NULL; - mutex_unlock(&aux_idr_mutex); + xa_unlock(&aux_xa); return aux_dev; } static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) { + static u32 next; + struct drm_dp_aux_dev *aux_dev; - int index; + int err; aux_dev = kzalloc(sizeof(*aux_dev), GFP_KERNEL); if (!aux_dev) @@ -79,15 +80,12 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) atomic_set(&aux_dev->usecount, 1); kref_init(&aux_dev->refcount); - mutex_lock(&aux_idr_mutex); - index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, - GFP_KERNEL); - mutex_unlock(&aux_idr_mutex); - if (index < 0) { + err = xa_alloc_cyclic(&aux_xa, &aux_dev->index, aux_dev, + XA_LIMIT(0, DRM_AUX_MINORS), &next, GFP_KERNEL); + if (err < 0) { kfree(aux_dev); - return ERR_PTR(index); + return ERR_PTR(err); } - aux_dev->index = index; return aux_dev; } @@ -246,22 +244,19 @@ static const struct file_operations auxdev_fops = { static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_aux(struct drm_dp_aux *aux) { - struct drm_dp_aux_dev *iter, *aux_dev = NULL; - int id; + struct drm_dp_aux_dev *aux_dev; + unsigned long id; /* don't increase kref count here because this function should only be * used by drm_dp_aux_unregister_devnode. Thus, it will always have at * least one reference - the one that drm_dp_aux_register_devnode * created */ - mutex_lock(&aux_idr_mutex); - idr_for_each_entry(&aux_idr, iter, id) { - if (iter->aux == aux) { - aux_dev = iter; + xa_for_each(&aux_xa, id, aux_dev) { + if (aux_dev->aux == aux) break; - } } - mutex_unlock(&aux_idr_mutex); + return aux_dev; } @@ -274,9 +269,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) if (!aux_dev) /* attach must have failed */ return; - mutex_lock(&aux_idr_mutex); - idr_remove(&aux_idr, aux_dev->index); - mutex_unlock(&aux_idr_mutex); + xa_erase(&aux_xa, aux_dev->index); atomic_dec(&aux_dev->usecount); wait_var_event(&aux_dev->usecount, !atomic_read(&aux_dev->usecount));
Signed-off-by: Matthew Wilcox <willy@infradead.org> --- drivers/gpu/drm/drm_dp_aux_dev.c | 41 +++++++++++++------------------- 1 file changed, 17 insertions(+), 24 deletions(-)