drm/nouveau/nvkm: add macros for subdev layout
authorBen Skeggs <bskeggs@redhat.com>
Sun, 6 Dec 2020 02:14:13 +0000 (12:14 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 11 Feb 2021 01:49:48 +0000 (11:49 +1000)
Rather than having to add new engines / engine instances to multiple places,
define everything in include/nvkm/core/layout.h and use macros to generate
the required plumbing.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/include/nvkm/core/layout.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
drivers/gpu/drm/nouveau/nvkm/core/subdev.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c

index b4c373b..66743f2 100644 (file)
@@ -3,6 +3,7 @@
 #define __NVKM_DEVICE_H__
 #include <core/oclass.h>
 #include <core/event.h>
+enum nvkm_subdev_type;
 
 #define nvkm_devidx nvkm_subdev_type
 
@@ -108,6 +109,11 @@ struct nvkm_device {
        struct nvkm_engine *vic;
        struct nvkm_engine *vp;
 
+#define NVKM_LAYOUT_ONCE(type,data,ptr) data *ptr;
+#define NVKM_LAYOUT_INST(type,data,ptr,cnt) data *ptr[cnt];
+#include <core/layout.h>
+#undef NVKM_LAYOUT_INST
+#undef NVKM_LAYOUT_ONCE
        struct list_head subdev;
 };
 
@@ -133,7 +139,15 @@ struct nvkm_device_quirk {
 
 struct nvkm_device_chip {
        const char *name;
-
+#define NVKM_LAYOUT_ONCE(type,data,ptr,...)                                                  \
+       struct {                                                                             \
+               u32 inst;                                                                    \
+               int (*ctor)(struct nvkm_device *, enum nvkm_subdev_type, int inst, data **); \
+       } ptr;
+#define NVKM_LAYOUT_INST(A...) NVKM_LAYOUT_ONCE(A)
+#include <core/layout.h>
+#undef NVKM_LAYOUT_INST
+#undef NVKM_LAYOUT_ONCE
        int (*acr     )(struct nvkm_device *, int idx, struct nvkm_acr **);
        int (*bar     )(struct nvkm_device *, int idx, struct nvkm_bar **);
        int (*bios    )(struct nvkm_device *, int idx, struct nvkm_bios **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h
new file mode 100644 (file)
index 0000000..7812f35
--- /dev/null
@@ -0,0 +1 @@
+/* SPDX-License-Identifier: MIT */
index a37f711..8f41393 100644 (file)
@@ -89,6 +89,7 @@ struct nvkm_subdev {
        u32 debug;
        struct list_head head;
 
+       void **pself;
        bool oneinit;
 };
 
@@ -111,6 +112,7 @@ void nvkm_subdev_ctor_(const struct nvkm_subdev_func *, bool old, struct nvkm_de
 #define nvkm_subdev_ctor_n(f,d,t,i,s) nvkm_subdev_ctor_((f), false, (d), (t), (i), (s))
 #define nvkm_subdev_ctor__(_1,_2,_3,_4,_5,IMPL,...) IMPL
 #define nvkm_subdev_ctor(A...) nvkm_subdev_ctor__(A, nvkm_subdev_ctor_n, nvkm_subdev_ctor_o)(A)
+void nvkm_subdev_disable(struct nvkm_device *, enum nvkm_subdev_type, int inst);
 void nvkm_subdev_del(struct nvkm_subdev **);
 int  nvkm_subdev_preinit(struct nvkm_subdev *);
 int  nvkm_subdev_init(struct nvkm_subdev *);
index 12a13d6..acfa3ba 100644 (file)
 
 const char *
 nvkm_subdev_type[NVKM_SUBDEV_NR] = {
+#define NVKM_LAYOUT_ONCE(type,data,ptr,...) [type] = #ptr,
+#define NVKM_LAYOUT_INST(A...) NVKM_LAYOUT_ONCE(A)
+#include <core/layout.h>
+#undef NVKM_LAYOUT_ONCE
+#undef NVKM_LAYOUT_INST
        [NVKM_SUBDEV_ACR     ] = "acr",
        [NVKM_SUBDEV_BAR     ] = "bar",
        [NVKM_SUBDEV_VBIOS   ] = "bios",
@@ -208,6 +213,19 @@ nvkm_subdev_del(struct nvkm_subdev **psubdev)
 }
 
 void
+nvkm_subdev_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
+{
+       struct nvkm_subdev *subdev;
+       list_for_each_entry(subdev, &device->subdev, head) {
+               if (subdev->type == type && subdev->inst == inst) {
+                       *subdev->pself = NULL;
+                       nvkm_subdev_del(&subdev);
+                       break;
+               }
+       }
+}
+
+void
 nvkm_subdev_ctor_(const struct nvkm_subdev_func *func, bool old,
                 struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
                 struct nvkm_subdev *subdev)
index a4d7d6c..de9f1d3 100644 (file)
@@ -3206,6 +3206,48 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
        }                                                                      \
        break
                switch (i) {
+#define NVKM_LAYOUT_ONCE(type,data,ptr) case type:                                           \
+       if (device->chip->ptr.inst && (subdev_mask & (BIT_ULL(type)))) {                     \
+               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;                               \
+               }                                                                            \
+       }                                                                                    \
+       break;
+#define NVKM_LAYOUT_INST(type,data,ptr,cnt) case type:                                       \
+       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)) && (subdev_mask & BIT_ULL(type))) {    \
+                       int inst = (device->chip->ptr.inst == 1) ? -1 : (j);                 \
+                       ret = device->chip->ptr.ctor(device, (type), inst, &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];                    \
+                       }                                                                    \
+               }                                                                            \
+       }                                                                                    \
+       break;
+#include <core/layout.h>
+#undef NVKM_LAYOUT_INST
+#undef NVKM_LAYOUT_ONCE
                _(NVKM_SUBDEV_ACR     ,      acr);
                _(NVKM_SUBDEV_BAR     ,      bar);
                _(NVKM_SUBDEV_VBIOS   ,     bios);