#ifndef __NVKM_FIFO_H__
 #define __NVKM_FIFO_H__
-#define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object)
-#define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine)
 #include <core/engine.h>
 #include <core/event.h>
 
 
 extern const struct nvkm_object_func nvkm_fifo_chan_func;
 
-#include <core/gpuobj.h>
-struct nvkm_fifo_base {
-       struct nvkm_gpuobj gpuobj;
-};
-
-#define nvkm_fifo_context_create(p,e,c,g,s,a,f,d)                           \
-       nvkm_gpuobj_create((p), (e), (c), NV_ENGCTX_CLASS, (g), (s), (a), (f), (d))
-#define nvkm_fifo_context_destroy(p)                                        \
-       nvkm_gpuobj_destroy(&(p)->gpuobj)
-#define nvkm_fifo_context_init(p)                                           \
-       nvkm_gpuobj_init(&(p)->gpuobj)
-#define nvkm_fifo_context_fini(p,s)                                         \
-       nvkm_gpuobj_fini(&(p)->gpuobj, (s))
-
-#define _nvkm_fifo_context_dtor _nvkm_gpuobj_dtor
-#define _nvkm_fifo_context_init _nvkm_gpuobj_init
-#define _nvkm_fifo_context_fini _nvkm_gpuobj_fini
-#define _nvkm_fifo_context_rd32 _nvkm_gpuobj_rd32
-#define _nvkm_fifo_context_wr32 _nvkm_gpuobj_wr32
-
 struct nvkm_fifo {
-       struct nvkm_engine engine;
        const struct nvkm_fifo_func *func;
-
-       struct nvkm_event cevent; /* channel creation event */
-       struct nvkm_event uevent; /* async user trigger */
+       struct nvkm_engine engine;
 
        DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR);
        int nr;
        struct list_head chan;
        spinlock_t lock;
 
-       void (*pause)(struct nvkm_fifo *, unsigned long *);
-       void (*start)(struct nvkm_fifo *, unsigned long *);
+       struct nvkm_event uevent; /* async user trigger */
+       struct nvkm_event cevent; /* channel creation event */
 };
 
-struct nvkm_fifo_func {
-       void *(*dtor)(struct nvkm_fifo *);
-       const struct nvkm_fifo_chan_oclass *chan[];
-};
+void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *);
+void nvkm_fifo_start(struct nvkm_fifo *, unsigned long *);
 
 void nvkm_fifo_chan_put(struct nvkm_fifo *, unsigned long flags,
                        struct nvkm_fifo_chan **);
 struct nvkm_fifo_chan *
 nvkm_fifo_chan_chid(struct nvkm_fifo *, int chid, unsigned long *flags);
 
-#define nvkm_fifo_create(o,e,c,fc,lc,d)                                     \
-       nvkm_fifo_create_((o), (e), (c), (fc), (lc), sizeof(**d), (void **)d)
-#define nvkm_fifo_init(p)                                                   \
-       nvkm_engine_init_old(&(p)->engine)
-#define nvkm_fifo_fini(p,s)                                                 \
-       nvkm_engine_fini_old(&(p)->engine, (s))
-
-int nvkm_fifo_create_(struct nvkm_object *, struct nvkm_object *,
-                        struct nvkm_oclass *, int min, int max,
-                        int size, void **);
-void nvkm_fifo_destroy(struct nvkm_fifo *);
-
-#define _nvkm_fifo_init _nvkm_engine_init
-#define _nvkm_fifo_fini _nvkm_engine_fini
-
-extern struct nvkm_oclass *nv04_fifo_oclass;
-extern struct nvkm_oclass *nv10_fifo_oclass;
-extern struct nvkm_oclass *nv17_fifo_oclass;
-extern struct nvkm_oclass *nv40_fifo_oclass;
-extern struct nvkm_oclass *nv50_fifo_oclass;
-extern struct nvkm_oclass *g84_fifo_oclass;
-extern struct nvkm_oclass *gf100_fifo_oclass;
-extern struct nvkm_oclass *gk104_fifo_oclass;
-extern struct nvkm_oclass *gk20a_fifo_oclass;
-extern struct nvkm_oclass *gk208_fifo_oclass;
-extern struct nvkm_oclass *gm204_fifo_oclass;
-extern struct nvkm_oclass *gm20b_fifo_oclass;
-
-int  nvkm_fifo_uevent_ctor(struct nvkm_object *, void *, u32,
-                          struct nvkm_notify *);
-void nvkm_fifo_uevent(struct nvkm_fifo *);
-
-void nv04_fifo_intr(struct nvkm_subdev *);
-int  nv04_fifo_context_attach(struct nvkm_object *, struct nvkm_object *);
+int nv04_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int nv10_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int nv17_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int nv40_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int nv50_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int g84_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gf100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gk104_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gk208_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gk20a_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gm204_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 #endif
 
        nvkm_object_destroy(&gpuobj->object);
 }
 
-#include <engine/fifo.h>
+#include <engine/fifo/chan.h>
 
 int
 nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine,
 
 
 #include <core/client.h>
 #include <core/enum.h>
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 
 #include <nvif/class.h>
 
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv04_fifo_new,
+       .fifo = nv04_fifo_new,
 //     .gr = nv04_gr_new,
 //     .sw = nv04_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv04_fifo_new,
+       .fifo = nv04_fifo_new,
 //     .gr = nv04_gr_new,
 //     .sw = nv04_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv10_fifo_new,
+       .fifo = nv10_fifo_new,
 //     .gr = nv10_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv10_fifo_new,
+       .fifo = nv10_fifo_new,
 //     .gr = nv10_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv10_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv10_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv10_fifo_new,
+       .fifo = nv10_fifo_new,
 //     .gr = nv10_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv10_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv20_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv25_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv25_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv2a_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv30_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv30_gr_new,
 //     .mpeg = nv31_mpeg_new,
 //     .sw = nv10_sw_new,
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv34_gr_new,
 //     .mpeg = nv31_mpeg_new,
 //     .sw = nv10_sw_new,
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv35_gr_new,
 //     .sw = nv10_sw_new,
 };
        .timer = nv04_timer_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv17_fifo_new,
+       .fifo = nv17_fifo_new,
 //     .gr = nv35_gr_new,
 //     .mpeg = nv31_mpeg_new,
 //     .sw = nv10_sw_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv40_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv40_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv40_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv40_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv50_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = nv50_fifo_new,
+       .fifo = nv50_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = nv50_mpeg_new,
 //     .pm = nv50_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .volt = nv40_volt_new,
        .disp = nv04_disp_new,
        .dma = nv04_dma_new,
-//     .fifo = nv40_fifo_new,
+       .fifo = nv40_fifo_new,
 //     .gr = nv40_gr_new,
 //     .mpeg = nv44_mpeg_new,
 //     .pm = nv40_pm_new,
        .cipher = g84_cipher_new,
        .disp = g84_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
 //     .pm = g84_pm_new,
        .cipher = g84_cipher_new,
        .disp = g84_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
 //     .pm = g84_pm_new,
        .cipher = g84_cipher_new,
        .disp = g84_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
 //     .pm = g84_pm_new,
        .cipher = g84_cipher_new,
        .disp = g94_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
 //     .pm = g84_pm_new,
        .bar = g84_bar_new,
        .volt = nv40_volt_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .sw = nv50_sw_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
        .bar = g84_bar_new,
        .volt = nv40_volt_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .sw = nv50_sw_new,
 //     .gr = nv50_gr_new,
        .mspdec = g98_mspdec_new,
        .cipher = g84_cipher_new,
        .disp = gt200_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
 //     .pm = gt200_pm_new,
        .ce[0] = gt215_ce_new,
        .disp = gt215_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
 //     .mpeg = g84_mpeg_new,
        .mspdec = gt215_mspdec_new,
        .ce[0] = gt215_ce_new,
        .disp = gt215_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
        .mspdec = gt215_mspdec_new,
        .msppp = gt215_msppp_new,
        .ce[0] = gt215_ce_new,
        .disp = gt215_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
        .mspdec = gt215_mspdec_new,
        .msppp = gt215_msppp_new,
        .volt = nv40_volt_new,
        .disp = g94_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
        .mspdec = g98_mspdec_new,
        .msppp = g98_msppp_new,
        .volt = nv40_volt_new,
        .disp = g94_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
        .mspdec = g98_mspdec_new,
        .msppp = g98_msppp_new,
        .ce[0] = gt215_ce_new,
        .disp = gt215_disp_new,
        .dma = nv50_dma_new,
-//     .fifo = g84_fifo_new,
+       .fifo = g84_fifo_new,
 //     .gr = nv50_gr_new,
        .mspdec = gt215_mspdec_new,
        .msppp = gt215_msppp_new,
        .ce[1] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf100_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[0] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf108_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[0] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf104_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[1] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf104_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[1] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf110_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[1] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf104_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[0] = gf100_ce_new,
        .disp = gt215_disp_new,
        .dma = gf100_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf104_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[0] = gf100_ce_new,
        .disp = gf119_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf117_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[0] = gf100_ce_new,
        .disp = gf119_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gf100_fifo_new,
