drm/vmwgfx: Assign eviction priorities to resources
TTM provides a means to assign eviction priorities to buffer object. This means that all buffer objects with a lower priority will be evicted first on memory pressure. Use this to make sure surfaces and in particular non-dirty surfaces are evicted first. Evicting in particular shaders, cotables and contexts imply a significant performance hit on vmwgfx, so make sure these resources are evicted last. Some buffer objects are sub-allocated in user-space which means we can have many resources attached to a single buffer object or resource. In that case the buffer object is given the highest priority of the attached resources. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Deepak Rawat <drawat@vmware.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
This commit is contained in:
@@ -34,6 +34,37 @@
|
||||
|
||||
#define VMW_RES_EVICT_ERR_COUNT 10
|
||||
|
||||
/**
|
||||
* vmw_resource_mob_attach - Mark a resource as attached to its backing mob
|
||||
* @res: The resource
|
||||
*/
|
||||
void vmw_resource_mob_attach(struct vmw_resource *res)
|
||||
{
|
||||
struct vmw_buffer_object *backup = res->backup;
|
||||
|
||||
lockdep_assert_held(&backup->base.resv->lock.base);
|
||||
res->used_prio = (res->res_dirty) ? res->func->dirty_prio :
|
||||
res->func->prio;
|
||||
list_add_tail(&res->mob_head, &backup->res_list);
|
||||
vmw_bo_prio_add(backup, res->used_prio);
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_resource_mob_detach - Mark a resource as detached from its backing mob
|
||||
* @res: The resource
|
||||
*/
|
||||
void vmw_resource_mob_detach(struct vmw_resource *res)
|
||||
{
|
||||
struct vmw_buffer_object *backup = res->backup;
|
||||
|
||||
lockdep_assert_held(&backup->base.resv->lock.base);
|
||||
if (vmw_resource_mob_attached(res)) {
|
||||
list_del_init(&res->mob_head);
|
||||
vmw_bo_prio_del(backup, res->used_prio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
|
||||
{
|
||||
kref_get(&res->kref);
|
||||
@@ -80,7 +111,7 @@ static void vmw_resource_release(struct kref *kref)
|
||||
struct ttm_buffer_object *bo = &res->backup->base;
|
||||
|
||||
ttm_bo_reserve(bo, false, false, NULL);
|
||||
if (!list_empty(&res->mob_head) &&
|
||||
if (vmw_resource_mob_attached(res) &&
|
||||
res->func->unbind != NULL) {
|
||||
struct ttm_validate_buffer val_buf;
|
||||
|
||||
@@ -89,7 +120,7 @@ static void vmw_resource_release(struct kref *kref)
|
||||
res->func->unbind(res, false, &val_buf);
|
||||
}
|
||||
res->backup_dirty = false;
|
||||
list_del_init(&res->mob_head);
|
||||
vmw_resource_mob_detach(res);
|
||||
ttm_bo_unreserve(bo);
|
||||
vmw_bo_unreference(&res->backup);
|
||||
}
|
||||
@@ -179,6 +210,7 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
|
||||
res->backup_offset = 0;
|
||||
res->backup_dirty = false;
|
||||
res->res_dirty = false;
|
||||
res->used_prio = 3;
|
||||
if (delay_id)
|
||||
return 0;
|
||||
else
|
||||
@@ -355,14 +387,14 @@ static int vmw_resource_do_validate(struct vmw_resource *res,
|
||||
}
|
||||
|
||||
if (func->bind &&
|
||||
((func->needs_backup && list_empty(&res->mob_head) &&
|
||||
((func->needs_backup && !vmw_resource_mob_attached(res) &&
|
||||
val_buf->bo != NULL) ||
|
||||
(!func->needs_backup && val_buf->bo != NULL))) {
|
||||
ret = func->bind(res, val_buf);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_bind_failed;
|
||||
if (func->needs_backup)
|
||||
list_add_tail(&res->mob_head, &res->backup->res_list);
|
||||
vmw_resource_mob_attach(res);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -402,15 +434,13 @@ void vmw_resource_unreserve(struct vmw_resource *res,
|
||||
|
||||
if (switch_backup && new_backup != res->backup) {
|
||||
if (res->backup) {
|
||||
lockdep_assert_held(&res->backup->base.resv->lock.base);
|
||||
list_del_init(&res->mob_head);
|
||||
vmw_resource_mob_detach(res);
|
||||
vmw_bo_unreference(&res->backup);
|
||||
}
|
||||
|
||||
if (new_backup) {
|
||||
res->backup = vmw_bo_reference(new_backup);
|
||||
lockdep_assert_held(&new_backup->base.resv->lock.base);
|
||||
list_add_tail(&res->mob_head, &new_backup->res_list);
|
||||
vmw_resource_mob_attach(res);
|
||||
} else {
|
||||
res->backup = NULL;
|
||||
}
|
||||
@@ -469,7 +499,7 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket,
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_reserve;
|
||||
|
||||
if (res->func->needs_backup && list_empty(&res->mob_head))
|
||||
if (res->func->needs_backup && !vmw_resource_mob_attached(res))
|
||||
return 0;
|
||||
|
||||
backup_dirty = res->backup_dirty;
|
||||
@@ -574,11 +604,11 @@ static int vmw_resource_do_evict(struct ww_acquire_ctx *ticket,
|
||||
return ret;
|
||||
|
||||
if (unlikely(func->unbind != NULL &&
|
||||
(!func->needs_backup || !list_empty(&res->mob_head)))) {
|
||||
(!func->needs_backup || vmw_resource_mob_attached(res)))) {
|
||||
ret = func->unbind(res, res->res_dirty, &val_buf);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_unbind;
|
||||
list_del_init(&res->mob_head);
|
||||
vmw_resource_mob_detach(res);
|
||||
}
|
||||
ret = func->destroy(res);
|
||||
res->backup_dirty = true;
|
||||
@@ -660,7 +690,7 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr)
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_validate;
|
||||
else if (!res->func->needs_backup && res->backup) {
|
||||
list_del_init(&res->mob_head);
|
||||
WARN_ON_ONCE(vmw_resource_mob_attached(res));
|
||||
vmw_bo_unreference(&res->backup);
|
||||
}
|
||||
|
||||
@@ -699,7 +729,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo)
|
||||
(void) res->func->unbind(res, res->res_dirty, &val_buf);
|
||||
res->backup_dirty = true;
|
||||
res->res_dirty = false;
|
||||
list_del_init(&res->mob_head);
|
||||
vmw_resource_mob_detach(res);
|
||||
}
|
||||
|
||||
(void) ttm_bo_wait(&vbo->base, false, false);
|
||||
|
Reference in New Issue
Block a user