Skip to content

Commit 64ad2ab

Browse files
committed
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: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
1 parent 24dc64c commit 64ad2ab

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_validation.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,12 @@ struct vmw_validation_res_node {
9494
*
9595
* Return: Pointer to the allocated memory on success. NULL on failure.
9696
*/
97-
void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, size_t size)
97+
void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
98+
unsigned int size)
9899
{
99100
void *addr;
100101

101-
size = ALIGN(size, sizeof(long));
102+
size = vmw_validation_align(size);
102103
if (size > PAGE_SIZE)
103104
return NULL;
104105

@@ -262,7 +263,9 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,
262263
}
263264
}
264265
val_buf = &bo_node->base;
265-
val_buf->bo = ttm_bo_reference(&vbo->base);
266+
val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);
267+
if (!val_buf->bo)
268+
return -ESRCH;
266269
val_buf->shared = false;
267270
list_add_tail(&val_buf->head, &ctx->bo_list);
268271
bo_node->as_mob = as_mob;
@@ -313,7 +316,10 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
313316
return ret;
314317
}
315318
}
316-
node->res = vmw_resource_reference(res);
319+
node->res = vmw_resource_reference_unless_doomed(res);
320+
if (!node->res)
321+
return -ESRCH;
322+
317323
node->first_usage = 1;
318324
if (!res->dev_priv->has_mob) {
319325
list_add_tail(&node->head, &ctx->resource_list);
@@ -715,3 +721,50 @@ void vmw_validation_done(struct vmw_validation_context *ctx,
715721
mutex_unlock(ctx->res_mutex);
716722
vmw_validation_unref_lists(ctx);
717723
}
724+
725+
/**
726+
* vmw_validation_preload_bo - Preload the validation memory allocator for a
727+
* call to vmw_validation_add_bo().
728+
* @ctx: Pointer to the validation context.
729+
*
730+
* Iff this function returns successfully, the next call to
731+
* vmw_validation_add_bo() is guaranteed not to sleep. An error is not fatal
732+
* but voids the guarantee.
733+
*
734+
* Returns: Zero if successful, %-EINVAL otherwise.
735+
*/
736+
int vmw_validation_preload_bo(struct vmw_validation_context *ctx)
737+
{
738+
unsigned int size = sizeof(struct vmw_validation_bo_node);
739+
740+
if (!vmw_validation_mem_alloc(ctx, size))
741+
return -ENOMEM;
742+
743+
ctx->mem_size_left += size;
744+
return 0;
745+
}
746+
747+
/**
748+
* vmw_validation_preload_res - Preload the validation memory allocator for a
749+
* call to vmw_validation_add_res().
750+
* @ctx: Pointer to the validation context.
751+
* @size: Size of the validation node extra data. See below.
752+
*
753+
* Iff this function returns successfully, the next call to
754+
* vmw_validation_add_res() with the same or smaller @size is guaranteed not to
755+
* sleep. An error is not fatal but voids the guarantee.
756+
*
757+
* Returns: Zero if successful, %-EINVAL otherwise.
758+
*/
759+
int vmw_validation_preload_res(struct vmw_validation_context *ctx,
760+
unsigned int size)
761+
{
762+
size = vmw_validation_align(sizeof(struct vmw_validation_res_node) +
763+
size) +
764+
vmw_validation_align(sizeof(struct vmw_validation_bo_node));
765+
if (!vmw_validation_mem_alloc(ctx, size))
766+
return -ENOMEM;
767+
768+
ctx->mem_size_left += size;
769+
return 0;
770+
}

drivers/gpu/drm/vmwgfx/vmwgfx_validation.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,18 @@ vmw_validation_context_init(struct vmw_validation_context *ctx)
177177
INIT_LIST_HEAD(&ctx->bo_list);
178178
}
179179

180+
/**
181+
* vmw_validation_align - Align a validation memory allocation
182+
* @val: The size to be aligned
183+
*
184+
* Returns: @val aligned to the granularity used by the validation memory
185+
* allocator.
186+
*/
187+
static inline unsigned int vmw_validation_align(unsigned int val)
188+
{
189+
return ALIGN(val, sizeof(long));
190+
}
191+
180192
int vmw_validation_add_bo(struct vmw_validation_context *ctx,
181193
struct vmw_buffer_object *vbo,
182194
bool as_mob, bool cpu_blit);
@@ -207,6 +219,9 @@ void vmw_validation_revert(struct vmw_validation_context *ctx);
207219
void vmw_validation_done(struct vmw_validation_context *ctx,
208220
struct vmw_fence_obj *fence);
209221

210-
void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx, size_t size);
211-
222+
void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
223+
unsigned int size);
224+
int vmw_validation_preload_bo(struct vmw_validation_context *ctx);
225+
int vmw_validation_preload_res(struct vmw_validation_context *ctx,
226+
unsigned int size);
212227
#endif

0 commit comments

Comments
 (0)