Commit 64ad2abf authored by Thomas Hellstrom's avatar Thomas Hellstrom

drm/vmwgfx: Adapt validation code for reference-free lookups

Adapt the validation code so that vmw_validation_add[res|bo] can be called
under an rcu read lock (non-sleeping) and with rcu-only protected resource-
or buffer object pointers.
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarSinclair Yeh <syeh@vmware.com>
parent 24dc64c1
...@@ -94,11 +94,12 @@ struct vmw_validation_res_node { ...@@ -94,11 +94,12 @@ struct vmw_validation_res_node {
* *
* Return: Pointer to the allocated memory on success. NULL on failure. * Return: Pointer to the allocated memory on success. NULL on failure.
*/ */
void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, size_t size) void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
unsigned int size)
{ {
void *addr; void *addr;
size = ALIGN(size, sizeof(long)); size = vmw_validation_align(size);
if (size > PAGE_SIZE) if (size > PAGE_SIZE)
return NULL; return NULL;
...@@ -262,7 +263,9 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, ...@@ -262,7 +263,9 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,
} }
} }
val_buf = &bo_node->base; val_buf = &bo_node->base;
val_buf->bo = ttm_bo_reference(&vbo->base); val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);
if (!val_buf->bo)
return -ESRCH;
val_buf->shared = false; val_buf->shared = false;
list_add_tail(&val_buf->head, &ctx->bo_list); list_add_tail(&val_buf->head, &ctx->bo_list);
bo_node->as_mob = as_mob; bo_node->as_mob = as_mob;
...@@ -313,7 +316,10 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx, ...@@ -313,7 +316,10 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
return ret; return ret;
} }
} }
node->res = vmw_resource_reference(res); node->res = vmw_resource_reference_unless_doomed(res);
if (!node->res)
return -ESRCH;
node->first_usage = 1; node->first_usage = 1;
if (!res->dev_priv->has_mob) { if (!res->dev_priv->has_mob) {
list_add_tail(&node->head, &ctx->resource_list); list_add_tail(&node->head, &ctx->resource_list);
...@@ -715,3 +721,50 @@ void vmw_validation_done(struct vmw_validation_context *ctx, ...@@ -715,3 +721,50 @@ void vmw_validation_done(struct vmw_validation_context *ctx,
mutex_unlock(ctx->res_mutex); mutex_unlock(ctx->res_mutex);
vmw_validation_unref_lists(ctx); vmw_validation_unref_lists(ctx);
} }
/**
* vmw_validation_preload_bo - Preload the validation memory allocator for a
* call to vmw_validation_add_bo().
* @ctx: Pointer to the validation context.
*
* Iff this function returns successfully, the next call to
* vmw_validation_add_bo() is guaranteed not to sleep. An error is not fatal
* but voids the guarantee.
*
* Returns: Zero if successful, %-EINVAL otherwise.
*/
int vmw_validation_preload_bo(struct vmw_validation_context *ctx)
{
unsigned int size = sizeof(struct vmw_validation_bo_node);
if (!vmw_validation_mem_alloc(ctx, size))
return -ENOMEM;
ctx->mem_size_left += size;
return 0;
}
/**
* vmw_validation_preload_res - Preload the validation memory allocator for a
* call to vmw_validation_add_res().
* @ctx: Pointer to the validation context.
* @size: Size of the validation node extra data. See below.
*
* Iff this function returns successfully, the next call to
* vmw_validation_add_res() with the same or smaller @size is guaranteed not to
* sleep. An error is not fatal but voids the guarantee.
*
* Returns: Zero if successful, %-EINVAL otherwise.
*/
int vmw_validation_preload_res(struct vmw_validation_context *ctx,
unsigned int size)
{
size = vmw_validation_align(sizeof(struct vmw_validation_res_node) +
size) +
vmw_validation_align(sizeof(struct vmw_validation_bo_node));
if (!vmw_validation_mem_alloc(ctx, size))
return -ENOMEM;
ctx->mem_size_left += size;
return 0;
}
...@@ -177,6 +177,18 @@ vmw_validation_context_init(struct vmw_validation_context *ctx) ...@@ -177,6 +177,18 @@ vmw_validation_context_init(struct vmw_validation_context *ctx)
INIT_LIST_HEAD(&ctx->bo_list); INIT_LIST_HEAD(&ctx->bo_list);
} }
/**
* vmw_validation_align - Align a validation memory allocation
* @val: The size to be aligned
*
* Returns: @val aligned to the granularity used by the validation memory
* allocator.
*/
static inline unsigned int vmw_validation_align(unsigned int val)
{
return ALIGN(val, sizeof(long));
}
int vmw_validation_add_bo(struct vmw_validation_context *ctx, int vmw_validation_add_bo(struct vmw_validation_context *ctx,
struct vmw_buffer_object *vbo, struct vmw_buffer_object *vbo,
bool as_mob, bool cpu_blit); bool as_mob, bool cpu_blit);
...@@ -207,6 +219,9 @@ void vmw_validation_revert(struct vmw_validation_context *ctx); ...@@ -207,6 +219,9 @@ void vmw_validation_revert(struct vmw_validation_context *ctx);
void vmw_validation_done(struct vmw_validation_context *ctx, void vmw_validation_done(struct vmw_validation_context *ctx,
struct vmw_fence_obj *fence); struct vmw_fence_obj *fence);
void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, size_t size); void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
unsigned int size);
int vmw_validation_preload_bo(struct vmw_validation_context *ctx);
int vmw_validation_preload_res(struct vmw_validation_context *ctx,
unsigned int size);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment