nvkm-y += nvkm/engine/fifo/gpfifog84.o
 nvkm-y += nvkm/engine/fifo/gpfifogf100.o
 nvkm-y += nvkm/engine/fifo/gpfifogk104.o
-nvkm-y += nvkm/engine/fifo/gpfifogk110.o
-nvkm-y += nvkm/engine/fifo/gpfifogm200.o
-nvkm-y += nvkm/engine/fifo/gpfifogp100.o
 
        nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
 }
 
+static int
+nvkm_fifo_class_new_(struct nvkm_device *device,
+                    const struct nvkm_oclass *oclass, void *data, u32 size,
+                    struct nvkm_object **pobject)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
+       return fifo->func->class_new(fifo, oclass, data, size, pobject);
+}
+
+static const struct nvkm_device_oclass
+nvkm_fifo_class_ = {
+       .ctor = nvkm_fifo_class_new_,
+};
+
 static int
 nvkm_fifo_class_new(struct nvkm_device *device,
                    const struct nvkm_oclass *oclass, void *data, u32 size,
        int c = 0;
 
        if (fifo->func->class_get) {
-               int ret = fifo->func->class_get(fifo, index, &sclass);
-               if (ret == 0) {
-                       oclass->base = sclass->base;
-                       oclass->engn = sclass;
-                       *class = &nvkm_fifo_class;
-                       return 0;
-               }
+               int ret = fifo->func->class_get(fifo, index, oclass);
+               if (ret == 0)
+                       *class = &nvkm_fifo_class_;
                return ret;
        }
 
 
        } engn[NVKM_SUBDEV_NR];
 };
 
-int gk104_fifo_gpfifo_new(struct nvkm_fifo *, const struct nvkm_oclass *,
+int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
                          void *data, u32 size, struct nvkm_object **);
-
-extern const struct nvkm_fifo_chan_oclass gk104_fifo_gpfifo_oclass;
-extern const struct nvkm_fifo_chan_oclass gk110_fifo_gpfifo_oclass;
-extern const struct nvkm_fifo_chan_oclass gm200_fifo_gpfifo_oclass;
-extern const struct nvkm_fifo_chan_oclass gp100_fifo_gpfifo_oclass;
 #endif
 
                   status->chan == &status->next ? "*" : " ");
 }
 
+static int
+gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                    void *argv, u32 argc, struct nvkm_object **pobject)
+{
+       struct gk104_fifo *fifo = gk104_fifo(base);
+       if (oclass->engn == &fifo->func->chan) {
+               const struct gk104_fifo_chan_user *user = oclass->engn;
+               return user->ctor(fifo, oclass, argv, argc, pobject);
+       }
+       WARN_ON(1);
+       return -EINVAL;
+}
+
 static int
 gk104_fifo_class_get(struct nvkm_fifo *base, int index,
-                    const struct nvkm_fifo_chan_oclass **psclass)
+                    struct nvkm_oclass *oclass)
 {
        struct gk104_fifo *fifo = gk104_fifo(base);
        int c = 0;
 
-       while ((*psclass = fifo->func->chan[c])) {
-               if (c++ == index)
-                       return 0;
+       if (fifo->func->chan.ctor && c++ == index) {
+               oclass->base =  fifo->func->chan.user;
+               oclass->engn = &fifo->func->chan;
+               return 0;
        }
 
        return c;
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
        .class_get = gk104_fifo_class_get,
+       .class_new = gk104_fifo_class_new,
 };
 
 int
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gk104_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
                const struct nvkm_enum *gpcclient;
        } fault;
 
-       const struct nvkm_fifo_chan_oclass *chan[];
+       struct gk104_fifo_chan_user {
+               struct nvkm_sclass user;
+               int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *,
+                           void *, u32, struct nvkm_object **);
+       } chan;
 };
 
 int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *,
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 static const struct gk104_fifo_func
 gk110_fifo = {
        .fault.access = gk104_fifo_fault_access,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gk110_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 static const struct gk104_fifo_func
 gk208_fifo = {
        .fault.access = gk104_fifo_fault_access,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gk104_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 static const struct gk104_fifo_func
 gk20a_fifo = {
        .fault.access = gk104_fifo_fault_access,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gk104_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 const struct nvkm_enum
 gm107_fifo_fault_engine[] = {
        { 0x01, "DISPLAY" },
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gk110_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 static const struct gk104_fifo_func
 gm200_fifo = {
        .fault.access = gk104_fifo_fault_access,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gm200_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 static const struct gk104_fifo_func
 gm20b_fifo = {
        .fault.access = gk104_fifo_fault_access,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gm200_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 const struct nvkm_enum
 gp100_fifo_fault_engine[] = {
        { 0x01, "DISPLAY" },
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gp100_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 #include "gk104.h"
 #include "changk104.h"
 
+#include <nvif/class.h>
+
 static const struct gk104_fifo_func
 gp10b_fifo = {
        .fault.access = gk104_fifo_fault_access,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
-       .chan = {
-               &gp100_fifo_gpfifo_oclass,
-               NULL
-       },
+       .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
 };
 
 int
 
 }
 
 int
-gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                      void *data, u32 size, struct nvkm_object **pobject)
 {
        struct nvkm_object *parent = oclass->parent;
        union {
                struct kepler_channel_gpfifo_a_v0 v0;
        } *args = data;
-       struct gk104_fifo *fifo = gk104_fifo(base);
        int ret = -ENOSYS;
 
        nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
 
        return ret;
 }
-
-const struct nvkm_fifo_chan_oclass
-gk104_fifo_gpfifo_oclass = {
-       .base.oclass = KEPLER_CHANNEL_GPFIFO_A,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = gk104_fifo_gpfifo_new,
-};
 
+++ /dev/null
-/*
- * Copyright 2016 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "changk104.h"
-
-#include <nvif/class.h>
-
-const struct nvkm_fifo_chan_oclass
-gk110_fifo_gpfifo_oclass = {
-       .base.oclass = KEPLER_CHANNEL_GPFIFO_B,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = gk104_fifo_gpfifo_new,
-};
 
+++ /dev/null
-/*
- * Copyright 2015 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "changk104.h"
-
-#include <nvif/class.h>
-
-const struct nvkm_fifo_chan_oclass
-gm200_fifo_gpfifo_oclass = {
-       .base.oclass = MAXWELL_CHANNEL_GPFIFO_A,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = gk104_fifo_gpfifo_new,
-};
 
+++ /dev/null
-/*
- * Copyright 2016 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "changk104.h"
-
-#include <nvif/class.h>
-
-const struct nvkm_fifo_chan_oclass
-gp100_fifo_gpfifo_oclass = {
-       .base.oclass = PASCAL_CHANNEL_GPFIFO_A,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = gk104_fifo_gpfifo_new,
-};
 
        void (*uevent_init)(struct nvkm_fifo *);
        void (*uevent_fini)(struct nvkm_fifo *);
        void (*recover_chan)(struct nvkm_fifo *, int chid);
-       int (*class_get)(struct nvkm_fifo *, int index,
-                        const struct nvkm_fifo_chan_oclass **);
+       int (*class_get)(struct nvkm_fifo *, int index, struct nvkm_oclass *);
+       int (*class_new)(struct nvkm_fifo *, const struct nvkm_oclass *,
+                        void *, u32, struct nvkm_object **);
        const struct nvkm_fifo_chan_oclass *chan[];
 };