diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1b7663258f42..5dd79453c525 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1805,7 +1805,7 @@ struct drm_i915_private {
 
 		/*
 		 * Lock associated with adding/modifying/removing OA configs
-		 * in dev_priv->perf.metrics_idr.
+		 * in dev_priv->perf.configs.
 		 */
 		struct mutex metrics_lock;
 
@@ -1813,7 +1813,7 @@ struct drm_i915_private {
 		 * List of dynamic configurations, you need to hold
 		 * dev_priv->perf.metrics_lock to access it.
 		 */
-		struct idr metrics_idr;
+		struct xarray configs;
 
 		/*
 		 * Lock associated with anything below within this structure
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 2b2eb57ca71f..8a053772a11e 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -400,7 +400,7 @@ static int get_oa_config(struct drm_i915_private *dev_priv,
 	if (ret)
 		return ret;
 
-	*out_config = idr_find(&dev_priv->perf.metrics_idr, metrics_set);
+	*out_config = xa_load(&dev_priv->perf.configs, metrics_set);
 	if (!*out_config)
 		ret = -EINVAL;
 	else
@@ -3142,7 +3142,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_perf_oa_config *args = data;
 	struct i915_oa_config *oa_config, *tmp;
-	int err, id;
+	unsigned long id;
+	int err;
 
 	if (!dev_priv->perf.initialized) {
 		DRM_DEBUG("i915 perf interface not available for this system\n");
@@ -3238,7 +3239,7 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
 	/* We shouldn't have too many configs, so this iteration shouldn't be
 	 * too costly.
 	 */
-	idr_for_each_entry(&dev_priv->perf.metrics_idr, tmp, id) {
+	xa_for_each(&dev_priv->perf.configs, id, tmp) {
 		if (!strcmp(tmp->uuid, oa_config->uuid)) {
 			DRM_DEBUG("OA config already exists with this uuid\n");
 			err = -EADDRINUSE;
@@ -3253,12 +3254,10 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
 	}
 
 	/* Config id 0 is invalid, id 1 for kernel stored test config. */
-	oa_config->id = idr_alloc(&dev_priv->perf.metrics_idr,
-				  oa_config, 2,
-				  0, GFP_KERNEL);
-	if (oa_config->id < 0) {
+	err = xa_alloc(&dev_priv->perf.configs, &oa_config->id, oa_config,
+			XA_LIMIT(2, UINT_MAX), GFP_KERNEL);
+	if (err < 0) {
 		DRM_DEBUG("Failed to create sysfs entry for OA config\n");
-		err = oa_config->id;
 		goto sysfs_err;
 	}
 
@@ -3309,7 +3308,7 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
 	if (ret)
 		goto lock_err;
 
-	oa_config = idr_find(&dev_priv->perf.metrics_idr, *arg);
+	oa_config = xa_erase(&dev_priv->perf.configs, *arg);
 	if (!oa_config) {
 		DRM_DEBUG("Failed to remove unknown OA config\n");
 		ret = -ENOENT;
@@ -3321,8 +3320,6 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
 	sysfs_remove_group(dev_priv->perf.metrics_kobj,
 			   &oa_config->sysfs_metric);
 
-	idr_remove(&dev_priv->perf.metrics_idr, *arg);
-
 	DRM_DEBUG("Removed config %s id=%i\n", oa_config->uuid, oa_config->id);
 
 	put_oa_config(dev_priv, oa_config);
@@ -3475,33 +3472,27 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
 		dev_priv->perf.sysctl_header = register_sysctl_table(dev_root);
 
 		mutex_init(&dev_priv->perf.metrics_lock);
-		idr_init(&dev_priv->perf.metrics_idr);
+		xa_init_flags(&dev_priv->perf.configs, XA_FLAGS_ALLOC);
 
 		dev_priv->perf.initialized = true;
 	}
 }
 
-static int destroy_config(int id, void *p, void *data)
-{
-	struct drm_i915_private *dev_priv = data;
-	struct i915_oa_config *oa_config = p;
-
-	put_oa_config(dev_priv, oa_config);
-
-	return 0;
-}
-
 /**
  * i915_perf_fini - Counter part to i915_perf_init()
  * @dev_priv: i915 device instance
  */
 void i915_perf_fini(struct drm_i915_private *dev_priv)
 {
+	struct i915_oa_config *oa_config;
+	unsigned long index;
+
 	if (!dev_priv->perf.initialized)
 		return;
 
-	idr_for_each(&dev_priv->perf.metrics_idr, destroy_config, dev_priv);
-	idr_destroy(&dev_priv->perf.metrics_idr);
+	xa_for_each(&dev_priv->perf.configs, index, oa_config)
+		put_oa_config(dev_priv, oa_config);
+	xa_destroy(&dev_priv->perf.configs);
 
 	unregister_sysctl_table(dev_priv->perf.sysctl_header);
 
