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

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

drm/nouveau/subdev: implement support for new-style nvkm_subdev



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent cbea21e2
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -106,13 +106,10 @@ struct nvkm_sclass {
		    struct nvkm_object **);
};

/* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
 * ".data". */
struct nvkm_oclass {
	s32 handle;
	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 **);
+26 −4
Original line number Diff line number Diff line
@@ -7,17 +7,37 @@

struct nvkm_subdev {
	struct nvkm_object object;

	const struct nvkm_subdev_func *func;
	struct nvkm_device *device;
	int index;
	u32 pmc_enable;

	struct mutex mutex;
	const char *name, *sname;
	u32 debug;
	bool oneinit;

	void (*intr)(struct nvkm_subdev *);
	u32 unit;
};

struct nvkm_subdev_func {
	void *(*dtor)(struct nvkm_subdev *);
	int (*preinit)(struct nvkm_subdev *);
	int (*oneinit)(struct nvkm_subdev *);
	int (*init)(struct nvkm_subdev *);
	int (*fini)(struct nvkm_subdev *, bool suspend);
	void (*intr)(struct nvkm_subdev *);
};

extern const char *nvkm_subdev_name[64];
void nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *,
		      int index, u32 pmc_enable, struct nvkm_subdev *);
void nvkm_subdev_del(struct nvkm_subdev **);
int  nvkm_subdev_preinit(struct nvkm_subdev *);
int  nvkm_subdev_init(struct nvkm_subdev *);
int  nvkm_subdev_fini(struct nvkm_subdev *, bool suspend);
void nvkm_subdev_intr(struct nvkm_subdev *);

static inline struct nvkm_subdev *
nv_subdev(void *obj)
{
@@ -55,8 +75,10 @@ int _nvkm_subdev_fini(struct nvkm_object *, bool suspend);
/* subdev logging */
#define nvkm_printk_(s,l,p,f,a...) do {                                        \
	struct nvkm_subdev *_subdev = (s);                                     \
	if (_subdev->debug >= (l))                                             \
		dev_##p(_subdev->device->dev, "%s: "f, _subdev->sname, ##a);   \
	if (_subdev->debug >= (l)) {                                           \
		dev_##p(_subdev->device->dev, "%s: "f,                         \
			nvkm_subdev_name[_subdev->index], ##a);                \
	}                                                                      \
} while(0)
#define nvkm_printk(s,l,p,f,a...) nvkm_printk_((s), NV_DBG_##l, p, f, ##a)
#define nvkm_fatal(s,f,a...) nvkm_printk((s), FATAL,   crit, f, ##a)
+4 −4
Original line number Diff line number Diff line
@@ -144,11 +144,11 @@ nvkm_engctx_init(struct nvkm_engctx *engctx)

	if (ret) {
		nvkm_error(pardev, "failed to attach %s context, %d\n",
			   subdev->name, ret);
			   nvkm_subdev_name[subdev->index], ret);
		return ret;
	}

	nvkm_trace(pardev, "attached %s context\n", subdev->name);
	nvkm_trace(pardev, "attached %s context\n", nvkm_subdev_name[subdev->index]);
	return 0;
}

@@ -171,11 +171,11 @@ nvkm_engctx_fini(struct nvkm_engctx *engctx, bool suspend)

	if (ret) {
		nvkm_error(pardev, "failed to detach %s context, %d\n",
			   subdev->name, ret);
			   nvkm_subdev_name[subdev->index], ret);
		return ret;
	}

	nvkm_trace(pardev, "detached %s context\n", subdev->name);
	nvkm_trace(pardev, "detached %s context\n", nvkm_subdev_name[subdev->index]);
	return nvkm_gpuobj_fini(&engctx->gpuobj, suspend);
}

+185 −4
Original line number Diff line number Diff line
@@ -25,6 +25,186 @@
#include <core/device.h>
#include <core/option.h>

static struct lock_class_key nvkm_subdev_lock_class[NVDEV_SUBDEV_NR];

