@@ -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;
@@ -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"
@@ -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;
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/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(-)