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

Commit 1f5ff7f5 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo/gk104: make use of topology info during gpfifo construction



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 19f89279
Loading
Loading
Loading
Loading
+12 −9
Original line number Original line Diff line number Diff line
@@ -3,19 +3,22 @@


struct kepler_channel_gpfifo_a_v0 {
struct kepler_channel_gpfifo_a_v0 {
	__u8  version;
	__u8  version;
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR                               0x01
	__u8  pad01[5];
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPDEC                           0x02
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPPP                            0x04
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSVLD                            0x08
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0                              0x10
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1                              0x20
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC                              0x40
	__u8  engine;
	__u16 chid;
	__u16 chid;
#define NVA06F_V0_ENGINE_SW                                          0x00000001
#define NVA06F_V0_ENGINE_GR                                          0x00000002
#define NVA06F_V0_ENGINE_MSVLD                                       0x00000010
#define NVA06F_V0_ENGINE_MSPDEC                                      0x00000020
#define NVA06F_V0_ENGINE_MSPPP                                       0x00000040
#define NVA06F_V0_ENGINE_MSENC                                       0x00000080
#define NVA06F_V0_ENGINE_CE0                                         0x00010000
#define NVA06F_V0_ENGINE_CE1                                         0x00020000
#define NVA06F_V0_ENGINE_CE2                                         0x00040000
	__u32 engines;
	__u32 ilength;
	__u32 ilength;
	__u64 ioffset;
	__u64 ioffset;
	__u64 vm;
	__u64 vm;
};
};


#define KEPLER_CHANNEL_GPFIFO_A_V0_NTFY_UEVENT                             0x00
#define NVA06F_V0_NTFY_UEVENT                                              0x00
#endif
#endif
+14 −4
Original line number Original line Diff line number Diff line
@@ -263,13 +263,23 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
	/* hack to allow channel engine type specification on kepler */
	/* hack to allow channel engine type specification on kepler */
	if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
	if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
		if (init->fb_ctxdma_handle != ~0)
		if (init->fb_ctxdma_handle != ~0)
			init->fb_ctxdma_handle = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
			init->fb_ctxdma_handle = NVA06F_V0_ENGINE_GR;
		else
		else {
			init->fb_ctxdma_handle = init->tt_ctxdma_handle;
			init->fb_ctxdma_handle = 0;
#define _(A,B) if (init->tt_ctxdma_handle & (A)) init->fb_ctxdma_handle |= (B)
			_(0x01, NVA06F_V0_ENGINE_GR);
			_(0x02, NVA06F_V0_ENGINE_MSPDEC);
			_(0x04, NVA06F_V0_ENGINE_MSPPP);
			_(0x08, NVA06F_V0_ENGINE_MSVLD);
			_(0x10, NVA06F_V0_ENGINE_CE0);
			_(0x20, NVA06F_V0_ENGINE_CE1);
			_(0x40, NVA06F_V0_ENGINE_MSENC);
#undef _
		}


		/* allow flips to be executed if this is a graphics channel */
		/* allow flips to be executed if this is a graphics channel */
		init->tt_ctxdma_handle = 0;
		init->tt_ctxdma_handle = 0;
		if (init->fb_ctxdma_handle == KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR)
		if (init->fb_ctxdma_handle == NVA06F_V0_ENGINE_GR)
			init->tt_ctxdma_handle = 1;
			init->tt_ctxdma_handle = 1;
	}
	}


