From: Matthew Wilcox Date: Thu, 14 Feb 2019 17:52:19 +0000 (-0500) Subject: drm/qxl: Convert surf_id_idr to XArray X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8ba62728aade3166d3464bcfd64667f899f6d68f;p=users%2Fwilly%2Fxarray.git drm/qxl: Convert surf_id_idr to XArray Signed-off-by: Matthew Wilcox --- diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 0a2e51af12308..9cd5b342c6faa 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -424,41 +424,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, @@ -501,9 +487,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; } @@ -525,10 +509,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; @@ -617,20 +599,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 66df823209151..76e5a4d925333 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -255,8 +255,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 e649bad39cd65..19a83e000e345 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -239,10 +239,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