[PATCH 02/21] drm/nouveau/nvkm: delay calling subdev ctor()'s until device oneinit()

Ben Skeggs bskeggs at nvidia.com
Thu Jun 13 16:59:54 UTC 2024


A later patch in the series converts nvkm_device_{pci_tegra}_new into
PCI/platform device probe functions, as a step towards moving all the
PCI/Tegra-specific handling into NVKM.

nouveau.ko has two module options (nouveau.config/nouveau.debug) that
affect the behaviour of NVKM, however, and the probe() functions will
not have access to these, which would break a user's configuration if
they depend on any of the options to workaround a problem, etc.

To avoid this, we delay calling constructors for each subdev (which
could depend on module parameters) until allocation of the first
nvif_device, which will allow the DRM driver a chance to override
device.{cfg,dbg}opt before they're needed.

Signed-off-by: Ben Skeggs <bskeggs at nvidia.com>
---
 drivers/gpu/drm/nouveau/nouveau_drm.c       |   3 +
 drivers/gpu/drm/nouveau/nvkm/device/base.c  | 112 ++++++++++++--------
 drivers/gpu/drm/nouveau/nvkm/device/pci.c   |   2 +-
 drivers/gpu/drm/nouveau/nvkm/device/priv.h  |   3 +-
 drivers/gpu/drm/nouveau/nvkm/device/tegra.c |   2 +-
 5 files changed, 71 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 965331e65fda..18990d21dc48 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -644,6 +644,9 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren
 
 	drm->nvkm = device;
 
+	device->cfgopt = nouveau_config;
+	device->dbgopt = nouveau_debug;
+
 	nvif_parent_ctor(&nouveau_parent, &drm->parent);
 
 	ret = nvkm_driver_ctor(device, &driver, &impl, &priv);
diff --git a/drivers/gpu/drm/nouveau/nvkm/device/base.c b/drivers/gpu/drm/nouveau/nvkm/device/base.c
index 20609571793e..1b76c2a60799 100644
--- a/drivers/gpu/drm/nouveau/nvkm/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/device/base.c
@@ -2908,6 +2908,62 @@ nvkm_device_preinit(struct nvkm_device *device)
 	return ret;
 }
 
