diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 13a0254b59a1..3abd432a4b85 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -238,9 +238,8 @@ struct qxl_device {
 	uint64_t	va_slot_mask;
 
 	spinlock_t	release_lock;
-	struct idr	release_idr;
+	struct xarray	releases;
 	uint32_t	release_seqno;
-	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 15238a413f9d..b2cc71c95142 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -247,8 +247,7 @@ int qxl_device_init(struct qxl_device *qdev,
 		goto release_ring_free;
 	}
 
-	idr_init(&qdev->release_idr);
-	spin_lock_init(&qdev->release_idr_lock);
+	xa_init_flags(&qdev->releases, XA_FLAGS_ALLOC1);
 	spin_lock_init(&qdev->release_lock);
 
 	idr_init(&qdev->surf_id_idr);
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index 30f85f0130cb..a1a42662ebf4 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -121,7 +121,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
 		  struct qxl_release **ret)
 {
 	struct qxl_release *release;
-	int handle;
+	int err;
 	size_t size = sizeof(*release);
 
 	release = kmalloc(size, GFP_KERNEL);
@@ -135,21 +135,19 @@ 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);
+	xa_lock(&qdev->releases);
+	err = __xa_alloc(&qdev->releases, &release->id, release, xa_limit_31b,
+			GFP_KERNEL);
 	release->base.seqno = ++qdev->release_seqno;
-	spin_unlock(&qdev->release_idr_lock);
-	idr_preload_end();
-	if (handle < 0) {
+	xa_unlock(&qdev->releases);
+	if (err < 0) {
 		kfree(release);
 		*ret = NULL;
-		return handle;
+		return err;
 	}
 	*ret = release;
-	DRM_DEBUG_DRIVER("allocated release %d\n", handle);
-	release->id = handle;
-	return handle;
+	DRM_DEBUG_DRIVER("allocated release %d\n", release->id);
+	return release->id;
 }
 
 static void
@@ -178,9 +176,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->releases, release->id);
 
 	if (release->base.ops) {
 		WARN_ON(list_empty(&release->bos));
@@ -288,14 +284,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 id;
 		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;
+		id = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
+		if (id < 0)
+			return id;
 		bo = create_rel->release_bo;
 
 		(*release)->release_bo = bo;
@@ -304,7 +300,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 = id;
 		qxl_release_unmap(qdev, *release, info);
 		return 0;
 	}
@@ -318,7 +314,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
 				       struct qxl_bo **rbo)
 {
 	struct qxl_bo *bo;
-	int idr_ret;
+	int id;
 	int ret = 0;
 	union qxl_release_info *info;
 	int cur_idx;
@@ -334,11 +330,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) {
+	id = qxl_release_alloc(qdev, type, release);
+	if (id < 0) {
 		if (rbo)
 			*rbo = NULL;
-		return idr_ret;
+		return id;
 	}
 
 	mutex_lock(&qdev->release_mutex);
@@ -375,7 +371,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 = id;
 	qxl_release_unmap(qdev, *release, info);
 
 	return ret;
@@ -386,13 +382,9 @@ 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);
-	if (!release) {
-		DRM_ERROR("failed to find id in release_idr\n");
-		return NULL;
-	}
+	release = xa_load(&qdev->releases, id);
+	if (!release)
+		DRM_ERROR("failed to find id in releases\n");
 
 	return release;
 }
