Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cbea21e2 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/object: implement support for new-style nvkm_object



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 89c651e2
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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));                           \
+59 −3
Original line number Diff line number Diff line
@@ -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
@@ -13,10 +15,14 @@
#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,
+4 −4
Original line number Diff line number Diff line
@@ -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
+6 −11
Original line number Diff line number Diff line
@@ -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,11 +304,9 @@ 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,
		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) {
+189 −38
Original line number Diff line number Diff line
@@ -24,74 +24,231 @@
#include <core/object.h>
#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);
	if (object->oclass) {
		if (object->oclass->ofuncs->rd08) {
			*data = object->oclass->ofuncs->rd08(object, addr);
			return 0;
		}
		*data = 0x00;
		return -ENODEV;
	}
	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);
	if (object->oclass) {
		if (object->oclass->ofuncs->rd16) {
			*data = object->oclass->ofuncs->rd16(object, addr);
			return 0;
		}
		*data = 0x0000;
		return -ENODEV;
	}
	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);
	if (object->oclass) {
		if (object->oclass->ofuncs->rd32) {
			*data = object->oclass->ofuncs->rd32(object, addr);
			return 0;
		}
	*data = 0x0000;
		*data = 0x00000000;
		return -ENODEV;
	}
	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);
	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);
	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);
	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,
@@ -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 @@ nvkm_object_inc(struct nvkm_object *object)
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 @@ nvkm_object_decs(struct nvkm_object *object)
	}

fail_engine:
	nv_ofuncs(object)->init(object);
	nvkm_object_init(object);

	return ret;
}
Loading