+       .fifo = gf100_fifo_new,
 //     .gr = gf119_gr_new,
        .mspdec = gf100_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gk104_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk104_fifo_new,
+       .fifo = gk104_fifo_new,
 //     .gr = gk104_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gk104_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk104_fifo_new,
+       .fifo = gk104_fifo_new,
 //     .gr = gk104_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gk104_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk104_fifo_new,
+       .fifo = gk104_fifo_new,
 //     .gr = gk104_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .volt = gk20a_volt_new,
        .ce[2] = gk104_ce_new,
        .dma = gf119_dma_new,
-//     .fifo = gk20a_fifo_new,
+       .fifo = gk20a_fifo_new,
 //     .gr = gk20a_gr_new,
 //     .pm = gk104_pm_new,
 //     .sw = gf100_sw_new,
        .ce[2] = gk104_ce_new,
        .disp = gk110_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk104_fifo_new,
+       .fifo = gk104_fifo_new,
 //     .gr = gk110_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gk110_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk104_fifo_new,
+       .fifo = gk104_fifo_new,
 //     .gr = gk110b_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gk110_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk208_fifo_new,
+       .fifo = gk208_fifo_new,
 //     .gr = gk208_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gk110_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk208_fifo_new,
+       .fifo = gk208_fifo_new,
 //     .gr = gk208_gr_new,
        .mspdec = gk104_mspdec_new,
        .msppp = gf100_msppp_new,
        .ce[2] = gk104_ce_new,
        .disp = gm107_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gk208_fifo_new,
+       .fifo = gk208_fifo_new,
 //     .gr = gm107_gr_new,
 //     .sw = gf100_sw_new,
 };
        .ce[2] = gm204_ce_new,
        .disp = gm204_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gm204_fifo_new,
+       .fifo = gm204_fifo_new,
 //     .gr = gm204_gr_new,
 //     .sw = gf100_sw_new,
 };
        .ce[2] = gm204_ce_new,
        .disp = gm204_disp_new,
        .dma = gf119_dma_new,
-//     .fifo = gm204_fifo_new,
+       .fifo = gm204_fifo_new,
 //     .gr = gm206_gr_new,
 //     .sw = gf100_sw_new,
 };
        .timer = gk20a_timer_new,
        .ce[2] = gm204_ce_new,
        .dma = gf119_dma_new,
-//     .fifo = gm20b_fifo_new,
+       .fifo = gm20b_fifo_new,
 //     .gr = gm20b_gr_new,
 //     .sw = gf100_sw_new,
 };
 
 {
        switch (device->chipset) {
        case 0xc0:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf100_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf100_pm_oclass;
                break;
        case 0xc4:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf100_pm_oclass;
                break;
        case 0xc3:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf100_pm_oclass;
                break;
        case 0xce:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf100_pm_oclass;
                break;
        case 0xcf:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf100_pm_oclass;
                break;
        case 0xc1:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf108_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf108_pm_oclass;
                break;
        case 0xc8:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf110_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf100_pm_oclass;
                break;
        case 0xd9:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf119_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf117_pm_oclass;
                break;
        case 0xd7:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gf100_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gf117_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gf117_pm_oclass;
 
 {
        switch (device->chipset) {
        case 0xe4:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gk104_pm_oclass;
                break;
        case 0xe7:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gk104_pm_oclass;
                break;
        case 0xe6:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk104_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gk104_pm_oclass;
                break;
        case 0xea:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk20a_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk20a_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = gk104_pm_oclass;
                break;
        case 0xf0:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk110_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = &gk110_pm_oclass;
                break;
        case 0xf1:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk110b_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] = &gk110_pm_oclass;
                break;
        case 0x106:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk208_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk208_gr_oclass;
                break;
        case 0x108:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk208_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gk208_gr_oclass;
                break;
 
 
 #if 0
 #endif
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk208_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gm107_gr_oclass;
 #if 0
 #endif
 #if 0
 #endif
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gm204_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gm204_gr_oclass;
 #if 0
 #endif
 #if 0
 #endif
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gm204_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gm206_gr_oclass;
 #if 0
                break;
        case 0x12b:
 
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  gm20b_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] =  gm20b_gr_oclass;
                break;
 
 {
        switch (device->chipset) {
        case 0x04:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv04_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv04_gr_oclass;
                break;
        case 0x05:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv04_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv04_gr_oclass;
                break;
 
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x15:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x16:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x1a:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x11:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x17:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x1f:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
        case 0x18:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_gr_oclass;
                break;
 
 {
        switch (device->chipset) {
        case 0x20:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv20_gr_oclass;
                break;
        case 0x25:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv25_gr_oclass;
                break;
        case 0x28:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv25_gr_oclass;
                break;
        case 0x2a:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv2a_gr_oclass;
                break;
 
 {
        switch (device->chipset) {
        case 0x30:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv30_gr_oclass;
                break;
        case 0x35:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv35_gr_oclass;
                break;
        case 0x31:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv30_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass;
                break;
        case 0x36:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv35_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass;
                break;
        case 0x34:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv34_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass;
 
 {
        switch (device->chipset) {
        case 0x40:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x41:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x42:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x43:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x45:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x47:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x49:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x4b:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x44:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x46:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x4a:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x4c:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x4e:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x63:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x67:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv40_pm_oclass;
                break;
        case 0x68:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv10_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv40_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
 
 {
        switch (device->chipset) {
        case 0x50:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv50_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &nv50_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  nv50_pm_oclass;
                break;
        case 0x84:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0x86:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0x92:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0x94:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0x96:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0x98:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0xa0:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  gt200_pm_oclass;
                break;
        case 0xaa:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0xac:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  g84_pm_oclass;
                break;
        case 0xa3:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_MPEG   ] = &g84_mpeg_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  gt215_pm_oclass;
                break;
        case 0xa5:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  gt215_pm_oclass;
                break;
        case 0xa8:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  gt215_pm_oclass;
                break;
        case 0xaf:
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  g84_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nv50_sw_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv50_gr_oclass;
                device->oclass[NVDEV_ENGINE_PM     ] =  gt215_pm_oclass;
 
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 #include <engine/falcon.h>
-#include <engine/fifo.h>
 
+#include <core/gpuobj.h>
 #include <subdev/timer.h>
+#include <engine/fifo.h>
 
 static int
 nvkm_falcon_oclass_get(struct nvkm_oclass *oclass, int index)
 
 nvkm-y += nvkm/engine/fifo/g84.o
 nvkm-y += nvkm/engine/fifo/gf100.o
 nvkm-y += nvkm/engine/fifo/gk104.o
-nvkm-y += nvkm/engine/fifo/gk20a.o
 nvkm-y += nvkm/engine/fifo/gk208.o
+nvkm-y += nvkm/engine/fifo/gk20a.o
 nvkm-y += nvkm/engine/fifo/gm204.o
 nvkm-y += nvkm/engine/fifo/gm20b.o
 
 
 #include "chan.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <core/notify.h>
 
 #include <nvif/event.h>
 #include <nvif/unpack.h>
 
+void
+nvkm_fifo_pause(struct nvkm_fifo *fifo, unsigned long *flags)
+{
+       return fifo->func->pause(fifo, flags);
+}
+
+void
+nvkm_fifo_start(struct nvkm_fifo *fifo, unsigned long *flags)
+{
+       return fifo->func->start(fifo, flags);
+}
+
 void
 nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
                   struct nvkm_fifo_chan **pchan)
        .ctor = nvkm_fifo_event_ctor,
 };
 
-int
+static void
+nvkm_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
+{
+       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+       fifo->func->uevent_fini(fifo);
+}
+
+static void
+nvkm_fifo_uevent_init(struct nvkm_event *event, int type, int index)
+{
+       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+       fifo->func->uevent_init(fifo);
+}
+
+static int
 nvkm_fifo_uevent_ctor(struct nvkm_object *object, void *data, u32 size,
                      struct nvkm_notify *notify)
 {
        return ret;
 }
 
+static const struct nvkm_event_func
+nvkm_fifo_uevent_func = {
+       .ctor = nvkm_fifo_uevent_ctor,
+       .init = nvkm_fifo_uevent_init,
+       .fini = nvkm_fifo_uevent_fini,
+};
+
 void
 nvkm_fifo_uevent(struct nvkm_fifo *fifo)
 {
        return c;
 }
 
-void
-nvkm_fifo_destroy(struct nvkm_fifo *fifo)
+static void
+nvkm_fifo_intr(struct nvkm_engine *engine)
 {
-       nvkm_event_fini(&fifo->uevent);
+       struct nvkm_fifo *fifo = nvkm_fifo(engine);
+       fifo->func->intr(fifo);
+}
+
+static int
+nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(engine);
+       if (fifo->func->fini)
+               fifo->func->fini(fifo);
+       return 0;
+}
+
+static int
+nvkm_fifo_oneinit(struct nvkm_engine *engine)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(engine);
+       if (fifo->func->oneinit)
+               return fifo->func->oneinit(fifo);
+       return 0;
+}
+
+static int
+nvkm_fifo_init(struct nvkm_engine *engine)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(engine);
+       fifo->func->init(fifo);
+       return 0;
+}
+
+static void *
+nvkm_fifo_dtor(struct nvkm_engine *engine)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(engine);
+       void *data = fifo;
+       if (fifo->func->dtor)
+               data = fifo->func->dtor(fifo);
        nvkm_event_fini(&fifo->cevent);
-       nvkm_engine_destroy(&fifo->engine);
+       nvkm_event_fini(&fifo->uevent);
+       return data;
 }
 
 static const struct nvkm_engine_func
-nvkm_fifo_func = {
+nvkm_fifo = {
+       .dtor = nvkm_fifo_dtor,
+       .oneinit = nvkm_fifo_oneinit,
+       .init = nvkm_fifo_init,
+       .fini = nvkm_fifo_fini,
+       .intr = nvkm_fifo_intr,
        .base.sclass = nvkm_fifo_class_get,
 };
 
 int
-nvkm_fifo_create_(struct nvkm_object *parent, struct nvkm_object *engine,
-                 struct nvkm_oclass *oclass,
-                 int min, int max, int length, void **pobject)
+nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+              int index, int nr, struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo;
-       int  nr = max + 1;
-       int cnt = nr - min;
        int ret;
 
-       ret = nvkm_engine_create_(parent, engine, oclass, true, "PFIFO",
-                                 "fifo", length, pobject);
-       fifo = *pobject;
-       if (ret)
-               return ret;
-
-       fifo->engine.func = &nvkm_fifo_func;
+       fifo->func = func;
        INIT_LIST_HEAD(&fifo->chan);
+       spin_lock_init(&fifo->lock);
 
-       fifo->nr = nr;
-       if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) {
+       if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR))
                fifo->nr = NVKM_FIFO_CHID_NR;
-               cnt = fifo->nr - min;
-       }
-       bitmap_fill(fifo->mask, NVKM_FIFO_CHID_NR);
-       bitmap_clear(fifo->mask, min, cnt);
+       else
+               fifo->nr = nr;
+       bitmap_clear(fifo->mask, 0, fifo->nr);
 
-       ret = nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &fifo->cevent);
+       ret = nvkm_engine_ctor(&nvkm_fifo, device, index, 0x00000100,
+                              true, &fifo->engine);
        if (ret)
                return ret;
 
-       spin_lock_init(&fifo->lock);
-       return 0;
+       if (func->uevent_init) {
+               ret = nvkm_event_init(&nvkm_fifo_uevent_func, 1, 1,
+                                     &fifo->uevent);
+               if (ret)
+                       return ret;
+       }
+
+       return nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &fifo->cevent);
 }
 
 #include "chan.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <core/oproxy.h>
 #include <subdev/mmu.h>
 #include <engine/dma.h>
 
 #ifndef __NVKM_FIFO_CHAN_H__
 #define __NVKM_FIFO_CHAN_H__
