drm/nouveau/dmaobj: switch to a slightly saner design
authorBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 18:10:24 +0000 (04:10 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 19:13:23 +0000 (05:13 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h

index b04d4572603cce1ea231dffb46aeba9114ed1fa4..2472c6b7489feba7042f31fda9fdff179dc9363d 100644 (file)
 #include "priv.h"
 
 static int
-nouveau_dmaobj_ctor(struct nouveau_object *parent,
+nvkm_dmaobj_bind(struct nouveau_dmaobj *dmaobj, struct nouveau_object *parent,
+                struct nouveau_gpuobj **pgpuobj)
+{
+       const struct nvkm_dmaeng_impl *impl = (void *)
+               nv_oclass(nv_object(dmaobj)->engine);
+       int ret = 0;
+
+       if (nv_object(dmaobj) == parent) { /* ctor bind */
+               if (nv_mclass(parent->parent) == NV_DEVICE) {
+                       /* delayed, or no, binding */
+                       return 0;
+               }
+               ret = impl->bind(dmaobj, parent, pgpuobj);
+               if (ret == 0)
+                       nouveau_object_ref(NULL, &parent);
+               return ret;
+       }
+
+       return impl->bind(dmaobj, parent, pgpuobj);
+}
+
+int
+nvkm_dmaobj_create_(struct nouveau_object *parent,
                    struct nouveau_object *engine,
-                   struct nouveau_oclass *oclass, void *data, u32 size,
-                   struct nouveau_object **pobject)
+                   struct nouveau_oclass *oclass, void **pdata, u32 *psize,
+                   int length, void **pobject)
 {
-       struct nouveau_dmaeng *dmaeng = (void *)engine;
+       struct nv_dma_class *args = *pdata;
        struct nouveau_dmaobj *dmaobj;
-       struct nouveau_gpuobj *gpuobj;
-       struct nv_dma_class *args = data;
        int ret;
 
-       if (size < sizeof(*args))
+       if (*psize < sizeof(*args))
                return -EINVAL;
+       *pdata = &args->conf0;
 
-       ret = nouveau_object_create(parent, engine, oclass, 0, &dmaobj);
-       *pobject = nv_object(dmaobj);
+       ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
+       dmaobj = *pobject;
        if (ret)
                return ret;
 
@@ -87,39 +108,9 @@ nouveau_dmaobj_ctor(struct nouveau_object *parent,
        dmaobj->start = args->start;
        dmaobj->limit = args->limit;
        dmaobj->conf0 = args->conf0;
-
-       switch (nv_mclass(parent)) {
-       case NV_DEVICE:
-               /* delayed, or no, binding */
-               break;
-       default:
-               ret = dmaeng->bind(dmaeng, *pobject, dmaobj, &gpuobj);
-               if (ret == 0) {
-                       nouveau_object_ref(NULL, pobject);
-                       *pobject = nv_object(gpuobj);
-               }
-               break;
-       }
-
        return ret;
 }
 
-static struct nouveau_ofuncs
-nouveau_dmaobj_ofuncs = {
-       .ctor = nouveau_dmaobj_ctor,
-       .dtor = nouveau_object_destroy,
-       .init = nouveau_object_init,
-       .fini = nouveau_object_fini,
-};
-
-static struct nouveau_oclass
-nouveau_dmaobj_sclass[] = {
-       { NV_DMA_FROM_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
-       { NV_DMA_TO_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
-       { NV_DMA_IN_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
-       {}
-};
-
 int
 _nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -135,7 +126,7 @@ _nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       nv_engine(dmaeng)->sclass = nouveau_dmaobj_sclass;
-       dmaeng->bind = impl->bind;
+       nv_engine(dmaeng)->sclass = impl->sclass;
+       dmaeng->bind = nvkm_dmaobj_bind;
        return 0;
 }
index 29fb95c5d058b1d546f8e49f426e6ad6640194ee..62d25a0634bef0a6942b68e42a41654b1e56bdee 100644 (file)
 
 #include "priv.h"
 
+struct nv04_dmaobj_priv {
+       struct nouveau_dmaobj base;
+       bool clone;
+       u32 flags0;
+       u32 flags2;
+};
+
 static int
-nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
                 struct nouveau_object *parent,
-                struct nouveau_dmaobj *dmaobj,
                 struct nouveau_gpuobj **pgpuobj)
 {
-       struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng);
+       struct nv04_dmaobj_priv *priv = (void *)dmaobj;
        struct nouveau_gpuobj *gpuobj;
-       u32 flags0 = nv_mclass(dmaobj);
-       u32 flags2 = 0x00000000;
-       u64 offset = dmaobj->start & 0xfffff000;
-       u64 adjust = dmaobj->start & 0x00000fff;
-       u32 length = dmaobj->limit - dmaobj->start;
+       u64 offset = priv->base.start & 0xfffff000;
+       u64 adjust = priv->base.start & 0x00000fff;
+       u32 length = priv->base.limit - priv->base.start;
        int ret;
 
        if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -57,58 +61,96 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
                }
        }
 
-       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];
-                       if (!dmaobj->start)
-                               return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
-                       offset  = nv_ro32(pgt, 8 + (offset >> 10));
-                       offset &= 0xfffff000;
-               }
+       if (priv->clone) {
+               struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaobj);
+               struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
+               if (!dmaobj->start)
+                       return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
+               offset  = nv_ro32(pgt, 8 + (offset >> 10));
+               offset &= 0xfffff000;
+       }
+
+       ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
+       *pgpuobj = gpuobj;
+       if (ret == 0) {
+               nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20));
+               nv_wo32(*pgpuobj, 0x04, length);
+               nv_wo32(*pgpuobj, 0x08, priv->flags2 | offset);
+               nv_wo32(*pgpuobj, 0x0c, priv->flags2 | offset);
+       }
+
+       return ret;
+}
+
+static int
+nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                struct nouveau_oclass *oclass, void *data, u32 size,
+                struct nouveau_object **pobject)
+{
+       struct nouveau_dmaeng *dmaeng = (void *)engine;
+       struct nv04_vmmgr_priv *vmm = nv04_vmmgr(engine);
+       struct nv04_dmaobj_priv *priv;
+       int ret;
+
+       ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
 
-               dmaobj->target = NV_MEM_TARGET_PCI;
-               dmaobj->access = NV_MEM_ACCESS_RW;
+       if (priv->base.target == NV_MEM_TARGET_VM) {
+               if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass)
+                       priv->clone = true;
+               priv->base.target = NV_MEM_TARGET_PCI;
+               priv->base.access = NV_MEM_ACCESS_RW;
        }
 
