switch (nv_mclass(parent)) {
        case NV_DEVICE_CLASS:
+               /* delayed, or no, binding */
                break;
-       case NV03_CHANNEL_DMA_CLASS:
-       case NV10_CHANNEL_DMA_CLASS:
-       case NV17_CHANNEL_DMA_CLASS:
-       case NV40_CHANNEL_DMA_CLASS:
-       case NV50_CHANNEL_DMA_CLASS:
-       case NV84_CHANNEL_DMA_CLASS:
-       case NV50_CHANNEL_IND_CLASS:
-       case NV84_CHANNEL_IND_CLASS:
+       default:
                ret = dmaeng->bind(dmaeng, *pobject, dmaobj, &gpuobj);
-               nouveau_object_ref(NULL, pobject);
-               *pobject = nv_object(gpuobj);
+               if (ret == 0) {
+                       nouveau_object_ref(NULL, pobject);
+                       *pobject = nv_object(gpuobj);
+               }
                break;
-       default:
-               return -EINVAL;
        }
 
        return ret;
 
        u32 length = dmaobj->limit - dmaobj->start;
        int ret;
 
+       if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
+               switch (nv_mclass(parent->parent)) {
+               case NV03_CHANNEL_DMA_CLASS:
+               case NV10_CHANNEL_DMA_CLASS:
+               case NV17_CHANNEL_DMA_CLASS:
+               case NV40_CHANNEL_DMA_CLASS:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
        if (dmaobj->target == NV_MEM_TARGET_VM) {
                if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) {
                        struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
 
        u32 flags = nv_mclass(dmaobj);
        int ret;
 
+       if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
+               switch (nv_mclass(parent->parent)) {
+               case NV50_CHANNEL_DMA_CLASS:
+               case NV84_CHANNEL_DMA_CLASS:
+               case NV50_CHANNEL_IND_CLASS:
+               case NV84_CHANNEL_IND_CLASS:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
        switch (dmaobj->target) {
        case NV_MEM_TARGET_VM:
                flags |= 0x00000000;
 
 
 #include <core/object.h>
 #include <core/handle.h>
+#include <core/class.h>
 
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
        dmaeng = (void *)chan->pushdma->base.engine;
        switch (chan->pushdma->base.oclass->handle) {
-       case 0x0002:
-       case 0x003d:
+       case NV_DMA_FROM_MEMORY_CLASS:
+       case NV_DMA_IN_MEMORY_CLASS:
                break;
        default:
                return -EINVAL;
        }
 
        if (dmaeng->bind) {
-               ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu);
+               ret = dmaeng->bind(dmaeng, parent, chan->pushdma,
+                                 &chan->pushgpu);
                if (ret)
                        return ret;
        }
 
 
 struct nouveau_dmaeng {
        struct nouveau_engine base;
-       int (*bind)(struct nouveau_dmaeng *, struct nouveau_object *parent,
-                   struct nouveau_dmaobj *, struct nouveau_gpuobj **);
+
+       /* creates a "physical" dma object from a struct nouveau_dmaobj */
+       int (*bind)(struct nouveau_dmaeng *dmaeng,
+                   struct nouveau_object *parent,
+                   struct nouveau_dmaobj *dmaobj,
+                   struct nouveau_gpuobj **);
 };
 
 #define nouveau_dmaeng_create(p,e,c,d)                                         \