static int nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, u32 handle, u32 engine, struct nouveau_channel **pchan) { static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A, FERMI_CHANNEL_GPFIFO, G82_CHANNEL_GPFIFO, NV50_CHANNEL_GPFIFO, 0 }; const u16 *oclass = oclasses; union { struct nv50_channel_gpfifo_v0 nv50; struct kepler_channel_gpfifo_a_v0 kepler; } args, *retn; struct nouveau_channel *chan; u32 size; int ret; /* allocate dma push buffer */ ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan); *pchan = chan; if (ret) return ret; /* create channel object */ do { if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { args.kepler.version = 0; args.kepler.engine = engine; args.kepler.pushbuf = chan->push.ctxdma.handle; args.kepler.ilength = 0x02000; args.kepler.ioffset = 0x10000 + chan->push.vma.offset; size = sizeof(args.kepler); } else { args.nv50.version = 0; args.nv50.pushbuf = chan->push.ctxdma.handle; args.nv50.ilength = 0x02000; args.nv50.ioffset = 0x10000 + chan->push.vma.offset; size = sizeof(args.nv50); } ret = nvif_object_new(nvif_object(device), handle, *oclass++, &args, size, &chan->object); if (ret == 0) { retn = chan->object->data; if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A) chan->chid = retn->kepler.chid; else chan->chid = retn->nv50.chid; return ret; } } while (*oclass); nouveau_channel_del(pchan); return ret; }
static int nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, u32 handle, struct nouveau_channel **pchan) { static const u16 oclasses[] = { NV40_CHANNEL_DMA, NV17_CHANNEL_DMA, NV10_CHANNEL_DMA, NV03_CHANNEL_DMA, 0 }; const u16 *oclass = oclasses; struct nv03_channel_dma_v0 args, *retn; struct nouveau_channel *chan; int ret; /* allocate dma push buffer */ ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan); *pchan = chan; if (ret) return ret; /* create channel object */ args.version = 0; args.pushbuf = chan->push.ctxdma.handle; args.offset = chan->push.vma.offset; do { ret = nvif_object_new(nvif_object(device), handle, *oclass++, &args, sizeof(args), &chan->object); if (ret == 0) { retn = chan->object->data; chan->chid = retn->chid; return ret; } } while (ret && *oclass); nouveau_channel_del(pchan); return ret; }
static int nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, u32 engine, struct nouveau_channel **pchan) { static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A, KEPLER_CHANNEL_GPFIFO_B, KEPLER_CHANNEL_GPFIFO_A, FERMI_CHANNEL_GPFIFO, G82_CHANNEL_GPFIFO, NV50_CHANNEL_GPFIFO, 0 }; const u16 *oclass = oclasses; union { struct nv50_channel_gpfifo_v0 nv50; struct fermi_channel_gpfifo_v0 fermi; struct kepler_channel_gpfifo_a_v0 kepler; } args; struct nouveau_channel *chan; u32 size; int ret; /* allocate dma push buffer */ ret = nouveau_channel_prep(drm, device, 0x12000, &chan); *pchan = chan; if (ret) return ret; /* create channel object */ do { if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { args.kepler.version = 0; args.kepler.engines = engine; args.kepler.ilength = 0x02000; args.kepler.ioffset = 0x10000 + chan->push.vma.offset; args.kepler.vm = 0; size = sizeof(args.kepler); } else if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { args.fermi.version = 0; args.fermi.ilength = 0x02000; args.fermi.ioffset = 0x10000 + chan->push.vma.offset; args.fermi.vm = 0; size = sizeof(args.fermi); } else { args.nv50.version = 0; args.nv50.ilength = 0x02000; args.nv50.ioffset = 0x10000 + chan->push.vma.offset; args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma); args.nv50.vm = 0; size = sizeof(args.nv50); } ret = nvif_object_init(&device->object, 0, *oclass++, &args, size, &chan->user); if (ret == 0) { if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) chan->chid = args.kepler.chid; else if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) chan->chid = args.fermi.chid; else chan->chid = args.nv50.chid; return ret; } } while (*oclass); nouveau_channel_del(pchan); return ret; }