drm/ttm: add resource iterator v4
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.koenig@amd.com> Tested-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2) Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-2-christian.koenig@amd.com
This commit is contained in:
parent
6a9b028994
commit
5d05b988f1
|
@ -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;
|
||||
|
||||
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 (!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 the inner loop terminated early, we have our candidate */
|
||||
if (&res->lru != &man->lru[i])
|
||||
if (ttm_bo_get_unless_zero(res->bo)) {
|
||||
bo = res->bo;
|
||||
break;
|
||||
|
||||
bo = NULL;
|
||||
}
|
||||
if (locked)
|
||||
dma_resv_unlock(res->bo->base.resv);
|
||||
}
|
||||
|
||||
if (!bo) {
|
||||
|
|
|
@ -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;
|
||||
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);
|
||||
|
||||
bo = res->bo;
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -188,6 +188,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
|
||||
*
|
||||
|
@ -333,6 +344,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,
|
||||
|
|
Loading…
Reference in New Issue