const char *
nvkm_subdev_name[64] = {
	[NVDEV_SUBDEV_BAR    ] = "bar",
	[NVDEV_SUBDEV_VBIOS  ] = "bios",
	[NVDEV_SUBDEV_BUS    ] = "bus",
	[NVDEV_SUBDEV_CLK    ] = "clk",
	[NVDEV_SUBDEV_DEVINIT] = "devinit",
	[NVDEV_SUBDEV_FB     ] = "fb",
	[NVDEV_SUBDEV_FUSE   ] = "fuse",
	[NVDEV_SUBDEV_GPIO   ] = "gpio",
	[NVDEV_SUBDEV_I2C    ] = "i2c",
	[NVDEV_SUBDEV_IBUS   ] = "priv",
	[NVDEV_SUBDEV_INSTMEM] = "imem",
	[NVDEV_SUBDEV_LTC    ] = "ltc",
	[NVDEV_SUBDEV_MC     ] = "mc",
	[NVDEV_SUBDEV_MMU    ] = "mmu",
	[NVDEV_SUBDEV_MXM    ] = "mxm",
	[NVDEV_SUBDEV_PMU    ] = "pmu",
	[NVDEV_SUBDEV_THERM  ] = "therm",
	[NVDEV_SUBDEV_TIMER  ] = "tmr",
	[NVDEV_SUBDEV_VOLT   ] = "volt",
	[NVDEV_ENGINE_BSP    ] = "bsp",
	[NVDEV_ENGINE_CE0    ] = "ce0",
	[NVDEV_ENGINE_CE1    ] = "ce1",
	[NVDEV_ENGINE_CE2    ] = "ce2",
	[NVDEV_ENGINE_CIPHER ] = "cipher",
	[NVDEV_ENGINE_DISP   ] = "disp",
	[NVDEV_ENGINE_DMAOBJ ] = "dma",
	[NVDEV_ENGINE_FIFO   ] = "fifo",
	[NVDEV_ENGINE_GR     ] = "gr",
	[NVDEV_ENGINE_IFB    ] = "ifb",
	[NVDEV_ENGINE_ME     ] = "me",
	[NVDEV_ENGINE_MPEG   ] = "mpeg",
	[NVDEV_ENGINE_MSENC  ] = "msenc",
	[NVDEV_ENGINE_MSPDEC ] = "mspdec",
	[NVDEV_ENGINE_MSPPP  ] = "msppp",
	[NVDEV_ENGINE_MSVLD  ] = "msvld",
	[NVDEV_ENGINE_PM     ] = "pm",
	[NVDEV_ENGINE_SEC    ] = "sec",
	[NVDEV_ENGINE_SW     ] = "sw",
	[NVDEV_ENGINE_VIC    ] = "vic",
	[NVDEV_ENGINE_VP     ] = "vp",
};

void
nvkm_subdev_intr(struct nvkm_subdev *subdev)
{
	if (subdev->func->intr)
		subdev->func->intr(subdev);
}

int
nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
{
	struct nvkm_device *device = subdev->device;
	const char *action = suspend ? "suspend" : "fini";
	u32 pmc_enable = subdev->pmc_enable;
	s64 time;

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

	if (subdev->func->fini) {
		int ret = subdev->func->fini(subdev, suspend);
		if (ret) {
			nvkm_error(subdev, "%s failed, %d\n", action, ret);
			if (suspend)
				return ret;
		}
	}

	if (pmc_enable) {
		nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
		nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
		nvkm_rd32(device, 0x000200);
	}

	time = ktime_to_us(ktime_get()) - time;
	nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
	return 0;
}

int
nvkm_subdev_preinit(struct nvkm_subdev *subdev)
{
	s64 time;

	nvkm_trace(subdev, "preinit running...\n");
	time = ktime_to_us(ktime_get());

	if (subdev->func->preinit) {
		int ret = subdev->func->preinit(subdev);
		if (ret) {
			nvkm_error(subdev, "preinit failed, %d\n", ret);
			return ret;
		}
	}

	time = ktime_to_us(ktime_get()) - time;
	nvkm_trace(subdev, "preinit completed in %lldus\n", time);
	return 0;
}