+#define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object)
 #include "priv.h"
 
 struct nvkm_fifo_chan_func {
 
        struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_memory *fctx = device->imem->ramfc;
-       struct ramfc_desc *c;
+       const struct nv04_fifo_ramfc *c;
        unsigned long flags;
        u32 mask = fifo->base.nr - 1;
        u32 data = chan->ramfc;
                nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0);
                nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0);
 
-               c = fifo->ramfc_desc;
+               c = fifo->ramfc;
                do {
                        u32 rm = ((1ULL << c->bits) - 1) << c->regs;
                        u32 cm = ((1ULL << c->bits) - 1) << c->ctxs;
                        nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs));
                } while ((++c)->bits);
 
-               c = fifo->ramfc_desc;
+               c = fifo->ramfc;
                do {
                        nvkm_wr32(device, c->regp, 0x00000000);
                } while ((++c)->bits);
        struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
        struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       struct ramfc_desc *c = fifo->ramfc_desc;
+       const struct nv04_fifo_ramfc *c = fifo->ramfc;
 
        nvkm_kmap(imem->ramfc);
        do {
 
 #include "regsnv04.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/instmem.h>
 
 #include <nvif/class.h>
 
 #include "regsnv04.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/instmem.h>
 
 #include <nvif/class.h>
 
 #include "channv50.h"
 
 static void
-g84_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
+g84_fifo_uevent_fini(struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x40000000, 0x00000000);
 }
 
 static void
-g84_fifo_uevent_init(struct nvkm_event *event, int type, int index)
+g84_fifo_uevent_init(struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x40000000, 0x40000000);
 }
 
-static const struct nvkm_event_func
-g84_fifo_uevent_func = {
-       .ctor = nvkm_fifo_uevent_ctor,
-       .init = g84_fifo_uevent_init,
-       .fini = g84_fifo_uevent_fini,
-};
-
 static const struct nvkm_fifo_func
-g84_fifo_func = {
+g84_fifo = {
+       .dtor = nv50_fifo_dtor,
+       .oneinit = nv50_fifo_oneinit,
+       .init = nv50_fifo_init,
+       .intr = nv04_fifo_intr,
+       .pause = nv04_fifo_pause,
+       .start = nv04_fifo_start,
+       .uevent_init = g84_fifo_uevent_init,
+       .uevent_fini = g84_fifo_uevent_fini,
        .chan = {
                &g84_fifo_dma_oclass,
                &g84_fifo_gpfifo_oclass,
        },
 };
 
-static int
-g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-             struct nvkm_oclass *oclass, void *data, u32 size,
-             struct nvkm_object **pobject)
+int
+g84_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       struct nvkm_device *device = (void *)parent;
-       struct nv50_fifo *fifo;
-       int ret;
-
-       ret = nvkm_fifo_create(parent, engine, oclass, 1, 127, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &g84_fifo_func;
-
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
-                             false, &fifo->runlist[0]);
-       if (ret)
-               return ret;
-
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
-                             false, &fifo->runlist[1]);
-       if (ret)
-               return ret;
-
-       ret = nvkm_event_init(&g84_fifo_uevent_func, 1, 1, &fifo->base.uevent);
-       if (ret)
-               return ret;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = nv04_fifo_intr;
-       fifo->base.pause = nv04_fifo_pause;
-       fifo->base.start = nv04_fifo_start;
-       return 0;
+       return nv50_fifo_new_(&g84_fifo, device, index, pfifo);
 }
-
-struct nvkm_oclass *
-g84_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0x84),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = g84_fifo_ctor,
-               .dtor = nv50_fifo_dtor,
-               .init = nv50_fifo_init,
-               .fini = _nvkm_fifo_fini,
-       },
-};
 
 
 #include <core/client.h>
 #include <core/enum.h>
+#include <core/gpuobj.h>
 #include <core/handle.h>
 #include <subdev/bar.h>
 #include <engine/sw.h>
 #include <nvif/class.h>
 
 static void
-gf100_fifo_uevent_init(struct nvkm_event *event, int type, int index)
+gf100_fifo_uevent_init(struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x80000000, 0x80000000);
 }
 
 static void
-gf100_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
+gf100_fifo_uevent_fini(struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
 }
 
-static const struct nvkm_event_func
-gf100_fifo_uevent_func = {
-       .ctor = nvkm_fifo_uevent_ctor,
-       .init = gf100_fifo_uevent_init,
-       .fini = gf100_fifo_uevent_fini,
-};
-
 void
 gf100_fifo_runlist_update(struct gf100_fifo *fifo)
 {
        struct nvkm_memory *cur;
        int nr = 0;
 
-       mutex_lock(&nv_subdev(fifo)->mutex);
+       mutex_lock(&subdev->mutex);
        cur = fifo->runlist.mem[fifo->runlist.active];
        fifo->runlist.active = !fifo->runlist.active;
 
                               !(nvkm_rd32(device, 0x00227c) & 0x00100000),
                               msecs_to_jiffies(2000)) == 0)
                nvkm_error(subdev, "runlist update timeout\n");
-       mutex_unlock(&nv_subdev(fifo)->mutex);
+       mutex_unlock(&subdev->mutex);
 }
 
 static inline int
 static inline struct nvkm_engine *
 gf100_fifo_engine(struct gf100_fifo *fifo, u32 engn)
 {
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+
        switch (engn) {
        case 0: engn = NVDEV_ENGINE_GR; break;
        case 1: engn = NVDEV_ENGINE_MSVLD; break;
                return NULL;
        }
 
-       return nvkm_engine(fifo, engn);
+       return nvkm_device_engine(device, engn);
 }
 
 static void
        list_del_init(&chan->head);
        chan->killed = true;
 
