union { int id; int chid; }; /*FIXME: remove later */
 
        struct nvkm_fifo *fifo;
-       u32 engm;
        struct nvkm_object object;
 
        struct list_head head;
 
        return 0;
 }
 
-static int
-nvkm_fifo_chan_child_get(struct nvkm_object *object, int index,
-                        struct nvkm_oclass *oclass)
-{
-       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
-       struct nvkm_fifo *fifo = chan->fifo;
-       struct nvkm_engine *engine;
-       u32 engm = chan->engm;
-       int engi, ret, c;
-
-       for (; c = 0, engi = __ffs(engm), engm; engm &= ~(1ULL << engi)) {
-               if (!(engine = fifo->func->id_engine(fifo, engi)))
-                       continue;
-               oclass->engine = engine;
-               oclass->base.oclass = 0;
-
-               if (engine->func->fifo.sclass) {
-                       ret = engine->func->fifo.sclass(oclass, index);
-                       if (oclass->base.oclass) {
-                               if (!oclass->base.ctor)
-                                       oclass->base.ctor = nvkm_object_new;
-                               oclass->ctor = nvkm_fifo_chan_child_new;
-                               return 0;
-                       }
-
-                       index -= ret;
-                       continue;
-               }
-
-               while (engine->func->sclass[c].oclass) {
-                       if (c++ == index) {
-                               oclass->base = engine->func->sclass[index];
-                               if (!oclass->base.ctor)
-                                       oclass->base.ctor = nvkm_object_new;
-                               oclass->ctor = nvkm_fifo_chan_child_new;
-                               return 0;
-                       }
-               }
-               index -= c;
-       }
-
-       return -EINVAL;
-}
-
 static int
 nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
 {
        .init = nvkm_fifo_chan_init,
        .fini = nvkm_fifo_chan_fini,
        .map = nvkm_fifo_chan_map,
-       .sclass = nvkm_fifo_chan_child_get,
        .uevent = nvkm_fifo_chan_uevent,
 };
 
 
        nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
        chan->fifo = fifo;
