drm/vmwgfx: Add an interface to pin a resource v3
For screen targets it appears we need to pin surfaces while they are bound as screen targets, so add a small interface to do that. v2: Always increase pin_count on pin. v3: Add missing reservation sem. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
parent
ee511a835a
commit
ed93394c14
|
@ -113,6 +113,7 @@ struct vmw_resource {
|
||||||
bool backup_dirty; /* Protected by backup buffer reserved */
|
bool backup_dirty; /* Protected by backup buffer reserved */
|
||||||
struct vmw_dma_buffer *backup;
|
struct vmw_dma_buffer *backup;
|
||||||
unsigned long backup_offset;
|
unsigned long backup_offset;
|
||||||
|
unsigned long pin_count; /* Protected by resource reserved */
|
||||||
const struct vmw_res_func *func;
|
const struct vmw_res_func *func;
|
||||||
struct list_head lru_head; /* Protected by the resource lock */
|
struct list_head lru_head; /* Protected by the resource lock */
|
||||||
struct list_head mob_head; /* Protected by @backup reserved */
|
struct list_head mob_head; /* Protected by @backup reserved */
|
||||||
|
@ -941,6 +942,9 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
|
||||||
int vmw_dumb_destroy(struct drm_file *file_priv,
|
int vmw_dumb_destroy(struct drm_file *file_priv,
|
||||||
struct drm_device *dev,
|
struct drm_device *dev,
|
||||||
uint32_t handle);
|
uint32_t handle);
|
||||||
|
extern int vmw_resource_pin(struct vmw_resource *res);
|
||||||
|
extern void vmw_resource_unpin(struct vmw_resource *res);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overlay control - vmwgfx_overlay.c
|
* Overlay control - vmwgfx_overlay.c
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1183,7 +1183,7 @@ void vmw_resource_unreserve(struct vmw_resource *res,
|
||||||
if (new_backup)
|
if (new_backup)
|
||||||
res->backup_offset = new_backup_offset;
|
res->backup_offset = new_backup_offset;
|
||||||
|
|
||||||
if (!res->func->may_evict || res->id == -1)
|
if (!res->func->may_evict || res->id == -1 || res->pin_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
write_lock(&dev_priv->resource_lock);
|
write_lock(&dev_priv->resource_lock);
|
||||||
|
@ -1573,3 +1573,92 @@ void vmw_resource_evict_all(struct vmw_private *dev_priv)
|
||||||
|
|
||||||
mutex_unlock(&dev_priv->cmdbuf_mutex);
|
mutex_unlock(&dev_priv->cmdbuf_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vmw_resource_pin - Add a pin reference on a resource
|
||||||
|
*
|
||||||
|
* @res: The resource to add a pin reference on
|
||||||
|
*
|
||||||
|
* This function adds a pin reference, and if needed validates the resource.
|
||||||
|
* Having a pin reference means that the resource can never be evicted, and
|
||||||
|
* its id will never change as long as there is a pin reference.
|
||||||
|
* This function returns 0 on success and a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int vmw_resource_pin(struct vmw_resource *res)
|
||||||
|
{
|
||||||
|
struct vmw_private *dev_priv = res->dev_priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ttm_write_lock(&dev_priv->reservation_sem, false);
|
||||||
|
mutex_lock(&dev_priv->cmdbuf_mutex);
|
||||||
|
ret = vmw_resource_reserve(res, false);
|
||||||
|
if (ret)
|
||||||
|
goto out_no_reserve;
|
||||||
|
|
||||||
|
if (res->pin_count == 0) {
|
||||||
|
struct ttm_buffer_object *bo = NULL;
|
||||||
|
|
||||||
|
if (res->backup) {
|
||||||
|
bo = &res->backup->base;
|
||||||
|
|
||||||
|
ttm_bo_reserve(bo, false, false, false, NULL);
|
||||||
|
ret = ttm_bo_validate(bo, res->func->backup_placement,
|
||||||
|
false, false);
|
||||||
|
if (ret) {
|
||||||
|
ttm_bo_unreserve(bo);
|
||||||
|
goto out_no_validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we really need to pin the MOB as well? */
|
||||||
|
vmw_bo_pin(bo, true);
|
||||||
|
}
|
||||||
|
ret = vmw_resource_validate(res);
|
||||||
|
if (bo)
|
||||||
|
ttm_bo_unreserve(bo);
|
||||||
|
if (ret)
|
||||||
|
goto out_no_validate;
|
||||||
|
}
|
||||||
|
res->pin_count++;
|
||||||
|
|
||||||
|
out_no_validate:
|
||||||
|
vmw_resource_unreserve(res, NULL, 0UL);
|
||||||
|
out_no_reserve:
|
||||||
|
mutex_unlock(&dev_priv->cmdbuf_mutex);
|
||||||
|
ttm_write_unlock(&dev_priv->reservation_sem);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vmw_resource_unpin - Remove a pin reference from a resource
|
||||||
|
*
|
||||||
|
* @res: The resource to remove a pin reference from
|
||||||
|
*
|
||||||
|
* Having a pin reference means that the resource can never be evicted, and
|
||||||
|
* its id will never change as long as there is a pin reference.
|
||||||
|
*/
|
||||||
|
void vmw_resource_unpin(struct vmw_resource *res)
|
||||||
|
{
|
||||||
|
struct vmw_private *dev_priv = res->dev_priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ttm_read_lock(&dev_priv->reservation_sem, false);
|
||||||
|
mutex_lock(&dev_priv->cmdbuf_mutex);
|
||||||
|
|
||||||
|
ret = vmw_resource_reserve(res, true);
|
||||||
|
WARN_ON(ret);
|
||||||
|
|
||||||
|
WARN_ON(res->pin_count == 0);
|
||||||
|
if (--res->pin_count == 0 && res->backup) {
|
||||||
|
struct ttm_buffer_object *bo = &res->backup->base;
|
||||||
|
|
||||||
|
ttm_bo_reserve(bo, false, false, false, NULL);
|
||||||
|
vmw_bo_pin(bo, false);
|
||||||
|
ttm_bo_unreserve(bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
vmw_resource_unreserve(res, NULL, 0UL);
|
||||||
|
|
||||||
|
mutex_unlock(&dev_priv->cmdbuf_mutex);
|
||||||
|
ttm_read_unlock(&dev_priv->reservation_sem);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue