Skip to content

Commit

Permalink
drm/vmwgfx: Add an interface to pin a resource v3
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Thomas Hellstrom committed Aug 5, 2015
1 parent ee511a8 commit ed93394
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
4 changes: 4 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ struct vmw_resource {
bool backup_dirty; /* Protected by backup buffer reserved */
struct vmw_dma_buffer *backup;
unsigned long backup_offset;
unsigned long pin_count; /* Protected by resource reserved */
const struct vmw_res_func *func;
struct list_head lru_head; /* Protected by the resource lock */
struct list_head mob_head; /* Protected by @backup reserved */
Expand Down Expand Up @@ -941,6 +942,9 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
int vmw_dumb_destroy(struct drm_file *file_priv,
struct drm_device *dev,
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
*/
Expand Down
91 changes: 90 additions & 1 deletion drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ void vmw_resource_unreserve(struct vmw_resource *res,
if (new_backup)
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;

write_lock(&dev_priv->resource_lock);
Expand Down Expand Up @@ -1573,3 +1573,92 @@ void vmw_resource_evict_all(struct vmw_private *dev_priv)

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);
}

0 comments on commit ed93394

Please sign in to comment.