drm/nouveau/object: implement support for new-style nvkm_object
authorBen Skeggs <bskeggs@redhat.com>
Thu, 20 Aug 2015 04:54:16 +0000 (14:54 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 28 Aug 2015 02:40:34 +0000 (12:40 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
drivers/gpu/drm/nouveau/include/nvkm/core/object.h
drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c
drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
drivers/gpu/drm/nouveau/nvkm/core/object.c
drivers/gpu/drm/nouveau/nvkm/core/ramht.c
drivers/gpu/drm/nouveau/nvkm/core/subdev.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c

index 4697578..2260aef 100644 (file)
@@ -68,8 +68,12 @@ void _nvkm_gpuobj_wr32(struct nvkm_object *, u64, u32);
        struct nvkm_gpuobj *_gpuobj = (o);                                     \
        (void)_gpuobj;                                                         \
 } while(0)
-#define nvkm_ro32(o,a)   nv_ofuncs(o)->rd32(&(o)->object, (a))
-#define nvkm_wo32(o,a,d) nv_ofuncs(o)->wr32(&(o)->object, (a), (d))
+#define nvkm_ro32(o,a) ({                                                      \
+       u32 _data;                                                             \
+       nvkm_object_rd32(&(o)->object, (a), &_data);                           \
+       _data;                                                                 \
+})
+#define nvkm_wo32(o,a,d) nvkm_object_wr32(&(o)->object, (a), (d))
 #define nvkm_mo32(o,a,m,d) ({                                                  \
        u32 _addr = (a), _data = nvkm_ro32((o), _addr);                        \
        nvkm_wo32((o), _addr, (_data & ~(m)) | (d));                           \
index 39a4962..84040a3 100644 (file)
@@ -2,6 +2,8 @@
 #define __NVKM_OBJECT_H__
 #include <core/os.h>
 #include <core/debug.h>
+struct nvkm_event;
+struct nvkm_gpuobj;
 
 #define NV_PARENT_CLASS 0x80000000
 #define NV_NAMEDB_CLASS 0x40000000
 #define NV_ENGCTX_CLASS 0x01000000
 
 struct nvkm_object {
+       const struct nvkm_object_func *func;
+       struct nvkm_client *client;
+       struct nvkm_engine *engine;
+       u32 oclass_name;
+       u32 handle;
+       struct nvkm_object *parent;
        struct nvkm_oclass *oclass;
        u32 pclass;
-       struct nvkm_object *parent;
-       struct nvkm_engine *engine;
        atomic_t refcount;
        atomic_t usecount;
 #if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
@@ -26,12 +32,44 @@ struct nvkm_object {
 #endif
 };
 
+struct nvkm_object_func {
+       void *(*dtor)(struct nvkm_object *);
+       int (*init)(struct nvkm_object *);
+       int (*fini)(struct nvkm_object *, bool suspend);
+       int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size);
+       int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **);
+       int (*map)(struct nvkm_object *, u64 *addr, u32 *size);
+       int (*rd08)(struct nvkm_object *, u64 addr, u8 *data);
+       int (*rd16)(struct nvkm_object *, u64 addr, u16 *data);
+       int (*rd32)(struct nvkm_object *, u64 addr, u32 *data);
+       int (*wr08)(struct nvkm_object *, u64 addr, u8 data);
+       int (*wr16)(struct nvkm_object *, u64 addr, u16 data);
+       int (*wr32)(struct nvkm_object *, u64 addr, u32 data);
+       int (*bind)(struct nvkm_object *, struct nvkm_gpuobj *, int align,
+                   struct nvkm_gpuobj **);
+       int (*sclass)(struct nvkm_object *, int index, struct nvkm_oclass *);
+};
+
+void nvkm_object_ctor(const struct nvkm_object_func *,
+                     const struct nvkm_oclass *, struct nvkm_object *);
+int nvkm_object_new_(const struct nvkm_object_func *,
+                    const struct nvkm_oclass *, void *data, u32 size,
+                    struct nvkm_object **);
+int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size,
+                   struct nvkm_object **);
+int nvkm_object_init(struct nvkm_object *);
+int nvkm_object_fini(struct nvkm_object *, bool suspend);
+int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size);
+int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **);
+int nvkm_object_map(struct nvkm_object *, u64 *addr, u32 *size);
 int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8  *data);
 int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data);
 int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data);
 int nvkm_object_wr08(struct nvkm_object *, u64 addr, u8   data);
 int nvkm_object_wr16(struct nvkm_object *, u64 addr, u16  data);
 int nvkm_object_wr32(struct nvkm_object *, u64 addr, u32  data);
