Commit ed93394c authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

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: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarSinclair Yeh <syeh@vmware.com>
parent ee511a83
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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
 */
+90 −1
Original line number Diff line number Diff line
@@ -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);
@@ -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);
}