-       fifo->mask |= 1ULL << nv_engidx(engine);
+       fifo->mask |= 1ULL << engine->subdev.index;
        schedule_work(&fifo->fault);
 }
 
                        nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
                        break;
                default:
-                       engine = nvkm_engine(fifo, eu->data2);
+                       engine = nvkm_device_engine(device, eu->data2);
                        break;
                }
        }
 }
 
 static void
-gf100_fifo_intr(struct nvkm_subdev *subdev)
+gf100_fifo_intr(struct nvkm_fifo *base)
 {
-       struct gf100_fifo *fifo = (void *)subdev;
-       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct gf100_fifo *fifo = gf100_fifo(base);
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
        u32 mask = nvkm_rd32(device, 0x002140);
        u32 stat = nvkm_rd32(device, 0x002100) & mask;
 
 }
 
 static int
-gf100_fifo_init(struct nvkm_object *object)
+gf100_fifo_oneinit(struct nvkm_fifo *base)
 {
-       struct gf100_fifo *fifo = (void *)object;
-       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
-       struct nvkm_device *device = subdev->device;
-       int ret, i;
+       struct gf100_fifo *fifo = gf100_fifo(base);
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       int ret;
 
-       ret = nvkm_fifo_init(&fifo->base);
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
+                             false, &fifo->runlist.mem[0]);
+       if (ret)
+               return ret;
+
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
+                             false, &fifo->runlist.mem[1]);
        if (ret)
                return ret;
 
+       init_waitqueue_head(&fifo->runlist.wait);
+
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000,
+                             0x1000, false, &fifo->user.mem);
+       if (ret)
+               return ret;
+
+       ret = nvkm_bar_umap(device->bar, 128 * 0x1000, 12, &fifo->user.bar);
+       if (ret)
+               return ret;
+
+       nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0);
+       return 0;
+}
+
+static void
+gf100_fifo_fini(struct nvkm_fifo *base)
+{
+       struct gf100_fifo *fifo = gf100_fifo(base);
+       flush_work(&fifo->fault);
+}
+
+static void
+gf100_fifo_init(struct nvkm_fifo *base)
+{
+       struct gf100_fifo *fifo = gf100_fifo(base);
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       int i;
+
        nvkm_wr32(device, 0x000204, 0xffffffff);
        nvkm_wr32(device, 0x002204, 0xffffffff);
 
        nvkm_wr32(device, 0x002100, 0xffffffff);
        nvkm_wr32(device, 0x002140, 0x7fffffff);
        nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */
-       return 0;
 }
 
-static void
-gf100_fifo_dtor(struct nvkm_object *object)
+static void *
+gf100_fifo_dtor(struct nvkm_fifo *base)
 {
-       struct gf100_fifo *fifo = (void *)object;
-
+       struct gf100_fifo *fifo = gf100_fifo(base);
        nvkm_vm_put(&fifo->user.bar);
        nvkm_memory_del(&fifo->user.mem);
        nvkm_memory_del(&fifo->runlist.mem[0]);
        nvkm_memory_del(&fifo->runlist.mem[1]);
-
-       nvkm_fifo_destroy(&fifo->base);
+       return fifo;
 }
 
 static const struct nvkm_fifo_func
-gf100_fifo_func = {
+gf100_fifo = {
+       .dtor = gf100_fifo_dtor,
+       .oneinit = gf100_fifo_oneinit,
+       .init = gf100_fifo_init,
+       .fini = gf100_fifo_fini,
+       .intr = gf100_fifo_intr,
+       .uevent_init = gf100_fifo_uevent_init,
+       .uevent_fini = gf100_fifo_uevent_fini,
        .chan = {
                &gf100_fifo_gpfifo_oclass,
                NULL
        },
 };
 
-static int
-gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-               struct nvkm_oclass *oclass, void *data, u32 size,
-               struct nvkm_object **pobject)
+int
+gf100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       struct nvkm_device *device = (void *)parent;
-       struct nvkm_bar *bar = device->bar;
        struct gf100_fifo *fifo;
-       int ret;
-
-       ret = nvkm_fifo_create(parent, engine, oclass, 0, 127, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &gf100_fifo_func;
 
+       if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
+               return -ENOMEM;
        INIT_LIST_HEAD(&fifo->chan);
        INIT_WORK(&fifo->fault, gf100_fifo_recover_work);
+       *pfifo = &fifo->base;
 
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
-                             false, &fifo->runlist.mem[0]);
-       if (ret)
-               return ret;
-
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
-                             false, &fifo->runlist.mem[1]);
-       if (ret)
-               return ret;
-
-       init_waitqueue_head(&fifo->runlist.wait);
-
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000,
-                             0x1000, false, &fifo->user.mem);
-       if (ret)
-               return ret;
-
-       ret = nvkm_bar_umap(bar, 128 * 0x1000, 12, &fifo->user.bar);
-       if (ret)
-               return ret;
-
-       nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0);
-
-       ret = nvkm_event_init(&gf100_fifo_uevent_func, 1, 1, &fifo->base.uevent);
-       if (ret)
-               return ret;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = gf100_fifo_intr;
-       return 0;
+       return nvkm_fifo_ctor(&gf100_fifo, device, index, 128, &fifo->base);
 }
-
-
-struct nvkm_oclass *
-gf100_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0xc0),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gf100_fifo_ctor,
-               .dtor = gf100_fifo_dtor,
-               .init = gf100_fifo_init,
-               .fini = _nvkm_fifo_fini,
-       },
-};
 
 
 #include <core/client.h>
 #include <core/enum.h>
+#include <core/gpuobj.h>
 #include <core/handle.h>
 #include <subdev/bar.h>
 #include <engine/sw.h>
 
 #include <nvif/class.h>
 
-static void
-gk104_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
+void
+gk104_fifo_uevent_fini(struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
 }
 
-static void
-gk104_fifo_uevent_init(struct nvkm_event *event, int type, int index)
+void
+gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
 {
-       struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x80000000, 0x80000000);
 }
 
-static const struct nvkm_event_func
-gk104_fifo_uevent_func = {
-       .ctor = nvkm_fifo_uevent_ctor,
-       .init = gk104_fifo_uevent_init,
-       .fini = gk104_fifo_uevent_fini,
-};
-
 void
 gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine)
 {
        struct nvkm_memory *cur;
        int nr = 0;
 
-       mutex_lock(&nv_subdev(fifo)->mutex);
+       mutex_lock(&subdev->mutex);
        cur = engn->runlist[engn->cur_runlist];
        engn->cur_runlist = !engn->cur_runlist;
 
                               (engine * 0x08)) & 0x00100000),
                                msecs_to_jiffies(2000)) == 0)
                nvkm_error(subdev, "runlist %d update timeout\n", engine);
-       mutex_unlock(&nv_subdev(fifo)->mutex);
+       mutex_unlock(&subdev->mutex);
 }
 
 static inline struct nvkm_engine *
 gk104_fifo_engine(struct gk104_fifo *fifo, u32 engn)
 {
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
        u64 subdevs = gk104_fifo_engine_subdev(engn);
        if (subdevs)
-               return nvkm_engine(fifo, __ffs(subdevs));
+               return nvkm_device_engine(device, __ffs(subdevs));
        return NULL;
 }
 
        u32 chid = chan->base.chid;
 
        nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n",
-                  nvkm_subdev_name[nv_subdev(engine)->index], chid);
+                  nvkm_subdev_name[engine->subdev.index], chid);
        assert_spin_locked(&fifo->base.lock);
 
        nvkm_mask(device, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800);
        list_del_init(&chan->head);
        chan->killed = true;
 
-       fifo->mask |= 1ULL << nv_engidx(engine);
+       fifo->mask |= 1ULL << engine->subdev.index;
        schedule_work(&fifo->fault);
 }
 
                        nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
                        break;
                default:
-                       engine = nvkm_engine(fifo, eu->data2);
+                       engine = nvkm_device_engine(device, eu->data2);
                        break;
                }
        }
        nvkm_fifo_uevent(&fifo->base);
 }
 
-static void
-gk104_fifo_intr(struct nvkm_subdev *subdev)
+void
+gk104_fifo_intr(struct nvkm_fifo *base)
 {
-       struct gk104_fifo *fifo = (void *)subdev;
-       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct gk104_fifo *fifo = gk104_fifo(base);
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
        u32 mask = nvkm_rd32(device, 0x002140);
        u32 stat = nvkm_rd32(device, 0x002100) & mask;
 
        }
 }
 
+void
+gk104_fifo_fini(struct nvkm_fifo *base)
+{
+       struct gk104_fifo *fifo = gk104_fifo(base);
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       flush_work(&fifo->fault);
+       /* allow mmu fault interrupts, even when we're not using fifo */
+       nvkm_mask(device, 0x002140, 0x10000000, 0x10000000);
+}
+
 int
