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)); \
#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
#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)
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 {
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
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,
_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
if (ret)
goto fail_ctor;
+ object->handle = _handle;
+
ret = nvkm_object_inc(object);
if (ret)
goto fail_init;
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;
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;
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;
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;
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;
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) {
#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)
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)
{
if (*ref) {
int dead = atomic_dec_and_test(&(*ref)->refcount);
if (dead)
- nvkm_object_dtor(*ref);
+ nvkm_object_del(ref);
}
*ref = obj;
goto fail_engine;
}
- ret = nv_ofuncs(object)->init(object);
+ ret = nvkm_object_init(object);
atomic_set(&object->usecount, 1);
if (ret)
goto fail_self;
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) {
{
int ret;
- ret = nv_ofuncs(object)->fini(object, true);
+ ret = nvkm_object_fini(object, true);
atomic_set(&object->usecount, 0);
if (ret)
return ret;
}
fail_engine:
- nv_ofuncs(object)->init(object);
+ nvkm_object_init(object);
return ret;
}
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;
{
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");
}
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));
}
}
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));
}
* 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)