[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