Loading drivers/gpu/drm/nouveau/include/nvif/cla06f.h +12 −9 Original line number Diff line number Diff line Loading @@ -3,19 +3,22 @@ struct kepler_channel_gpfifo_a_v0 { __u8 version; #define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01 #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; __u8 pad01[5]; __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; __u64 ioffset; __u64 vm; }; #define KEPLER_CHANNEL_GPFIFO_A_V0_NTFY_UEVENT 0x00 #define NVA06F_V0_NTFY_UEVENT 0x00 #endif drivers/gpu/drm/nouveau/nouveau_abi16.c +14 −4 Original line number Diff line number Diff line Loading @@ -263,13 +263,23 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) /* hack to allow channel engine type specification on kepler */ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (init->fb_ctxdma_handle != ~0) init->fb_ctxdma_handle = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR; else init->fb_ctxdma_handle = init->tt_ctxdma_handle; init->fb_ctxdma_handle = NVA06F_V0_ENGINE_GR; else { 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 */ 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; } Loading drivers/gpu/drm/nouveau/nouveau_chan.c +1 −1 Original line number Diff line number Diff line Loading @@ -217,7 +217,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, do { if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { args.kepler.version = 0; args.kepler.engine = engine; args.kepler.engines = engine; args.kepler.ilength = 0x02000; args.kepler.ioffset = 0x10000 + chan->push.vma.offset; args.kepler.vm = 0; Loading drivers/gpu/drm/nouveau/nouveau_drm.c +3 −3 Original line number Diff line number Diff line Loading @@ -215,13 +215,13 @@ nouveau_accel_init(struct nouveau_drm *drm) if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { ret = nouveau_channel_new(drm, &drm->device, KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, NVA06F_V0_ENGINE_CE0 | NVA06F_V0_ENGINE_CE1, 0, &drm->cechan); if (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; } else if (device->info.chipset >= 0xa3 && Loading drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +97 −47 Original line number Diff line number Diff line Loading @@ -202,73 +202,79 @@ gk104_fifo_gpfifo_func = { .engine_fini = gk104_fifo_gpfifo_engine_fini, }; int gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) struct gk104_fifo_chan_func { u32 engine; 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_object *parent = oclass->parent; struct gk104_fifo_chan *chan; u64 usermem, ioffset, ilength; u32 engines; int ret = -ENOSYS, i; 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.engine); } else return ret; int runlist = -1, ret = -ENOSYS, i, j; u32 engines = 0, present = 0; u64 subdevs = 0; u64 usermem; /* Determine which downstream engines are present */ for (i = 0; i < fifo->engine_nr; i++) { struct nvkm_engine *engine = fifo->engine[i].engine; if (engine) { u64 submask = BIT_ULL(engine->subdev.index); for (j = 0; func[j].subdev; j++) { if (func[j].subdev & submask) { present |= func[j].engine; break; } } /* determine which downstream engines are present */ for (i = 0, engines = 0; i < fifo->runlist_nr; i++) { u64 subdevs = gk104_fifo_engine_subdev(i); if (!nvkm_device_engine(device, __ffs64(subdevs))) if (!func[j].subdev) 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 */ if (!args->v0.engine) { args->v0.engine = engines; /* Just an engine mask query? All done here! */ if (!*engmask) { *engmask = present; return nvkm_object_new(oclass, NULL, 0, pobject); } /* check that we support a requested engine - note that the user * argument is a mask in order to allow the user to request (for * example) *any* copy engine, but doesn't matter which. */ args->v0.engine &= engines; if (!args->v0.engine) { nvif_ioctl(parent, "no supported engine\n"); /* No runlist? No supported engines. */ *engmask = present; if (runlist < 0) return -ENODEV; } *engmask = engines; /* allocate the channel */ /* Allocate the channel. */ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; *pobject = &chan->base.object; chan->fifo = fifo; chan->runl = __ffs(args->v0.engine); chan->runl = runlist; INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, 0x1000, 0x1000, true, args->v0.vm, 0, gk104_fifo_engine_subdev(chan->runl), 0x1000, 0x1000, true, vm, 0, subdevs, 1, fifo->user.bar.offset, 0x200, oclass, &chan->base); if (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); if (ret) return ret; Loading @@ -284,10 +290,9 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, if (ret) return ret; /* clear channel control registers */ /* Clear channel control registers. */ usermem = chan->base.chid * 0x200; ioffset = args->v0.ioffset; ilength = order_base_2(args->v0.ilength / 8); ilength = order_base_2(ilength / 8); nvkm_kmap(fifo->user.mem); for (i = 0; i < 0x200; i += 4) Loading Loading @@ -316,6 +321,51 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, 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 gk104_fifo_gpfifo_oclass = { .base.oclass = KEPLER_CHANNEL_GPFIFO_A, Loading Loading
drivers/gpu/drm/nouveau/include/nvif/cla06f.h +12 −9 Original line number Diff line number Diff line Loading @@ -3,19 +3,22 @@ struct kepler_channel_gpfifo_a_v0 { __u8 version; #define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01 #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; __u8 pad01[5]; __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; __u64 ioffset; __u64 vm; }; #define KEPLER_CHANNEL_GPFIFO_A_V0_NTFY_UEVENT 0x00 #define NVA06F_V0_NTFY_UEVENT 0x00 #endif
drivers/gpu/drm/nouveau/nouveau_abi16.c +14 −4 Original line number Diff line number Diff line Loading @@ -263,13 +263,23 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) /* hack to allow channel engine type specification on kepler */ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (init->fb_ctxdma_handle != ~0) init->fb_ctxdma_handle = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR; else init->fb_ctxdma_handle = init->tt_ctxdma_handle; init->fb_ctxdma_handle = NVA06F_V0_ENGINE_GR; else { 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 */ 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; } Loading
drivers/gpu/drm/nouveau/nouveau_chan.c +1 −1 Original line number Diff line number Diff line Loading @@ -217,7 +217,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, do { if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { args.kepler.version = 0; args.kepler.engine = engine; args.kepler.engines = engine; args.kepler.ilength = 0x02000; args.kepler.ioffset = 0x10000 + chan->push.vma.offset; args.kepler.vm = 0; Loading
drivers/gpu/drm/nouveau/nouveau_drm.c +3 −3 Original line number Diff line number Diff line Loading @@ -215,13 +215,13 @@ nouveau_accel_init(struct nouveau_drm *drm) if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { ret = nouveau_channel_new(drm, &drm->device, KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, NVA06F_V0_ENGINE_CE0 | NVA06F_V0_ENGINE_CE1, 0, &drm->cechan); if (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; } else if (device->info.chipset >= 0xa3 && Loading
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +97 −47 Original line number Diff line number Diff line Loading @@ -202,73 +202,79 @@ gk104_fifo_gpfifo_func = { .engine_fini = gk104_fifo_gpfifo_engine_fini, }; int gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) struct gk104_fifo_chan_func { u32 engine; 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_object *parent = oclass->parent; struct gk104_fifo_chan *chan; u64 usermem, ioffset, ilength; u32 engines; int ret = -ENOSYS, i; 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.engine); } else return ret; int runlist = -1, ret = -ENOSYS, i, j; u32 engines = 0, present = 0; u64 subdevs = 0; u64 usermem; /* Determine which downstream engines are present */ for (i = 0; i < fifo->engine_nr; i++) { struct nvkm_engine *engine = fifo->engine[i].engine; if (engine) { u64 submask = BIT_ULL(engine->subdev.index); for (j = 0; func[j].subdev; j++) { if (func[j].subdev & submask) { present |= func[j].engine; break; } } /* determine which downstream engines are present */ for (i = 0, engines = 0; i < fifo->runlist_nr; i++) { u64 subdevs = gk104_fifo_engine_subdev(i); if (!nvkm_device_engine(device, __ffs64(subdevs))) if (!func[j].subdev) 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 */ if (!args->v0.engine) { args->v0.engine = engines; /* Just an engine mask query? All done here! */ if (!*engmask) { *engmask = present; return nvkm_object_new(oclass, NULL, 0, pobject); } /* check that we support a requested engine - note that the user * argument is a mask in order to allow the user to request (for * example) *any* copy engine, but doesn't matter which. */ args->v0.engine &= engines; if (!args->v0.engine) { nvif_ioctl(parent, "no supported engine\n"); /* No runlist? No supported engines. */ *engmask = present; if (runlist < 0) return -ENODEV; } *engmask = engines; /* allocate the channel */ /* Allocate the channel. */ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; *pobject = &chan->base.object; chan->fifo = fifo; chan->runl = __ffs(args->v0.engine); chan->runl = runlist; INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, 0x1000, 0x1000, true, args->v0.vm, 0, gk104_fifo_engine_subdev(chan->runl), 0x1000, 0x1000, true, vm, 0, subdevs, 1, fifo->user.bar.offset, 0x200, oclass, &chan->base); if (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); if (ret) return ret; Loading @@ -284,10 +290,9 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, if (ret) return ret; /* clear channel control registers */ /* Clear channel control registers. */ usermem = chan->base.chid * 0x200; ioffset = args->v0.ioffset; ilength = order_base_2(args->v0.ilength / 8); ilength = order_base_2(ilength / 8); nvkm_kmap(fifo->user.mem); for (i = 0; i < 0x200; i += 4) Loading Loading @@ -316,6 +321,51 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, 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 gk104_fifo_gpfifo_oclass = { .base.oclass = KEPLER_CHANNEL_GPFIFO_A, Loading