-gk104_fifo_fini(struct nvkm_object *object, bool suspend)
+gk104_fifo_oneinit(struct nvkm_fifo *base)
 {
-       struct gk104_fifo *fifo = (void *)object;
+       struct gk104_fifo *fifo = gk104_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
-       int ret;
+       int ret, i;
 
-       ret = nvkm_fifo_fini(&fifo->base, suspend);
+       for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) {
+               ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
+                                     0x8000, 0x1000, false,
+                                     &fifo->engine[i].runlist[0]);
+               if (ret)
+                       return ret;
+
+               ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
+                                     0x8000, 0x1000, false,
+                                     &fifo->engine[i].runlist[1]);
+               if (ret)
+                       return ret;
+
+               init_waitqueue_head(&fifo->engine[i].wait);
+               INIT_LIST_HEAD(&fifo->engine[i].chan);
+       }
+
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
+                             fifo->base.nr * 0x200, 0x1000, true,
+                             &fifo->user.mem);
        if (ret)
                return ret;
 
-       /* allow mmu fault interrupts, even when we're not using fifo */
-       nvkm_mask(device, 0x002140, 0x10000000, 0x10000000);
+       ret = nvkm_bar_umap(device->bar, fifo->base.nr * 0x200, 12,
+                           &fifo->user.bar);
+       if (ret)
+               return ret;
+
+       nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0);
        return 0;
 }
 
-int
-gk104_fifo_init(struct nvkm_object *object)
+void
+gk104_fifo_init(struct nvkm_fifo *base)
 {
-       struct gk104_fifo *fifo = (void *)object;
+       struct gk104_fifo *fifo = gk104_fifo(base);
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
-       int ret, i;
-
-       ret = nvkm_fifo_init(&fifo->base);
-       if (ret)
-               return ret;
+       int i;
 
        /* enable all available PBDMA units */
        nvkm_wr32(device, 0x000204, 0xffffffff);
 
        nvkm_wr32(device, 0x002100, 0xffffffff);
        nvkm_wr32(device, 0x002140, 0x7fffffff);
-       return 0;
 }
 
-void
-gk104_fifo_dtor(struct nvkm_object *object)
+void *
+gk104_fifo_dtor(struct nvkm_fifo *base)
 {
-       struct gk104_fifo *fifo = (void *)object;
+       struct gk104_fifo *fifo = gk104_fifo(base);
        int i;
 
        nvkm_vm_put(&fifo->user.bar);
                nvkm_memory_del(&fifo->engine[i].runlist[0]);
        }
 
-       nvkm_fifo_destroy(&fifo->base);
+       return fifo;
+}
+
+int
+gk104_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+               int index, int nr, struct nvkm_fifo **pfifo)
+{
+       struct gk104_fifo *fifo;
+
+       if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
+               return -ENOMEM;
+       INIT_WORK(&fifo->fault, gk104_fifo_recover_work);
+       *pfifo = &fifo->base;
+
+       return nvkm_fifo_ctor(func, device, index, nr, &fifo->base);
 }
 
 static const struct nvkm_fifo_func
-gk104_fifo_func = {
+gk104_fifo = {
+       .dtor = gk104_fifo_dtor,
+       .oneinit = gk104_fifo_oneinit,
+       .init = gk104_fifo_init,
+       .fini = gk104_fifo_fini,
+       .intr = gk104_fifo_intr,
+       .uevent_init = gk104_fifo_uevent_init,
+       .uevent_fini = gk104_fifo_uevent_fini,
        .chan = {
                &gk104_fifo_gpfifo_oclass,
                NULL
 };
 
 int
-gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-               struct nvkm_oclass *oclass, void *data, u32 size,
-               struct nvkm_object **pobject)
+gk104_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       struct nvkm_device *device = (void *)parent;
-       struct nvkm_bar *bar = device->bar;
-       struct gk104_fifo_impl *impl = (void *)oclass;
-       struct gk104_fifo *fifo;
-       int ret, i;
-
-       ret = nvkm_fifo_create(parent, engine, oclass, 0,
-                              impl->channels - 1, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &gk104_fifo_func;
-
-       INIT_WORK(&fifo->fault, gk104_fifo_recover_work);
-
-       for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) {
-               ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
-                                     0x8000, 0x1000, false,
-                                     &fifo->engine[i].runlist[0]);
-               if (ret)
-                       return ret;
-
-               ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
-                                     0x8000, 0x1000, false,
-                                     &fifo->engine[i].runlist[1]);
-               if (ret)
-                       return ret;
-
-               init_waitqueue_head(&fifo->engine[i].wait);
-               INIT_LIST_HEAD(&fifo->engine[i].chan);
-       }
-
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
-                             impl->channels * 0x200, 0x1000,
-                             true, &fifo->user.mem);
-       if (ret)
-               return ret;
-
-       ret = nvkm_bar_umap(bar, impl->channels * 0x200, 12, &fifo->user.bar);
-       if (ret)
-               return ret;
-
-       nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0);
-
-       ret = nvkm_event_init(&gk104_fifo_uevent_func, 1, 1, &fifo->base.uevent);
-       if (ret)
-               return ret;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = gk104_fifo_intr;
-       return 0;
+       return gk104_fifo_new_(&gk104_fifo, device, index, 4096, pfifo);
 }
-
-struct nvkm_oclass *
-gk104_fifo_oclass = &(struct gk104_fifo_impl) {
-       .base.handle = NV_ENGINE(FIFO, 0xe0),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gk104_fifo_ctor,
-               .dtor = gk104_fifo_dtor,
-               .init = gk104_fifo_init,
-               .fini = gk104_fifo_fini,
-       },
-       .channels = 4096,
-}.base;
 
        int spoon_nr;
 };
 
-struct gk104_fifo_impl {
-       struct nvkm_oclass base;
-       u32 channels;
-};
-
-int  gk104_fifo_ctor(struct nvkm_object *, struct nvkm_object *,
-                   struct nvkm_oclass *, void *, u32,
-                   struct nvkm_object **);
-void gk104_fifo_dtor(struct nvkm_object *);
-int  gk104_fifo_init(struct nvkm_object *);
-int  gk104_fifo_fini(struct nvkm_object *, bool);
+int gk104_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *,
+                   int index, int nr, struct nvkm_fifo **);
+void *gk104_fifo_dtor(struct nvkm_fifo *);
+int gk104_fifo_oneinit(struct nvkm_fifo *);
+void gk104_fifo_init(struct nvkm_fifo *);
+void gk104_fifo_fini(struct nvkm_fifo *);
+void gk104_fifo_intr(struct nvkm_fifo *);
+void gk104_fifo_uevent_init(struct nvkm_fifo *);
+void gk104_fifo_uevent_fini(struct nvkm_fifo *);
 void gk104_fifo_runlist_update(struct gk104_fifo *, u32 engine);
 
-int  gm204_fifo_ctor(struct nvkm_object *, struct nvkm_object *,
-                   struct nvkm_oclass *, void *, u32,
-                   struct nvkm_object **);
-
 static inline u64
 gk104_fifo_engine_subdev(int engine)
 {
 
  * Authors: Ben Skeggs
  */
 #include "gk104.h"
+#include "changk104.h"
 
-struct nvkm_oclass *
-gk208_fifo_oclass = &(struct gk104_fifo_impl) {
-       .base.handle = NV_ENGINE(FIFO, 0x08),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gk104_fifo_ctor,
-               .dtor = gk104_fifo_dtor,
-               .init = gk104_fifo_init,
-               .fini = _nvkm_fifo_fini,
+static const struct nvkm_fifo_func
+gk208_fifo = {
+       .dtor = gk104_fifo_dtor,
+       .oneinit = gk104_fifo_oneinit,
+       .init = gk104_fifo_init,
+       .fini = gk104_fifo_fini,
+       .intr = gk104_fifo_intr,
+       .uevent_init = gk104_fifo_uevent_init,
+       .uevent_fini = gk104_fifo_uevent_fini,
+       .chan = {
+               &gk104_fifo_gpfifo_oclass,
+               NULL
        },
-       .channels = 1024,
-}.base;
+};
+
+int
+gk208_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return gk104_fifo_new_(&gk208_fifo, device, index, 1024, pfifo);
+}
 
  * DEALINGS IN THE SOFTWARE.
  */
 #include "gk104.h"
+#include "changk104.h"
 
-struct nvkm_oclass *
-gk20a_fifo_oclass = &(struct gk104_fifo_impl) {
-       .base.handle = NV_ENGINE(FIFO, 0xea),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gk104_fifo_ctor,
-               .dtor = gk104_fifo_dtor,
-               .init = gk104_fifo_init,
-               .fini = gk104_fifo_fini,
+static const struct nvkm_fifo_func
+gk20a_fifo = {
+       .dtor = gk104_fifo_dtor,
+       .oneinit = gk104_fifo_oneinit,
+       .init = gk104_fifo_init,
+       .fini = gk104_fifo_fini,
+       .intr = gk104_fifo_intr,
+       .uevent_init = gk104_fifo_uevent_init,
+       .uevent_fini = gk104_fifo_uevent_fini,
+       .chan = {
+               &gk104_fifo_gpfifo_oclass,
+               NULL
        },
-       .channels = 128,
-}.base;
+};
+
+int
+gk20a_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return gk104_fifo_new_(&gk20a_fifo, device, index, 128, pfifo);
+}
 
 #include "changk104.h"
 
 static const struct nvkm_fifo_func
