Commit a6fd8f93 authored by Ben Skeggs's avatar Ben Skeggs Committed by Dave Airlie

drm/nouveau/disp: add supervisor mutex

Will be used to protect NVIF_CLASS_OUTP method calls from racing with
in-progress supervisor handling.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 32dd9236
...@@ -22,6 +22,7 @@ struct nvkm_disp { ...@@ -22,6 +22,7 @@ struct nvkm_disp {
struct workqueue_struct *wq; struct workqueue_struct *wq;
struct work_struct work; struct work_struct work;
u32 pending; u32 pending;
struct mutex mutex;
} super; } super;
#define NVKM_DISP_EVENT_CHAN_AWAKEN BIT(0) #define NVKM_DISP_EVENT_CHAN_AWAKEN BIT(0)
......
...@@ -399,8 +399,11 @@ nvkm_disp_dtor(struct nvkm_engine *engine) ...@@ -399,8 +399,11 @@ nvkm_disp_dtor(struct nvkm_engine *engine)
nvkm_gpuobj_del(&disp->inst); nvkm_gpuobj_del(&disp->inst);
nvkm_event_fini(&disp->uevent); nvkm_event_fini(&disp->uevent);
if (disp->super.wq)
if (disp->super.wq) {
destroy_workqueue(disp->super.wq); destroy_workqueue(disp->super.wq);
mutex_destroy(&disp->super.mutex);
}
nvkm_event_fini(&disp->vblank); nvkm_event_fini(&disp->vblank);
nvkm_event_fini(&disp->hpd); nvkm_event_fini(&disp->hpd);
...@@ -467,6 +470,7 @@ nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, ...@@ -467,6 +470,7 @@ nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device,
return -ENOMEM; return -ENOMEM;
INIT_WORK(&disp->super.work, func->super); 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); return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), &disp->uevent);
......
...@@ -995,6 +995,8 @@ gf119_disp_super(struct work_struct *work) ...@@ -995,6 +995,8 @@ gf119_disp_super(struct work_struct *work)
u32 mask[4]; u32 mask[4];
nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super.pending)); nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super.pending));
mutex_lock(&disp->super.mutex);
list_for_each_entry(head, &disp->heads, head) { list_for_each_entry(head, &disp->heads, head) {
mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800)); mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800));
HEAD_DBG(head, "%08x", mask[head->id]); HEAD_DBG(head, "%08x", mask[head->id]);
...@@ -1037,7 +1039,9 @@ gf119_disp_super(struct work_struct *work) ...@@ -1037,7 +1039,9 @@ gf119_disp_super(struct work_struct *work)
list_for_each_entry(head, &disp->heads, head) list_for_each_entry(head, &disp->heads, head)
nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000); nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000);
nvkm_wr32(device, 0x6101d0, 0x80000000); nvkm_wr32(device, 0x6101d0, 0x80000000);
mutex_unlock(&disp->super.mutex);
} }
void void
......
...@@ -818,8 +818,10 @@ gv100_disp_super(struct work_struct *work) ...@@ -818,8 +818,10 @@ gv100_disp_super(struct work_struct *work)
struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_subdev *subdev = &disp->engine.subdev;
struct nvkm_device *device = subdev->device; struct nvkm_device *device = subdev->device;
struct nvkm_head *head; struct nvkm_head *head;
u32 stat = nvkm_rd32(device, 0x6107a8); u32 stat, mask[4];
u32 mask[4];
mutex_lock(&disp->super.mutex);
stat = nvkm_rd32(device, 0x6107a8);
nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super.pending), stat); nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super.pending), stat);
list_for_each_entry(head, &disp->heads, head) { list_for_each_entry(head, &disp->heads, head) {
...@@ -864,7 +866,9 @@ gv100_disp_super(struct work_struct *work) ...@@ -864,7 +866,9 @@ gv100_disp_super(struct work_struct *work)
list_for_each_entry(head, &disp->heads, head) list_for_each_entry(head, &disp->heads, head)
nvkm_wr32(device, 0x6107ac + (head->id * 4), 0x00000000); nvkm_wr32(device, 0x6107ac + (head->id * 4), 0x00000000);
nvkm_wr32(device, 0x6107a8, 0x80000000); nvkm_wr32(device, 0x6107a8, 0x80000000);
mutex_unlock(&disp->super.mutex);
} }
static void static void
......
...@@ -1345,7 +1345,10 @@ nv50_disp_super(struct work_struct *work) ...@@ -1345,7 +1345,10 @@ nv50_disp_super(struct work_struct *work)
struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_subdev *subdev = &disp->engine.subdev;
struct nvkm_device *device = subdev->device; struct nvkm_device *device = subdev->device;
struct nvkm_head *head; 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); nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super.pending, super);
...@@ -1387,6 +1390,7 @@ nv50_disp_super(struct work_struct *work) ...@@ -1387,6 +1390,7 @@ nv50_disp_super(struct work_struct *work)
} }
nvkm_wr32(device, 0x610030, 0x80000000); nvkm_wr32(device, 0x610030, 0x80000000);
mutex_unlock(&disp->super.mutex);
} }
const struct nvkm_enum const struct nvkm_enum
......
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