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

Commit 6cf813fb authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/device: prepare for new-style subdevs



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7974dd1b
Loading
Loading
Loading
Loading
+48 −2
Original line number Diff line number Diff line
@@ -84,9 +84,9 @@ struct nvkm_device {

	struct nvkm_event event;

	const char *cname;
	u64 disable_mask;

	const struct nvkm_device_chip *chip;
	enum {
		NV_04    = 0x04,
		NV_10    = 0x10,
@@ -104,7 +104,6 @@ struct nvkm_device {
	u32 crystal;

	struct nvkm_oclass *oclass[NVDEV_SUBDEV_NR];
	struct nvkm_object *subdev[NVDEV_SUBDEV_NR];

	struct {
		struct notifier_block nb;
@@ -153,6 +152,9 @@ struct nvkm_device {
	struct nouveau_platform_gpu *gpu;
};

struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int index);
struct nvkm_engine *nvkm_device_engine(struct nvkm_device *, int index);

struct nvkm_device_func {
	struct nvkm_device_pci *(*pci)(struct nvkm_device *);
	struct nvkm_device_tegra *(*tegra)(struct nvkm_device *);
@@ -164,6 +166,50 @@ struct nvkm_device_func {
struct nvkm_device_quirk {
};

struct nvkm_device_chip {
	const char *name;

	int (*bar    )(struct nvkm_device *, int idx, struct nvkm_bar **);
	int (*bios   )(struct nvkm_device *, int idx, struct nvkm_bios **);
	int (*bus    )(struct nvkm_device *, int idx, struct nvkm_bus **);
	int (*clk    )(struct nvkm_device *, int idx, struct nvkm_clk **);
	int (*devinit)(struct nvkm_device *, int idx, struct nvkm_devinit **);
	int (*fb     )(struct nvkm_device *, int idx, struct nvkm_fb **);
	int (*fuse   )(struct nvkm_device *, int idx, struct nvkm_fuse **);
	int (*gpio   )(struct nvkm_device *, int idx, struct nvkm_gpio **);
	int (*i2c    )(struct nvkm_device *, int idx, struct nvkm_i2c **);
	int (*ibus   )(struct nvkm_device *, int idx, struct nvkm_subdev **);
	int (*imem   )(struct nvkm_device *, int idx, struct nvkm_instmem **);
	int (*ltc    )(struct nvkm_device *, int idx, struct nvkm_ltc **);
	int (*mc     )(struct nvkm_device *, int idx, struct nvkm_mc **);
	int (*mmu    )(struct nvkm_device *, int idx, struct nvkm_mmu **);
	int (*mxm    )(struct nvkm_device *, int idx, struct nvkm_subdev **);
	int (*pmu    )(struct nvkm_device *, int idx, struct nvkm_pmu **);
	int (*therm  )(struct nvkm_device *, int idx, struct nvkm_therm **);
	int (*timer  )(struct nvkm_device *, int idx, struct nvkm_timer **);
	int (*volt   )(struct nvkm_device *, int idx, struct nvkm_volt **);

	int (*bsp    )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*ce[3]  )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*cipher )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*disp   )(struct nvkm_device *, int idx, struct nvkm_disp **);
	int (*dma    )(struct nvkm_device *, int idx, struct nvkm_dmaeng **);
	int (*fifo   )(struct nvkm_device *, int idx, struct nvkm_fifo **);
	int (*gr     )(struct nvkm_device *, int idx, struct nvkm_gr **);
	int (*ifb    )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*me     )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*mpeg   )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*msenc  )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*mspdec )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*msppp  )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*msvld  )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*pm     )(struct nvkm_device *, int idx, struct nvkm_pm **);
	int (*sec    )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*sw     )(struct nvkm_device *, int idx, struct nvkm_sw **);
	int (*vic    )(struct nvkm_device *, int idx, struct nvkm_engine **);
	int (*vp     )(struct nvkm_device *, int idx, struct nvkm_engine **);
};

struct nvkm_device *nvkm_device_find(u64 name);
int nvkm_device_list(u64 *name, int size);