-       switch (dmaobj->target) {
+       priv->flags0 = nv_mclass(priv);
+       switch (priv->base.target) {
        case NV_MEM_TARGET_VRAM:
-               flags0 |= 0x00003000;
+               priv->flags0 |= 0x00003000;
                break;
        case NV_MEM_TARGET_PCI:
-               flags0 |= 0x00023000;
+               priv->flags0 |= 0x00023000;
                break;
        case NV_MEM_TARGET_PCI_NOSNOOP:
-               flags0 |= 0x00033000;
+               priv->flags0 |= 0x00033000;
                break;
        default:
                return -EINVAL;
        }
 
-       switch (dmaobj->access) {
+       switch (priv->base.access) {
        case NV_MEM_ACCESS_RO:
-               flags0 |= 0x00004000;
+               priv->flags0 |= 0x00004000;
                break;
        case NV_MEM_ACCESS_WO:
-               flags0 |= 0x00008000;
+               priv->flags0 |= 0x00008000;
        case NV_MEM_ACCESS_RW:
-               flags2 |= 0x00000002;
+               priv->flags2 |= 0x00000002;
                break;
        default:
                return -EINVAL;
        }
 
-       ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
-       *pgpuobj = gpuobj;
-       if (ret == 0) {
-               nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20));
-               nv_wo32(*pgpuobj, 0x04, length);
-               nv_wo32(*pgpuobj, 0x08, flags2 | offset);
-               nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
-       }
-
-       return ret;
+       return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
+static struct nouveau_ofuncs
+nv04_dmaobj_ofuncs = {
+       .ctor =  nv04_dmaobj_ctor,
+       .dtor = _nvkm_dmaobj_dtor,
+       .init = _nvkm_dmaobj_init,
+       .fini = _nvkm_dmaobj_fini,
+};
+
+static struct nouveau_oclass
+nv04_dmaeng_sclass[] = {
+       { NV_DMA_FROM_MEMORY_CLASS, &nv04_dmaobj_ofuncs },
+       { NV_DMA_TO_MEMORY_CLASS, &nv04_dmaobj_ofuncs },
+       { NV_DMA_IN_MEMORY_CLASS, &nv04_dmaobj_ofuncs },
+       {}
+};
+
 struct nouveau_oclass *
 nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
        .base.handle = NV_ENGINE(DMAOBJ, 0x04),
