Skip to content

Commit

Permalink
drm: Add helpers for locking an array of BO reservations.
Browse files Browse the repository at this point in the history
Now that we have the reservation object in the GEM object, it's easy
to provide a helper for this common case.  Noticed while reviewing
panfrost and lima drivers.  This particular version came out of v3d,
which in turn was a copy from vc4.

v2: Fix kerneldoc warnings.

Signed-off-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20190308161716.2466-2-eric@anholt.net
Acked-by: Rob Herring <robh@kernel.org> (v1)
  • Loading branch information
Eric Anholt committed Mar 14, 2019
1 parent f435fe8 commit 7edc3e3
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
78 changes: 78 additions & 0 deletions drivers/gpu/drm/drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,3 +1233,81 @@ void drm_gem_vunmap(struct drm_gem_object *obj, void *vaddr)
obj->dev->driver->gem_prime_vunmap(obj, vaddr);
}
EXPORT_SYMBOL(drm_gem_vunmap);

/**
* drm_gem_lock_reservations - Sets up the ww context and acquires
* the lock on an array of GEM objects.
*
* Once you've locked your reservations, you'll want to set up space
* for your shared fences (if applicable), submit your job, then
* drm_gem_unlock_reservations().
*
* @objs: drm_gem_objects to lock
* @count: Number of objects in @objs
* @acquire_ctx: struct ww_acquire_ctx that will be initialized as
* part of tracking this set of locked reservations.
*/
int
drm_gem_lock_reservations(struct drm_gem_object **objs, int count,
struct ww_acquire_ctx *acquire_ctx)
{
int contended = -1;
int i, ret;

ww_acquire_init(acquire_ctx, &reservation_ww_class);

retry:
if (contended != -1) {
struct drm_gem_object *obj = objs[contended];

ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock,
acquire_ctx);
if (ret) {
ww_acquire_done(acquire_ctx);
return ret;
}
}

for (i = 0; i < count; i++) {
if (i == contended)
continue;

ret = ww_mutex_lock_interruptible(&objs[i]->resv->lock,
acquire_ctx);
if (ret) {
int j;

for (j = 0; j < i; j++)
ww_mutex_unlock(&objs[j]->resv->lock);

if (contended != -1 && contended >= i)
ww_mutex_unlock(&objs[contended]->resv->lock);

if (ret == -EDEADLK) {
contended = i;
goto retry;
}

ww_acquire_done(acquire_ctx);
return ret;
}
}

ww_acquire_done(acquire_ctx);

return 0;
}
EXPORT_SYMBOL(drm_gem_lock_reservations);

void
drm_gem_unlock_reservations(struct drm_gem_object **objs, int count,
struct ww_acquire_ctx *acquire_ctx)
{
int i;

for (i = 0; i < count; i++)
ww_mutex_unlock(&objs[i]->resv->lock);

ww_acquire_fini(acquire_ctx);
}
EXPORT_SYMBOL(drm_gem_unlock_reservations);
4 changes: 4 additions & 0 deletions include/drm/drm_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle);
long drm_gem_reservation_object_wait(struct drm_file *filep, u32 handle,
bool wait_all, unsigned long timeout);
int drm_gem_lock_reservations(struct drm_gem_object **objs, int count,
struct ww_acquire_ctx *acquire_ctx);
void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count,
struct ww_acquire_ctx *acquire_ctx);
int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
u32 handle, u64 *offset);
int drm_gem_dumb_destroy(struct drm_file *file,
Expand Down

0 comments on commit 7edc3e3

Please sign in to comment.