From: Qiang Liu <[email protected]> Replace the release_idr + release_idr_lock to an XArray. IDR internally uses xarray so we can use it directly which simplifies our code by removing the need to do external locking.
Signed-off-by: Qiang Liu <[email protected]> --- drivers/gpu/drm/qxl/qxl_drv.h | 6 ++--- drivers/gpu/drm/qxl/qxl_kms.c | 4 +-- drivers/gpu/drm/qxl/qxl_release.c | 45 ++++++++++++++----------------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index cc02b5f10ad9..cf9decf39022 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -35,6 +35,7 @@ #include <linux/firmware.h> #include <linux/platform_device.h> #include <linux/workqueue.h> +#include <linux/xarray.h> #include <drm/drm_crtc.h> #include <drm/drm_encoder.h> @@ -208,11 +209,10 @@ struct qxl_device { struct qxl_memslot surfaces_slot; spinlock_t release_lock; - struct idr release_idr; - uint32_t release_seqno; + struct xarray release_xa; + atomic_t release_seqno; atomic_t release_count; wait_queue_head_t release_event; - spinlock_t release_idr_lock; struct mutex async_io_mutex; unsigned int last_sent_io_cmd; diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 461b7ab9ad5c..0cebaf88f407 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -227,8 +227,8 @@ int qxl_device_init(struct qxl_device *qdev, goto cursor_ring_free; } - idr_init_base(&qdev->release_idr, 1); - spin_lock_init(&qdev->release_idr_lock); + xa_init_flags(&qdev->release_xa, XA_FLAGS_ALLOC1); + atomic_set(&qdev->release_seqno, 0); spin_lock_init(&qdev->release_lock); idr_init_base(&qdev->surf_id_idr, 1); diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 06979d0e8a9f..f24089dd69cc 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -90,6 +90,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type, struct qxl_release *release; int handle; size_t size = sizeof(*release); + int r; release = kmalloc(size, GFP_KERNEL); if (!release) { @@ -102,16 +103,12 @@ qxl_release_alloc(struct qxl_device *qdev, int type, release->surface_release_id = 0; INIT_LIST_HEAD(&release->bos); - idr_preload(GFP_KERNEL); - spin_lock(&qdev->release_idr_lock); - handle = idr_alloc(&qdev->release_idr, release, 1, 0, GFP_NOWAIT); - release->base.seqno = ++qdev->release_seqno; - spin_unlock(&qdev->release_idr_lock); - idr_preload_end(); - if (handle < 0) { + r = xa_alloc(&qdev->release_xa, &handle, release, xa_limit_32b, GFP_NOWAIT); + release->base.seqno = atomic_inc_return(&qdev->release_seqno); + if (r < 0) { kfree(release); *ret = NULL; - return handle; + return r; } *ret = release; DRM_DEBUG_DRIVER("allocated release %d\n", handle); @@ -143,9 +140,7 @@ qxl_release_free(struct qxl_device *qdev, if (release->surface_release_id) qxl_surface_id_dealloc(qdev, release->surface_release_id); - spin_lock(&qdev->release_idr_lock); - idr_remove(&qdev->release_idr, release->id); - spin_unlock(&qdev->release_idr_lock); + xa_erase(&qdev->release_xa, release->id); if (dma_fence_was_initialized(&release->base)) { WARN_ON(list_empty(&release->bos)); @@ -261,14 +256,14 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, struct qxl_release **release) { if (surface_cmd_type == QXL_SURFACE_CMD_DESTROY && create_rel) { - int idr_ret; + int xa_ret; struct qxl_bo *bo; union qxl_release_info *info; /* stash the release after the create command */ - idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release); - if (idr_ret < 0) - return idr_ret; + xa_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release); + if (xa_ret < 0) + return xa_ret; bo = create_rel->release_bo; (*release)->release_bo = bo; @@ -277,7 +272,7 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, qxl_release_list_add(*release, bo); info = qxl_release_map(qdev, *release); - info->id = idr_ret; + info->id = xa_ret; qxl_release_unmap(qdev, *release, info); return 0; } @@ -291,7 +286,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, struct qxl_bo **rbo) { struct qxl_bo *bo, *free_bo = NULL; - int idr_ret; + int xa_ret; int ret = 0; union qxl_release_info *info; int cur_idx; @@ -312,11 +307,11 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, return -EINVAL; } - idr_ret = qxl_release_alloc(qdev, type, release); - if (idr_ret < 0) { + xa_ret = qxl_release_alloc(qdev, type, release); + if (xa_ret < 0) { if (rbo) *rbo = NULL; - return idr_ret; + return xa_ret; } atomic_inc(&qdev->release_count); @@ -362,7 +357,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, } info = qxl_release_map(qdev, *release); - info->id = idr_ret; + info->id = xa_ret; qxl_release_unmap(qdev, *release, info); return ret; @@ -373,11 +368,11 @@ struct qxl_release *qxl_release_from_id_locked(struct qxl_device *qdev, { struct qxl_release *release; - spin_lock(&qdev->release_idr_lock); - release = idr_find(&qdev->release_idr, id); - spin_unlock(&qdev->release_idr_lock); + xa_lock(&qdev->release_xa); + release = xa_load(&qdev->release_xa, id); + xa_unlock(&qdev->release_xa); if (!release) { - DRM_ERROR("failed to find id in release_idr\n"); + DRM_ERROR("failed to find id in release_xa\n"); return NULL; } -- 2.43.0