-gm204_fifo_func = {
+gm204_fifo = {
+       .dtor = gk104_fifo_dtor,
+       .oneinit = gk104_fifo_oneinit,
+       .init = gk104_fifo_init,
+       .fini = gk104_fifo_fini,
+       .intr = gk104_fifo_intr,
+       .uevent_init = gk104_fifo_uevent_init,
+       .uevent_fini = gk104_fifo_uevent_fini,
        .chan = {
                &gm204_fifo_gpfifo_oclass,
                NULL
 };
 
 int
-gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-               struct nvkm_oclass *oclass, void *data, u32 size,
-               struct nvkm_object **pobject)
+gm204_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       int ret = gk104_fifo_ctor(parent, engine, oclass, data, size, pobject);
-       if (ret == 0) {
-               struct gk104_fifo *fifo = (void *)*pobject;
-               fifo->base.func = &gm204_fifo_func;
-       }
-       return ret;
+       return gk104_fifo_new_(&gm204_fifo, device, index, 4096, pfifo);
 }
-
-struct nvkm_oclass *
-gm204_fifo_oclass = &(struct gk104_fifo_impl) {
-       .base.handle = NV_ENGINE(FIFO, 0x24),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gm204_fifo_ctor,
-               .dtor = gk104_fifo_dtor,
-               .init = gk104_fifo_init,
-               .fini = _nvkm_fifo_fini,
-       },
-       .channels = 4096,
-}.base;
 
  * DEALINGS IN THE SOFTWARE.
  */
 #include "gk104.h"
+#include "changk104.h"
 
-struct nvkm_oclass *
-gm20b_fifo_oclass = &(struct gk104_fifo_impl) {
-       .base.handle = NV_ENGINE(FIFO, 0x2b),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gm204_fifo_ctor,
-               .dtor = gk104_fifo_dtor,
-               .init = gk104_fifo_init,
-               .fini = gk104_fifo_fini,
+static const struct nvkm_fifo_func
+gm20b_fifo = {
+       .dtor = gk104_fifo_dtor,
+       .oneinit = gk104_fifo_oneinit,
+       .init = gk104_fifo_init,
+       .fini = gk104_fifo_fini,
+       .intr = gk104_fifo_intr,
+       .uevent_init = gk104_fifo_uevent_init,
+       .uevent_fini = gk104_fifo_uevent_fini,
+       .chan = {
+               &gm204_fifo_gpfifo_oclass,
+               NULL
        },
-       .channels = 512,
-}.base;
+};
+
+int
+gm20b_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return gk104_fifo_new_(&gm20b_fifo, device, index, 512, pfifo);
+}
 
 #include "changf100.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/fb.h>
 #include <subdev/timer.h>
 
 
 #include "changk104.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/fb.h>
 #include <subdev/mmu.h>
 #include <subdev/timer.h>
 
 #include <subdev/timer.h>
 #include <engine/sw.h>
 
-static struct ramfc_desc
-nv04_ramfc[] = {
+static const struct nv04_fifo_ramfc
+nv04_fifo_ramfc[] = {
        { 32,  0, 0x00,  0, NV04_PFIFO_CACHE1_DMA_PUT },
        { 32,  0, 0x04,  0, NV04_PFIFO_CACHE1_DMA_GET },
        { 16,  0, 0x08,  0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
 };
 
 void
-nv04_fifo_pause(struct nvkm_fifo *obj, unsigned long *pflags)
+nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags)
 __acquires(fifo->base.lock)
 {
-       struct nv04_fifo *fifo = container_of(obj, typeof(*fifo), base);
+       struct nv04_fifo *fifo = nv04_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        unsigned long flags;
 
 }
 
 void
-nv04_fifo_start(struct nvkm_fifo *obj, unsigned long *pflags)
+nv04_fifo_start(struct nvkm_fifo *base, unsigned long *pflags)
 __releases(fifo->base.lock)
 {
-       struct nv04_fifo *fifo = container_of(obj, typeof(*fifo), base);
+       struct nv04_fifo *fifo = nv04_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        unsigned long flags = *pflags;
 
 }
 
 void
-nv04_fifo_intr(struct nvkm_subdev *subdev)
+nv04_fifo_intr(struct nvkm_fifo *base)
 {
+       struct nv04_fifo *fifo = nv04_fifo(base);
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
-       struct nv04_fifo *fifo = (void *)subdev;
        u32 mask = nvkm_rd32(device, NV03_PFIFO_INTR_EN_0);
        u32 stat = nvkm_rd32(device, NV03_PFIFO_INTR_0) & mask;
        u32 reassign, chid, get, sem;
        nvkm_wr32(device, NV03_PFIFO_CACHES, reassign);
 }
 
-int
-nv04_fifo_init(struct nvkm_object *object)
+void
+nv04_fifo_init(struct nvkm_fifo *base)
 {
-       struct nv04_fifo *fifo = (void *)object;
+       struct nv04_fifo *fifo = nv04_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_instmem *imem = device->imem;
        struct nvkm_ramht *ramht = imem->ramht;
        struct nvkm_memory *ramro = imem->ramro;
        struct nvkm_memory *ramfc = imem->ramfc;
-       int ret;
-
-       ret = nvkm_fifo_init(&fifo->base);
-       if (ret)
-               return ret;
 
        nvkm_wr32(device, NV04_PFIFO_DELAY_0, 0x000000ff);
        nvkm_wr32(device, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff);
        nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
        nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
        nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
-       return 0;
 }
 
-void
-nv04_fifo_dtor(struct nvkm_object *object)
-{
-       struct nv04_fifo *fifo = (void *)object;
-       nvkm_fifo_destroy(&fifo->base);
-}
-
-static const struct nvkm_fifo_func
-nv04_fifo_func = {
-       .chan = {
-               &nv04_fifo_dma_oclass,
-               NULL
-       },
-};
-
-static int
-nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-              struct nvkm_oclass *oclass, void *data, u32 size,
-              struct nvkm_object **pobject)
+int
+nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+              int index, int nr, const struct nv04_fifo_ramfc *ramfc,
+              struct nvkm_fifo **pfifo)
 {
        struct nv04_fifo *fifo;
        int ret;
 
-       ret = nvkm_fifo_create(parent, engine, oclass, 0, 15, &fifo);
-       *pobject = nv_object(fifo);
+       if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
+               return -ENOMEM;
+       fifo->ramfc = ramfc;
+       *pfifo = &fifo->base;
+
+       ret = nvkm_fifo_ctor(func, device, index, nr, &fifo->base);
        if (ret)
                return ret;
 
-       fifo->base.func = &nv04_fifo_func;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = nv04_fifo_intr;
-       fifo->base.pause = nv04_fifo_pause;
-       fifo->base.start = nv04_fifo_start;
-       fifo->ramfc_desc = nv04_ramfc;
+       set_bit(nr - 1, fifo->base.mask); /* inactive channel */
        return 0;
 }
 
-struct nvkm_oclass *
-nv04_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0x04),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_fifo_ctor,
-               .dtor = nv04_fifo_dtor,
-               .init = nv04_fifo_init,
-               .fini = _nvkm_fifo_fini,
+static const struct nvkm_fifo_func
+nv04_fifo = {
+       .init = nv04_fifo_init,
+       .intr = nv04_fifo_intr,
+       .pause = nv04_fifo_pause,
+       .start = nv04_fifo_start,
+       .chan = {
+               &nv04_fifo_dma_oclass,
+               NULL
        },
 };
+
+int
+nv04_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return nv04_fifo_new_(&nv04_fifo, device, index, 16,
+                             nv04_fifo_ramfc, pfifo);
+}
 
 #define nv04_fifo(p) container_of((p), struct nv04_fifo, base)
 #include "priv.h"
 
