struct nvkm_engine *engine)
 {
        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-       struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
+       struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine);
        u64 limit, start;
        int offset;
 
                          struct nvkm_object *object)
 {
        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-       int engn = engine->subdev.index;
 
        if (g84_fifo_chan_engine_addr(engine) < 0)
                return 0;
 
-       return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+       return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine));
 }
 
 static int
 
        struct gf100_fifo_engn {
                struct nvkm_gpuobj *inst;
                struct nvkm_vma *vma;
-       } engn[NVKM_SUBDEV_NR];
+       } engn[NVKM_FIFO_ENGN_NR];
 };
 
 extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass;
 
        struct gk104_fifo_engn {
                struct nvkm_gpuobj *inst;
                struct nvkm_vma *vma;
-       } engn[NVKM_SUBDEV_NR];
+       } engn[NVKM_FIFO_ENGN_NR];
 };
 
 extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func;
 void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *);
 void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *);
 void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *);
+struct gk104_fifo_engn *gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *, struct nvkm_engine *);
 int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *,
                                  struct nvkm_object *);
 void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *,
 
 #define NV04_FIFO_ENGN_GR   1
 #define NV04_FIFO_ENGN_MPEG 2
 #define NV04_FIFO_ENGN_DMA  3
-       struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR];
+       struct nvkm_gpuobj *engn[NVKM_FIFO_ENGN_NR];
 };
 
 extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func;
 
        }
 }
 
+struct nvkm_gpuobj **
+nv50_fifo_chan_engine(struct nv50_fifo_chan *chan, struct nvkm_engine *engine)
+{
+       int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
+       if (engi >= 0)
+               return &chan->engn[engi];
+       return NULL;
+}
+
 static int
 nv50_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
                           struct nvkm_engine *engine, bool suspend)
                           struct nvkm_engine *engine)
 {
        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-       struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
+       struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine);
        u64 limit, start;
        int offset;
 
                           struct nvkm_engine *engine)
 {
        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-       nvkm_gpuobj_del(&chan->engn[engine->subdev.index]);
+       nvkm_gpuobj_del(nv50_fifo_chan_engine(chan, engine));
 }
 
 static int
                           struct nvkm_object *object)
 {
        struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-       int engn = engine->subdev.index;
 
        if (nv50_fifo_chan_engine_addr(engine) < 0)
                return 0;
 
-       return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+       return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine));
 }
 
 void
 
 #define G84_FIFO_ENGN_BSP    6
 #define G84_FIFO_ENGN_MSVLD  6
 #define G84_FIFO_ENGN_DMA    7
-       struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR];
+       struct nvkm_gpuobj *engn[NVKM_FIFO_ENGN_NR];
 };
 
 int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
                        const struct nvkm_oclass *, struct nv50_fifo_chan *);
 void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *);
 void nv50_fifo_chan_fini(struct nvkm_fifo_chan *);
+struct nvkm_gpuobj **nv50_fifo_chan_engine(struct nv50_fifo_chan *, struct nvkm_engine *);
 void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *);
 void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
 
 
        }
 }
 
+static struct nvkm_gpuobj **
+nv40_fifo_dma_engn(struct nv04_fifo_chan *chan, struct nvkm_engine *engine)
+{
+       int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
+       if (engi >= 0)
+               return &chan->engn[engi];
+       return NULL;
+}
+
 static int
 nv40_fifo_dma_engine_fini(struct nvkm_fifo_chan *base,
                          struct nvkm_engine *engine, bool suspend)
 
        if (!nv40_fifo_dma_engine(engine, ®, &ctx))
                return 0;
-       inst = chan->engn[engine->subdev.index]->addr >> 4;
+       inst = (*nv40_fifo_dma_engn(chan, engine))->addr >> 4;
 
        spin_lock_irqsave(&fifo->base.lock, flags);
        nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
                          struct nvkm_engine *engine)
 {
        struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
-       nvkm_gpuobj_del(&chan->engn[engine->subdev.index]);
+       nvkm_gpuobj_del(nv40_fifo_dma_engn(chan, engine));
 }
 
 static int
                          struct nvkm_object *object)
 {
        struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
-       const int engn = engine->subdev.index;
        u32 reg, ctx;
 
        if (!nv40_fifo_dma_engine(engine, ®, &ctx))
                return 0;
 
-       return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+       return nvkm_object_bind(object, NULL, 0, nv40_fifo_dma_engn(chan, engine));
 }
 
 static int
 
        }
 }
 
