Blob Blame History Raw
From 3607bfd398204ddb11f63c09b1cc608adf85f96c Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Fri, 19 May 2017 23:59:35 +1000
Subject: [PATCH] drm/nouveau/disp/nv50-: execute supervisor on its own workqueue
Git-commit: 3607bfd398204ddb11f63c09b1cc608adf85f96c
Patch-mainline: v4.13-rc1
References: bsc#1095094

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c |    2 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c  |   10 ++++++++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h  |    1 +
 3 files changed, 10 insertions(+), 3 deletions(-)

--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -459,7 +459,7 @@ gf119_disp_intr(struct nv50_disp *disp)
 		u32 stat = nvkm_rd32(device, 0x6100ac);
 		if (stat & 0x00000007) {
 			disp->super = (stat & 0x00000007);
-			schedule_work(&disp->supervisor);
+			queue_work(disp->wq, &disp->supervisor);
 			nvkm_wr32(device, 0x6100ac, disp->super);
 			stat &= ~0x00000007;
 		}
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -111,6 +111,8 @@ nv50_disp_dtor_(struct nvkm_disp *base)
 {
 	struct nv50_disp *disp = nv50_disp(base);
 	nvkm_event_fini(&disp->uevent);
+	if (disp->wq)
+		destroy_workqueue(disp->wq);
 	return disp;
 }
 
@@ -136,7 +138,6 @@ nv50_disp_new_(const struct nv50_disp_fu
 
 	if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL)))
 		return -ENOMEM;
-	INIT_WORK(&disp->supervisor, func->super);
 	disp->func = func;
 	*pdisp = &disp->base;
 
@@ -144,6 +145,11 @@ nv50_disp_new_(const struct nv50_disp_fu
 	if (ret)
 		return ret;
 
+	disp->wq = create_singlethread_workqueue("nvkm-disp");
+	if (!disp->wq)
+		return -ENOMEM;
+	INIT_WORK(&disp->supervisor, func->super);
+
 	for (i = 0; func->head.new && i < heads; i++) {
 		ret = func->head.new(&disp->base, i);
 		if (ret)
@@ -803,7 +809,7 @@ nv50_disp_intr(struct nv50_disp *disp)
 
 	if (intr1 & 0x00000070) {
 		disp->super = (intr1 & 0x00000070);
-		schedule_work(&disp->supervisor);
+		queue_work(disp->wq, &disp->supervisor);
 		nvkm_wr32(device, 0x610024, disp->super);
 	}
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
@@ -12,6 +12,7 @@ struct nv50_disp {
 	const struct nv50_disp_func *func;
 	struct nvkm_disp base;
 
+	struct workqueue_struct *wq;
 	struct work_struct supervisor;
 	u32 super;