-struct ramfc_desc {
+struct nv04_fifo_ramfc {
        unsigned bits:6;
        unsigned ctxs:5;
        unsigned ctxp:8;
 
 struct nv04_fifo {
        struct nvkm_fifo base;
-       struct ramfc_desc *ramfc_desc;
+       const struct nv04_fifo_ramfc *ramfc;
 };
 
-void nv04_fifo_dtor(struct nvkm_object *);
-int  nv04_fifo_init(struct nvkm_object *);
+int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *,
+                  int index, int nr, const struct nv04_fifo_ramfc *,
+                  struct nvkm_fifo **);
+void nv04_fifo_init(struct nvkm_fifo *);
 #endif
 
 #include "channv04.h"
 #include "regsnv04.h"
 
-static struct ramfc_desc
-nv10_ramfc[] = {
+static const struct nv04_fifo_ramfc
+nv10_fifo_ramfc[] = {
        { 32,  0, 0x00,  0, NV04_PFIFO_CACHE1_DMA_PUT },
        { 32,  0, 0x04,  0, NV04_PFIFO_CACHE1_DMA_GET },
        { 32,  0, 0x08,  0, NV10_PFIFO_CACHE1_REF_CNT },
 };
 
 static const struct nvkm_fifo_func
-nv10_fifo_func = {
+nv10_fifo = {
+       .init = nv04_fifo_init,
+       .intr = nv04_fifo_intr,
+       .pause = nv04_fifo_pause,
+       .start = nv04_fifo_start,
        .chan = {
                &nv10_fifo_dma_oclass,
                NULL
        },
 };
 
-static int
-nv10_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-              struct nvkm_oclass *oclass, void *data, u32 size,
-              struct nvkm_object **pobject)
+int
+nv10_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       struct nv04_fifo *fifo;
-       int ret;
-
-       ret = nvkm_fifo_create(parent, engine, oclass, 0, 31, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &nv10_fifo_func;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = nv04_fifo_intr;
-       fifo->base.pause = nv04_fifo_pause;
-       fifo->base.start = nv04_fifo_start;
-       fifo->ramfc_desc = nv10_ramfc;
-       return 0;
+       return nv04_fifo_new_(&nv10_fifo, device, index, 32,
+                             nv10_fifo_ramfc, pfifo);
 }
-
-struct nvkm_oclass *
-nv10_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0x10),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv10_fifo_ctor,
-               .dtor = nv04_fifo_dtor,
-               .init = nv04_fifo_init,
-               .fini = _nvkm_fifo_fini,
-       },
-};
 
 #include <core/ramht.h>
 #include <subdev/instmem.h>
 
-static struct ramfc_desc
-nv17_ramfc[] = {
+static const struct nv04_fifo_ramfc
+nv17_fifo_ramfc[] = {
        { 32,  0, 0x00,  0, NV04_PFIFO_CACHE1_DMA_PUT },
        { 32,  0, 0x04,  0, NV04_PFIFO_CACHE1_DMA_GET },
        { 32,  0, 0x08,  0, NV10_PFIFO_CACHE1_REF_CNT },
        {}
 };
 
-static int
-nv17_fifo_init(struct nvkm_object *object)
+static void
+nv17_fifo_init(struct nvkm_fifo *base)
 {
-       struct nv04_fifo *fifo = (void *)object;
+       struct nv04_fifo *fifo = nv04_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_instmem *imem = device->imem;
        struct nvkm_ramht *ramht = imem->ramht;
        struct nvkm_memory *ramro = imem->ramro;
        struct nvkm_memory *ramfc = imem->ramfc;
-       int ret;
-
-       ret = nvkm_fifo_init(&fifo->base);
-       if (ret)
-               return ret;
 
        nvkm_wr32(device, NV04_PFIFO_DELAY_0, 0x000000ff);
        nvkm_wr32(device, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff);
        nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
        nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
        nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
-       return 0;
 }
 
 static const struct nvkm_fifo_func
-nv17_fifo_func = {
+nv17_fifo = {
+       .init = nv17_fifo_init,
+       .intr = nv04_fifo_intr,
+       .pause = nv04_fifo_pause,
+       .start = nv04_fifo_start,
        .chan = {
                &nv17_fifo_dma_oclass,
                NULL
        },
 };
 
-static int
-nv17_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-              struct nvkm_oclass *oclass, void *data, u32 size,
-              struct nvkm_object **pobject)
+int
+nv17_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       struct nv04_fifo *fifo;
-       int ret;
-
-       ret = nvkm_fifo_create(parent, engine, oclass, 0, 31, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &nv17_fifo_func;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = nv04_fifo_intr;
-       fifo->base.pause = nv04_fifo_pause;
-       fifo->base.start = nv04_fifo_start;
-       fifo->ramfc_desc = nv17_ramfc;
-       return 0;
+       return nv04_fifo_new_(&nv17_fifo, device, index, 32,
+                             nv17_fifo_ramfc, pfifo);
 }
-
-struct nvkm_oclass *
-nv17_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0x17),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv17_fifo_ctor,
-               .dtor = nv04_fifo_dtor,
-               .init = nv17_fifo_init,
-               .fini = _nvkm_fifo_fini,
-       },
-};
 
 #include <subdev/fb.h>
 #include <subdev/instmem.h>
 
-static struct ramfc_desc
-nv40_ramfc[] = {
+static const struct nv04_fifo_ramfc
+nv40_fifo_ramfc[] = {
        { 32,  0, 0x00,  0, NV04_PFIFO_CACHE1_DMA_PUT },
        { 32,  0, 0x04,  0, NV04_PFIFO_CACHE1_DMA_GET },
        { 32,  0, 0x08,  0, NV10_PFIFO_CACHE1_REF_CNT },
        {}
 };
 
-static int
-nv40_fifo_init(struct nvkm_object *object)
+static void
+nv40_fifo_init(struct nvkm_fifo *base)
 {
-       struct nv04_fifo *fifo = (void *)object;
+       struct nv04_fifo *fifo = nv04_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_fb *fb = device->fb;
        struct nvkm_instmem *imem = device->imem;
        struct nvkm_ramht *ramht = imem->ramht;
        struct nvkm_memory *ramro = imem->ramro;
        struct nvkm_memory *ramfc = imem->ramfc;
-       int ret;
-
-       ret = nvkm_fifo_init(&fifo->base);
-       if (ret)
-               return ret;
 
        nvkm_wr32(device, 0x002040, 0x000000ff);
        nvkm_wr32(device, 0x002044, 0x2101ffff);
                                            (ramht->gpuobj->addr >> 8));
        nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8);
 
-       switch (nv_device(fifo)->chipset) {
+       switch (device->chipset) {
        case 0x47:
        case 0x49:
        case 0x4b:
        nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
        nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
        nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
-       return 0;
 }
 
 static const struct nvkm_fifo_func
-nv40_fifo_func = {
+nv40_fifo = {
+       .init = nv40_fifo_init,
+       .intr = nv04_fifo_intr,
+       .pause = nv04_fifo_pause,
+       .start = nv04_fifo_start,
        .chan = {
                &nv40_fifo_dma_oclass,
                NULL
        },
 };
 
-static int
-nv40_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-              struct nvkm_oclass *oclass, void *data, u32 size,
-              struct nvkm_object **pobject)
+int
+nv40_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
 {
-       struct nv04_fifo *fifo;
-       int ret;
-
-       ret = nvkm_fifo_create(parent, engine, oclass, 0, 31, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &nv40_fifo_func;
-
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = nv04_fifo_intr;
-       fifo->base.pause = nv04_fifo_pause;
-       fifo->base.start = nv04_fifo_start;
-       fifo->ramfc_desc = nv40_ramfc;
-       return 0;
+       return nv04_fifo_new_(&nv40_fifo, device, index, 32,
+                             nv40_fifo_ramfc, pfifo);
 }
-
-struct nvkm_oclass *
-nv40_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0x40),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv40_fifo_ctor,
-               .dtor = nv04_fifo_dtor,
-               .init = nv40_fifo_init,
-               .fini = _nvkm_fifo_fini,
-       },
-};
 
 #include "nv50.h"
 #include "channv50.h"
 
+#include <core/gpuobj.h>
+
 static void
 nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo)
 {
 void
 nv50_fifo_runlist_update(struct nv50_fifo *fifo)
 {
-       mutex_lock(&nv_subdev(fifo)->mutex);
+       mutex_lock(&fifo->base.engine.subdev.mutex);
        nv50_fifo_runlist_update_locked(fifo);
-       mutex_unlock(&nv_subdev(fifo)->mutex);
+       mutex_unlock(&fifo->base.engine.subdev.mutex);
 }
 
 int
-nv50_fifo_init(struct nvkm_object *object)
+nv50_fifo_oneinit(struct nvkm_fifo *base)
 {
-       struct nv50_fifo *fifo = (void *)object;
+       struct nv50_fifo *fifo = nv50_fifo(base);
        struct nvkm_device *device = fifo->base.engine.subdev.device;
-       int ret, i;
+       int ret;
 
-       ret = nvkm_fifo_init(&fifo->base);
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
+                             false, &fifo->runlist[0]);
        if (ret)
                return ret;
 
+       return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
+                              false, &fifo->runlist[1]);
+}
+
+void
+nv50_fifo_init(struct nvkm_fifo *base)
+{
+       struct nv50_fifo *fifo = nv50_fifo(base);
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       int i;
+
        nvkm_mask(device, 0x000200, 0x00000100, 0x00000000);
        nvkm_mask(device, 0x000200, 0x00000100, 0x00000100);
        nvkm_wr32(device, 0x00250c, 0x6f3cfc34);
        nvkm_wr32(device, 0x003200, 0x00000001);
        nvkm_wr32(device, 0x003250, 0x00000001);
        nvkm_wr32(device, 0x002500, 0x00000001);
-       return 0;
 }
 