-       chan->engm = engm;
        INIT_LIST_HEAD(&chan->head);
 
        /* Join channel group.
 
        nvkm_mask(device, 0x002140, 0x40000000, 0x40000000);
 }
 
-struct nvkm_engine *
-g84_fifo_id_engine(struct nvkm_fifo *fifo, int engi)
-{
-       struct nvkm_device *device = fifo->engine.subdev.device;
-       struct nvkm_engine *engine;
-       enum nvkm_subdev_type type;
-
-       switch (engi) {
-       case G84_FIFO_ENGN_SW    : type = NVKM_ENGINE_SW; break;
-       case G84_FIFO_ENGN_GR    : type = NVKM_ENGINE_GR; break;
-       case G84_FIFO_ENGN_MPEG  :
-               if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSPPP, 0)))
-                       return engine;
-               type = NVKM_ENGINE_MPEG;
-               break;
-       case G84_FIFO_ENGN_ME    :
-               if ((engine = nvkm_device_engine(device, NVKM_ENGINE_CE, 0)))
-                       return engine;
-               type = NVKM_ENGINE_ME;
-               break;
-       case G84_FIFO_ENGN_VP    :
-               if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSPDEC, 0)))
-                       return engine;
-               type = NVKM_ENGINE_VP;
-               break;
-       case G84_FIFO_ENGN_CIPHER:
-               if ((engine = nvkm_device_engine(device, NVKM_ENGINE_VIC, 0)))
-                       return engine;
-               if ((engine = nvkm_device_engine(device, NVKM_ENGINE_SEC, 0)))
-                       return engine;
-               type = NVKM_ENGINE_CIPHER;
-               break;
-       case G84_FIFO_ENGN_BSP   :
-               if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSVLD, 0)))
-                       return engine;
-               type = NVKM_ENGINE_BSP;
-               break;
-       case G84_FIFO_ENGN_DMA   : type = NVKM_ENGINE_DMAOBJ; break;
-       default:
-               WARN_ON(1);
-               return NULL;
-       }
-
-       return nvkm_device_engine(fifo->engine.subdev.device, type, 0);
-}
-
 int
 g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
 {
        .init = nv50_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = g84_fifo_engine_id,
-       .id_engine = g84_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .uevent_init = g84_fifo_uevent_init,
 
        .init = nv50_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = g84_fifo_engine_id,
-       .id_engine = g84_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .uevent_init = g84_fifo_uevent_init,
 
        .intr = gf100_fifo_intr,
        .mmu_fault = &gf100_fifo_mmu_fault,
        .engine_id = gf100_fifo_engine_id,
-       .id_engine = gf100_fifo_id_engine,
        .uevent_init = gf100_fifo_uevent_init,
        .uevent_fini = gf100_fifo_uevent_fini,
        .runl = &gf100_runl,
 
        .init = gk104_fifo_pbdma_init,
 };
 
-struct nvkm_engine *
-gk104_fifo_id_engine(struct nvkm_fifo *base, int engi)
-{
-       if (engi == GK104_FIFO_ENGN_SW)
-               return nvkm_device_engine(base->engine.subdev.device, NVKM_ENGINE_SW, 0);
-
-       return gk104_fifo(base)->engine[engi].engine;
-}
-
 int
 gk104_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
 {
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
        .fault.hubclient = gv100_fifo_fault_hubclient,
        .fault.gpcclient = gv100_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
 
 nv04_runl = {
 };
 
-struct nvkm_engine *
-nv04_fifo_id_engine(struct nvkm_fifo *fifo, int engi)
-{
-       enum nvkm_subdev_type type;
-
-       switch (engi) {
-       case NV04_FIFO_ENGN_SW  : type = NVKM_ENGINE_SW; break;
-       case NV04_FIFO_ENGN_GR  : type = NVKM_ENGINE_GR; break;
-       case NV04_FIFO_ENGN_MPEG: type = NVKM_ENGINE_MPEG; break;
-       case NV04_FIFO_ENGN_DMA : type = NVKM_ENGINE_DMAOBJ; break;
-       default:
-               WARN_ON(1);
-               return NULL;
-       }
-
-       return nvkm_device_engine(fifo->engine.subdev.device, type, 0);
-}
-
 int
 nv04_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
 {
        .init = nv04_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = nv04_fifo_engine_id,
-       .id_engine = nv04_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .runl = &nv04_runl,
 
        .init = nv04_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = nv04_fifo_engine_id,
-       .id_engine = nv04_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .runl = &nv04_runl,
 
        .init = nv17_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = nv04_fifo_engine_id,
-       .id_engine = nv04_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .runl = &nv04_runl,
 
        .init = nv40_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = nv04_fifo_engine_id,
-       .id_engine = nv04_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .runl = &nv04_runl,
 
        .init = nv50_fifo_init,
        .intr = nv04_fifo_intr,
        .engine_id = nv04_fifo_engine_id,
-       .id_engine = nv04_fifo_id_engine,
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .runl = &nv50_runl,
 
 void nv50_fifo_runlist_update(struct nv50_fifo *);
 
 int g84_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
-struct nvkm_engine *g84_fifo_id_engine(struct nvkm_fifo *, int);
 void g84_fifo_uevent_init(struct nvkm_fifo *);
 void g84_fifo_uevent_fini(struct nvkm_fifo *);
 #endif
 
        } fault;
 
        int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *);
-       struct nvkm_engine *(*id_engine)(struct nvkm_fifo *, int engi);
        void (*pause)(struct nvkm_fifo *, unsigned long *);
        void (*start)(struct nvkm_fifo *, unsigned long *);
        void (*uevent_init)(struct nvkm_fifo *);
 void nv04_fifo_init(struct nvkm_fifo *);
 void nv04_fifo_intr(struct nvkm_fifo *);
 int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
-struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int);
 void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
 void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
 extern const struct nvkm_runl_func nv04_runl;
 void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *);
 void gk104_fifo_recover_chan(struct nvkm_fifo *, int);
 int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
-struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int);
 extern const struct nvkm_runq_func gk104_runq;
 extern const struct nvkm_engn_func gk104_engn;
 extern const struct nvkm_engn_func gk104_engn_ce;
 
        .fault.hubclient = gv100_fifo_fault_hubclient,
        .fault.gpcclient = gv100_fifo_fault_gpcclient,
        .engine_id = gk104_fifo_engine_id,
-       .id_engine = gk104_fifo_id_engine,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = tu102_fifo_recover_chan,
 
 #define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object)
 #include "cgrp.h"
 #include "chan.h"
+#include "runl.h"
 
 #include <core/oproxy.h>
 
 nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
 {
        struct nvkm_chan *chan = nvkm_uchan(object)->chan;
+       struct nvkm_engn *engn;
        int ret;
 
-       ret = chan->object.func->sclass(&chan->object, index, oclass);
-       if (ret)
-               return ret;
+       nvkm_runl_foreach_engn(engn, chan->cgrp->runl) {
+               struct nvkm_engine *engine = engn->engine;
+               int c = 0;
+
+               oclass->engine = engine;
+               oclass->base.oclass = 0;
+
+               if (engine->func->fifo.sclass) {
+                       ret = engine->func->fifo.sclass(oclass, index);
+                       if (oclass->base.oclass) {
+                               if (!oclass->base.ctor)
+                                       oclass->base.ctor = nvkm_object_new;
+                               oclass->ctor = nvkm_uchan_object_new;
+                               return 0;
+                       }
+
+                       index -= ret;
+                       continue;
+               }
+
+               while (engine->func->sclass[c].oclass) {
+                       if (c++ == index) {
+                               oclass->base = engine->func->sclass[index];
+                               if (!oclass->base.ctor)
+                                       oclass->base.ctor = nvkm_object_new;
+                               oclass->ctor = nvkm_uchan_object_new;
+                               return 0;
+                       }
+               }
+
+               index -= c;
+       }
 
-       oclass->ctor = nvkm_uchan_object_new;
-       return 0;
+       return -EINVAL;
 }
 
 static int