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@xxxxxxxxxx> --- 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