]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/nouveau/disp: add supervisor mutex
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:46:31 +0000 (20:46 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 26 Jul 2022 23:05:48 +0000 (09:05 +1000)
Will be used to protect NVIF_CLASS_OUTP method calls from racing with
in-progress supervisor handling.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c

index 64bda44a13e55a73c59d07263bb6fc9acf0267fa..8b5d8a434be863217d2e4f7fb00a8ddafc2b2501 100644 (file)
@@ -22,6 +22,7 @@ struct nvkm_disp {
                struct workqueue_struct *wq;
                struct work_struct work;
                u32 pending;
+               struct mutex mutex;
        } super;
 
 #define NVKM_DISP_EVENT_CHAN_AWAKEN BIT(0)
index 10d4a3359a3f0775133e965489194147bebe748e..65c99d948b686709c0e7c8951c299e501a042427 100644 (file)
@@ -399,8 +399,11 @@ nvkm_disp_dtor(struct nvkm_engine *engine)
        nvkm_gpuobj_del(&disp->inst);
 
        nvkm_event_fini(&disp->uevent);
-       if (disp->super.wq)
+
+       if (disp->super.wq) {
                destroy_workqueue(disp->super.wq);
+               mutex_destroy(&disp->super.mutex);
+       }
 
        nvkm_event_fini(&disp->vblank);
        nvkm_event_fini(&disp->hpd);
@@ -467,6 +470,7 @@ nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device,
                        return -ENOMEM;
 
                INIT_WORK(&disp->super.work, func->super);
+               mutex_init(&disp->super.mutex);
        }
 
        return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), &disp->uevent);
index 3af527d2328ce33c0b39777b032a4c5a4ee29d2f..39822f1b5b9506ba1ad817b771fc061e795e4a53 100644 (file)
@@ -995,6 +995,8 @@ gf119_disp_super(struct work_struct *work)
        u32 mask[4];
 
        nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super.pending));
+       mutex_lock(&disp->super.mutex);
+
        list_for_each_entry(head, &disp->heads, head) {
                mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800));
                HEAD_DBG(head, "%08x", mask[head->id]);
@@ -1037,7 +1039,9 @@ gf119_disp_super(struct work_struct *work)
 
        list_for_each_entry(head, &disp->heads, head)
                nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000);
+
        nvkm_wr32(device, 0x6101d0, 0x80000000);
+       mutex_unlock(&disp->super.mutex);
 }
 
 void
index 9106743a636875bdef8a7ca8426baa108159b819..6b9d49270fa7a424c19bb56d951b2e6c468b3e2d 100644 (file)
@@ -818,8 +818,10 @@ gv100_disp_super(struct work_struct *work)
        struct nvkm_subdev *subdev = &disp->engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_head *head;
-       u32 stat = nvkm_rd32(device, 0x6107a8);
-       u32 mask[4];
+       u32 stat, mask[4];
+
+       mutex_lock(&disp->super.mutex);
+       stat = nvkm_rd32(device, 0x6107a8);
 
        nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super.pending), stat);
        list_for_each_entry(head, &disp->heads, head) {
@@ -864,7 +866,9 @@ gv100_disp_super(struct work_struct *work)
 
        list_for_each_entry(head, &disp->heads, head)
                nvkm_wr32(device, 0x6107ac + (head->id * 4), 0x00000000);
+
        nvkm_wr32(device, 0x6107a8, 0x80000000);
+       mutex_unlock(&disp->super.mutex);
 }
 
 static void
index 237f5aa06850ecb6a5c764592a3a5691a95659bc..a46e13cc9ff13674e8fa19fc56c90a295d96328d 100644 (file)
@@ -1345,7 +1345,10 @@ nv50_disp_super(struct work_struct *work)
        struct nvkm_subdev *subdev = &disp->engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_head *head;
-       u32 super = nvkm_rd32(device, 0x610030);
+       u32 super;
+
+       mutex_lock(&disp->super.mutex);
+       super = nvkm_rd32(device, 0x610030);
 
        nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super.pending, super);
 
@@ -1387,6 +1390,7 @@ nv50_disp_super(struct work_struct *work)
        }
 
        nvkm_wr32(device, 0x610030, 0x80000000);
+       mutex_unlock(&disp->super.mutex);
 }
 
 const struct nvkm_enum