With prime, we are running into false circular dependencies based on the
order in which two drivers may lock their own struct_mutex wrt to a
common lock (like the reservation->lock). Work around this by adding the
lock_class_key to the struct drm_driver such that each driver can have
its own subclass of struct_mutex. Circular dependencies between drivers
will now be ignored, but real circular dependencies on any one mutex
will still be caught. A driver creating more than one device will still
need to be careful!

Reported-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de>
Reported-by: Hans de Goede <hdegoede at redhat.com>
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/drm_drv.c | 4 +++-
 include/drm/drm_drv.h     | 6 ++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 2fa4e4fa7c33..82b521146e71 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -488,7 +488,9 @@ int drm_dev_init(struct drm_device *dev,

        spin_lock_init(&dev->buf_lock);
        spin_lock_init(&dev->event_lock);
-       mutex_init(&dev->struct_mutex);
+       __mutex_init(&dev->struct_mutex,
+                    "&dev->struct_mutex",
+                    &driver->class.struct_mutex_key);
        mutex_init(&dev->filelist_mutex);
        mutex_init(&dev->ctxlist_mutex);
        mutex_init(&dev->master_mutex);
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 554104ccb939..5d521923404a 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -39,6 +39,10 @@ struct dma_buf_attachment;
 struct drm_display_mode;
 struct drm_mode_create_dumb;

+struct drm_driver_class {
+       struct lock_class_key struct_mutex_key;
+};
+
 /* driver capabilities and requirements mask */
 #define DRIVER_USE_AGP                 0x1
 #define DRIVER_LEGACY                  0x2
@@ -64,6 +68,8 @@ struct drm_mode_create_dumb;
  * structure for GEM drivers.
  */
 struct drm_driver {
+       struct drm_driver_class class;
+
        int (*load) (struct drm_device *, unsigned long flags);
        int (*firstopen) (struct drm_device *);
        int (*open) (struct drm_device *, struct drm_file *);
-- 
2.11.0

Reply via email to