int
nvkm_subdev_init(struct nvkm_subdev *subdev)
{
	s64 time;
	int ret;

	nvkm_trace(subdev, "init running...\n");
	time = ktime_to_us(ktime_get());

	if (subdev->func->oneinit && !subdev->oneinit) {
		s64 time;
		nvkm_trace(subdev, "one-time init running...\n");
		time = ktime_to_us(ktime_get());
		ret = subdev->func->oneinit(subdev);
		if (ret) {
			nvkm_error(subdev, "one-time init failed, %d\n", ret);
			return ret;
		}

		subdev->oneinit = true;
		time = ktime_to_us(ktime_get()) - time;
		nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
	}

	if (subdev->func->init) {
		ret = subdev->func->init(subdev);
		if (ret) {
			nvkm_error(subdev, "init failed, %d\n", ret);
			return ret;
		}
	}

	time = ktime_to_us(ktime_get()) - time;
	nvkm_trace(subdev, "init completed in %lldus\n", time);
	return 0;
}

void
nvkm_subdev_del(struct nvkm_subdev **psubdev)
{
	struct nvkm_subdev *subdev = *psubdev;
	s64 time;
	if (subdev && !WARN_ON(!subdev->func)) {
		nvkm_trace(subdev, "destroy running...\n");
		time = ktime_to_us(ktime_get());
		if (subdev->func->dtor)
			*psubdev = subdev->func->dtor(subdev);
		time = ktime_to_us(ktime_get()) - time;
		nvkm_trace(subdev, "destroy completed in %lldus\n", time);
		kfree(*psubdev);
		*psubdev = NULL;
	}
}

static const struct nvkm_object_func
nvkm_subdev_func = {
};

void
nvkm_subdev_ctor(const struct nvkm_subdev_func *func,
		 struct nvkm_device *device, int index, u32 pmc_enable,
		 struct nvkm_subdev *subdev)
{
	const char *name = nvkm_subdev_name[index];
	struct nvkm_oclass hack = {};
	nvkm_object_ctor(&nvkm_subdev_func, &hack, &subdev->object);
	subdev->func = func;
	subdev->device = device;
	subdev->index = index;
	subdev->pmc_enable = pmc_enable;

	__mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[index]);
	subdev->debug = nvkm_dbgopt(device->dbgopt, name);
}

struct nvkm_subdev *
nvkm_subdev(void *obj, int idx)
{
@@ -103,6 +283,8 @@ nvkm_subdev_create_(struct nvkm_object *parent, struct nvkm_object *engine,
		    const char *subname, const char *sysname,
		    int size, void **pobject)
{
	const int subidx = oclass->handle & 0xff;
	const char *name = nvkm_subdev_name[subidx];
	struct nvkm_subdev *subdev;
	int ret;

@@ -112,13 +294,12 @@ nvkm_subdev_create_(struct nvkm_object *parent, struct nvkm_object *engine,
	if (ret)
		return ret;

	__mutex_init(&subdev->mutex, subname, &oclass->lock_class_key);
	subdev->name = subname;
	subdev->sname = sysname;
	__mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[subidx]);
	subdev->index = subidx;

	if (parent) {
		struct nvkm_device *device = nv_device(parent);
		subdev->debug = nvkm_dbgopt(device->dbgopt, subname);
		subdev->debug = nvkm_dbgopt(device->dbgopt, name);
		subdev->device = device;
	} else {
		subdev->device = nv_device(subdev);
+1 −1
Original line number Diff line number Diff line
@@ -471,7 +471,7 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
	unsigned long flags;

	nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n",
		   engine->subdev.name, chid);
		   nvkm_subdev_name[engine->subdev.index], chid);

	nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
	chan->state = KILLED;
Loading