drm/nouveau/nvkm: give each nvkm_event its own lockdep class
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:46:51 +0000 (20:46 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 9 Nov 2022 00:44:35 +0000 (10:44 +1000)
The vblank and nonstall events have some annoying interactions with DRM
locking, and aren't able to do certain things as a result.

However, other uses of event notifications don't have such requirements,
and upcoming patches take advantage of this for various improvements.

Having separate classes for each nvkm_event's spinlocks allows lockdep
to distinguish between them and avoid false-positives.

v2: __always_inline + comment

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/core/event.h
drivers/gpu/drm/nouveau/nvkm/core/event.c

index 8e8fb4b..82b267c 100644 (file)
@@ -25,8 +25,23 @@ struct nvkm_event_func {
        void (*fini)(struct nvkm_event *, int type, int index);
 };
 
-int  nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr,
-                    int index_nr, struct nvkm_event *);
+int  __nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr,
+                      int index_nr, struct nvkm_event *);
+
+/* Each nvkm_event needs its own lockdep class due to inter-dependencies, to
+ * prevent lockdep false-positives.
+ *
+ * Inlining the spinlock initialisation ensures each is unique.
+ */
+static __always_inline int
+nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
+               int types_nr, int index_nr, struct nvkm_event *event)
+{
+       spin_lock_init(&event->refs_lock);
+       spin_lock_init(&event->list_lock);
+       return __nvkm_event_init(func, subdev, types_nr, index_nr, event);
+}
+
 void nvkm_event_fini(struct nvkm_event *);
 
 #define NVKM_EVENT_KEEP 0
index 622df36..a6c8771 100644 (file)
@@ -198,8 +198,8 @@ nvkm_event_fini(struct nvkm_event *event)
 }
 
 int
-nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
-               int types_nr, int index_nr, struct nvkm_event *event)
+__nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
+                 int types_nr, int index_nr, struct nvkm_event *event)
 {
        event->refs = kzalloc(array3_size(index_nr, types_nr, sizeof(*event->refs)), GFP_KERNEL);
        if (!event->refs)
@@ -209,8 +209,6 @@ nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
        event->subdev = subdev;
        event->types_nr = types_nr;
        event->index_nr = index_nr;
-       spin_lock_init(&event->refs_lock);
-       spin_lock_init(&event->list_lock);
        INIT_LIST_HEAD(&event->ntfy);
        return 0;
 }