+int nvkm_object_bind(struct nvkm_object *, struct nvkm_gpuobj *, int align,
+                    struct nvkm_gpuobj **);
 
 static inline struct nvkm_object *
 nv_object(void *obj)
@@ -59,6 +97,15 @@ int _nvkm_object_ctor(struct nvkm_object *, struct nvkm_object *,
 
 extern struct nvkm_ofuncs nvkm_object_ofuncs;
 
+struct nvkm_sclass {
+       int minver;
+       int maxver;
+       s32 oclass;
+       const struct nvkm_object_func *func;
+       int (*ctor)(const struct nvkm_oclass *, void *data, u32 size,
+                   struct nvkm_object **);
+};
+
 /* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
  * ".data". */
 struct nvkm_oclass {
@@ -66,6 +113,16 @@ struct nvkm_oclass {
        struct nvkm_ofuncs * const ofuncs;
        struct nvkm_omthds * const omthds;
        struct lock_class_key lock_class_key;
+
+       int (*ctor)(const struct nvkm_oclass *, void *data, u32 size,
+                   struct nvkm_object **);
+       struct nvkm_sclass base;
+       const void *priv;
+       const void *engn;
+       u64 object;
+       struct nvkm_client *client;
+       struct nvkm_object *parent;
+       struct nvkm_engine *engine;
 };
 
 #define nv_oclass(o)    nv_object(o)->oclass
@@ -87,7 +144,6 @@ struct nvkm_omthds {
        int (*call)(struct nvkm_object *, u32, void *, u32);
 };
 
-struct nvkm_event;
 struct nvkm_ofuncs {
        int  (*ctor)(struct nvkm_object *, struct nvkm_object *,
                     struct nvkm_oclass *, void *data, u32 size,
index 1ca5479..bc4b3c2 100644 (file)
@@ -182,20 +182,20 @@ u32
 _nvkm_gpuobj_rd32(struct nvkm_object *object, u64 addr)
 {
        struct nvkm_gpuobj *gpuobj = nv_gpuobj(object);
-       struct nvkm_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent);
+       u32 data;
        if (gpuobj->node)
                addr += gpuobj->node->offset;
-       return pfuncs->rd32(gpuobj->parent, addr);
+       nvkm_object_rd32(gpuobj->parent, addr, &data);
+       return data;
 }
 
 void
 _nvkm_gpuobj_wr32(struct nvkm_object *object, u64 addr, u32 data)
 {
        struct nvkm_gpuobj *gpuobj = nv_gpuobj(object);
-       struct nvkm_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent);
        if (gpuobj->node)
                addr += gpuobj->node->offset;
-       pfuncs->wr32(gpuobj->parent, addr, data);
+       nvkm_object_wr32(gpuobj->parent, addr, data);
 }
 
 static struct nvkm_oclass
index 7a15b15..6e5ff94 100644 (file)
@@ -152,6 +152,8 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
        if (ret)
                goto fail_ctor;
 
+       object->handle = _handle;
+
        ret = nvkm_object_inc(object);
        if (ret)
                goto fail_init;
@@ -205,7 +207,6 @@ static int
 nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size)
 {
        struct nvkm_object *object = handle->object;
-       struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs;
        union {
                struct nvif_ioctl_mthd_v0 v0;
        } *args = data;
@@ -215,8 +216,7 @@ nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size)
        if (nvif_unpack(args->v0, 0, 0, true)) {
                nvif_ioctl(object, "mthd vers %d mthd %02x\n",
                           args->v0.version, args->v0.method);
-               if (ret = -ENODEV, ofuncs->mthd)
-                       ret = ofuncs->mthd(object, args->v0.method, data, size);
+               ret = nvkm_object_mthd(object, args->v0.method, data, size);
        }
 
        return ret;
@@ -296,7 +296,6 @@ static int
 nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size)
 {
        struct nvkm_object *object = handle->object;
-       struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs;
        union {
                struct nvif_ioctl_map_v0 v0;
        } *args = data;
@@ -305,10 +304,8 @@ nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size)
        nvif_ioctl(object, "map size %d\n", size);
        if (nvif_unpack(args->v0, 0, 0, false)) {
                nvif_ioctl(object, "map vers %d\n", args->v0.version);
-               if (ret = -ENODEV, ofuncs->map) {
-                       ret = ofuncs->map(object, &args->v0.handle,
-                                                 &args->v0.length);
-               }
+               ret = nvkm_object_map(object, &args->v0.handle,
+                                             &args->v0.length);
        }
 
        return ret;
