drm: Don't complain too much about struct_mutex.
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 15 Jul 2017 09:53:28 +0000 (11:53 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 18 Jul 2017 07:17:22 +0000 (09:17 +0200)
For modern drivers the DRM core doesn't use struct_mutex at all, which
means it's defacto a driver-private lock. But since we still need it
for legacy drivers we can't initialize it in drivers, which means all
the different instances share one lockdep key. Despite that they might
be placed in totally different places in the locking hierarchy.

This results in a lot of bogus lockdep splats when running stuff on
systems with multiple gpus. Partially remedy the situation by only
doing might_lock checks on drivers that do use struct_mutex still for
gem locking.

A more complete solution would be to do the mutex_init in the drm core
only for legacy drivers, plus add it to each modern driver that still
needs it, which would also give each its own lockdep key. Trying to do
that dynamically doesn't work, because lockdep requires it's keys to
be statically allocated.

v2: {} everywhere (Chris)

Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170715095328.25671-1-daniel.vetter@ffwll.ch
drivers/gpu/drm/drm_gem.c

index 8dc11064253d9e5ed58f8c817a471b36c25c5951..5df028a6dd9f26eafd24fa17973f481fccd8a69b 100644 (file)
@@ -826,13 +826,15 @@ drm_gem_object_put_unlocked(struct drm_gem_object *obj)
                return;
 
        dev = obj->dev;
-       might_lock(&dev->struct_mutex);
 
-       if (dev->driver->gem_free_object_unlocked)
+       if (dev->driver->gem_free_object_unlocked) {
                kref_put(&obj->refcount, drm_gem_object_free);
-       else if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
+       } else {
+               might_lock(&dev->struct_mutex);
+               if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
                                &dev->struct_mutex))
-               mutex_unlock(&dev->struct_mutex);
+                       mutex_unlock(&dev->struct_mutex);
+       }
 }
 EXPORT_SYMBOL(drm_gem_object_put_unlocked);