mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 21:54:06 +08:00
drm/nouveau/dmaobj: switch to a slightly saner design
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
bc98540b7b
commit
b2c817031b
@ -30,22 +30,43 @@
|
||||
#include "priv.h"
|
||||
|
||||
static int
|
||||
nouveau_dmaobj_ctor(struct nouveau_object *parent,
|
||||
struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
nvkm_dmaobj_bind(struct nouveau_dmaobj *dmaobj, struct nouveau_object *parent,
|
||||
struct nouveau_gpuobj **pgpuobj)
|
||||
{
|
||||
struct nouveau_dmaeng *dmaeng = (void *)engine;
|
||||
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 **pdata, u32 *psize,
|
||||
int length, void **pobject)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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)) {
|
||||
@ -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;
|
||||
}
|
||||
|
||||
dmaobj->target = NV_MEM_TARGET_PCI;
|
||||
dmaobj->access = NV_MEM_ACCESS_RW;
|
||||
}
|
||||
|
||||
switch (dmaobj->target) {
|
||||
case NV_MEM_TARGET_VRAM:
|
||||
flags0 |= 0x00003000;
|
||||
break;
|
||||
case NV_MEM_TARGET_PCI:
|
||||
flags0 |= 0x00023000;
|
||||
break;
|
||||
case NV_MEM_TARGET_PCI_NOSNOOP:
|
||||
flags0 |= 0x00033000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (dmaobj->access) {
|
||||
case NV_MEM_ACCESS_RO:
|
||||
flags0 |= 0x00004000;
|
||||
break;
|
||||
case NV_MEM_ACCESS_WO:
|
||||
flags0 |= 0x00008000;
|
||||
case NV_MEM_ACCESS_RW:
|
||||
flags2 |= 0x00000002;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
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, flags0 | (adjust << 20));
|
||||
nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20));
|
||||
nv_wo32(*pgpuobj, 0x04, length);
|
||||
nv_wo32(*pgpuobj, 0x08, flags2 | offset);
|
||||
nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
|
||||
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;
|
||||
|
||||
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:
|
||||
priv->flags0 |= 0x00003000;
|
||||
break;
|
||||
case NV_MEM_TARGET_PCI:
|
||||
priv->flags0 |= 0x00023000;
|
||||
break;
|
||||
case NV_MEM_TARGET_PCI_NOSNOOP:
|
||||
priv->flags0 |= 0x00033000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (priv->base.access) {
|
||||
case NV_MEM_ACCESS_RO:
|
||||
priv->flags0 |= 0x00004000;
|
||||
break;
|
||||
case NV_MEM_ACCESS_WO:
|
||||
priv->flags0 |= 0x00008000;
|
||||
case NV_MEM_ACCESS_RW:
|
||||
priv->flags2 |= 0x00000002;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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)) {
|
||||
@ -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;
|
||||
|
@ -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)) {
|
||||
@ -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;
|
||||
|
@ -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)) {
|
||||
@ -64,33 +64,11 @@ 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;
|
||||
} else {
|
||||
dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
|
||||
dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
|
||||
}
|
||||
}
|
||||
|
||||
flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
|
||||
flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
|
||||
|
||||
switch (dmaobj->target) {
|
||||
case NV_MEM_TARGET_VRAM:
|
||||
flags0 |= 0x00000009;
|
||||
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, 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);
|
||||
@ -99,6 +77,73 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
|
||||
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 {
|
||||
args->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
|
||||
args->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
|
||||
}
|
||||
}
|
||||
|
||||
priv->flags0 |= (args->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
|
||||
priv->flags0 |= (args->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
|
||||
|
||||
switch (priv->base.target) {
|
||||
case NV_MEM_TARGET_VRAM:
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 **);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user