drm/nouveau/fifo/gk104-: support enabling privileged ce functions
Will be used by SVM code to allow direct (without going through MMU) memcpy using the GPU copy engines. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
86b442d74c
commit
85532bd984
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
struct kepler_channel_gpfifo_a_v0 {
|
struct kepler_channel_gpfifo_a_v0 {
|
||||||
__u8 version;
|
__u8 version;
|
||||||
__u8 pad01[1];
|
__u8 priv;
|
||||||
__u16 chid;
|
__u16 chid;
|
||||||
__u32 ilength;
|
__u32 ilength;
|
||||||
__u64 ioffset;
|
__u64 ioffset;
|
||||||
|
|
|
@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
|
||||||
|
|
||||||
/* create channel object and initialise dma and fence management */
|
/* create channel object and initialise dma and fence management */
|
||||||
ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
|
ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
|
||||||
init->tt_ctxdma_handle, &chan->chan);
|
init->tt_ctxdma_handle, false, &chan->chan);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
|
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
|
||||||
u64 runlist, struct nouveau_channel **pchan)
|
u64 runlist, bool priv, struct nouveau_channel **pchan)
|
||||||
{
|
{
|
||||||
struct nouveau_cli *cli = (void *)device->object.client;
|
struct nouveau_cli *cli = (void *)device->object.client;
|
||||||
static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
|
static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
|
||||||
|
@ -253,6 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
|
||||||
args.kepler.ioffset = 0x10000 + chan->push.addr;
|
args.kepler.ioffset = 0x10000 + chan->push.addr;
|
||||||
args.kepler.runlist = runlist;
|
args.kepler.runlist = runlist;
|
||||||
args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
|
args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
|
||||||
|
args.kepler.priv = priv;
|
||||||
size = sizeof(args.kepler);
|
size = sizeof(args.kepler);
|
||||||
} else
|
} else
|
||||||
if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
|
if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
|
||||||
|
@ -450,7 +451,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
|
||||||
|
|
||||||
int
|
int
|
||||||
nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
|
nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
|
||||||
u32 arg0, u32 arg1, struct nouveau_channel **pchan)
|
u32 arg0, u32 arg1, bool priv,
|
||||||
|
struct nouveau_channel **pchan)
|
||||||
{
|
{
|
||||||
struct nouveau_cli *cli = (void *)device->object.client;
|
struct nouveau_cli *cli = (void *)device->object.client;
|
||||||
bool super;
|
bool super;
|
||||||
|
@ -460,7 +462,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
|
||||||
super = cli->base.super;
|
super = cli->base.super;
|
||||||
cli->base.super = true;
|
cli->base.super = true;
|
||||||
|
|
||||||
ret = nouveau_channel_ind(drm, device, arg0, pchan);
|
ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
|
NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
|
||||||
ret = nouveau_channel_dma(drm, device, pchan);
|
ret = nouveau_channel_dma(drm, device, pchan);
|
||||||
|
|
|
@ -49,7 +49,8 @@ struct nouveau_channel {
|
||||||
int nouveau_channels_init(struct nouveau_drm *);
|
int nouveau_channels_init(struct nouveau_drm *);
|
||||||
|
|
||||||
int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
|
int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
|
||||||
u32 arg0, u32 arg1, struct nouveau_channel **);
|
u32 arg0, u32 arg1, bool priv,
|
||||||
|
struct nouveau_channel **);
|
||||||
void nouveau_channel_del(struct nouveau_channel **);
|
void nouveau_channel_del(struct nouveau_channel **);
|
||||||
int nouveau_channel_idle(struct nouveau_channel *);
|
int nouveau_channel_idle(struct nouveau_channel *);
|
||||||
|
|
||||||
|
|
|
@ -370,7 +370,7 @@ 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->client.device,
|
ret = nouveau_channel_new(drm, &drm->client.device,
|
||||||
nvif_fifo_runlist_ce(device), 0,
|
nvif_fifo_runlist_ce(device), 0,
|
||||||
&drm->cechan);
|
true, &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);
|
||||||
|
|
||||||
|
@ -381,7 +381,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
|
||||||
device->info.chipset != 0xaa &&
|
device->info.chipset != 0xaa &&
|
||||||
device->info.chipset != 0xac) {
|
device->info.chipset != 0xac) {
|
||||||
ret = nouveau_channel_new(drm, &drm->client.device,
|
ret = nouveau_channel_new(drm, &drm->client.device,
|
||||||
NvDmaFB, NvDmaTT, &drm->cechan);
|
NvDmaFB, NvDmaTT, false,
|
||||||
|
&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);
|
||||||
|
|
||||||
|
@ -393,7 +394,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nouveau_channel_new(drm, &drm->client.device,
|
ret = nouveau_channel_new(drm, &drm->client.device,
|
||||||
arg0, arg1, &drm->channel);
|
arg0, arg1, false, &drm->channel);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
|
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
|
||||||
nouveau_accel_fini(drm);
|
nouveau_accel_fini(drm);
|
||||||
|
|
|
@ -240,7 +240,7 @@ gk104_fifo_gpfifo_func = {
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
|
gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
|
||||||
u64 vmm, u64 ioffset, u64 ilength, u64 *inst,
|
u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
|
||||||
const struct nvkm_oclass *oclass,
|
const struct nvkm_oclass *oclass,
|
||||||
struct nvkm_object **pobject)
|
struct nvkm_object **pobject)
|
||||||
{
|
{
|
||||||
|
@ -316,6 +316,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
|
||||||
nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
|
nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
|
||||||
nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
|
nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
|
||||||
nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
|
nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
|
||||||
|
nvkm_wo32(chan->base.inst, 0xe4, priv ? 0x00000020 : 0x00000000);
|
||||||
nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
|
nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
|
||||||
nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
|
nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
|
||||||
nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
|
nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
|
||||||
|
@ -338,9 +339,11 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
|
||||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||||
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
|
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
|
||||||
"ioffset %016llx ilength %08x "
|
"ioffset %016llx ilength %08x "
|
||||||
"runlist %016llx\n",
|
"runlist %016llx priv %d\n",
|
||||||
args->v0.version, args->v0.vmm, args->v0.ioffset,
|
args->v0.version, args->v0.vmm, args->v0.ioffset,
|
||||||
args->v0.ilength, args->v0.runlist);
|
args->v0.ilength, args->v0.runlist, args->v0.priv);
|
||||||
|
if (args->v0.priv && !oclass->client->super)
|
||||||
|
return -EINVAL;
|
||||||
return gk104_fifo_gpfifo_new_(fifo,
|
return gk104_fifo_gpfifo_new_(fifo,
|
||||||
&args->v0.runlist,
|
&args->v0.runlist,
|
||||||
&args->v0.chid,
|
&args->v0.chid,
|
||||||
|
@ -348,6 +351,7 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
|
||||||
args->v0.ioffset,
|
args->v0.ioffset,
|
||||||
args->v0.ilength,
|
args->v0.ilength,
|
||||||
&args->v0.inst,
|
&args->v0.inst,
|
||||||
|
args->v0.priv,
|
||||||
oclass, pobject);
|
oclass, pobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ gv100_fifo_gpfifo_func = {
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
|
gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
|
||||||
u64 vmm, u64 ioffset, u64 ilength, u64 *inst,
|
u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
|
||||||
const struct nvkm_oclass *oclass,
|
const struct nvkm_oclass *oclass,
|
||||||
struct nvkm_object **pobject)
|
struct nvkm_object **pobject)
|
||||||
{
|
{
|
||||||
|
@ -185,9 +185,9 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
|
||||||
(ilength << 16));
|
(ilength << 16));
|
||||||
nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
|
nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
|
||||||
nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
|
nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
|
||||||
nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020);
|
nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
|
||||||
nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
|
nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
|
||||||
nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100);
|
nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000);
|
||||||
nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
|
nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
|
||||||
nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
|
nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
|
||||||
nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
|
nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
|
||||||
|
@ -210,9 +210,11 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
|
||||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||||
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
|
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
|
||||||
"ioffset %016llx ilength %08x "
|
"ioffset %016llx ilength %08x "
|
||||||
"runlist %016llx\n",
|
"runlist %016llx priv %d\n",
|
||||||
args->v0.version, args->v0.vmm, args->v0.ioffset,
|
args->v0.version, args->v0.vmm, args->v0.ioffset,
|
||||||
args->v0.ilength, args->v0.runlist);
|
args->v0.ilength, args->v0.runlist, args->v0.priv);
|
||||||
|
if (args->v0.priv && !oclass->client->super)
|
||||||
|
return -EINVAL;
|
||||||
return gv100_fifo_gpfifo_new_(fifo,
|
return gv100_fifo_gpfifo_new_(fifo,
|
||||||
&args->v0.runlist,
|
&args->v0.runlist,
|
||||||
&args->v0.chid,
|
&args->v0.chid,
|
||||||
|
@ -220,6 +222,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
|
||||||
args->v0.ioffset,
|
args->v0.ioffset,
|
||||||
args->v0.ilength,
|
args->v0.ilength,
|
||||||
&args->v0.inst,
|
&args->v0.inst,
|
||||||
|
args->v0.priv,
|
||||||
oclass, pobject);
|
oclass, pobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue