Signed-off-by: Matthew Wilcox <wi...@infradead.org>
---
 drivers/gpu/drm/qxl/qxl_cmd.c | 60 ++++++++++++-----------------------
 drivers/gpu/drm/qxl/qxl_drv.h |  3 +-
 drivers/gpu/drm/qxl/qxl_kms.c |  5 +--
 3 files changed, 23 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index dffc5093ff16..afe8079453af 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -420,41 +420,27 @@ void qxl_io_monitors_config(struct qxl_device *qdev)
 int qxl_surface_id_alloc(struct qxl_device *qdev,
                      struct qxl_bo *surf)
 {
-       uint32_t handle;
-       int idr_ret;
-       int count = 0;
+       int ret;
 again:
-       idr_preload(GFP_ATOMIC);
-       spin_lock(&qdev->surf_id_idr_lock);
-       idr_ret = idr_alloc(&qdev->surf_id_idr, NULL, 1, 0, GFP_NOWAIT);
-       spin_unlock(&qdev->surf_id_idr_lock);
-       idr_preload_end();
-       if (idr_ret < 0)
-               return idr_ret;
-       handle = idr_ret;
-
-       if (handle >= qdev->rom->n_surfaces) {
-               count++;
-               spin_lock(&qdev->surf_id_idr_lock);
-               idr_remove(&qdev->surf_id_idr, handle);
-               spin_unlock(&qdev->surf_id_idr_lock);
+       ret = xa_alloc(&qdev->surfaces, &surf->surface_id, NULL,
+                       XA_LIMIT(0, qdev->rom->n_surfaces - 1), GFP_ATOMIC);
+       if (ret == -EBUSY) {
                qxl_reap_surface_id(qdev, 2);
                goto again;
        }
-       surf->surface_id = handle;
+       if (ret < 0)
+               return ret;
 
-       spin_lock(&qdev->surf_id_idr_lock);
-       qdev->last_alloced_surf_id = handle;
-       spin_unlock(&qdev->surf_id_idr_lock);
+       xa_lock(&qdev->surfaces);
+       qdev->last_alloced_surf_id = surf->surface_id;
+       xa_unlock(&qdev->surfaces);
        return 0;
 }
 
 void qxl_surface_id_dealloc(struct qxl_device *qdev,
                            uint32_t surface_id)
 {
-       spin_lock(&qdev->surf_id_idr_lock);
-       idr_remove(&qdev->surf_id_idr, surface_id);
-       spin_unlock(&qdev->surf_id_idr_lock);
+       xa_erase(&qdev->surfaces, surface_id);
 }
 
 int qxl_hw_surface_alloc(struct qxl_device *qdev,
@@ -507,9 +493,7 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
        qxl_release_fence_buffer_objects(release);
 
        surf->hw_surf_alloc = true;
-       spin_lock(&qdev->surf_id_idr_lock);
-       idr_replace(&qdev->surf_id_idr, surf, surf->surface_id);
-       spin_unlock(&qdev->surf_id_idr_lock);
+       xa_store(&qdev->surfaces, surf->surface_id, surf, GFP_KERNEL);
        return 0;
 }
 
@@ -531,10 +515,8 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev,
                return ret;
 
        surf->surf_create = NULL;
-       /* remove the surface from the idr, but not the surface id yet */
-       spin_lock(&qdev->surf_id_idr_lock);
-       idr_replace(&qdev->surf_id_idr, NULL, surf->surface_id);
-       spin_unlock(&qdev->surf_id_idr_lock);
+       /* remove the surface from the array, but don't free the surface id */
+       xa_store(&qdev->surfaces, surf->surface_id, NULL, 0);
        surf->hw_surf_alloc = false;
 
        id = surf->surface_id;
@@ -623,20 +605,20 @@ static int qxl_reap_surface_id(struct qxl_device *qdev, 
int max_to_reap)
        mutex_lock(&qdev->surf_evict_mutex);
 again:
 
-       spin_lock(&qdev->surf_id_idr_lock);
+       xa_lock(&qdev->surfaces);
        start = qdev->last_alloced_surf_id + 1;
-       spin_unlock(&qdev->surf_id_idr_lock);
+       xa_unlock(&qdev->surfaces);
 
        for (i = start; i < start + qdev->rom->n_surfaces; i++) {
                void *objptr;
                int surfid = i % qdev->rom->n_surfaces;
 
-               /* this avoids the case where the objects is in the
-                  idr but has been evicted half way - its makes
-                  the idr lookup atomic with the eviction */
-               spin_lock(&qdev->surf_id_idr_lock);
-               objptr = idr_find(&qdev->surf_id_idr, surfid);
-               spin_unlock(&qdev->surf_id_idr_lock);
+               /* this avoids the case where the object is in the
+                  array but has been evicted half way - it makes
+                  the array lookup atomic with the eviction */
+               xa_lock(&qdev->surfaces);
+               objptr = xa_load(&qdev->surfaces, surfid);
+               xa_unlock(&qdev->surfaces);
 
                if (!objptr)
                        continue;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 3abd432a4b85..8d0254a133dc 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -260,8 +260,7 @@ struct qxl_device {
 
        struct mutex            update_area_mutex;
 
-       struct idr      surf_id_idr;
-       spinlock_t surf_id_idr_lock;
+       struct xarray   surfaces;
        int last_alloced_surf_id;
 
        struct mutex surf_evict_mutex;
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index b2cc71c95142..dafdb61f7a32 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -249,10 +249,7 @@ int qxl_device_init(struct qxl_device *qdev,
 
        xa_init_flags(&qdev->releases, XA_FLAGS_ALLOC1);
        spin_lock_init(&qdev->release_lock);
-
-       idr_init(&qdev->surf_id_idr);
-       spin_lock_init(&qdev->surf_id_idr_lock);
-
+       xa_init_flags(&qdev->surfaces, XA_FLAGS_ALLOC1);
        mutex_init(&qdev->async_io_mutex);
 
        /* reset the device into a known state - no memslots, no primary
-- 
2.20.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to