diff options
author | Ben Skeggs | 2022-06-01 20:46:31 +1000 |
---|---|---|
committer | Dave Airlie | 2022-07-27 09:05:48 +1000 |
commit | a6fd8f936402c3bcc5ac6aed9cca8e73b5ca08f7 (patch) | |
tree | a672ce34eb30bf18dd356350bc75f54dda6d25e0 /drivers/gpu/drm | |
parent | 32dd9236698bcd2ffdb69954b167a851fd50182a (diff) |
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: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
5 files changed, 21 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index 64bda44a13e5..8b5d8a434be8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -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) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 10d4a3359a3f..65c99d948b68 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index 3af527d2328c..39822f1b5b95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 9106743a6368..6b9d49270fa7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 237f5aa06850..a46e13cc9ff1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -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 |