-void
-nv50_fifo_dtor(struct nvkm_object *object)
+void *
+nv50_fifo_dtor(struct nvkm_fifo *base)
 {
-       struct nv50_fifo *fifo = (void *)object;
-
+       struct nv50_fifo *fifo = nv50_fifo(base);
        nvkm_memory_del(&fifo->runlist[1]);
        nvkm_memory_del(&fifo->runlist[0]);
-
-       nvkm_fifo_destroy(&fifo->base);
+       return fifo;
 }
 
-static const struct nvkm_fifo_func
-nv50_fifo_func = {
-       .chan = {
-               &nv50_fifo_dma_oclass,
-               &nv50_fifo_gpfifo_oclass,
-               NULL
-       },
-};
-
-static int
-nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-              struct nvkm_oclass *oclass, void *data, u32 size,
-              struct nvkm_object **pobject)
+int
+nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+              int index, struct nvkm_fifo **pfifo)
 {
-       struct nvkm_device *device = (void *)parent;
        struct nv50_fifo *fifo;
        int ret;
 
-       ret = nvkm_fifo_create(parent, engine, oclass, 1, 127, &fifo);
-       *pobject = nv_object(fifo);
-       if (ret)
-               return ret;
-
-       fifo->base.func = &nv50_fifo_func;
-
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
-                             false, &fifo->runlist[0]);
-       if (ret)
-               return ret;
+       if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
+               return -ENOMEM;
+       *pfifo = &fifo->base;
 
-       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
-                             false, &fifo->runlist[1]);
+       ret = nvkm_fifo_ctor(func, device, index, 128, &fifo->base);
        if (ret)
                return ret;
 
-       nv_subdev(fifo)->unit = 0x00000100;
-       nv_subdev(fifo)->intr = nv04_fifo_intr;
-       fifo->base.pause = nv04_fifo_pause;
-       fifo->base.start = nv04_fifo_start;
+       set_bit(0, fifo->base.mask); /* PIO channel */
+       set_bit(127, fifo->base.mask); /* inactive channel */
        return 0;
 }
 
-struct nvkm_oclass *
-nv50_fifo_oclass = &(struct nvkm_oclass) {
-       .handle = NV_ENGINE(FIFO, 0x50),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_fifo_ctor,
-               .dtor = nv50_fifo_dtor,
-               .init = nv50_fifo_init,
-               .fini = _nvkm_fifo_fini,
+static const struct nvkm_fifo_func
+nv50_fifo = {
+       .dtor = nv50_fifo_dtor,
+       .oneinit = nv50_fifo_oneinit,
+       .init = nv50_fifo_init,
+       .intr = nv04_fifo_intr,
+       .pause = nv04_fifo_pause,
+       .start = nv04_fifo_start,
+       .chan = {
+               &nv50_fifo_dma_oclass,
+               &nv50_fifo_gpfifo_oclass,
+               NULL
        },
 };
+
+int
+nv50_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return nv50_fifo_new_(&nv50_fifo, device, index, pfifo);
+}
 
        int cur_runlist;
 };
 
-void nv50_fifo_dtor(struct nvkm_object *);
-int  nv50_fifo_init(struct nvkm_object *);
+int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *,
+                  int index, struct nvkm_fifo **);
+
+void *nv50_fifo_dtor(struct nvkm_fifo *);
+int nv50_fifo_oneinit(struct nvkm_fifo *);
+void nv50_fifo_init(struct nvkm_fifo *);
 void nv50_fifo_runlist_update(struct nv50_fifo *);
 #endif
 
 #ifndef __NVKM_FIFO_PRIV_H__
 #define __NVKM_FIFO_PRIV_H__
+#define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine)
 #include <engine/fifo.h>
 
+int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *,
+                  int index, int nr, struct nvkm_fifo *);
+void nvkm_fifo_uevent(struct nvkm_fifo *);
+
+struct nvkm_fifo_func {
+       void *(*dtor)(struct nvkm_fifo *);
+       int (*oneinit)(struct nvkm_fifo *);
+       void (*init)(struct nvkm_fifo *);
+       void (*fini)(struct nvkm_fifo *);
+       void (*intr)(struct nvkm_fifo *);
+       void (*pause)(struct nvkm_fifo *, unsigned long *);
+       void (*start)(struct nvkm_fifo *, unsigned long *);
+       void (*uevent_init)(struct nvkm_fifo *);
+       void (*uevent_fini)(struct nvkm_fifo *);
+       const struct nvkm_fifo_chan_oclass *chan[];
+};
+
+void nv04_fifo_intr(struct nvkm_fifo *);
 void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
 void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
 #endif
 
 #include "regs.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 #include <subdev/instmem.h>
 
 #include "regs.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 #include <subdev/fb.h>
        struct nvkm_fb_tile *tile = &device->fb->tile.region[i];
        unsigned long flags;
 
-       fifo->pause(fifo, &flags);
+       nvkm_fifo_pause(fifo, &flags);
        nv04_gr_idle(&gr->base);
 
        nvkm_wr32(device, NV10_PGRAPH_TLIMIT(i), tile->limit);
        nvkm_wr32(device, NV10_PGRAPH_TSIZE(i), tile->pitch);
        nvkm_wr32(device, NV10_PGRAPH_TILE(i), tile->addr);
 
-       fifo->start(fifo, &flags);
+       nvkm_fifo_start(fifo, &flags);
 }
 
 const struct nvkm_bitfield nv10_gr_intr_name[] = {
 
 #include "regs.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 #include <subdev/fb.h>
        struct nvkm_fb_tile *tile = &device->fb->tile.region[i];
        unsigned long flags;
 
-       fifo->pause(fifo, &flags);
+       nvkm_fifo_pause(fifo, &flags);
        nv04_gr_idle(&gr->base);
 
        nvkm_wr32(device, NV20_PGRAPH_TLIMIT(i), tile->limit);
                nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->zcomp);
        }
 
-       fifo->start(fifo, &flags);
+       nvkm_fifo_start(fifo, &flags);
 }
 
 void
 
 #include "nv20.h"
 #include "regs.h"
 
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 
 
 #include "nv20.h"
 #include "regs.h"
 
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 
 
 #include "nv20.h"
 #include "regs.h"
 
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 #include <subdev/fb.h>
 
 #include "nv20.h"
 #include "regs.h"
 
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 
 
 #include "nv20.h"
 #include "regs.h"
 
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 #include <engine/fifo/chan.h>
 
 
 #include "regs.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/fb.h>
 #include <subdev/timer.h>
 #include <engine/fifo.h>
        struct nvkm_fb_tile *tile = &device->fb->tile.region[i];
        unsigned long flags;
 
-       fifo->pause(fifo, &flags);
+       nvkm_fifo_pause(fifo, &flags);
        nv04_gr_idle(&gr->base);
 
        switch (nv_device(gr)->chipset) {
                break;
        }
 
-       fifo->start(fifo, &flags);
+       nvkm_fifo_start(fifo, &flags);
 }
 
 static void
 
 #include "nv50.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/timer.h>
 #include <engine/fifo.h>
 
 
 #include "nv31.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <subdev/fb.h>
 #include <subdev/timer.h>
 #include <engine/fifo.h>
 
 #include "priv.h"
 
 #include <core/client.h>
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 
 #include <nvif/class.h>
 
 
 #include <core/client.h>
 #include <core/enum.h>
+#include <core/gpuobj.h>
 
 #include <nvif/class.h>
 
 
  */
 #include "nv50.h"
 
+#include <core/gpuobj.h>
 #include <subdev/bar.h>
 #include <engine/disp.h>
 #include <engine/fifo.h>
 
  */
 #include "nv50.h"
 
+#include <core/gpuobj.h>
 #include <core/handle.h>
 #include <engine/disp.h>
 #include <engine/fifo/chan.h>
 
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 #include <engine/xtensa.h>
+
+#include <core/gpuobj.h>
 #include <engine/fifo.h>
 
 static int
 
                return -EBUSY;
 
        if (fifo)
-               fifo->pause(fifo, flags);
+               nvkm_fifo_pause(fifo, flags);
 
        if (nvkm_msec(device, 2000,
                if (nvkm_rd32(device, 0x002504) & 0x00000010)
        struct nvkm_fifo *fifo = device->fifo;
 
        if (fifo && flags)
-               fifo->start(fifo, flags);
+               nvkm_fifo_start(fifo, flags);
 
        nvkm_mask(device, 0x002504, 0x00000001, 0x00000000);
        nvkm_mask(device, 0x020060, 0x00070000, 0x00040000);