+10 −0
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ static int
nvkm_engine_fini(struct nvkm_subdev *obj, bool suspend)
{
	struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev);
	if (engine->subdev.object.oclass)
		return engine->subdev.object.oclass->ofuncs->fini(&engine->subdev.object, suspend);
	if (engine->func->fini)
		return engine->func->fini(engine, suspend);
	return 0;
@@ -86,6 +88,9 @@ nvkm_engine_init(struct nvkm_subdev *obj)
		return ret;
	}

	if (engine->subdev.object.oclass)
		return engine->subdev.object.oclass->ofuncs->init(&engine->subdev.object);

	if (engine->func->oneinit && !engine->subdev.oneinit) {
		nvkm_trace(subdev, "one-time init running...\n");
		time = ktime_to_us(ktime_get());
@@ -110,6 +115,10 @@ static void *
nvkm_engine_dtor(struct nvkm_subdev *obj)
{
	struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev);
	if (engine->subdev.object.oclass) {
		engine->subdev.object.oclass->ofuncs->dtor(&engine->subdev.object);
		return NULL;
	}
	if (engine->func->dtor)
		return engine->func->dtor(engine);
	return engine;
@@ -201,5 +210,6 @@ nvkm_engine_create_(struct nvkm_object *parent, struct nvkm_object *engobj,

	INIT_LIST_HEAD(&engine->contexts);
	spin_lock_init(&engine->lock);
	engine->subdev.func = &nvkm_engine_func;
	return 0;
}
+14 −11
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
	struct nvkm_object *engctx = NULL;
	struct nvkm_object *object = NULL;
	struct nvkm_parent *parent;
	struct nvkm_object *engine;
	struct nvkm_engine *engine;
	struct nvkm_oclass *oclass;
	u32 _handle, _oclass;
	int ret;
@@ -117,7 +117,8 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
	parent = nv_parent(handle->object);

	/* check that parent supports the requested subclass */
	ret = nvkm_parent_sclass(&parent->object, _oclass, &engine, &oclass);
	ret = nvkm_parent_sclass(&parent->object, _oclass,
				 (struct nvkm_object **)&engine, &oclass);
	if (ret) {
		nvif_debug(&parent->object, "illegal class 0x%04x\n", _oclass);
		goto fail_class;
@@ -128,18 +129,20 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
	 * state calculated at init (ie. default context construction)
	 */
	if (engine) {
		ret = nvkm_object_inc(engine);
		if (ret)
		engine = nvkm_engine_ref(engine);
		if (IS_ERR(engine)) {
			ret = PTR_ERR(engine);
			engine = NULL;
			goto fail_class;
		}
	}

	/* if engine requires it, create a context object to insert
	 * between the parent and its children (eg. PGRAPH context)
	 */
	if (engine && nv_engine(engine)->cclass) {
		ret = nvkm_object_old(&parent->object, engine,
				       nv_engine(engine)->cclass,
				       data, size, &engctx);
	if (engine && engine->cclass) {
		ret = nvkm_object_old(&parent->object, &engine->subdev.object,
				      engine->cclass, data, size, &engctx);
		if (ret)
			goto fail_engctx;
	} else {
@@ -147,7 +150,8 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
	}

	/* finally, create new object and bind it to its handle */
	ret = nvkm_object_old(engctx, engine, oclass, data, size, &object);
	ret = nvkm_object_old(engctx, &engine->subdev.object, oclass,
			      data, size, &object);
	client->data = object;
	if (ret)
		goto fail_ctor;
@@ -178,8 +182,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
fail_ctor:
	nvkm_object_ref(NULL, &engctx);
fail_engctx:
	if (engine)
		nvkm_object_dec(engine, false);
	nvkm_engine_unref(&engine);
fail_class:
	return ret;
}
+8 −40
Original line number Diff line number Diff line
@@ -201,6 +201,7 @@ nvkm_object_del(struct nvkm_object **pobject)
	if (object && !WARN_ON(!object->func)) {
		if (object->func->dtor)
			*pobject = object->func->dtor(object);
		nvkm_engine_unref(&object->engine);
		kfree(*pobject);
		*pobject = NULL;
	}
@@ -212,7 +213,7 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
{
	object->func = func;
	object->client = oclass->client;
	object->engine = oclass->engine;
	object->engine = nvkm_engine_ref(oclass->engine);
	object->oclass_name = oclass->base.oclass;
	object->handle = oclass->handle;
	object->parent = oclass->parent;
@@ -251,10 +252,11 @@ nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
}

int
nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine,
nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engobj,
		    struct nvkm_oclass *oclass, u32 pclass,
		    int size, void **pobject)
{
	struct nvkm_engine *engine = engobj ? nv_engine(engobj) : NULL;
	struct nvkm_object *object;

	object = *pobject = kzalloc(size, GFP_KERNEL);
@@ -262,7 +264,7 @@ nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine,
		return -ENOMEM;

	nvkm_object_ref(parent, &object->parent);
	nvkm_object_ref(engine, (struct nvkm_object **)&object->engine);
	object->engine = nvkm_engine_ref(engine);
	object->oclass = oclass;
	object->pclass = pclass;
	atomic_set(&object->refcount, 1);
@@ -287,7 +289,7 @@ _nvkm_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
void
nvkm_object_destroy(struct nvkm_object *object)
{
	nvkm_object_ref(NULL, (struct nvkm_object **)&object->engine);
	nvkm_engine_unref(&object->engine);
	nvkm_object_ref(NULL, &object->parent);
	kfree(object);
}
@@ -333,6 +335,7 @@ nvkm_object_old(struct nvkm_object *parent, struct nvkm_object *engine,
	}

	if (ret == 0) {
		if (!nv_iclass(object, NV_SUBDEV_CLASS))
			atomic_set(&object->refcount, 1);
	}

@@ -370,14 +373,6 @@ nvkm_object_inc(struct nvkm_object *object)
			goto fail_parent;
	}

	if (object->engine) {
		mutex_lock(&nv_subdev(object->engine)->mutex);
		ret = nvkm_object_inc(&object->engine->subdev.object);
		mutex_unlock(&nv_subdev(object->engine)->mutex);
		if (ret)
			goto fail_engine;
	}

	ret = nvkm_object_init(object);
	atomic_set(&object->usecount, 1);
	if (ret)
@@ -386,12 +381,6 @@ nvkm_object_inc(struct nvkm_object *object)
	return 0;

fail_self:
	if (object->engine) {
		mutex_lock(&nv_subdev(object->engine)->mutex);
		nvkm_object_dec(&object->engine->subdev.object, false);
		mutex_unlock(&nv_subdev(object->engine)->mutex);
	}
fail_engine:
	if (object->parent)
		 nvkm_object_dec(object->parent, false);
fail_parent:
@@ -405,12 +394,6 @@ nvkm_object_decf(struct nvkm_object *object)
	nvkm_object_fini(object, false);
	atomic_set(&object->usecount, 0);

	if (object->engine) {
		mutex_lock(&nv_subdev(object->engine)->mutex);
		nvkm_object_dec(&object->engine->subdev.object, false);
		mutex_unlock(&nv_subdev(object->engine)->mutex);
	}

	if (object->parent)
		nvkm_object_dec(object->parent, false);

@@ -427,14 +410,6 @@ nvkm_object_decs(struct nvkm_object *object)
	if (ret)
		return ret;

	if (object->engine) {
		mutex_lock(&nv_subdev(object->engine)->mutex);
		ret = nvkm_object_dec(&object->engine->subdev.object, true);
		mutex_unlock(&nv_subdev(object->engine)->mutex);
		if (ret)
			goto fail_engine;
	}

	if (object->parent) {
		ret = nvkm_object_dec(object->parent, true);
		if (ret)
@@ -444,13 +419,6 @@ nvkm_object_decs(struct nvkm_object *object)
	return 0;

fail_parent:
	if (object->engine) {
		mutex_lock(&nv_subdev(object->engine)->mutex);
		nvkm_object_inc(&object->engine->subdev.object);
		mutex_unlock(&nv_subdev(object->engine)->mutex);
	}

fail_engine:
	nvkm_object_init(object);

	return ret;
+34 −5
Original line number Diff line number Diff line
@@ -74,6 +74,12 @@ nvkm_subdev_name[64] = {
void
nvkm_subdev_intr(struct nvkm_subdev *subdev)
{
	if (subdev->object.oclass) {
		if (subdev->intr)
			subdev->intr(subdev);
		return;
	}

	if (subdev->func->intr)
		subdev->func->intr(subdev);
}
@@ -85,10 +91,18 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
	const char *action = suspend ? "suspend" : "fini";
	u32 pmc_enable = subdev->pmc_enable;
	s64 time;
	int ret;

	nvkm_trace(subdev, "%s running...\n", action);
	time = ktime_to_us(ktime_get());

	if (!subdev->func) {
		ret = subdev->object.oclass->ofuncs->fini(&subdev->object, suspend);
		if (ret)
			return ret;
		goto done;
	}

	if (subdev->func->fini) {
		int ret = subdev->func->fini(subdev, suspend);
		if (ret) {
@@ -104,6 +118,7 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
		nvkm_rd32(device, 0x000200);
	}

done:
	time = ktime_to_us(ktime_get()) - time;
	nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
	return 0;
@@ -117,7 +132,7 @@ nvkm_subdev_preinit(struct nvkm_subdev *subdev)
	nvkm_trace(subdev, "preinit running...\n");
	time = ktime_to_us(ktime_get());

	if (subdev->func->preinit) {
	if (!subdev->object.oclass && subdev->func->preinit) {
		int ret = subdev->func->preinit(subdev);
		if (ret) {
			nvkm_error(subdev, "preinit failed, %d\n", ret);
@@ -139,6 +154,13 @@ nvkm_subdev_init(struct nvkm_subdev *subdev)
	nvkm_trace(subdev, "init running...\n");
	time = ktime_to_us(ktime_get());

	if (!subdev->func) {
		ret = subdev->object.oclass->ofuncs->init(&subdev->object);
		if (ret)
			return ret;
		goto done;
	}

	if (subdev->func->oneinit && !subdev->oneinit) {
		s64 time;
		nvkm_trace(subdev, "one-time init running...\n");
@@ -162,6 +184,7 @@ nvkm_subdev_init(struct nvkm_subdev *subdev)
		}
	}

done:
	time = ktime_to_us(ktime_get()) - time;
	nvkm_trace(subdev, "init completed in %lldus\n", time);
	return 0;
@@ -172,6 +195,12 @@ nvkm_subdev_del(struct nvkm_subdev **psubdev)
{
	struct nvkm_subdev *subdev = *psubdev;
	s64 time;

	if (subdev && subdev->object.oclass) {
		subdev->object.oclass->ofuncs->dtor(&subdev->object);
		return;
	}

	if (subdev && !WARN_ON(!subdev->func)) {
		nvkm_trace(subdev, "destroy running...\n");
		time = ktime_to_us(ktime_get());
@@ -211,8 +240,10 @@ nvkm_subdev(void *obj, int idx)
	struct nvkm_object *object = nv_object(obj);
	while (object && !nv_iclass(object, NV_SUBDEV_CLASS))
		object = object->parent;
	if (object == NULL || !object->parent || nv_subidx(nv_subdev(object)) != idx)
		object = nv_device(obj)->subdev[idx];
	if (object == NULL || !object->parent || nv_subidx(nv_subdev(object)) != idx) {
		struct nvkm_device *device = nv_device(obj);
		return nvkm_device_subdev(device, idx);
	}
	return object ? nv_subdev(object) : NULL;
}

@@ -266,8 +297,6 @@ _nvkm_subdev_fini(struct nvkm_object *object, bool suspend)
void
nvkm_subdev_destroy(struct nvkm_subdev *subdev)
{
	int subidx = nv_hclass(subdev) & 0xff;
	nv_device(subdev)->subdev[subidx] = NULL;
	nvkm_object_destroy(&subdev->object);
}

Loading