Commit 7621350c authored by Christian König's avatar Christian König

drm/syncobj: make lockdep complain on WAIT_FOR_SUBMIT v3

DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT can't be used when we hold locks
since we are basically waiting for userspace to do something.

Holding a lock while doing so can trivial deadlock with page faults
etc...

So make lockdep complain when a driver tries to do this.

v2: Add lockdep_assert_none_held() macro.
v3: Add might_sleep() and also use lockdep_assert_none_held() in the
    IOCTL path.
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patchwork.freedesktop.org/patch/414944/
parent f987c9e0
...@@ -387,6 +387,15 @@ int drm_syncobj_find_fence(struct drm_file *file_private, ...@@ -387,6 +387,15 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
if (!syncobj) if (!syncobj)
return -ENOENT; return -ENOENT;
/* Waiting for userspace with locks help is illegal cause that can
* trivial deadlock with page faults for example. Make lockdep complain
* about it early on.
*/
if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
might_sleep();
lockdep_assert_none_held_once();
}
*fence = drm_syncobj_fence_get(syncobj); *fence = drm_syncobj_fence_get(syncobj);
drm_syncobj_put(syncobj); drm_syncobj_put(syncobj);
...@@ -940,6 +949,9 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, ...@@ -940,6 +949,9 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
uint64_t *points; uint64_t *points;
uint32_t signaled_count, i; uint32_t signaled_count, i;
if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)
lockdep_assert_none_held_once();
points = kmalloc_array(count, sizeof(*points), GFP_KERNEL); points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
if (points == NULL) if (points == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -310,6 +310,10 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); ...@@ -310,6 +310,10 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \ WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \
} while (0) } while (0)
#define lockdep_assert_none_held_once() do { \
WARN_ON_ONCE(debug_locks && current->lockdep_depth); \
} while (0)
#define lockdep_recursing(tsk) ((tsk)->lockdep_recursion) #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion)
#define lockdep_pin_lock(l) lock_pin_lock(&(l)->dep_map) #define lockdep_pin_lock(l) lock_pin_lock(&(l)->dep_map)
...@@ -387,6 +391,7 @@ extern int lockdep_is_held(const void *); ...@@ -387,6 +391,7 @@ extern int lockdep_is_held(const void *);
#define lockdep_assert_held_write(l) do { (void)(l); } while (0) #define lockdep_assert_held_write(l) do { (void)(l); } while (0)
#define lockdep_assert_held_read(l) do { (void)(l); } while (0) #define lockdep_assert_held_read(l) do { (void)(l); } while (0)
#define lockdep_assert_held_once(l) do { (void)(l); } while (0) #define lockdep_assert_held_once(l) do { (void)(l); } while (0)
#define lockdep_assert_none_held_once() do { } while (0)
#define lockdep_recursing(tsk) (0) #define lockdep_recursing(tsk) (0)
......
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