[PATCH 049/156] drm/nouveau/nvkm: detach user handling from nvkm_outp

Ben Skeggs bskeggs at nvidia.com
Tue Apr 16 23:38:15 UTC 2024


- preparation for upcoming patches
- open-code current nvkm_uoutp() macro

Signed-off-by: Ben Skeggs <bskeggs at nvidia.com>
---
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |   3 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 131 ++++++++++--------
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.h  |   6 +
 3 files changed, 78 insertions(+), 62 deletions(-)
 create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.h

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
index ebd2f499b4b1..1beba54f80eb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
@@ -63,10 +63,11 @@ struct nvkm_outp {
 		} dp;
 	};
 
-	struct nvkm_object object;
 	struct {
 		struct nvkm_head *head;
 	} asy;
+
+	bool user; /* protected by disp->user.lock */
 };
 
 int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *, int index,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 75669d5f8a42..8d39dad73a40 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -19,8 +19,7 @@
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  */
-#define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object)
-#include "outp.h"
+#include "uoutp.h"
 #include "dp.h"
 #include "head.h"
 #include "ior.h"
@@ -29,6 +28,11 @@
 
 #include <nvif/if0012.h>
 
+struct nvif_outp_priv {
+	struct nvkm_object object;
+	struct nvkm_outp *outp;
+};
+
 static int
 nvkm_uoutp_mthd_dp_mst_vcpi(struct nvkm_outp *outp, void *argv, u32 argc)
 {
@@ -543,7 +547,7 @@ nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc
 static int
 nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
 {
-	struct nvkm_outp *outp = nvkm_uoutp(object);
+	struct nvkm_outp *outp = container_of(object, struct nvif_outp_priv, object)->outp;
 	struct nvkm_disp *disp = outp->disp;
 	bool invalid = false;
 	int ret;
@@ -567,13 +571,13 @@ nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
 static void *
 nvkm_uoutp_dtor(struct nvkm_object *object)
 {
-	struct nvkm_outp *outp = nvkm_uoutp(object);
-	struct nvkm_disp *disp = outp->disp;
+	struct nvif_outp_priv *uoutp = container_of(object, typeof(*uoutp), object);
+	struct nvkm_disp *disp = uoutp->outp->disp;
 
 	spin_lock(&disp->user.lock);
-	outp->object.func = NULL;
+	uoutp->outp->user = false;
 	spin_unlock(&disp->user.lock);
-	return NULL;
+	return uoutp;
 }
 
 static const struct nvkm_object_func
@@ -589,7 +593,7 @@ nvkm_uoutp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
 	struct nvkm_disp *disp = container_of(oclass->parent, struct nvif_disp_priv, object)->disp;
 	struct nvkm_outp *outt, *outp = NULL;
 	union nvif_outp_args *args = argv;
-	int ret;
+	struct nvif_outp_priv *uoutp;
 
 	if (argc != sizeof(args->v0) || args->v0.version != 0)
 		return -ENOSYS;
@@ -604,63 +608,68 @@ nvkm_uoutp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
 	if (!outp)
 		return -EINVAL;
 
-	ret = -EBUSY;
-	spin_lock(&disp->user.lock);
-	if (!outp->object.func) {
-		switch (outp->info.type) {
-		case DCB_OUTPUT_ANALOG:
-			args->v0.type = NVIF_OUTP_V0_TYPE_DAC;
-			args->v0.proto = NVIF_OUTP_V0_PROTO_RGB_CRT;
-			args->v0.rgb_crt.freq_max = outp->info.crtconf.maxfreq;
-			break;
-		case DCB_OUTPUT_TMDS:
-			if (!outp->info.location) {
-				args->v0.type = NVIF_OUTP_V0_TYPE_SOR;
-				args->v0.tmds.dual = (outp->info.tmdsconf.sor.link == 3);
-			} else {
-				args->v0.type = NVIF_OUTP_V0_TYPE_PIOR;
-				args->v0.tmds.dual = 0;
-			}
-			args->v0.proto = NVIF_OUTP_V0_PROTO_TMDS;
-			break;
-		case DCB_OUTPUT_LVDS:
+	switch (outp->info.type) {
+	case DCB_OUTPUT_ANALOG:
+		args->v0.type = NVIF_OUTP_V0_TYPE_DAC;
+		args->v0.proto = NVIF_OUTP_V0_PROTO_RGB_CRT;
+		args->v0.rgb_crt.freq_max = outp->info.crtconf.maxfreq;
+		break;
+	case DCB_OUTPUT_TMDS:
+		if (!outp->info.location) {
 			args->v0.type = NVIF_OUTP_V0_TYPE_SOR;
-			args->v0.proto = NVIF_OUTP_V0_PROTO_LVDS;
-			args->v0.lvds.acpi_edid = outp->info.lvdsconf.use_acpi_for_edid;
-			break;
-		case DCB_OUTPUT_DP:
-			if (!outp->info.location) {
-				args->v0.type = NVIF_OUTP_V0_TYPE_SOR;
-				args->v0.dp.aux = outp->info.i2c_index;
-			} else {
-				args->v0.type = NVIF_OUTP_V0_TYPE_PIOR;
-				args->v0.dp.aux = NVKM_I2C_AUX_EXT(outp->info.extdev);
-			}
-			args->v0.proto = NVIF_OUTP_V0_PROTO_DP;
-			args->v0.dp.mst = outp->dp.mst;
-			args->v0.dp.increased_wm = outp->dp.increased_wm;
-			args->v0.dp.link_nr = outp->info.dpconf.link_nr;
-			args->v0.dp.link_bw = outp->info.dpconf.link_bw * 27000;
-			break;
-		default:
-			WARN_ON(1);
-			ret = -EINVAL;
-			goto done;
+			args->v0.tmds.dual = (outp->info.tmdsconf.sor.link == 3);
+		} else {
+			args->v0.type = NVIF_OUTP_V0_TYPE_PIOR;
+			args->v0.tmds.dual = 0;
 		}
+		args->v0.proto = NVIF_OUTP_V0_PROTO_TMDS;
+		break;
+	case DCB_OUTPUT_LVDS:
+		args->v0.type = NVIF_OUTP_V0_TYPE_SOR;
+		args->v0.proto = NVIF_OUTP_V0_PROTO_LVDS;
+		args->v0.lvds.acpi_edid = outp->info.lvdsconf.use_acpi_for_edid;
+		break;
+	case DCB_OUTPUT_DP:
+		if (!outp->info.location) {
+			args->v0.type = NVIF_OUTP_V0_TYPE_SOR;
+			args->v0.dp.aux = outp->info.i2c_index;
+		} else {
+			args->v0.type = NVIF_OUTP_V0_TYPE_PIOR;
+			args->v0.dp.aux = NVKM_I2C_AUX_EXT(outp->info.extdev);
+		}
+		args->v0.proto = NVIF_OUTP_V0_PROTO_DP;
+		args->v0.dp.mst = outp->dp.mst;
+		args->v0.dp.increased_wm = outp->dp.increased_wm;
+		args->v0.dp.link_nr = outp->info.dpconf.link_nr;
+		args->v0.dp.link_bw = outp->info.dpconf.link_bw * 27000;
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
 
-		if (outp->info.location)
-			args->v0.ddc = NVKM_I2C_BUS_EXT(outp->info.extdev);
-		else
-			args->v0.ddc = outp->info.i2c_index;
-		args->v0.heads = outp->info.heads;
-		args->v0.conn = outp->info.connector;
+	if (outp->info.location)
+		args->v0.ddc = NVKM_I2C_BUS_EXT(outp->info.extdev);
+	else
+		args->v0.ddc = outp->info.i2c_index;
+	args->v0.heads = outp->info.heads;
+	args->v0.conn = outp->info.connector;
 
-		nvkm_object_ctor(&nvkm_uoutp, oclass, &outp->object);
-		*pobject = &outp->object;
-		ret = 0;
-	}
+	uoutp = kzalloc(sizeof(*uoutp), GFP_KERNEL);
+	if (!uoutp)
+		return -ENOMEM;
 
-done:
+	spin_lock(&disp->user.lock);
+	if (outp->user) {
+		spin_unlock(&disp->user.lock);
+		kfree(uoutp);
+		return -EBUSY;
+	}
+	outp->user = true;
 	spin_unlock(&disp->user.lock);
-	return ret;
+
+	nvkm_object_ctor(&nvkm_uoutp, oclass, &uoutp->object);
+	uoutp->outp = outp;
+	*pobject = &uoutp->object;
+	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.h
new file mode 100644
index 000000000000..37ecd2891a1a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_UOUTP_H__
+#define __NVKM_UOUTP_H__
+#include "outp.h"
+
+#endif
-- 
2.41.0



More information about the Nouveau mailing list