Instead of duplicating that at different places add an iterator over all
the resources in a resource manager.

v2: add lockdep annotation and kerneldoc
v3: fix various bugs pointed out by Felix
v4: simplify the code a bit more

Signed-off-by: Christian König <christian.koe...@amd.com>
Tested-by: Bas Nieuwenhuizen <b...@basnieuwenhuizen.nl>
Reviewed-by: Daniel Vetter <daniel.vet...@ffwll.ch> (v2)
Reviewed-by: Felix Kuehling <felix.kuehl...@amd.com>
---
 drivers/gpu/drm/ttm/ttm_bo.c       | 37 ++++++++--------------
 drivers/gpu/drm/ttm/ttm_device.c   | 26 +++++++--------
 drivers/gpu/drm/ttm/ttm_resource.c | 51 ++++++++++++++++++++++++++++++
 include/drm/ttm/ttm_resource.h     | 23 ++++++++++++++
 4 files changed, 99 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index cb0fa932d495..b119af33e7d7 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -579,38 +579,29 @@ int ttm_mem_evict_first(struct ttm_device *bdev,
                        struct ww_acquire_ctx *ticket)
 {
        struct ttm_buffer_object *bo = NULL, *busy_bo = NULL;
+       struct ttm_resource_cursor cursor;
        struct ttm_resource *res;
        bool locked = false;
-       unsigned i;
        int ret;
 
        spin_lock(&bdev->lru_lock);
-       for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
-               list_for_each_entry(res, &man->lru[i], lru) {
-                       bool busy;
+       ttm_resource_manager_for_each_res(man, &cursor, res) {
+               bool busy;
+
+               if (!ttm_bo_evict_swapout_allowable(res->bo, ctx, place,
+                                                   &locked, &busy)) {
+                       if (busy && !busy_bo && ticket !=
+                           dma_resv_locking_ctx(res->bo->base.resv))
+                               busy_bo = res->bo;
+                       continue;
+               }
 
+               if (ttm_bo_get_unless_zero(res->bo)) {
                        bo = res->bo;
-                       if (!ttm_bo_evict_swapout_allowable(bo, ctx, place,
-                                                           &locked, &busy)) {
-                               if (busy && !busy_bo && ticket !=
-                                   dma_resv_locking_ctx(bo->base.resv))
-                                       busy_bo = bo;
-                               continue;
-                       }
-
-                       if (!ttm_bo_get_unless_zero(bo)) {
-                               if (locked)
-                                       dma_resv_unlock(bo->base.resv);
-                               continue;
-                       }
                        break;
                }
-
-               /* If the inner loop terminated early, we have our candidate */
-               if (&res->lru != &man->lru[i])
-                       break;
-
-               bo = NULL;
+               if (locked)
+                       dma_resv_unlock(res->bo->base.resv);
        }
 
        if (!bo) {
diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c
index ba35887147ba..a0562ab386f5 100644
--- a/drivers/gpu/drm/ttm/ttm_device.c
+++ b/drivers/gpu/drm/ttm/ttm_device.c
@@ -142,10 +142,10 @@ EXPORT_SYMBOL(ttm_global_swapout);
 int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,
                       gfp_t gfp_flags)
 {
+       struct ttm_resource_cursor cursor;
        struct ttm_resource_manager *man;
-       struct ttm_buffer_object *bo;
        struct ttm_resource *res;
-       unsigned i, j;
+       unsigned i;
        int ret;
 
        spin_lock(&bdev->lru_lock);
@@ -154,20 +154,16 @@ int ttm_device_swapout(struct ttm_device *bdev, struct 
ttm_operation_ctx *ctx,
                if (!man || !man->use_tt)
                        continue;
 
-               for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) {
-                       list_for_each_entry(res, &man->lru[j], lru) {
-                               uint32_t num_pages;
-
-                               bo = res->bo;
-                               num_pages = PFN_UP(bo->base.size);
+               ttm_resource_manager_for_each_res(man, &cursor, res) {
+                       struct ttm_buffer_object *bo = res->bo;
+                       uint32_t num_pages = PFN_UP(bo->base.size);
 
-                               ret = ttm_bo_swapout(bo, ctx, gfp_flags);
-                               /* ttm_bo_swapout has dropped the lru_lock */
-                               if (!ret)
-                                       return num_pages;
-                               if (ret != -EBUSY)
-                                       return ret;
-                       }
+                       ret = ttm_bo_swapout(bo, ctx, gfp_flags);
+                       /* ttm_bo_swapout has dropped the lru_lock */
+                       if (!ret)
+                               return num_pages;
+                       if (ret != -EBUSY)
+                               return ret;
                }
        }
        spin_unlock(&bdev->lru_lock);
diff --git a/drivers/gpu/drm/ttm/ttm_resource.c 
b/drivers/gpu/drm/ttm/ttm_resource.c
index 8c253b6de6cc..81676c3dbeee 100644
--- a/drivers/gpu/drm/ttm/ttm_resource.c
+++ b/drivers/gpu/drm/ttm/ttm_resource.c
@@ -385,6 +385,57 @@ void ttm_resource_manager_debug(struct 
ttm_resource_manager *man,
 }
 EXPORT_SYMBOL(ttm_resource_manager_debug);
 
+/**
+ * ttm_resource_manager_first
+ *
+ * @man: resource manager to iterate over
+ * @cursor: cursor to record the position
+ *
+ * Returns the first resource from the resource manager.
+ */
+struct ttm_resource *
+ttm_resource_manager_first(struct ttm_resource_manager *man,
+                          struct ttm_resource_cursor *cursor)
+{
+       struct ttm_resource *res;
+
+       lockdep_assert_held(&man->bdev->lru_lock);
+
+       for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY;
+            ++cursor->priority)
+               list_for_each_entry(res, &man->lru[cursor->priority], lru)
+                       return res;
+
+       return NULL;
+}
+
+/**
+ * ttm_resource_manager_next
+ *
+ * @man: resource manager to iterate over
+ * @cursor: cursor to record the position
+ * @res: the current resource pointer
+ *
+ * Returns the next resource from the resource manager.
+ */
+struct ttm_resource *
+ttm_resource_manager_next(struct ttm_resource_manager *man,
+                         struct ttm_resource_cursor *cursor,
+                         struct ttm_resource *res)
+{
+       lockdep_assert_held(&man->bdev->lru_lock);
+
+       list_for_each_entry_continue(res, &man->lru[cursor->priority], lru)
+               return res;
+
+       for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY;
+            ++cursor->priority)
+               list_for_each_entry(res, &man->lru[cursor->priority], lru)
+                       return res;
+
+       return NULL;
+}
+
 static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter,
                                          struct dma_buf_map *dmap,
                                          pgoff_t i)
diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h
index 181e82e3d806..ef0ec700e896 100644
--- a/include/drm/ttm/ttm_resource.h
+++ b/include/drm/ttm/ttm_resource.h
@@ -184,6 +184,17 @@ struct ttm_resource {
        struct list_head lru;
 };
 
+/**
+ * struct ttm_resource_cursor
+ *
+ * @priority: the current priority
+ *
+ * Cursor to iterate over the resources in a manager.
+ */
+struct ttm_resource_cursor {
+       unsigned int priority;
+};
+
 /**
  * struct ttm_lru_bulk_move_pos
  *
@@ -328,6 +339,18 @@ uint64_t ttm_resource_manager_usage(struct 
ttm_resource_manager *man);
 void ttm_resource_manager_debug(struct ttm_resource_manager *man,
                                struct drm_printer *p);
 
+struct ttm_resource *
+ttm_resource_manager_first(struct ttm_resource_manager *man,
+                          struct ttm_resource_cursor *cursor);
+struct ttm_resource *
+ttm_resource_manager_next(struct ttm_resource_manager *man,
+                         struct ttm_resource_cursor *cursor,
+                         struct ttm_resource *res);
+
+#define ttm_resource_manager_for_each_res(man, cursor, res)            \
+       for (res = ttm_resource_manager_first(man, cursor); res;        \
+            res = ttm_resource_manager_next(man, cursor, res))
+
 struct ttm_kmap_iter *
 ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io,
                         struct io_mapping *iomap,
-- 
2.25.1

Reply via email to