]> www.infradead.org Git - users/willy/xarray.git/commitdiff
drm/i915: Convert get_page to XArray
authorMatthew Wilcox <willy@infradead.org>
Wed, 24 Oct 2018 19:33:54 +0000 (15:33 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 8 Aug 2019 03:39:33 +0000 (23:39 -0400)
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 <willy@infradead.org>
drivers/gpu/drm/i915/gem/i915_gem_object.c
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gem/i915_gem_pages.c

index 41fb6422ddc551f5a9700b327eb3717a3fedcc5c..db43fbb2dc5900dec0d33c33a01fc78fe2e5ffbf 100644 (file)
@@ -75,7 +75,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
                                 NULL, 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);
 }
 
index 18bf4f8d6d809a169199f01e1d2703787def2bfb..9d2b9191a1930f0fbacf046e68c570bc1a2e410f 100644 (file)
@@ -198,7 +198,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;
 
index 65eb430cedba050caa9d7442407b76a2af55e95a..10d8fe4b9d349c67afa9e8f65d0b4745c319dda6 100644 (file)
@@ -141,13 +141,7 @@ void i915_gem_object_writeback(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);
 }
 
 struct sg_table *
@@ -394,8 +388,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
@@ -410,7 +404,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;
@@ -420,24 +414,21 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
        while (idx + count <= n) {
                void *entry;
                unsigned long i;
-               int ret;
+               const gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;
 
                /* 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) == 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, sg, gfp) ==
+                                       XA_ERROR(-ENOMEM))
                                goto scan;
                }
 
@@ -455,7 +446,7 @@ scan:
        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) {
@@ -470,11 +461,11 @@ scan:
 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.
@@ -483,7 +474,7 @@ lookup:
        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;