@@ -118,5 +160,6 @@ nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
                .init = _nvkm_dmaeng_init,
                .fini = _nvkm_dmaeng_fini,
        },
+       .sclass = nv04_dmaeng_sclass,
        .bind = nv04_dmaobj_bind,
 }.base;
index a1603a8721961a620585c5c6fa3d733e8cdc0d59..5996a30b22ab7567b7fc9eceeca57179b3c502b7 100644 (file)
 
 #include "priv.h"
 
+struct nv50_dmaobj_priv {
+       struct nouveau_dmaobj base;
+       u32 flags0;
+       u32 flags5;
+};
+
 static int
-nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
                 struct nouveau_object *parent,
-                struct nouveau_dmaobj *dmaobj,
                 struct nouveau_gpuobj **pgpuobj)
 {
-       u32 flags0 = nv_mclass(dmaobj);
-       u32 flags5 = 0x00000000;
+       struct nv50_dmaobj_priv *priv = (void *)dmaobj;
        int ret;
 
        if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -66,68 +70,107 @@ nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
                }
        }
 
-       if (!(dmaobj->conf0 & NV50_DMA_CONF0_ENABLE)) {
-               if (dmaobj->target == NV_MEM_TARGET_VM) {
-                       dmaobj->conf0  = NV50_DMA_CONF0_PRIV_VM;
-                       dmaobj->conf0 |= NV50_DMA_CONF0_PART_VM;
-                       dmaobj->conf0 |= NV50_DMA_CONF0_COMP_VM;
-                       dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_VM;
+       ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+       if (ret == 0) {
+               nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
+               nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
+               nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
+               nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
+                                       upper_32_bits(priv->base.start));
+               nv_wo32(*pgpuobj, 0x10, 0x00000000);
+               nv_wo32(*pgpuobj, 0x14, priv->flags5);
+       }
+
+       return ret;
+}
+
+static int
+nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                struct nouveau_oclass *oclass, void *data, u32 size,
+                struct nouveau_object **pobject)
+{
+       struct nouveau_dmaeng *dmaeng = (void *)engine;
+       struct nv50_dmaobj_priv *priv;
+       union {
+               u32 conf0;
+       } *args;
+       int ret;
+
+       ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+       args = data;
+
+       if (!(args->conf0 & NV50_DMA_CONF0_ENABLE)) {
+               if (priv->base.target == NV_MEM_TARGET_VM) {
+                       args->conf0  = NV50_DMA_CONF0_PRIV_VM;
+                       args->conf0 |= NV50_DMA_CONF0_PART_VM;
+                       args->conf0 |= NV50_DMA_CONF0_COMP_VM;
+                       args->conf0 |= NV50_DMA_CONF0_TYPE_VM;
                } else {
-                       dmaobj->conf0  = NV50_DMA_CONF0_PRIV_US;
-                       dmaobj->conf0 |= NV50_DMA_CONF0_PART_256;
-                       dmaobj->conf0 |= NV50_DMA_CONF0_COMP_NONE;
-                       dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR;
+                       args->conf0  = NV50_DMA_CONF0_PRIV_US;
+                       args->conf0 |= NV50_DMA_CONF0_PART_256;
+                       args->conf0 |= NV50_DMA_CONF0_COMP_NONE;
+                       args->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR;
                }
        }
 
-       flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_COMP) << 22;
-       flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_TYPE) << 22;
-       flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_PRIV);
-       flags5 |= (dmaobj->conf0 & NV50_DMA_CONF0_PART);
+       priv->flags0 |= (args->conf0 & NV50_DMA_CONF0_COMP) << 22;
+       priv->flags0 |= (args->conf0 & NV50_DMA_CONF0_TYPE) << 22;
+       priv->flags0 |= (args->conf0 & NV50_DMA_CONF0_PRIV);
+       priv->flags5 |= (args->conf0 & NV50_DMA_CONF0_PART);
 