+1 −1
Original line number Original line Diff line number Diff line
@@ -217,7 +217,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
	do {
	do {
		if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
		if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
			args.kepler.version = 0;
			args.kepler.version = 0;
			args.kepler.engine  = engine;
			args.kepler.engines = engine;
			args.kepler.ilength = 0x02000;
			args.kepler.ilength = 0x02000;
			args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
			args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
			args.kepler.vm = 0;
			args.kepler.vm = 0;
+3 −3
Original line number Original line Diff line number Diff line
@@ -215,13 +215,13 @@ nouveau_accel_init(struct nouveau_drm *drm)


	if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
	if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
		ret = nouveau_channel_new(drm, &drm->device,
		ret = nouveau_channel_new(drm, &drm->device,
					  KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
					  NVA06F_V0_ENGINE_CE0 |
					  KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
					  NVA06F_V0_ENGINE_CE1,
					  0, &drm->cechan);
					  0, &drm->cechan);
		if (ret)
		if (ret)
			NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
			NV_ERROR(drm, "failed to create ce channel, %d\n", ret);


		arg0 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
		arg0 = NVA06F_V0_ENGINE_GR;
		arg1 = 1;
		arg1 = 1;
	} else
	} else
	if (device->info.chipset >= 0xa3 &&
	if (device->info.chipset >= 0xa3 &&
+97 −47
Original line number Original line Diff line number Diff line
@@ -202,73 +202,79 @@ gk104_fifo_gpfifo_func = {
	.engine_fini = gk104_fifo_gpfifo_engine_fini,
	.engine_fini = gk104_fifo_gpfifo_engine_fini,
};
};


int
struct gk104_fifo_chan_func {
gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
	u32 engine;
		      void *data, u32 size, struct nvkm_object **pobject)
	u64 subdev;
};

static int
gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func,
		       struct gk104_fifo *fifo, u32 *engmask, u16 *chid,
		       u64 vm, u64 ioffset, u64 ilength,
		       const struct nvkm_oclass *oclass,
		       struct nvkm_object **pobject)
{
{
	union {
		struct kepler_channel_gpfifo_a_v0 v0;
	} *args = data;
	struct gk104_fifo *fifo = gk104_fifo(base);
	struct nvkm_device *device = fifo->base.engine.subdev.device;
	struct nvkm_device *device = fifo->base.engine.subdev.device;
	struct nvkm_object *parent = oclass->parent;
	struct gk104_fifo_chan *chan;
	struct gk104_fifo_chan *chan;
	u64 usermem, ioffset, ilength;
	int runlist = -1, ret = -ENOSYS, i, j;
	u32 engines;
	u32 engines = 0, present = 0;
	int ret = -ENOSYS, i;
	u64 subdevs = 0;

	u64 usermem;
	nvif_ioctl(parent, "create channel gpfifo size %d\n", size);

	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
	/* Determine which downstream engines are present */
		nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
	for (i = 0; i < fifo->engine_nr; i++) {
				   "ioffset %016llx ilength %08x engine %08x\n",
		struct nvkm_engine *engine = fifo->engine[i].engine;
			   args->v0.version, args->v0.vm, args->v0.ioffset,
		if (engine) {
			   args->v0.ilength, args->v0.engine);
			u64 submask = BIT_ULL(engine->subdev.index);
	} else
			for (j = 0; func[j].subdev; j++) {
		return ret;
				if (func[j].subdev & submask) {
					present |= func[j].engine;
					break;
				}
			}


	/* determine which downstream engines are present */
			if (!func[j].subdev)
	for (i = 0, engines = 0; i < fifo->runlist_nr; i++) {
		u64 subdevs = gk104_fifo_engine_subdev(i);
		if (!nvkm_device_engine(device, __ffs64(subdevs)))
				continue;
				continue;
		engines |= (1 << i);

			if (runlist < 0 && (*engmask & present))
				runlist = fifo->engine[i].runl;
			if (runlist == fifo->engine[i].runl) {
				engines |= func[j].engine;
				subdevs |= func[j].subdev;
			}
		}
	}
	}


	/* if this is an engine mask query, we're done */
	/* Just an engine mask query?  All done here! */
	if (!args->v0.engine) {
	if (!*engmask) {
		args->v0.engine = engines;
		*engmask = present;
		return nvkm_object_new(oclass, NULL, 0, pobject);
		return nvkm_object_new(oclass, NULL, 0, pobject);
	}
	}


	/* check that we support a requested engine - note that the user
	/* No runlist?  No supported engines. */
	 * argument is a mask in order to allow the user to request (for
	*engmask = present;
	 * example) *any* copy engine, but doesn't matter which.
	if (runlist < 0)
	 */
	args->v0.engine &= engines;
	if (!args->v0.engine) {
		nvif_ioctl(parent, "no supported engine\n");
		return -ENODEV;
		return -ENODEV;
	}
	*engmask = engines;


	/* allocate the channel */
	/* Allocate the channel. */
	if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
	if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
		return -ENOMEM;
		return -ENOMEM;
	*pobject = &chan->base.object;
	*pobject = &chan->base.object;
	chan->fifo = fifo;
	chan->fifo = fifo;
	chan->runl = __ffs(args->v0.engine);
	chan->runl = runlist;
	INIT_LIST_HEAD(&chan->head);
	INIT_LIST_HEAD(&chan->head);


	ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
	ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
				  0x1000, 0x1000, true, args->v0.vm, 0,
				  0x1000, 0x1000, true, vm, 0, subdevs,
				  gk104_fifo_engine_subdev(chan->runl),
				  1, fifo->user.bar.offset, 0x200,
				  1, fifo->user.bar.offset, 0x200,
				  oclass, &chan->base);
				  oclass, &chan->base);
	if (ret)
	if (ret)
		return ret;
		return ret;


	args->v0.chid = chan->base.chid;
	*chid = chan->base.chid;


	/* page directory */
	/* Page directory. */
	ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
	ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
	if (ret)
	if (ret)
		return ret;
		return ret;
