This initially seemed like an ideal use-case for the store_range
functionality, but there's no easy way to determine where we were
relative to the base of the entry.  So this is a straightforward
conversion which doesn't even touch the locking.

Signed-off-by: Matthew Wilcox <wi...@infradead.org>
---
 drivers/gpu/drm/i915/i915_gem.c         | 38 ++++++++++---------------
 drivers/gpu/drm/i915/i915_gem_context.h |  2 +-
 drivers/gpu/drm/i915/i915_gem_object.h  |  4 +--
 3 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0cdccc886587..f8c36c2d32c2 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2428,13 +2428,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object 
*obj,
 
 static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj)
 {
-       struct radix_tree_iter iter;
-       void __rcu **slot;
-
-       rcu_read_lock();
-       radix_tree_for_each_slot(slot, &obj->mm.get_page.radix, &iter, 0)
-               radix_tree_delete(&obj->mm.get_page.radix, iter.index);
-       rcu_read_unlock();
+       xa_destroy(&obj->mm.get_page.xa);
 }
 
 static struct sg_table *
@@ -4716,7 +4710,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
        init_request_active(&obj->frontbuffer_write, frontbuffer_retire);
 
        obj->mm.madv = I915_MADV_WILLNEED;
-       INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
+       xa_init(&obj->mm.get_page.xa);
        mutex_init(&obj->mm.get_page.lock);
 
        i915_gem_info_add_obj(to_i915(obj->base.dev), obj->base.size);
@@ -6073,8 +6067,8 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
        GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
        GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
 
-       /* As we iterate forward through the sg, we record each entry in a
-        * radixtree for quick repeated (backwards) lookups. If we have seen
+       /* As we iterate forward through the sg, we record each entry in an
+        * xarray for quick repeated (backwards) lookups. If we have seen
         * this index previously, we will have an entry for it.
         *
         * Initial lookup is O(N), but this is amortized to O(1) for
@@ -6089,7 +6083,7 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 
        /* We prefer to reuse the last sg so that repeated lookup of this
         * (or the subsequent) sg are fast - comparing against the last
-        * sg is faster than going through the radixtree.
+        * sg is faster than going through the xarray.
         */
 
        sg = iter->sg_pos;
@@ -6099,24 +6093,22 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
        while (idx + count <= n) {
                void *entry;
                unsigned long i;
-               int ret;
 
                /* If we cannot allocate and insert this entry, or the
                 * individual pages from this range, cancel updating the
                 * sg_idx so that on this lookup we are forced to linearly
                 * scan onwards, but on future lookups we will try the
-                * insertion again (in which case we need to be careful of
-                * the error return reporting that we have already inserted
-                * this index).
+                * insertion again.
                 */
-               ret = radix_tree_insert(&iter->radix, idx, sg);
-               if (ret && ret != -EEXIST)
+               if (xa_store(&iter->xa, idx, sg, GFP_KERNEL | __GFP_NOWARN)
+                               == XA_ERROR(-ENOMEM))
                        goto scan;
 
                entry = xa_mk_value(idx);
                for (i = 1; i < count; i++) {
-                       ret = radix_tree_insert(&iter->radix, idx + i, entry);
-                       if (ret && ret != -EEXIST)
+                       if (xa_store(&iter->xa, idx + i, entry,
+                                       GFP_KERNEL | __GFP_NOWARN)
+                                               == XA_ERROR(-ENOMEM))
                                goto scan;
                }
 
@@ -6134,7 +6126,7 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
        if (unlikely(n < idx)) /* insertion completed by another thread */
                goto lookup;
 
-       /* In case we failed to insert the entry into the radixtree, we need
+       /* In case we failed to insert the entry into the xarray, we need
         * to look beyond the current sg.
         */
        while (idx + count <= n) {
@@ -6149,11 +6141,11 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 lookup:
        rcu_read_lock();
 
-       sg = radix_tree_lookup(&iter->radix, n);
+       sg = xa_load(&iter->xa, n);
        GEM_BUG_ON(!sg);
 
        /* If this index is in the middle of multi-page sg entry,
-        * the radix tree will contain a value entry that points
+        * the xarray will contain a value entry that points
         * to the start of that range. We will return the pointer to
         * the base page and the offset of this page within the
         * sg entry's range.
@@ -6162,7 +6154,7 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
        if (unlikely(xa_is_value(sg))) {
                unsigned long base = xa_to_value(sg);
 
-               sg = radix_tree_lookup(&iter->radix, base);
+               sg = xa_load(&iter->xa, base);
                GEM_BUG_ON(!sg);
 
                *offset = n - base;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h 
b/drivers/gpu/drm/i915/i915_gem_context.h
index ec22de370a22..052ad66a5bae 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -27,7 +27,7 @@
 
 #include <linux/bitops.h>
 #include <linux/list.h>
-#include <linux/radix-tree.h>
+#include <linux/xarray.h>
 
 #include "i915_gem.h"
 #include "i915_scheduler.h"
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h 
b/drivers/gpu/drm/i915/i915_gem_object.h
index 7f6493229f50..9febe70b4da9 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -40,7 +40,7 @@ struct drm_i915_gem_object;
 
 /*
  * struct i915_lut_handle tracks the fast lookups from handle to vma used
- * for execbuf. Although we use a radixtree for that mapping, in order to
+ * for execbuf. Although we use an xarray for that mapping, in order to
  * remove them as the object or context is closed, we need a secondary list
  * and a translation entry (i915_lut_handle).
  */
@@ -218,7 +218,7 @@ struct drm_i915_gem_object {
                        struct scatterlist *sg_pos;
                        unsigned int sg_idx; /* in pages, but 32bit eek! */
 
-                       struct radix_tree_root radix;
+                       struct xarray xa;
                        struct mutex lock; /* protects this cache */
                } get_page;
 
-- 
2.20.1

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

Reply via email to