Message ID | 20240614102548.4364-2-thomas.hellstrom@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TTM shrinker helpers and xe buffer object shrinker | expand |
Hi Thomas, kernel test robot noticed the following build errors: [auto build test ERROR on drm-xe/drm-xe-next] [also build test ERROR on linus/master v6.10-rc3 next-20240613] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Hellstr-m/drm-ttm-Allow-TTM-LRU-list-nodes-of-different-types/20240614-182911 base: https://gitlab.freedesktop.org/drm/xe/kernel.git drm-xe-next patch link: https://lore.kernel.org/r/20240614102548.4364-2-thomas.hellstrom%40linux.intel.com patch subject: [PATCH v4 01/12] drm/ttm: Allow TTM LRU list nodes of different types config: loongarch-randconfig-001-20240615 (https://download.01.org/0day-ci/archive/20240615/202406151512.Smo5bzLx-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240615/202406151512.Smo5bzLx-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202406151512.Smo5bzLx-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from include/linux/build_bug.h:5, from include/linux/container_of.h:5, from include/linux/list.h:5, from include/drm/ttm/ttm_resource.h:29, from drivers/gpu/drm/ttm/tests/ttm_resource_test.c:5: drivers/gpu/drm/ttm/tests/ttm_resource_test.c: In function 'ttm_resource_fini_basic': >> drivers/gpu/drm/ttm/tests/ttm_resource_test.c:201:44: error: passing argument 1 of 'list_empty' from incompatible pointer type [-Werror=incompatible-pointer-types] 201 | KUNIT_ASSERT_TRUE(test, list_empty(&res->lru)); | ^~~~~~~~~ | | | struct ttm_lru_item * include/linux/compiler.h:76:45: note: in definition of macro 'likely' 76 | # define likely(x) __builtin_expect(!!(x), 1) | ^ include/kunit/test.h:668:9: note: in expansion of macro 'KUNIT_UNARY_ASSERTION' 668 | KUNIT_UNARY_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1232:9: note: in expansion of macro 'KUNIT_TRUE_MSG_ASSERTION' 1232 | KUNIT_TRUE_MSG_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1229:9: note: in expansion of macro 'KUNIT_ASSERT_TRUE_MSG' 1229 | KUNIT_ASSERT_TRUE_MSG(test, condition, NULL) | ^~~~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_resource_test.c:201:9: note: in expansion of macro 'KUNIT_ASSERT_TRUE' 201 | KUNIT_ASSERT_TRUE(test, list_empty(&res->lru)); | ^~~~~~~~~~~~~~~~~ include/linux/list.h:371:54: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 371 | static inline int list_empty(const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ cc1: some warnings being treated as errors -- In file included from include/drm/drm_kunit_helpers.h:10, from drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h:13, from drivers/gpu/drm/ttm/tests/ttm_bo_test.c:17: drivers/gpu/drm/ttm/tests/ttm_bo_test.c: In function 'ttm_bo_unreserve_basic': >> drivers/gpu/drm/ttm/tests/ttm_bo_test.c:268:38: error: passing argument 1 of 'list_is_last' from incompatible pointer type [-Werror=incompatible-pointer-types] 268 | list_is_last(&res1->lru, &man->lru[bo->priority]), 1); | ^~~~~~~~~~ | | | struct ttm_lru_item * include/kunit/test.h:707:22: note: in definition of macro 'KUNIT_BASE_BINARY_ASSERTION' 707 | const typeof(left) __left = (left); \ | ^~~~ include/kunit/test.h:1271:9: note: in expansion of macro 'KUNIT_BINARY_INT_ASSERTION' 1271 | KUNIT_BINARY_INT_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1268:9: note: in expansion of macro 'KUNIT_ASSERT_EQ_MSG' 1268 | KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) | ^~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:267:9: note: in expansion of macro 'KUNIT_ASSERT_EQ' 267 | KUNIT_ASSERT_EQ(test, | ^~~~~~~~~~~~~~~ In file included from include/linux/mutex.h:15, from include/linux/ww_mutex.h:20, from include/linux/dma-resv.h:42, from drivers/gpu/drm/ttm/tests/ttm_bo_test.c:5: include/linux/list.h:352:56: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 352 | static inline int list_is_last(const struct list_head *list, const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ >> drivers/gpu/drm/ttm/tests/ttm_bo_test.c:268:38: error: passing argument 1 of 'list_is_last' from incompatible pointer type [-Werror=incompatible-pointer-types] 268 | list_is_last(&res1->lru, &man->lru[bo->priority]), 1); | ^~~~~~~~~~ | | | struct ttm_lru_item * include/kunit/test.h:707:38: note: in definition of macro 'KUNIT_BASE_BINARY_ASSERTION' 707 | const typeof(left) __left = (left); \ | ^~~~ include/kunit/test.h:1271:9: note: in expansion of macro 'KUNIT_BINARY_INT_ASSERTION' 1271 | KUNIT_BINARY_INT_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1268:9: note: in expansion of macro 'KUNIT_ASSERT_EQ_MSG' 1268 | KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) | ^~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:267:9: note: in expansion of macro 'KUNIT_ASSERT_EQ' 267 | KUNIT_ASSERT_EQ(test, | ^~~~~~~~~~~~~~~ include/linux/list.h:352:56: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 352 | static inline int list_is_last(const struct list_head *list, const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c: In function 'ttm_bo_unreserve_pinned': drivers/gpu/drm/ttm/tests/ttm_bo_test.c:305:38: error: passing argument 1 of 'list_is_last' from incompatible pointer type [-Werror=incompatible-pointer-types] 305 | list_is_last(&res2->lru, &priv->ttm_dev->pinned), 1); | ^~~~~~~~~~ | | | struct ttm_lru_item * include/kunit/test.h:707:22: note: in definition of macro 'KUNIT_BASE_BINARY_ASSERTION' 707 | const typeof(left) __left = (left); \ | ^~~~ include/kunit/test.h:1271:9: note: in expansion of macro 'KUNIT_BINARY_INT_ASSERTION' 1271 | KUNIT_BINARY_INT_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1268:9: note: in expansion of macro 'KUNIT_ASSERT_EQ_MSG' 1268 | KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) | ^~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:304:9: note: in expansion of macro 'KUNIT_ASSERT_EQ' 304 | KUNIT_ASSERT_EQ(test, | ^~~~~~~~~~~~~~~ include/linux/list.h:352:56: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 352 | static inline int list_is_last(const struct list_head *list, const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:305:38: error: passing argument 1 of 'list_is_last' from incompatible pointer type [-Werror=incompatible-pointer-types] 305 | list_is_last(&res2->lru, &priv->ttm_dev->pinned), 1); | ^~~~~~~~~~ | | | struct ttm_lru_item * include/kunit/test.h:707:38: note: in definition of macro 'KUNIT_BASE_BINARY_ASSERTION' 707 | const typeof(left) __left = (left); \ | ^~~~ include/kunit/test.h:1271:9: note: in expansion of macro 'KUNIT_BINARY_INT_ASSERTION' 1271 | KUNIT_BINARY_INT_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1268:9: note: in expansion of macro 'KUNIT_ASSERT_EQ_MSG' 1268 | KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) | ^~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:304:9: note: in expansion of macro 'KUNIT_ASSERT_EQ' 304 | KUNIT_ASSERT_EQ(test, | ^~~~~~~~~~~~~~~ include/linux/list.h:352:56: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 352 | static inline int list_is_last(const struct list_head *list, const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:309:38: error: passing argument 1 of 'list_is_last' from incompatible pointer type [-Werror=incompatible-pointer-types] 309 | list_is_last(&res1->lru, &priv->ttm_dev->pinned), 1); | ^~~~~~~~~~ | | | struct ttm_lru_item * include/kunit/test.h:707:22: note: in definition of macro 'KUNIT_BASE_BINARY_ASSERTION' 707 | const typeof(left) __left = (left); \ | ^~~~ include/kunit/test.h:1271:9: note: in expansion of macro 'KUNIT_BINARY_INT_ASSERTION' 1271 | KUNIT_BINARY_INT_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1268:9: note: in expansion of macro 'KUNIT_ASSERT_EQ_MSG' 1268 | KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) | ^~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:308:9: note: in expansion of macro 'KUNIT_ASSERT_EQ' 308 | KUNIT_ASSERT_EQ(test, | ^~~~~~~~~~~~~~~ include/linux/list.h:352:56: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 352 | static inline int list_is_last(const struct list_head *list, const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:309:38: error: passing argument 1 of 'list_is_last' from incompatible pointer type [-Werror=incompatible-pointer-types] 309 | list_is_last(&res1->lru, &priv->ttm_dev->pinned), 1); | ^~~~~~~~~~ | | | struct ttm_lru_item * include/kunit/test.h:707:38: note: in definition of macro 'KUNIT_BASE_BINARY_ASSERTION' 707 | const typeof(left) __left = (left); \ | ^~~~ include/kunit/test.h:1271:9: note: in expansion of macro 'KUNIT_BINARY_INT_ASSERTION' 1271 | KUNIT_BINARY_INT_ASSERTION(test, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~ include/kunit/test.h:1268:9: note: in expansion of macro 'KUNIT_ASSERT_EQ_MSG' 1268 | KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) | ^~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/ttm/tests/ttm_bo_test.c:308:9: note: in expansion of macro 'KUNIT_ASSERT_EQ' 308 | KUNIT_ASSERT_EQ(test, | ^~~~~~~~~~~~~~~ include/linux/list.h:352:56: note: expected 'const struct list_head *' but argument is of type 'struct ttm_lru_item *' 352 | static inline int list_is_last(const struct list_head *list, const struct list_head *head) | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~ vim +/list_empty +201 drivers/gpu/drm/ttm/tests/ttm_resource_test.c 9afc1e0aa4851e Karolina Stolarek 2023-11-29 180 9afc1e0aa4851e Karolina Stolarek 2023-11-29 181 static void ttm_resource_fini_basic(struct kunit *test) 9afc1e0aa4851e Karolina Stolarek 2023-11-29 182 { 9afc1e0aa4851e Karolina Stolarek 2023-11-29 183 struct ttm_resource_test_priv *priv = test->priv; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 184 struct ttm_resource *res; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 185 struct ttm_buffer_object *bo; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 186 struct ttm_place *place; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 187 struct ttm_resource_manager *man; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 188 9afc1e0aa4851e Karolina Stolarek 2023-11-29 189 ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 190 bo = priv->bo; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 191 place = priv->place; 9afc1e0aa4851e Karolina Stolarek 2023-11-29 192 9afc1e0aa4851e Karolina Stolarek 2023-11-29 193 man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 194 9afc1e0aa4851e Karolina Stolarek 2023-11-29 195 res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 196 KUNIT_ASSERT_NOT_NULL(test, res); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 197 9afc1e0aa4851e Karolina Stolarek 2023-11-29 198 ttm_resource_init(bo, place, res); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 199 ttm_resource_fini(man, res); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 200 9afc1e0aa4851e Karolina Stolarek 2023-11-29 @201 KUNIT_ASSERT_TRUE(test, list_empty(&res->lru)); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 202 KUNIT_ASSERT_EQ(test, man->usage, 0); 9afc1e0aa4851e Karolina Stolarek 2023-11-29 203 } 9afc1e0aa4851e Karolina Stolarek 2023-11-29 204
diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 434cf0258000..09411978a13a 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -274,14 +274,14 @@ static void ttm_device_clear_lru_dma_mappings(struct ttm_device *bdev, struct ttm_resource *res; spin_lock(&bdev->lru_lock); - while ((res = list_first_entry_or_null(list, typeof(*res), lru))) { + while ((res = ttm_lru_first_res_or_null(list))) { struct ttm_buffer_object *bo = res->bo; /* Take ref against racing releases once lru_lock is unlocked */ if (!ttm_bo_get_unless_zero(bo)) continue; - list_del_init(&res->lru); + list_del_init(&bo->resource->lru.link); spin_unlock(&bdev->lru_lock); if (bo->ttm) diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 4a66b851b67d..db9a7a3717c4 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -70,8 +70,8 @@ void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) dma_resv_assert_held(pos->last->bo->base.resv); man = ttm_manager_type(pos->first->bo->bdev, i); - list_bulk_move_tail(&man->lru[j], &pos->first->lru, - &pos->last->lru); + list_bulk_move_tail(&man->lru[j], &pos->first->lru.link, + &pos->last->lru.link); } } } @@ -84,14 +84,38 @@ ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res) return &bulk->pos[res->mem_type][res->bo->priority]; } +/* Return the previous resource on the list (skip over non-resource list items) */ +static struct ttm_resource *ttm_lru_prev_res(struct ttm_resource *cur) +{ + struct ttm_lru_item *lru = &cur->lru; + + do { + lru = list_prev_entry(lru, link); + } while (!ttm_lru_item_is_res(lru)); + + return ttm_lru_item_to_res(lru); +} + +/* Return the next resource on the list (skip over non-resource list items) */ +static struct ttm_resource *ttm_lru_next_res(struct ttm_resource *cur) +{ + struct ttm_lru_item *lru = &cur->lru; + + do { + lru = list_next_entry(lru, link); + } while (!ttm_lru_item_is_res(lru)); + + return ttm_lru_item_to_res(lru); +} + /* Move the resource to the tail of the bulk move range */ static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos, struct ttm_resource *res) { if (pos->last != res) { if (pos->first == res) - pos->first = list_next_entry(res, lru); - list_move(&res->lru, &pos->last->lru); + pos->first = ttm_lru_next_res(res); + list_move(&res->lru.link, &pos->last->lru.link); pos->last = res; } } @@ -122,11 +146,11 @@ static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, pos->first = NULL; pos->last = NULL; } else if (pos->first == res) { - pos->first = list_next_entry(res, lru); + pos->first = ttm_lru_next_res(res); } else if (pos->last == res) { - pos->last = list_prev_entry(res, lru); + pos->last = ttm_lru_prev_res(res); } else { - list_move(&res->lru, &pos->last->lru); + list_move(&res->lru.link, &pos->last->lru.link); } } @@ -155,7 +179,7 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res) lockdep_assert_held(&bo->bdev->lru_lock); if (bo->pin_count) { - list_move_tail(&res->lru, &bdev->pinned); + list_move_tail(&res->lru.link, &bdev->pinned); } else if (bo->bulk_move) { struct ttm_lru_bulk_move_pos *pos = @@ -166,7 +190,7 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res) struct ttm_resource_manager *man; man = ttm_manager_type(bdev, res->mem_type); - list_move_tail(&res->lru, &man->lru[bo->priority]); + list_move_tail(&res->lru.link, &man->lru[bo->priority]); } } @@ -197,9 +221,9 @@ void ttm_resource_init(struct ttm_buffer_object *bo, man = ttm_manager_type(bo->bdev, place->mem_type); spin_lock(&bo->bdev->lru_lock); if (bo->pin_count) - list_add_tail(&res->lru, &bo->bdev->pinned); + list_add_tail(&res->lru.link, &bo->bdev->pinned); else - list_add_tail(&res->lru, &man->lru[bo->priority]); + list_add_tail(&res->lru.link, &man->lru[bo->priority]); man->usage += res->size; spin_unlock(&bo->bdev->lru_lock); } @@ -221,7 +245,7 @@ void ttm_resource_fini(struct ttm_resource_manager *man, struct ttm_device *bdev = man->bdev; spin_lock(&bdev->lru_lock); - list_del_init(&res->lru); + list_del_init(&res->lru.link); man->usage -= res->size; spin_unlock(&bdev->lru_lock); } @@ -472,14 +496,16 @@ struct ttm_resource * ttm_resource_manager_first(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor) { - struct ttm_resource *res; + struct ttm_lru_item *lru; 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; + list_for_each_entry(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) + return ttm_lru_item_to_res(lru); + } return NULL; } @@ -498,15 +524,40 @@ ttm_resource_manager_next(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor, struct ttm_resource *res) { + struct ttm_lru_item *lru = &res->lru; + lockdep_assert_held(&man->bdev->lru_lock); - list_for_each_entry_continue(res, &man->lru[cursor->priority], lru) - return res; + list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) + return ttm_lru_item_to_res(lru); + } for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY; ++cursor->priority) - list_for_each_entry(res, &man->lru[cursor->priority], lru) - return res; + list_for_each_entry(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) + ttm_lru_item_to_res(lru); + } + + return NULL; +} + +/** + * ttm_lru_first_res_or_null() - Return the first resource on an lru list + * @head: The list head of the lru list. + * + * Return: Pointer to the first resource on the lru list or NULL if + * there is none. + */ +struct ttm_resource *ttm_lru_first_res_or_null(struct list_head *head) +{ + struct ttm_lru_item *lru; + + list_for_each_entry(lru, head, link) { + if (ttm_lru_item_is_res(lru)) + return ttm_lru_item_to_res(lru); + } return NULL; } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 69769355139f..1511d91e290d 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -49,6 +49,43 @@ struct io_mapping; struct sg_table; struct scatterlist; +/** + * enum ttm_lru_item_type - enumerate ttm_lru_item subclasses + */ +enum ttm_lru_item_type { + /** @TTM_LRU_RESOURCE: The resource subclass */ + TTM_LRU_RESOURCE, + /** @TTM_LRU_HITCH: The iterator hitch subclass */ + TTM_LRU_HITCH +}; + +/** + * struct ttm_lru_item - The TTM lru list node base class + * @link: The list link + * @type: The subclass type + */ +struct ttm_lru_item { + struct list_head link; + enum ttm_lru_item_type type; +}; + +/** + * ttm_lru_item_init() - initialize a struct ttm_lru_item + * @item: The item to initialize + * @type: The subclass type + */ +static inline void ttm_lru_item_init(struct ttm_lru_item *item, + enum ttm_lru_item_type type) +{ + item->type = type; + INIT_LIST_HEAD(&item->link); +} + +static inline bool ttm_lru_item_is_res(const struct ttm_lru_item *item) +{ + return item->type == TTM_LRU_RESOURCE; +} + struct ttm_resource_manager_func { /** * struct ttm_resource_manager_func member alloc @@ -217,9 +254,21 @@ struct ttm_resource { /** * @lru: Least recently used list, see &ttm_resource_manager.lru */ - struct list_head lru; + struct ttm_lru_item lru; }; +/** + * ttm_lru_item_to_res() - Downcast a struct ttm_lru_item to a struct ttm_resource + * @item: The struct ttm_lru_item to downcast + * + * Return: Pointer to the embedding struct ttm_resource + */ +static inline struct ttm_resource * +ttm_lru_item_to_res(struct ttm_lru_item *item) +{ + return container_of(item, struct ttm_resource, lru); +} + /** * struct ttm_resource_cursor * @@ -393,6 +442,9 @@ ttm_resource_manager_next(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor, struct ttm_resource *res); +struct ttm_resource * +ttm_lru_first_res_or_null(struct list_head *head); + /** * ttm_resource_manager_for_each_res - iterate over all resources * @man: the resource manager