@@ -284,10 +290,9 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
	if (ret)
	if (ret)
		return ret;
		return ret;


	/* clear channel control registers */
	/* Clear channel control registers. */
	usermem = chan->base.chid * 0x200;
	usermem = chan->base.chid * 0x200;
	ioffset = args->v0.ioffset;
	ilength = order_base_2(ilength / 8);
	ilength = order_base_2(args->v0.ilength / 8);


	nvkm_kmap(fifo->user.mem);
	nvkm_kmap(fifo->user.mem);
	for (i = 0; i < 0x200; i += 4)
	for (i = 0; i < 0x200; i += 4)
@@ -316,6 +321,51 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
	return 0;
	return 0;
}
}


static const struct gk104_fifo_chan_func
gk104_fifo_gpfifo[] = {
	{ NVA06F_V0_ENGINE_SW | NVA06F_V0_ENGINE_GR,
		BIT_ULL(NVKM_ENGINE_SW) | BIT_ULL(NVKM_ENGINE_GR)
	},
	{ NVA06F_V0_ENGINE_MSVLD , BIT_ULL(NVKM_ENGINE_MSVLD ) },
	{ NVA06F_V0_ENGINE_MSPDEC, BIT_ULL(NVKM_ENGINE_MSPDEC) },
	{ NVA06F_V0_ENGINE_MSPPP , BIT_ULL(NVKM_ENGINE_MSPPP ) },
	{ NVA06F_V0_ENGINE_MSENC , BIT_ULL(NVKM_ENGINE_MSENC ) },
	{ NVA06F_V0_ENGINE_CE0   , BIT_ULL(NVKM_ENGINE_CE0   ) },
	{ NVA06F_V0_ENGINE_CE1   , BIT_ULL(NVKM_ENGINE_CE1   ) },
	{ NVA06F_V0_ENGINE_CE2   , BIT_ULL(NVKM_ENGINE_CE2   ) },
	{}
};

int
gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
		      void *data, u32 size, struct nvkm_object **pobject)
{
	struct nvkm_object *parent = oclass->parent;
	union {
		struct kepler_channel_gpfifo_a_v0 v0;
	} *args = data;
	struct gk104_fifo *fifo = gk104_fifo(base);
	int ret = -ENOSYS;

	nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
		nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
				   "ioffset %016llx ilength %08x engine %08x\n",
			   args->v0.version, args->v0.vm, args->v0.ioffset,
			   args->v0.ilength, args->v0.engines);
		return gk104_fifo_gpfifo_new_(gk104_fifo_gpfifo, fifo,
					      &args->v0.engines,
					      &args->v0.chid,
					       args->v0.vm,
					       args->v0.ioffset,
					       args->v0.ilength,
					      oclass, pobject);

	}

	return ret;
}

const struct nvkm_fifo_chan_oclass
const struct nvkm_fifo_chan_oclass
gk104_fifo_gpfifo_oclass = {
gk104_fifo_gpfifo_oclass = {
	.base.oclass = KEPLER_CHANNEL_GPFIFO_A,
	.base.oclass = KEPLER_CHANNEL_GPFIFO_A,