-       switch (dmaobj->target) {
+       switch (priv->base.target) {
        case NV_MEM_TARGET_VM:
-               flags0 |= 0x00000000;
+               priv->flags0 |= 0x00000000;
                break;
        case NV_MEM_TARGET_VRAM:
-               flags0 |= 0x00010000;
+               priv->flags0 |= 0x00010000;
                break;
        case NV_MEM_TARGET_PCI:
-               flags0 |= 0x00020000;
+               priv->flags0 |= 0x00020000;
                break;
        case NV_MEM_TARGET_PCI_NOSNOOP:
-               flags0 |= 0x00030000;
+               priv->flags0 |= 0x00030000;
                break;
        default:
                return -EINVAL;
        }
 
-       switch (dmaobj->access) {
+       switch (priv->base.access) {
        case NV_MEM_ACCESS_VM:
                break;
        case NV_MEM_ACCESS_RO:
-               flags0 |= 0x00040000;
+               priv->flags0 |= 0x00040000;
                break;
        case NV_MEM_ACCESS_WO:
        case NV_MEM_ACCESS_RW:
-               flags0 |= 0x00080000;
+               priv->flags0 |= 0x00080000;
                break;
+       default:
+               return -EINVAL;
        }
 
-       ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
-       if (ret == 0) {
-               nv_wo32(*pgpuobj, 0x00, flags0);
-               nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
-               nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
-               nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
-                                       upper_32_bits(dmaobj->start));
-               nv_wo32(*pgpuobj, 0x10, 0x00000000);
-               nv_wo32(*pgpuobj, 0x14, flags5);
-       }
-
-       return ret;
+       return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
+static struct nouveau_ofuncs
+nv50_dmaobj_ofuncs = {
+       .ctor =  nv50_dmaobj_ctor,
+       .dtor = _nvkm_dmaobj_dtor,
+       .init = _nvkm_dmaobj_init,
+       .fini = _nvkm_dmaobj_fini,
+};
+
+static struct nouveau_oclass
+nv50_dmaeng_sclass[] = {
+       { NV_DMA_FROM_MEMORY_CLASS, &nv50_dmaobj_ofuncs },
+       { NV_DMA_TO_MEMORY_CLASS, &nv50_dmaobj_ofuncs },
+       { NV_DMA_IN_MEMORY_CLASS, &nv50_dmaobj_ofuncs },
+       {}
+};
+
 struct nouveau_oclass *
 nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
        .base.handle = NV_ENGINE(DMAOBJ, 0x50),
@@ -137,5 +180,6 @@ nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
                .init = _nvkm_dmaeng_init,
                .fini = _nvkm_dmaeng_fini,
        },
+       .sclass = nv50_dmaeng_sclass,
        .bind = nv50_dmaobj_bind,
 }.base;
index bd639de7fea0f13e25fcc7d0c5694ab52f9cdfef..c6753a08d3a4f77f588d8e495f62ce3173ae511b 100644 (file)
 
 #include "priv.h"
 
+struct nvc0_dmaobj_priv {
+       struct nouveau_dmaobj base;
+       u32 flags0;
+       u32 flags5;
+};
+
 static int
-nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nvc0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
                 struct nouveau_object *parent,
-                struct nouveau_dmaobj *dmaobj,
                 struct nouveau_gpuobj **pgpuobj)
 {
-       u32 flags0 = nv_mclass(dmaobj);
-       u32 flags5 = 0x00000000;
+       struct nvc0_dmaobj_priv *priv = (void *)dmaobj;
        int ret;
 
        if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -52,64 +56,101 @@ nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
        } else
                return 0;
 