@@ -335,7 +332,6 @@ static int
 nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size)
 {
        struct nvkm_object *object = handle->object;
-       struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs;
        union {
                struct nvif_ioctl_ntfy_new_v0 v0;
        } *args = data;
@@ -346,8 +342,7 @@ nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size)
        if (nvif_unpack(args->v0, 0, 0, true)) {
                nvif_ioctl(object, "ntfy new vers %d event %02x\n",
                           args->v0.version, args->v0.event);
-               if (ret = -ENODEV, ofuncs->ntfy)
-                       ret = ofuncs->ntfy(object, args->v0.event, &event);
+               ret = nvkm_object_ntfy(object, args->v0.event, &event);
                if (ret == 0) {
                        ret = nvkm_client_notify_new(object, event, data, size);
                        if (ret >= 0) {
index 1c117f0..0abee78 100644 (file)
 #include <core/engine.h>
 
 int
+nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+{
+       if (object->oclass) {
+               if (object->oclass->ofuncs->mthd)
+                       return object->oclass->ofuncs->mthd(object, mthd, data, size);
+               return -ENODEV;
+       }
+       if (likely(object->func->mthd))
+               return object->func->mthd(object, mthd, data, size);
+       return -ENODEV;
+}
+
+int
+nvkm_object_ntfy(struct nvkm_object *object, u32 mthd,
+                struct nvkm_event **pevent)
+{
+       if (object->oclass) {
+               if (object->oclass->ofuncs->ntfy)
+                       return object->oclass->ofuncs->ntfy(object, mthd, pevent);
+               return -ENODEV;
+       }
+       if (likely(object->func->ntfy))
+               return object->func->ntfy(object, mthd, pevent);
+       return -ENODEV;
+}
+
+int
+nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size)
+{
+       if (object->oclass) {
+               if (object->oclass->ofuncs->map)
+                       return object->oclass->ofuncs->map(object, addr, size);
+               return -ENODEV;
+       }
+       if (likely(object->func->map))
+               return object->func->map(object, addr, size);
+       return -ENODEV;
+}
+
+int
 nvkm_object_rd08(struct nvkm_object *object, u64 addr, u8 *data)
 {
-       const struct nvkm_oclass *oclass = object->oclass;
-       if (oclass->ofuncs && oclass->ofuncs->rd08) {
-               *data = oclass->ofuncs->rd08(object, addr);
-               return 0;
+       if (object->oclass) {
+               if (object->oclass->ofuncs->rd08) {
+                       *data = object->oclass->ofuncs->rd08(object, addr);
+                       return 0;
+               }
+               *data = 0x00;
+               return -ENODEV;
        }
-       *data = 0x00;
+       if (likely(object->func->rd08))
+               return object->func->rd08(object, addr, data);
        return -ENODEV;
 }
 
 int
 nvkm_object_rd16(struct nvkm_object *object, u64 addr, u16 *data)
 {
-       const struct nvkm_oclass *oclass = object->oclass;
-       if (oclass->ofuncs && oclass->ofuncs->rd16) {
-               *data = oclass->ofuncs->rd16(object, addr);
-               return 0;
+       if (object->oclass) {
+               if (object->oclass->ofuncs->rd16) {
+                       *data = object->oclass->ofuncs->rd16(object, addr);
+                       return 0;
+               }
+               *data = 0x0000;
+               return -ENODEV;
        }
-       *data = 0x0000;
+       if (likely(object->func->rd16))
+               return object->func->rd16(object, addr, data);
        return -ENODEV;
 }
 
 int
 nvkm_object_rd32(struct nvkm_object *object, u64 addr, u32 *data)
 {
-       const struct nvkm_oclass *oclass = object->oclass;
-       if (oclass->ofuncs && oclass->ofuncs->rd32) {
-               *data = oclass->ofuncs->rd32(object, addr);
-               return 0;
+       if (object->oclass) {
+               if (object->oclass->ofuncs->rd32) {
+                       *data = object->oclass->ofuncs->rd32(object, addr);
+                       return 0;
+               }
+               *data = 0x00000000;
+               return -ENODEV;
        }
-       *data = 0x0000;
+       if (likely(object->func->rd32))
+               return object->func->rd32(object, addr, data);
        return -ENODEV;
 }
 
 int
 nvkm_object_wr08(struct nvkm_object *object, u64 addr, u8 data)
 {
-       const struct nvkm_oclass *oclass = object->oclass;
-       if (oclass->ofuncs && oclass->ofuncs->wr08) {
-               oclass->ofuncs->wr08(object, addr, data);
-               return 0;
+       if (object->oclass) {
+               if (object->oclass->ofuncs->wr08) {
+                       object->oclass->ofuncs->wr08(object, addr, data);
+                       return 0;
+               }
+               return -ENODEV;
        }
+       if (likely(object->func->wr08))
+               return object->func->wr08(object, addr, data);
        return -ENODEV;
 }
 
 int
 nvkm_object_wr16(struct nvkm_object *object, u64 addr, u16 data)
 {
-       const struct nvkm_oclass *oclass = object->oclass;
-       if (oclass->ofuncs && oclass->ofuncs->wr16) {
-               oclass->ofuncs->wr16(object, addr, data);
-               return 0;
+       if (object->oclass) {
+               if (object->oclass->ofuncs->wr16) {
+                       object->oclass->ofuncs->wr16(object, addr, data);
+                       return 0;
+               }
+               return -ENODEV;
        }
+       if (likely(object->func->wr16))
+               return object->func->wr16(object, addr, data);
        return -ENODEV;
 }
 
 int
 nvkm_object_wr32(struct nvkm_object *object, u64 addr, u32 data)
 {
-       const struct nvkm_oclass *oclass = object->oclass;
-       if (oclass->ofuncs && oclass->ofuncs->wr32) {
-               oclass->ofuncs->wr32(object, addr, data);
-               return 0;
+       if (object->oclass) {
+               if (object->oclass->ofuncs->wr32) {
+                       object->oclass->ofuncs->wr32(object, addr, data);
+                       return 0;
+               }
+               return -ENODEV;
        }
+       if (likely(object->func->wr32))
+               return object->func->wr32(object, addr, data);
        return -ENODEV;
 }
 
 int
+nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
+                int align, struct nvkm_gpuobj **pgpuobj)
+{
+       if (object->oclass)
+               return -ENODEV;
+       if (object->func->bind)
+               return object->func->bind(object, gpuobj, align, pgpuobj);
+       return -ENODEV;
+}
+
+int
+nvkm_object_fini(struct nvkm_object *object, bool suspend)
+{
+       if (object->oclass)
+               return object->oclass->ofuncs->fini(object, suspend);
+       if (object->func->fini)
+               return object->func->fini(object, suspend);
+       return 0;
+}
+
+int
+nvkm_object_init(struct nvkm_object *object)
+{
+       if (object->oclass)
+               return object->oclass->ofuncs->init(object);
+       if (object->func->init)
+               return object->func->init(object);
+       return 0;
+}
+
+static void
+nvkm_object_del(struct nvkm_object **pobject)
+{
+       struct nvkm_object *object = *pobject;
+
+       if (object && object->oclass) {
+               object->oclass->ofuncs->dtor(object);
+               return;
+       }
+
+       if (object && !WARN_ON(!object->func)) {
+               if (object->func->dtor)
+                       *pobject = object->func->dtor(object);
+               kfree(*pobject);
+               *pobject = NULL;
+       }
+}
+
+void
+nvkm_object_ctor(const struct nvkm_object_func *func,
+                const struct nvkm_oclass *oclass, struct nvkm_object *object)
+{
+       object->func = func;
+       object->client = oclass->client;
+       object->engine = oclass->engine;
+       object->oclass_name = oclass->base.oclass;
+       object->handle = oclass->handle;
+       object->parent = oclass->parent;
+       atomic_set(&object->refcount, 1);
+       atomic_set(&object->usecount, 0);
+#ifdef NVKM_OBJECT_MAGIC
+       object->_magic = NVKM_OBJECT_MAGIC;
+#endif
+}
+
+int
+nvkm_object_new_(const struct nvkm_object_func *func,
+                const struct nvkm_oclass *oclass, void *data, u32 size,
+                struct nvkm_object **pobject)
+{
+       if (size == 0) {
+               if (!(*pobject = kzalloc(sizeof(**pobject), GFP_KERNEL)))
+                       return -ENOMEM;
+               nvkm_object_ctor(func, oclass, *pobject);
+               return 0;
+       }
+       return -ENOSYS;
+}
+
+static const struct nvkm_object_func
+nvkm_object_func = {
+};
+
+int
+nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+               struct nvkm_object **pobject)
+{
+       const struct nvkm_object_func *func =
+               oclass->base.func ? oclass->base.func : &nvkm_object_func;
+       return nvkm_object_new_(func, oclass, data, size, pobject);
+}
+
+int
 nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine,
                    struct nvkm_oclass *oclass, u32 pclass,
                    int size, void **pobject)
@@ -182,12 +339,6 @@ nvkm_object_old(struct nvkm_object *parent, struct nvkm_object *engine,
        return 0;
 }
 
-static void
-nvkm_object_dtor(struct nvkm_object *object)
-{
-       nv_ofuncs(object)->dtor(object);
-}
-
 void
 nvkm_object_ref(struct nvkm_object *obj, struct nvkm_object **ref)
 {
@@ -198,7 +349,7 @@ nvkm_object_ref(struct nvkm_object *obj, struct nvkm_object **ref)
        if (*ref) {
                int dead = atomic_dec_and_test(&(*ref)->refcount);
                if (dead)
-                       nvkm_object_dtor(*ref);
+                       nvkm_object_del(ref);
        }
 
        *ref = obj;
@@ -227,7 +378,7 @@ nvkm_object_inc(struct nvkm_object *object)
                        goto fail_engine;
        }
 
-       ret = nv_ofuncs(object)->init(object);
+       ret = nvkm_object_init(object);
        atomic_set(&object->usecount, 1);
        if (ret)
                goto fail_self;
@@ -251,7 +402,7 @@ fail_parent:
 static int
 nvkm_object_decf(struct nvkm_object *object)
 {
-       nv_ofuncs(object)->fini(object, false);
+       nvkm_object_fini(object, false);
        atomic_set(&object->usecount, 0);
 
        if (object->engine) {
@@ -271,7 +422,7 @@ nvkm_object_decs(struct nvkm_object *object)
 {
        int ret;
 
-       ret = nv_ofuncs(object)->fini(object, true);
+       ret = nvkm_object_fini(object, true);
        atomic_set(&object->usecount, 0);
        if (ret)
                return ret;
@@ -300,7 +451,7 @@ fail_parent:
        }
 
 fail_engine:
-       nv_ofuncs(object)->init(object);
+       nvkm_object_init(object);
 
        return ret;
 }
index c61bb0f..4717af0 100644 (file)
@@ -102,7 +102,7 @@ nvkm_ramht_new(struct nvkm_object *parent, struct nvkm_object *pargpu,
        int ret;
 
        ret = nvkm_gpuobj_create(parent, parent->engine ?
-                                &parent->engine->subdev.object : parent, /* <nv50 ramht */
+                                &parent->engine->subdev.object : NULL, /* <nv50 ramht */
                                 &nvkm_ramht_oclass, 0, pargpu, size,
                                 align, NVOBJ_FLAG_ZERO_ALLOC, &ramht);
        *pramht = ramht;
index 3f6795f..9e9e0ca 100644 (file)
@@ -41,7 +41,7 @@ nvkm_subdev_reset(struct nvkm_object *obj)
 {
        struct nvkm_subdev *subdev = container_of(obj, typeof(*subdev), object);
        nvkm_trace(subdev, "resetting...\n");
-       nv_ofuncs(subdev)->fini(&subdev->object, false);
+       nvkm_object_fini(&subdev->object, false);
        nvkm_trace(subdev, "reset\n");
 }
 
index 1fa3822..dd7fe30 100644 (file)
@@ -451,8 +451,8 @@ gf100_fifo_recover_work(struct work_struct *work)
 
        for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
                if ((engine = (void *)nvkm_engine(fifo, engn))) {
-                       nv_ofuncs(engine)->fini(engine, false);
-                       WARN_ON(nv_ofuncs(engine)->init(engine));
+                       nvkm_object_fini(engine, false);
+                       WARN_ON(nvkm_object_init(engine));
                }
        }
 
index 3562b79..9d75dba 100644 (file)
@@ -497,8 +497,8 @@ gk104_fifo_recover_work(struct work_struct *work)
 
        for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
                if ((engine = (void *)nvkm_engine(fifo, engn))) {
-                       nv_ofuncs(engine)->fini(engine, false);
-                       WARN_ON(nv_ofuncs(engine)->init(engine));
+                       nvkm_object_fini(engine, false);
+                       WARN_ON(nvkm_object_init(engine));
                }
                gk104_fifo_runlist_update(fifo, gk104_fifo_engidx(fifo, engn));
        }
index bbcc308..bf40509 100644 (file)
@@ -117,7 +117,7 @@ nv50_devinit_init(struct nvkm_object *object)
         * the vbios engineers didn't make the scripts just work...
         */
        if (init->base.post && ibus)
-               nv_ofuncs(ibus)->init(nv_object(ibus));
+               nvkm_object_init(&ibus->object);
 
        ret = nvkm_devinit_init(&init->base);
        if (ret)