+static int
+nvkm_device_oneinit(struct nvkm_device *device)
+{
+	struct nvkm_subdev *subdev, *subtmp;
+	int ret, j;
+
+#define NVKM_LAYOUT_ONCE(type,data,ptr)                                                      \
+	if (device->chip->ptr.inst) {                                                        \
+		WARN_ON(device->chip->ptr.inst != 0x00000001);                               \
+		ret = device->chip->ptr.ctor(device, (type), -1, &device->ptr);              \
+		subdev = nvkm_device_subdev(device, (type), 0);                              \
+		if (ret) {                                                                   \
+			nvkm_subdev_del(&subdev);                                            \
+			device->ptr = NULL;                                                  \
+			if (ret != -ENODEV) {                                                \
+				nvdev_error(device, "%s ctor failed: %d\n",                  \
+					    nvkm_subdev_type[(type)], ret);                  \
+				goto done;                                                   \
+			}                                                                    \
+		} else {                                                                     \
+			subdev->pself = (void **)&device->ptr;                               \
+		}                                                                            \
+	}
+#define NVKM_LAYOUT_INST(type,data,ptr,cnt)                                                  \
+	WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1));             \
+	for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) {            \
+		if (device->chip->ptr.inst & BIT(j)) {                                       \
+			ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]);  \
+			subdev = nvkm_device_subdev(device, (type), (j));                    \
+			if (ret) {                                                           \
+				nvkm_subdev_del(&subdev);                                    \
+				device->ptr[j] = NULL;                                       \
+				if (ret != -ENODEV) {                                        \
+					nvdev_error(device, "%s%d ctor failed: %d\n",        \
+						    nvkm_subdev_type[(type)], (j), ret);     \
+					goto done;                                           \
+				}                                                            \
+			} else {                                                             \
+				subdev->pself = (void **)&device->ptr[j];                    \
+			}                                                                    \
+		}                                                                            \
+	}
+#include <core/layout.h>
+#undef NVKM_LAYOUT_INST
+#undef NVKM_LAYOUT_ONCE
+
+	ret = nvkm_intr_install(device);
+done:
+	if (ret) {
+		list_for_each_entry_safe_reverse(subdev, subtmp, &device->subdev, head)
+			nvkm_subdev_del(&subdev);
+	}
+
+	return ret;
+}
+
 int
 nvkm_device_init(struct nvkm_device *device)
 {
@@ -2915,6 +2971,12 @@ nvkm_device_init(struct nvkm_device *device)
 	int ret;
 	s64 time;
 
+	if (list_empty(&device->subdev)) {
+		ret = nvkm_device_oneinit(device);
+		if (ret)
+			return ret;
+	}
+
 	ret = nvkm_device_preinit(device);
 	if (ret)
 		return ret;
@@ -3012,13 +3074,11 @@ int
 nvkm_device_ctor(const struct nvkm_device_func *func,
 		 const struct nvkm_device_quirk *quirk,
 		 struct device *dev, enum nvkm_device_type type, u64 handle,
-		 const char *name, const char *cfg, const char *dbg,
-		 struct nvkm_device *device)
+		 const char *name, struct nvkm_device *device)
 {
-	struct nvkm_subdev *subdev;
 	u64 mmio_base, mmio_size;
 	u32 boot0, boot1, strap;
-	int ret = -EEXIST, j;
+	int ret = -EEXIST;
 	unsigned chipset;
 
 	device->func = func;
@@ -3026,8 +3086,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
 	device->dev = dev;
 	device->type = type;
 	device->handle = handle;
-	device->cfgopt = cfg;
-	device->dbgopt = dbg;
 	device->name = name;
 	device->debug = nvkm_dbgopt(device->dbgopt, "device");
 	INIT_LIST_HEAD(&device->subdev);
@@ -3265,47 +3323,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
 	mutex_init(&device->mutex);
 	nvkm_intr_ctor(device);
 
-#define NVKM_LAYOUT_ONCE(type,data,ptr)                                                      \
-	if (device->chip->ptr.inst) {                                                        \
-		WARN_ON(device->chip->ptr.inst != 0x00000001);                               \
-		ret = device->chip->ptr.ctor(device, (type), -1, &device->ptr);              \
-		subdev = nvkm_device_subdev(device, (type), 0);                              \
-		if (ret) {                                                                   \
-			nvkm_subdev_del(&subdev);                                            \
-			device->ptr = NULL;                                                  \
-			if (ret != -ENODEV) {                                                \
-				nvdev_error(device, "%s ctor failed: %d\n",                  \
-					    nvkm_subdev_type[(type)], ret);                  \
-				goto done;                                                   \
-			}                                                                    \
-		} else {                                                                     \
-			subdev->pself = (void **)&device->ptr;                               \
-		}                                                                            \
-	}
-#define NVKM_LAYOUT_INST(type,data,ptr,cnt)                                                  \
-	WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1));             \
-	for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) {            \
-		if (device->chip->ptr.inst & BIT(j)) {                                       \
-			ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]);  \
-			subdev = nvkm_device_subdev(device, (type), (j));                    \
-			if (ret) {                                                           \
-				nvkm_subdev_del(&subdev);                                    \
-				device->ptr[j] = NULL;                                       \
-				if (ret != -ENODEV) {                                        \
-					nvdev_error(device, "%s%d ctor failed: %d\n",        \
-						    nvkm_subdev_type[(type)], (j), ret);     \
-					goto done;                                           \
-				}                                                            \
-			} else {                                                             \
-				subdev->pself = (void **)&device->ptr[j];                    \
-			}                                                                    \
-		}                                                                            \
-	}
-#include <core/layout.h>
-#undef NVKM_LAYOUT_INST
-#undef NVKM_LAYOUT_ONCE
-
-	ret = nvkm_intr_install(device);
+	ret = 0;
 done:
 	if (ret && device->pri) {
 		iounmap(device->pri);
diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c
index 3ff6436007fa..8bfedd79d7a5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c
@@ -1679,7 +1679,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
 				    pci_dev->bus->number << 16 |
 				    PCI_SLOT(pci_dev->devfn) << 8 |
 				    PCI_FUNC(pci_dev->devfn), name,
-			       cfg, dbg, &pdev->device);
+			       &pdev->device);
 
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/device/priv.h
index e42b18820a95..176cb1dfb2fe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/device/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/device/priv.h
@@ -54,8 +54,7 @@
 int  nvkm_device_ctor(const struct nvkm_device_func *,
 		      const struct nvkm_device_quirk *,
 		      struct device *, enum nvkm_device_type, u64 handle,
-		      const char *name, const char *cfg, const char *dbg,
-		      struct nvkm_device *);
+		      const char *name, struct nvkm_device *);
 int  nvkm_device_init(struct nvkm_device *);
 int  nvkm_device_fini(struct nvkm_device *, bool suspend);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c
index d1c294f00665..bb514ccdfff4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c
@@ -310,7 +310,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
 	tdev->gpu_speedo_id = tegra_sku_info.gpu_speedo_id;
 	ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
 			       NVKM_DEVICE_TEGRA, pdev->id, NULL,
-			       cfg, dbg, &tdev->device);
+			       &tdev->device);
 	if (ret)
 		goto powerdown;
 
-- 
2.44.0



More information about the Nouveau mailing list