-       if (!(dmaobj->conf0 & NVC0_DMA_CONF0_ENABLE)) {
-               if (dmaobj->target == NV_MEM_TARGET_VM) {
-                       dmaobj->conf0  = NVC0_DMA_CONF0_PRIV_VM;
-                       dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_VM;
+       ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+       if (ret == 0) {
+               nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
+               nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
+               nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
+               nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
+                                       upper_32_bits(priv->base.start));
+               nv_wo32(*pgpuobj, 0x10, 0x00000000);
+               nv_wo32(*pgpuobj, 0x14, priv->flags5);
+       }
+
+       return ret;
+}
+
+static int
+nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                struct nouveau_oclass *oclass, void *data, u32 size,
+                struct nouveau_object **pobject)
+{
+       struct nouveau_dmaeng *dmaeng = (void *)engine;
+       struct nvc0_dmaobj_priv *priv;
+       union {
+               u32 conf0;
+       } *args;
+       int ret;
+
+       ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+       args = data;
+
+       if (!(args->conf0 & NVC0_DMA_CONF0_ENABLE)) {
+               if (priv->base.target == NV_MEM_TARGET_VM) {
+                       args->conf0  = NVC0_DMA_CONF0_PRIV_VM;
+                       args->conf0 |= NVC0_DMA_CONF0_TYPE_VM;
                } else {
-                       dmaobj->conf0  = NVC0_DMA_CONF0_PRIV_US;
-                       dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR;
-                       dmaobj->conf0 |= 0x00020000;
+                       args->conf0  = NVC0_DMA_CONF0_PRIV_US;
+                       args->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR;
+                       args->conf0 |= 0x00020000;
                }
        }
 
-       flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_TYPE) << 22;
-       flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_PRIV);
-       flags5 |= (dmaobj->conf0 & NVC0_DMA_CONF0_UNKN);
+       priv->flags0 |= (args->conf0 & NVC0_DMA_CONF0_TYPE) << 22;
+       priv->flags0 |= (args->conf0 & NVC0_DMA_CONF0_PRIV);
+       priv->flags5 |= (args->conf0 & NVC0_DMA_CONF0_UNKN);
 
-       switch (dmaobj->target) {
+       switch (priv->base.target) {
        case NV_MEM_TARGET_VM:
-               flags0 |= 0x00000000;
+               priv->flags0 |= 0x00000000;
                break;
        case NV_MEM_TARGET_VRAM:
-               flags0 |= 0x00010000;
+               priv->flags0 |= 0x00010000;
                break;
        case NV_MEM_TARGET_PCI:
-               flags0 |= 0x00020000;
+               priv->flags0 |= 0x00020000;
                break;
        case NV_MEM_TARGET_PCI_NOSNOOP:
-               flags0 |= 0x00030000;
+               priv->flags0 |= 0x00030000;
                break;
        default:
                return -EINVAL;
        }
 
-       switch (dmaobj->access) {
+       switch (priv->base.access) {
        case NV_MEM_ACCESS_VM:
                break;
        case NV_MEM_ACCESS_RO:
-               flags0 |= 0x00040000;
+               priv->flags0 |= 0x00040000;
                break;
        case NV_MEM_ACCESS_WO:
        case NV_MEM_ACCESS_RW:
-               flags0 |= 0x00080000;
+               priv->flags0 |= 0x00080000;
                break;
        }
 
-       ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
-       if (ret == 0) {
-               nv_wo32(*pgpuobj, 0x00, flags0);
-               nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
-               nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
-               nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
-                                       upper_32_bits(dmaobj->start));
-               nv_wo32(*pgpuobj, 0x10, 0x00000000);
-               nv_wo32(*pgpuobj, 0x14, flags5);
-       }
-
-       return ret;
+       return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
+static struct nouveau_ofuncs
+nvc0_dmaobj_ofuncs = {
+       .ctor =  nvc0_dmaobj_ctor,
+       .dtor = _nvkm_dmaobj_dtor,
+       .init = _nvkm_dmaobj_init,
+       .fini = _nvkm_dmaobj_fini,
+};
+
+static struct nouveau_oclass
+nvc0_dmaeng_sclass[] = {
+       { NV_DMA_FROM_MEMORY_CLASS, &nvc0_dmaobj_ofuncs },
+       { NV_DMA_TO_MEMORY_CLASS, &nvc0_dmaobj_ofuncs },
+       { NV_DMA_IN_MEMORY_CLASS, &nvc0_dmaobj_ofuncs },
+       {}
+};
+
 struct nouveau_oclass *
 nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
        .base.handle = NV_ENGINE(DMAOBJ, 0xc0),
@@ -119,5 +160,6 @@ nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
                .init = _nvkm_dmaeng_init,
                .fini = _nvkm_dmaeng_fini,
        },
