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 <bske...@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

Reply via email to