+static struct gf100_fifo_engn *
+gf100_fifo_gpfifo_engine(struct gf100_fifo_chan *chan, struct nvkm_engine *engine)
+{
+       int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
+       if (engi >= 0)
+               return &chan->engn[engi];
+       return NULL;
+}
+
 static int
 gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
                              struct nvkm_engine *engine, bool suspend)
 {
        const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
        struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine);
        struct nvkm_gpuobj *inst = chan->base.inst;
 
        if (offset) {
-               u64 addr = chan->engn[engine->subdev.index].vma->addr;
                nvkm_kmap(inst);
-               nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4);
-               nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr));
+               nvkm_wo32(inst, offset + 0x00, lower_32_bits(engn->vma->addr) | 4);
+               nvkm_wo32(inst, offset + 0x04, upper_32_bits(engn->vma->addr));
                nvkm_done(inst);
        }
 
                              struct nvkm_engine *engine)
 {
        struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
-       nvkm_vmm_put(chan->base.vmm, &chan->engn[engine->subdev.index].vma);
-       nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
+       struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine);
+       nvkm_vmm_put(chan->base.vmm, &engn->vma);
+       nvkm_gpuobj_del(&engn->inst);
 }
 
 static int
                              struct nvkm_object *object)
 {
        struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
-       int engn = engine->subdev.index;
+       struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine);
        int ret;
 
        if (!gf100_fifo_gpfifo_engine_addr(engine))
                return 0;
 
-       ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst);
+       ret = nvkm_object_bind(object, NULL, 0, &engn->inst);
        if (ret)
                return ret;
 
-       ret = nvkm_vmm_get(chan->base.vmm, 12, chan->engn[engn].inst->size,
-                          &chan->engn[engn].vma);
+       ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma);
        if (ret)
                return ret;
 
-       return nvkm_memory_map(chan->engn[engn].inst, 0, chan->base.vmm,
-                              chan->engn[engn].vma, NULL, 0);
+       return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0);
 }
 
 static void
 
        }
 }
 
+struct gk104_fifo_engn *
+gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *chan, struct nvkm_engine *engine)
+{
+       int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
+       if (engi >= 0)
+               return &chan->engn[engi];
+       return NULL;
+}
+
 static int
 gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
                              struct nvkm_engine *engine, bool suspend)
                              struct nvkm_engine *engine)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
        struct nvkm_gpuobj *inst = chan->base.inst;
        u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
 
        if (offset) {
-               u64   addr = chan->engn[engine->subdev.index].vma->addr;
-               u32 datalo = lower_32_bits(addr) | 0x00000004;
-               u32 datahi = upper_32_bits(addr);
+               u32 datalo = lower_32_bits(engn->vma->addr) | 0x00000004;
+               u32 datahi = upper_32_bits(engn->vma->addr);
                nvkm_kmap(inst);
                nvkm_wo32(inst, (offset & 0xffff) + 0x00, datalo);
                nvkm_wo32(inst, (offset & 0xffff) + 0x04, datahi);
                              struct nvkm_engine *engine)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
-       nvkm_vmm_put(chan->base.vmm, &chan->engn[engine->subdev.index].vma);
-       nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
+       struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
+       nvkm_vmm_put(chan->base.vmm, &engn->vma);
+       nvkm_gpuobj_del(&engn->inst);
 }
 
 int
                              struct nvkm_object *object)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
-       int engn = engine->subdev.index;
+       struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
        int ret;
 
        if (!gk104_fifo_gpfifo_engine_addr(engine))
                return 0;
 
-       ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst);
+       ret = nvkm_object_bind(object, NULL, 0, &engn->inst);
        if (ret)
                return ret;
 
-       ret = nvkm_vmm_get(chan->base.vmm, 12, chan->engn[engn].inst->size,
-                          &chan->engn[engn].vma);
+       ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma);
        if (ret)
                return ret;
 
-       return nvkm_memory_map(chan->engn[engn].inst, 0, chan->base.vmm,
-                              chan->engn[engn].vma, NULL, 0);
+       return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0);
 }
 
 void
 
                              struct nvkm_engine *engine)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
        struct nvkm_gpuobj *inst = chan->base.inst;
-       u64 addr;
 
        if (engine->subdev.index >= NVKM_ENGINE_CE0 &&
            engine->subdev.index <= NVKM_ENGINE_CE_LAST)
                return 0;
 
-       addr = chan->engn[engine->subdev.index].vma->addr;
        nvkm_kmap(inst);
-       nvkm_wo32(inst, 0x210, lower_32_bits(addr) | 0x00000004);
-       nvkm_wo32(inst, 0x214, upper_32_bits(addr));
+       nvkm_wo32(inst, 0x210, lower_32_bits(engn->vma->addr) | 0x00000004);
+       nvkm_wo32(inst, 0x214, upper_32_bits(engn->vma->addr));
        nvkm_done(inst);
 
        return gv100_fifo_gpfifo_engine_valid(chan, false, true);