+       .sclass = nvc0_dmaeng_sclass,
        .bind = nvc0_dmaobj_bind,
 }.base;
index 461cc01a0d50181f53aabedcecdd79bdc32839cc..c4b9b8deed71853bd37b4221f6333792a21d1315 100644 (file)
 
 #include "priv.h"
 
-struct nvd0_dmaeng_priv {
-       struct nouveau_dmaeng base;
+struct nvd0_dmaobj_priv {
+       struct nouveau_dmaobj base;
+       u32 flags0;
 };
 
 static int
-nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nvd0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
                 struct nouveau_object *parent,
-                struct nouveau_dmaobj *dmaobj,
                 struct nouveau_gpuobj **pgpuobj)
 {
-       u32 flags0 = 0x00000000;
+       struct nvd0_dmaobj_priv *priv = (void *)dmaobj;
        int ret;
 
        if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -64,41 +64,86 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
        } else
                return 0;
 
-       if (!(dmaobj->conf0 & NVD0_DMA_CONF0_ENABLE)) {
-               if (dmaobj->target == NV_MEM_TARGET_VM) {
-                       dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_VM;
-                       dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_LP;
+       ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+       if (ret == 0) {
+               nv_wo32(*pgpuobj, 0x00, priv->flags0);
+               nv_wo32(*pgpuobj, 0x04, priv->base.start >> 8);
+               nv_wo32(*pgpuobj, 0x08, priv->base.limit >> 8);
+               nv_wo32(*pgpuobj, 0x0c, 0x00000000);
+               nv_wo32(*pgpuobj, 0x10, 0x00000000);
+               nv_wo32(*pgpuobj, 0x14, 0x00000000);
+       }
+
+       return ret;
+}
+
+static int
+nvd0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                struct nouveau_oclass *oclass, void *data, u32 size,
+                struct nouveau_object **pobject)
+{
+       struct nouveau_dmaeng *dmaeng = (void *)engine;
+       struct nvd0_dmaobj_priv *priv;
+       union {
+               u32 conf0;
+       } *args;
+       int ret;
+
+       ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+       args = data;
+
+       if (!(args->conf0 & NVD0_DMA_CONF0_ENABLE)) {
+               if (priv->base.target == NV_MEM_TARGET_VM) {
+                       args->conf0 |= NVD0_DMA_CONF0_TYPE_VM;
+                       args->conf0 |= NVD0_DMA_CONF0_PAGE_LP;
                } else {
-                       dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
-                       dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
+                       args->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
+                       args->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
                }
        }
 
-       flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
-       flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
+       priv->flags0 |= (args->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
+       priv->flags0 |= (args->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
 
-       switch (dmaobj->target) {
+       switch (priv->base.target) {
        case NV_MEM_TARGET_VRAM:
-               flags0 |= 0x00000009;
+               priv->flags0 |= 0x00000009;
+               break;
+       case NV_MEM_TARGET_VM:
+       case NV_MEM_TARGET_PCI:
+       case NV_MEM_TARGET_PCI_NOSNOOP:
+               /* XXX: don't currently know how to construct a real one
+                *      of these.  we only use them to represent pushbufs
+                *      on these chipsets, and the classes that use them
+                *      deal with the target themselves.
+                */
                break;
        default:
                return -EINVAL;
-               break;
-       }
-
-       ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
-       if (ret == 0) {
-               nv_wo32(*pgpuobj, 0x00, flags0);
-               nv_wo32(*pgpuobj, 0x04, dmaobj->start >> 8);
-               nv_wo32(*pgpuobj, 0x08, dmaobj->limit >> 8);
-               nv_wo32(*pgpuobj, 0x0c, 0x00000000);
-               nv_wo32(*pgpuobj, 0x10, 0x00000000);
-               nv_wo32(*pgpuobj, 0x14, 0x00000000);
        }
 
-       return ret;
+       return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
+static struct nouveau_ofuncs
+nvd0_dmaobj_ofuncs = {
+       .ctor =  nvd0_dmaobj_ctor,
+       .dtor = _nvkm_dmaobj_dtor,
+       .init = _nvkm_dmaobj_init,
+       .fini = _nvkm_dmaobj_fini,
+};
+
+static struct nouveau_oclass
+nvd0_dmaeng_sclass[] = {
+       { NV_DMA_FROM_MEMORY_CLASS, &nvd0_dmaobj_ofuncs },
+       { NV_DMA_TO_MEMORY_CLASS, &nvd0_dmaobj_ofuncs },
+       { NV_DMA_IN_MEMORY_CLASS, &nvd0_dmaobj_ofuncs },
+       {}
+};
+
 struct nouveau_oclass *
 nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
        .base.handle = NV_ENGINE(DMAOBJ, 0xd0),
@@ -108,5 +153,6 @@ nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
                .init = _nvkm_dmaeng_init,
                .fini = _nvkm_dmaeng_fini,
        },
+       .sclass = nvd0_dmaeng_sclass,
        .bind = nvd0_dmaobj_bind,
 }.base;
index f9aeea5564d99482b0cf61f6a68de723d661a3a1..36f74386693748fb474f5f59f281dcef5ab15b0e 100644 (file)
@@ -3,6 +3,16 @@
 
 #include <engine/dmaobj.h>
 
+#define nvkm_dmaobj_create(p,e,c,pa,sa,d)                                      \
+       nvkm_dmaobj_create_((p), (e), (c), (pa), (sa), sizeof(**d), (void **)d)
+
+int nvkm_dmaobj_create_(struct nouveau_object *, struct nouveau_object *,
+                       struct nouveau_oclass *, void **, u32 *,
+                       int, void **);
+#define _nvkm_dmaobj_dtor nouveau_object_destroy
+#define _nvkm_dmaobj_init nouveau_object_init
+#define _nvkm_dmaobj_fini nouveau_object_fini
+
 int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
                      struct nouveau_oclass *, void *, u32,
                      struct nouveau_object **);
@@ -12,8 +22,9 @@ int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
 
 struct nvkm_dmaeng_impl {
        struct nouveau_oclass base;
-       int (*bind)(struct nouveau_dmaeng *, struct nouveau_object *,
-                   struct nouveau_dmaobj *, struct nouveau_gpuobj **);
+       struct nouveau_oclass *sclass;
+       int (*bind)(struct nouveau_dmaobj *, struct nouveau_object *,
+                   struct nouveau_gpuobj **);
 };
 
 #endif
index 812d85dc9f52ef34b7e749574ed72c2cc2af92d4..2f81cbc4b4723f6a2a8a5cbc13032f4a80e770af 100644 (file)
@@ -83,7 +83,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
                return -EINVAL;
        }
 
-       ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu);
+       ret = dmaeng->bind(chan->pushdma, parent, &chan->pushgpu);
        if (ret)
                return ret;
 
index e09df667094bf0d718d0453c427962884c4c7a3d..f060b063d7defc615e0f8253188861b2cf013249 100644 (file)
@@ -19,9 +19,8 @@ struct nouveau_dmaeng {
        struct nouveau_engine base;
 
        /* creates a "physical" dma object from a struct nouveau_dmaobj */
-       int (*bind)(struct nouveau_dmaeng *dmaeng,
+       int (*bind)(struct nouveau_dmaobj *dmaobj,
                    struct nouveau_object *parent,
-                   struct nouveau_dmaobj *dmaobj,
                    struct nouveau_gpuobj **);
 };