Loading drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c +32 −41 Original line number Diff line number Diff line Loading @@ -30,22 +30,43 @@ #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; Loading Loading @@ -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, Loading @@ -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; } drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c +79 −36 Original line number Diff line number Diff line Loading @@ -30,19 +30,23 @@ #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)) { Loading @@ -57,8 +61,8 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, } } if (dmaobj->target == NV_MEM_TARGET_VM) { if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) { 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); Loading @@ -66,48 +70,86 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, offset &= 0xfffff000; } dmaobj->target = NV_MEM_TARGET_PCI; dmaobj->access = NV_MEM_ACCESS_RW; 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; } switch (dmaobj->target) { 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; 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; } 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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; drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c +82 −38 Original line number Diff line number Diff line Loading @@ -29,14 +29,18 @@ #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)) { Loading Loading @@ -66,67 +70,106 @@ 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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; drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c +76 −34 Original line number Diff line number Diff line Loading @@ -30,14 +30,18 @@ #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)) { Loading @@ -52,63 +56,100 @@ 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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; drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c +73 −27 Original line number Diff line number Diff line Loading @@ -30,17 +30,17 @@ #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)) { Loading @@ -64,40 +64,85 @@ 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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; Loading
drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c +32 −41 Original line number Diff line number Diff line Loading @@ -30,22 +30,43 @@ #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; Loading Loading @@ -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, Loading @@ -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; }
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c +79 −36 Original line number Diff line number Diff line Loading @@ -30,19 +30,23 @@ #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)) { Loading @@ -57,8 +61,8 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, } } if (dmaobj->target == NV_MEM_TARGET_VM) { if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) { 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); Loading @@ -66,48 +70,86 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, offset &= 0xfffff000; } dmaobj->target = NV_MEM_TARGET_PCI; dmaobj->access = NV_MEM_ACCESS_RW; 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; } switch (dmaobj->target) { 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; 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; } 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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;
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c +82 −38 Original line number Diff line number Diff line Loading @@ -29,14 +29,18 @@ #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)) { Loading Loading @@ -66,67 +70,106 @@ 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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;
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c +76 −34 Original line number Diff line number Diff line Loading @@ -30,14 +30,18 @@ #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)) { Loading @@ -52,63 +56,100 @@ 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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;
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c +73 −27 Original line number Diff line number Diff line Loading @@ -30,17 +30,17 @@ #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)) { Loading @@ -64,40 +64,85 @@ 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 dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); } return ret; } 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) { Loading @@ -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;