aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-09 14:10:24 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-08-09 15:13:23 -0400
commitb2c817031bc99d6e809fa10dcd8bf709b61d088d (patch)
treea9d6063890e59dbaad4b0bbe9c69c5ac9014de68 /drivers/gpu/drm/nouveau/core
parentbc98540b7b506689a9bd7bedffb9f60f9c62d945 (diff)
drm/nouveau/dmaobj: switch to a slightly saner design
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c73
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c115
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c120
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c110
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c100
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h15
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h3
8 files changed, 357 insertions, 181 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
index b04d4572603c..2472c6b7489f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
@@ -30,22 +30,43 @@
30#include "priv.h" 30#include "priv.h"
31 31
32static int 32static int
33nouveau_dmaobj_ctor(struct nouveau_object *parent, 33nvkm_dmaobj_bind(struct nouveau_dmaobj *dmaobj, struct nouveau_object *parent,
34 struct nouveau_gpuobj **pgpuobj)
35{
36 const struct nvkm_dmaeng_impl *impl = (void *)
37 nv_oclass(nv_object(dmaobj)->engine);
38 int ret = 0;
39
40 if (nv_object(dmaobj) == parent) { /* ctor bind */
41 if (nv_mclass(parent->parent) == NV_DEVICE) {
42 /* delayed, or no, binding */
43 return 0;
44 }
45 ret = impl->bind(dmaobj, parent, pgpuobj);
46 if (ret == 0)
47 nouveau_object_ref(NULL, &parent);
48 return ret;
49 }
50
51 return impl->bind(dmaobj, parent, pgpuobj);
52}
53
54int
55nvkm_dmaobj_create_(struct nouveau_object *parent,
34 struct nouveau_object *engine, 56 struct nouveau_object *engine,
35 struct nouveau_oclass *oclass, void *data, u32 size, 57 struct nouveau_oclass *oclass, void **pdata, u32 *psize,
36 struct nouveau_object **pobject) 58 int length, void **pobject)
37{ 59{
38 struct nouveau_dmaeng *dmaeng = (void *)engine; 60 struct nv_dma_class *args = *pdata;
39 struct nouveau_dmaobj *dmaobj; 61 struct nouveau_dmaobj *dmaobj;
40 struct nouveau_gpuobj *gpuobj;
41 struct nv_dma_class *args = data;
42 int ret; 62 int ret;
43 63
44 if (size < sizeof(*args)) 64 if (*psize < sizeof(*args))
45 return -EINVAL; 65 return -EINVAL;
66 *pdata = &args->conf0;
46 67
47 ret = nouveau_object_create(parent, engine, oclass, 0, &dmaobj); 68 ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
48 *pobject = nv_object(dmaobj); 69 dmaobj = *pobject;
49 if (ret) 70 if (ret)
50 return ret; 71 return ret;
51 72
@@ -87,39 +108,9 @@ nouveau_dmaobj_ctor(struct nouveau_object *parent,
87 dmaobj->start = args->start; 108 dmaobj->start = args->start;
88 dmaobj->limit = args->limit; 109 dmaobj->limit = args->limit;
89 dmaobj->conf0 = args->conf0; 110 dmaobj->conf0 = args->conf0;
90
91 switch (nv_mclass(parent)) {
92 case NV_DEVICE:
93 /* delayed, or no, binding */
94 break;
95 default:
96 ret = dmaeng->bind(dmaeng, *pobject, dmaobj, &gpuobj);
97 if (ret == 0) {
98 nouveau_object_ref(NULL, pobject);
99 *pobject = nv_object(gpuobj);
100 }
101 break;
102 }
103
104 return ret; 111 return ret;
105} 112}
106 113
107static struct nouveau_ofuncs
108nouveau_dmaobj_ofuncs = {
109 .ctor = nouveau_dmaobj_ctor,
110 .dtor = nouveau_object_destroy,
111 .init = nouveau_object_init,
112 .fini = nouveau_object_fini,
113};
114
115static struct nouveau_oclass
116nouveau_dmaobj_sclass[] = {
117 { NV_DMA_FROM_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
118 { NV_DMA_TO_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
119 { NV_DMA_IN_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
120 {}
121};
122
123int 114int
124_nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 115_nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
125 struct nouveau_oclass *oclass, void *data, u32 size, 116 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -135,7 +126,7 @@ _nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
135 if (ret) 126 if (ret)
136 return ret; 127 return ret;
137 128
138 nv_engine(dmaeng)->sclass = nouveau_dmaobj_sclass; 129 nv_engine(dmaeng)->sclass = impl->sclass;
139 dmaeng->bind = impl->bind; 130 dmaeng->bind = nvkm_dmaobj_bind;
140 return 0; 131 return 0;
141} 132}
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
index 29fb95c5d058..62d25a0634be 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
@@ -30,19 +30,23 @@
30 30
31#include "priv.h" 31#include "priv.h"
32 32
33struct nv04_dmaobj_priv {
34 struct nouveau_dmaobj base;
35 bool clone;
36 u32 flags0;
37 u32 flags2;
38};
39
33static int 40static int
34nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, 41nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
35 struct nouveau_object *parent, 42 struct nouveau_object *parent,
36 struct nouveau_dmaobj *dmaobj,
37 struct nouveau_gpuobj **pgpuobj) 43 struct nouveau_gpuobj **pgpuobj)
38{ 44{
39 struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng); 45 struct nv04_dmaobj_priv *priv = (void *)dmaobj;
40 struct nouveau_gpuobj *gpuobj; 46 struct nouveau_gpuobj *gpuobj;
41 u32 flags0 = nv_mclass(dmaobj); 47 u64 offset = priv->base.start & 0xfffff000;
42 u32 flags2 = 0x00000000; 48 u64 adjust = priv->base.start & 0x00000fff;
43 u64 offset = dmaobj->start & 0xfffff000; 49 u32 length = priv->base.limit - priv->base.start;
44 u64 adjust = dmaobj->start & 0x00000fff;
45 u32 length = dmaobj->limit - dmaobj->start;
46 int ret; 50 int ret;
47 51
48 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { 52 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -57,58 +61,96 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
57 } 61 }
58 } 62 }
59 63
60 if (dmaobj->target == NV_MEM_TARGET_VM) { 64 if (priv->clone) {
61 if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) { 65 struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaobj);
62 struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0]; 66 struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
63 if (!dmaobj->start) 67 if (!dmaobj->start)
64 return nouveau_gpuobj_dup(parent, pgt, pgpuobj); 68 return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
65 offset = nv_ro32(pgt, 8 + (offset >> 10)); 69 offset = nv_ro32(pgt, 8 + (offset >> 10));
66 offset &= 0xfffff000; 70 offset &= 0xfffff000;
67 } 71 }
72
73 ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
74 *pgpuobj = gpuobj;
75 if (ret == 0) {
76 nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20));
77 nv_wo32(*pgpuobj, 0x04, length);
78 nv_wo32(*pgpuobj, 0x08, priv->flags2 | offset);
79 nv_wo32(*pgpuobj, 0x0c, priv->flags2 | offset);
80 }
81
82 return ret;
83}
84
85static int
86nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
87 struct nouveau_oclass *oclass, void *data, u32 size,
88 struct nouveau_object **pobject)
89{
90 struct nouveau_dmaeng *dmaeng = (void *)engine;
91 struct nv04_vmmgr_priv *vmm = nv04_vmmgr(engine);
92 struct nv04_dmaobj_priv *priv;
93 int ret;
94
95 ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
96 *pobject = nv_object(priv);
97 if (ret)
98 return ret;
68 99
69 dmaobj->target = NV_MEM_TARGET_PCI; 100 if (priv->base.target == NV_MEM_TARGET_VM) {
70 dmaobj->access = NV_MEM_ACCESS_RW; 101 if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass)
102 priv->clone = true;
103 priv->base.target = NV_MEM_TARGET_PCI;
104 priv->base.access = NV_MEM_ACCESS_RW;
71 } 105 }
72 106
73 switch (dmaobj->target) { 107 priv->flags0 = nv_mclass(priv);
108 switch (priv->base.target) {
74 case NV_MEM_TARGET_VRAM: 109 case NV_MEM_TARGET_VRAM:
75 flags0 |= 0x00003000; 110 priv->flags0 |= 0x00003000;
76 break; 111 break;
77 case NV_MEM_TARGET_PCI: 112 case NV_MEM_TARGET_PCI:
78 flags0 |= 0x00023000; 113 priv->flags0 |= 0x00023000;
79 break; 114 break;
80 case NV_MEM_TARGET_PCI_NOSNOOP: 115 case NV_MEM_TARGET_PCI_NOSNOOP:
81 flags0 |= 0x00033000; 116 priv->flags0 |= 0x00033000;
82 break; 117 break;
83 default: 118 default:
84 return -EINVAL; 119 return -EINVAL;
85 } 120 }
86 121
87 switch (dmaobj->access) { 122 switch (priv->base.access) {
88 case NV_MEM_ACCESS_RO: 123 case NV_MEM_ACCESS_RO:
89 flags0 |= 0x00004000; 124 priv->flags0 |= 0x00004000;
90 break; 125 break;
91 case NV_MEM_ACCESS_WO: 126 case NV_MEM_ACCESS_WO:
92 flags0 |= 0x00008000; 127 priv->flags0 |= 0x00008000;
93 case NV_MEM_ACCESS_RW: 128 case NV_MEM_ACCESS_RW:
94 flags2 |= 0x00000002; 129 priv->flags2 |= 0x00000002;
95 break; 130 break;
96 default: 131 default:
97 return -EINVAL; 132 return -EINVAL;
98 } 133 }
99 134
100 ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj); 135 return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
101 *pgpuobj = gpuobj;
102 if (ret == 0) {
103 nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20));
104 nv_wo32(*pgpuobj, 0x04, length);
105 nv_wo32(*pgpuobj, 0x08, flags2 | offset);
106 nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
107 }
108
109 return ret;
110} 136}
111 137
138static struct nouveau_ofuncs
139nv04_dmaobj_ofuncs = {
140 .ctor = nv04_dmaobj_ctor,
141 .dtor = _nvkm_dmaobj_dtor,
142 .init = _nvkm_dmaobj_init,
143 .fini = _nvkm_dmaobj_fini,
144};
145
146static struct nouveau_oclass
147nv04_dmaeng_sclass[] = {
148 { NV_DMA_FROM_MEMORY_CLASS, &nv04_dmaobj_ofuncs },
149 { NV_DMA_TO_MEMORY_CLASS, &nv04_dmaobj_ofuncs },
150 { NV_DMA_IN_MEMORY_CLASS, &nv04_dmaobj_ofuncs },
151 {}
152};
153
112struct nouveau_oclass * 154struct nouveau_oclass *
113nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { 155nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
114 .base.handle = NV_ENGINE(DMAOBJ, 0x04), 156 .base.handle = NV_ENGINE(DMAOBJ, 0x04),
@@ -118,5 +160,6 @@ nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
118 .init = _nvkm_dmaeng_init, 160 .init = _nvkm_dmaeng_init,
119 .fini = _nvkm_dmaeng_fini, 161 .fini = _nvkm_dmaeng_fini,
120 }, 162 },
163 .sclass = nv04_dmaeng_sclass,
121 .bind = nv04_dmaobj_bind, 164 .bind = nv04_dmaobj_bind,
122}.base; 165}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
index a1603a872196..5996a30b22ab 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
@@ -29,14 +29,18 @@
29 29
30#include "priv.h" 30#include "priv.h"
31 31
32struct nv50_dmaobj_priv {
33 struct nouveau_dmaobj base;
34 u32 flags0;
35 u32 flags5;
36};
37
32static int 38static int
33nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng, 39nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
34 struct nouveau_object *parent, 40 struct nouveau_object *parent,
35 struct nouveau_dmaobj *dmaobj,
36 struct nouveau_gpuobj **pgpuobj) 41 struct nouveau_gpuobj **pgpuobj)
37{ 42{
38 u32 flags0 = nv_mclass(dmaobj); 43 struct nv50_dmaobj_priv *priv = (void *)dmaobj;
39 u32 flags5 = 0x00000000;
40 int ret; 44 int ret;
41 45
42 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { 46 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -66,68 +70,107 @@ nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
66 } 70 }
67 } 71 }
68 72
69 if (!(dmaobj->conf0 & NV50_DMA_CONF0_ENABLE)) { 73 ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
70 if (dmaobj->target == NV_MEM_TARGET_VM) { 74 if (ret == 0) {
71 dmaobj->conf0 = NV50_DMA_CONF0_PRIV_VM; 75 nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
72 dmaobj->conf0 |= NV50_DMA_CONF0_PART_VM; 76 nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
73 dmaobj->conf0 |= NV50_DMA_CONF0_COMP_VM; 77 nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
74 dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_VM; 78 nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
79 upper_32_bits(priv->base.start));
80 nv_wo32(*pgpuobj, 0x10, 0x00000000);
81 nv_wo32(*pgpuobj, 0x14, priv->flags5);
82 }
83
84 return ret;
85}
86
87static int
88nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
89 struct nouveau_oclass *oclass, void *data, u32 size,
90 struct nouveau_object **pobject)
91{
92 struct nouveau_dmaeng *dmaeng = (void *)engine;
93 struct nv50_dmaobj_priv *priv;
94 union {
95 u32 conf0;
96 } *args;
97 int ret;
98
99 ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
100 *pobject = nv_object(priv);
101 if (ret)
102 return ret;
103 args = data;
104
105 if (!(args->conf0 & NV50_DMA_CONF0_ENABLE)) {
106 if (priv->base.target == NV_MEM_TARGET_VM) {
107 args->conf0 = NV50_DMA_CONF0_PRIV_VM;
108 args->conf0 |= NV50_DMA_CONF0_PART_VM;
109 args->conf0 |= NV50_DMA_CONF0_COMP_VM;
110 args->conf0 |= NV50_DMA_CONF0_TYPE_VM;
75 } else { 111 } else {
76 dmaobj->conf0 = NV50_DMA_CONF0_PRIV_US; 112 args->conf0 = NV50_DMA_CONF0_PRIV_US;
77 dmaobj->conf0 |= NV50_DMA_CONF0_PART_256; 113 args->conf0 |= NV50_DMA_CONF0_PART_256;
78 dmaobj->conf0 |= NV50_DMA_CONF0_COMP_NONE; 114 args->conf0 |= NV50_DMA_CONF0_COMP_NONE;
79 dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR; 115 args->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR;
80 } 116 }
81 } 117 }
82 118
83 flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_COMP) << 22; 119 priv->flags0 |= (args->conf0 & NV50_DMA_CONF0_COMP) << 22;
84 flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_TYPE) << 22; 120 priv->flags0 |= (args->conf0 & NV50_DMA_CONF0_TYPE) << 22;
85 flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_PRIV); 121 priv->flags0 |= (args->conf0 & NV50_DMA_CONF0_PRIV);
86 flags5 |= (dmaobj->conf0 & NV50_DMA_CONF0_PART); 122 priv->flags5 |= (args->conf0 & NV50_DMA_CONF0_PART);
87 123
88 switch (dmaobj->target) { 124 switch (priv->base.target) {
89 case NV_MEM_TARGET_VM: 125 case NV_MEM_TARGET_VM:
90 flags0 |= 0x00000000; 126 priv->flags0 |= 0x00000000;
91 break; 127 break;
92 case NV_MEM_TARGET_VRAM: 128 case NV_MEM_TARGET_VRAM:
93 flags0 |= 0x00010000; 129 priv->flags0 |= 0x00010000;
94 break; 130 break;
95 case NV_MEM_TARGET_PCI: 131 case NV_MEM_TARGET_PCI:
96 flags0 |= 0x00020000; 132 priv->flags0 |= 0x00020000;
97 break; 133 break;
98 case NV_MEM_TARGET_PCI_NOSNOOP: 134 case NV_MEM_TARGET_PCI_NOSNOOP:
99 flags0 |= 0x00030000; 135 priv->flags0 |= 0x00030000;
100 break; 136 break;
101 default: 137 default:
102 return -EINVAL; 138 return -EINVAL;
103 } 139 }
104 140
105 switch (dmaobj->access) { 141 switch (priv->base.access) {
106 case NV_MEM_ACCESS_VM: 142 case NV_MEM_ACCESS_VM:
107 break; 143 break;
108 case NV_MEM_ACCESS_RO: 144 case NV_MEM_ACCESS_RO:
109 flags0 |= 0x00040000; 145 priv->flags0 |= 0x00040000;
110 break; 146 break;
111 case NV_MEM_ACCESS_WO: 147 case NV_MEM_ACCESS_WO:
112 case NV_MEM_ACCESS_RW: 148 case NV_MEM_ACCESS_RW:
113 flags0 |= 0x00080000; 149 priv->flags0 |= 0x00080000;
114 break; 150 break;
151 default:
152 return -EINVAL;
115 } 153 }
116 154
117 ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); 155 return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
118 if (ret == 0) {
119 nv_wo32(*pgpuobj, 0x00, flags0);
120 nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
121 nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
122 nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
123 upper_32_bits(dmaobj->start));
124 nv_wo32(*pgpuobj, 0x10, 0x00000000);
125 nv_wo32(*pgpuobj, 0x14, flags5);
126 }
127
128 return ret;
129} 156}
130 157
158static struct nouveau_ofuncs
159nv50_dmaobj_ofuncs = {
160 .ctor = nv50_dmaobj_ctor,
161 .dtor = _nvkm_dmaobj_dtor,
162 .init = _nvkm_dmaobj_init,
163 .fini = _nvkm_dmaobj_fini,
164};
165
166static struct nouveau_oclass
167nv50_dmaeng_sclass[] = {
168 { NV_DMA_FROM_MEMORY_CLASS, &nv50_dmaobj_ofuncs },
169 { NV_DMA_TO_MEMORY_CLASS, &nv50_dmaobj_ofuncs },
170 { NV_DMA_IN_MEMORY_CLASS, &nv50_dmaobj_ofuncs },
171 {}
172};
173
131struct nouveau_oclass * 174struct nouveau_oclass *
132nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { 175nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
133 .base.handle = NV_ENGINE(DMAOBJ, 0x50), 176 .base.handle = NV_ENGINE(DMAOBJ, 0x50),
@@ -137,5 +180,6 @@ nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
137 .init = _nvkm_dmaeng_init, 180 .init = _nvkm_dmaeng_init,
138 .fini = _nvkm_dmaeng_fini, 181 .fini = _nvkm_dmaeng_fini,
139 }, 182 },
183 .sclass = nv50_dmaeng_sclass,
140 .bind = nv50_dmaobj_bind, 184 .bind = nv50_dmaobj_bind,
141}.base; 185}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
index bd639de7fea0..c6753a08d3a4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
@@ -30,14 +30,18 @@
30 30
31#include "priv.h" 31#include "priv.h"
32 32
33struct nvc0_dmaobj_priv {
34 struct nouveau_dmaobj base;
35 u32 flags0;
36 u32 flags5;
37};
38
33static int 39static int
34nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng, 40nvc0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
35 struct nouveau_object *parent, 41 struct nouveau_object *parent,
36 struct nouveau_dmaobj *dmaobj,
37 struct nouveau_gpuobj **pgpuobj) 42 struct nouveau_gpuobj **pgpuobj)
38{ 43{
39 u32 flags0 = nv_mclass(dmaobj); 44 struct nvc0_dmaobj_priv *priv = (void *)dmaobj;
40 u32 flags5 = 0x00000000;
41 int ret; 45 int ret;
42 46
43 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { 47 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -52,64 +56,101 @@ nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
52 } else 56 } else
53 return 0; 57 return 0;
54 58
55 if (!(dmaobj->conf0 & NVC0_DMA_CONF0_ENABLE)) { 59 ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
56 if (dmaobj->target == NV_MEM_TARGET_VM) { 60 if (ret == 0) {
57 dmaobj->conf0 = NVC0_DMA_CONF0_PRIV_VM; 61 nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
58 dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_VM; 62 nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
63 nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
64 nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
65 upper_32_bits(priv->base.start));
66 nv_wo32(*pgpuobj, 0x10, 0x00000000);
67 nv_wo32(*pgpuobj, 0x14, priv->flags5);
68 }
69
70 return ret;
71}
72
73static int
74nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
75 struct nouveau_oclass *oclass, void *data, u32 size,
76 struct nouveau_object **pobject)
77{
78 struct nouveau_dmaeng *dmaeng = (void *)engine;
79 struct nvc0_dmaobj_priv *priv;
80 union {
81 u32 conf0;
82 } *args;
83 int ret;
84
85 ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
86 *pobject = nv_object(priv);
87 if (ret)
88 return ret;
89 args = data;
90
91 if (!(args->conf0 & NVC0_DMA_CONF0_ENABLE)) {
92 if (priv->base.target == NV_MEM_TARGET_VM) {
93 args->conf0 = NVC0_DMA_CONF0_PRIV_VM;
94 args->conf0 |= NVC0_DMA_CONF0_TYPE_VM;
59 } else { 95 } else {
60 dmaobj->conf0 = NVC0_DMA_CONF0_PRIV_US; 96 args->conf0 = NVC0_DMA_CONF0_PRIV_US;
61 dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR; 97 args->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR;
62 dmaobj->conf0 |= 0x00020000; 98 args->conf0 |= 0x00020000;
63 } 99 }
64 } 100 }
65 101
66 flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_TYPE) << 22; 102 priv->flags0 |= (args->conf0 & NVC0_DMA_CONF0_TYPE) << 22;
67 flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_PRIV); 103 priv->flags0 |= (args->conf0 & NVC0_DMA_CONF0_PRIV);
68 flags5 |= (dmaobj->conf0 & NVC0_DMA_CONF0_UNKN); 104 priv->flags5 |= (args->conf0 & NVC0_DMA_CONF0_UNKN);
69 105
70 switch (dmaobj->target) { 106 switch (priv->base.target) {
71 case NV_MEM_TARGET_VM: 107 case NV_MEM_TARGET_VM:
72 flags0 |= 0x00000000; 108 priv->flags0 |= 0x00000000;
73 break; 109 break;
74 case NV_MEM_TARGET_VRAM: 110 case NV_MEM_TARGET_VRAM:
75 flags0 |= 0x00010000; 111 priv->flags0 |= 0x00010000;
76 break; 112 break;
77 case NV_MEM_TARGET_PCI: 113 case NV_MEM_TARGET_PCI:
78 flags0 |= 0x00020000; 114 priv->flags0 |= 0x00020000;
79 break; 115 break;
80 case NV_MEM_TARGET_PCI_NOSNOOP: 116 case NV_MEM_TARGET_PCI_NOSNOOP:
81 flags0 |= 0x00030000; 117 priv->flags0 |= 0x00030000;
82 break; 118 break;
83 default: 119 default:
84 return -EINVAL; 120 return -EINVAL;
85 } 121 }
86 122
87 switch (dmaobj->access) { 123 switch (priv->base.access) {
88 case NV_MEM_ACCESS_VM: 124 case NV_MEM_ACCESS_VM:
89 break; 125 break;
90 case NV_MEM_ACCESS_RO: 126 case NV_MEM_ACCESS_RO:
91 flags0 |= 0x00040000; 127 priv->flags0 |= 0x00040000;
92 break; 128 break;
93 case NV_MEM_ACCESS_WO: 129 case NV_MEM_ACCESS_WO:
94 case NV_MEM_ACCESS_RW: 130 case NV_MEM_ACCESS_RW:
95 flags0 |= 0x00080000; 131 priv->flags0 |= 0x00080000;
96 break; 132 break;
97 } 133 }
98 134
99 ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); 135 return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
100 if (ret == 0) {
101 nv_wo32(*pgpuobj, 0x00, flags0);
102 nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
103 nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
104 nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
105 upper_32_bits(dmaobj->start));
106 nv_wo32(*pgpuobj, 0x10, 0x00000000);
107 nv_wo32(*pgpuobj, 0x14, flags5);
108 }
109
110 return ret;
111} 136}
112 137
138static struct nouveau_ofuncs
139nvc0_dmaobj_ofuncs = {
140 .ctor = nvc0_dmaobj_ctor,
141 .dtor = _nvkm_dmaobj_dtor,
142 .init = _nvkm_dmaobj_init,
143 .fini = _nvkm_dmaobj_fini,
144};
145
146static struct nouveau_oclass
147nvc0_dmaeng_sclass[] = {
148 { NV_DMA_FROM_MEMORY_CLASS, &nvc0_dmaobj_ofuncs },
149 { NV_DMA_TO_MEMORY_CLASS, &nvc0_dmaobj_ofuncs },
150 { NV_DMA_IN_MEMORY_CLASS, &nvc0_dmaobj_ofuncs },
151 {}
152};
153
113struct nouveau_oclass * 154struct nouveau_oclass *
114nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { 155nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
115 .base.handle = NV_ENGINE(DMAOBJ, 0xc0), 156 .base.handle = NV_ENGINE(DMAOBJ, 0xc0),
@@ -119,5 +160,6 @@ nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
119 .init = _nvkm_dmaeng_init, 160 .init = _nvkm_dmaeng_init,
120 .fini = _nvkm_dmaeng_fini, 161 .fini = _nvkm_dmaeng_fini,
121 }, 162 },
163 .sclass = nvc0_dmaeng_sclass,
122 .bind = nvc0_dmaobj_bind, 164 .bind = nvc0_dmaobj_bind,
123}.base; 165}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
index 461cc01a0d50..c4b9b8deed71 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
@@ -30,17 +30,17 @@
30 30
31#include "priv.h" 31#include "priv.h"
32 32
33struct nvd0_dmaeng_priv { 33struct nvd0_dmaobj_priv {
34 struct nouveau_dmaeng base; 34 struct nouveau_dmaobj base;
35 u32 flags0;
35}; 36};
36 37
37static int 38static int
38nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng, 39nvd0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
39 struct nouveau_object *parent, 40 struct nouveau_object *parent,
40 struct nouveau_dmaobj *dmaobj,
41 struct nouveau_gpuobj **pgpuobj) 41 struct nouveau_gpuobj **pgpuobj)
42{ 42{
43 u32 flags0 = 0x00000000; 43 struct nvd0_dmaobj_priv *priv = (void *)dmaobj;
44 int ret; 44 int ret;
45 45
46 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { 46 if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
@@ -64,41 +64,86 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
64 } else 64 } else
65 return 0; 65 return 0;
66 66
67 if (!(dmaobj->conf0 & NVD0_DMA_CONF0_ENABLE)) { 67 ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
68 if (dmaobj->target == NV_MEM_TARGET_VM) { 68 if (ret == 0) {
69 dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_VM; 69 nv_wo32(*pgpuobj, 0x00, priv->flags0);
70 dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_LP; 70 nv_wo32(*pgpuobj, 0x04, priv->base.start >> 8);
71 nv_wo32(*pgpuobj, 0x08, priv->base.limit >> 8);
72 nv_wo32(*pgpuobj, 0x0c, 0x00000000);
73 nv_wo32(*pgpuobj, 0x10, 0x00000000);
74 nv_wo32(*pgpuobj, 0x14, 0x00000000);
75 }
76
77 return ret;
78}
79
80static int
81nvd0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
82 struct nouveau_oclass *oclass, void *data, u32 size,
83 struct nouveau_object **pobject)
84{
85 struct nouveau_dmaeng *dmaeng = (void *)engine;
86 struct nvd0_dmaobj_priv *priv;
87 union {
88 u32 conf0;
89 } *args;
90 int ret;
91
92 ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
93 *pobject = nv_object(priv);
94 if (ret)
95 return ret;
96 args = data;
97
98 if (!(args->conf0 & NVD0_DMA_CONF0_ENABLE)) {
99 if (priv->base.target == NV_MEM_TARGET_VM) {
100 args->conf0 |= NVD0_DMA_CONF0_TYPE_VM;
101 args->conf0 |= NVD0_DMA_CONF0_PAGE_LP;
71 } else { 102 } else {
72 dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR; 103 args->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
73 dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_SP; 104 args->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
74 } 105 }
75 } 106 }
76 107
77 flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_TYPE) << 20; 108 priv->flags0 |= (args->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
78 flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_PAGE) >> 4; 109 priv->flags0 |= (args->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
79 110
80 switch (dmaobj->target) { 111 switch (priv->base.target) {
81 case NV_MEM_TARGET_VRAM: 112 case NV_MEM_TARGET_VRAM:
82 flags0 |= 0x00000009; 113 priv->flags0 |= 0x00000009;
114 break;
115 case NV_MEM_TARGET_VM:
116 case NV_MEM_TARGET_PCI:
117 case NV_MEM_TARGET_PCI_NOSNOOP:
118 /* XXX: don't currently know how to construct a real one
119 * of these. we only use them to represent pushbufs
120 * on these chipsets, and the classes that use them
121 * deal with the target themselves.
122 */
83 break; 123 break;
84 default: 124 default:
85 return -EINVAL; 125 return -EINVAL;
86 break;
87 }
88
89 ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
90 if (ret == 0) {
91 nv_wo32(*pgpuobj, 0x00, flags0);
92 nv_wo32(*pgpuobj, 0x04, dmaobj->start >> 8);
93 nv_wo32(*pgpuobj, 0x08, dmaobj->limit >> 8);
94 nv_wo32(*pgpuobj, 0x0c, 0x00000000);
95 nv_wo32(*pgpuobj, 0x10, 0x00000000);
96 nv_wo32(*pgpuobj, 0x14, 0x00000000);
97 } 126 }
98 127
99 return ret; 128 return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
100} 129}
101 130
131static struct nouveau_ofuncs
132nvd0_dmaobj_ofuncs = {
133 .ctor = nvd0_dmaobj_ctor,
134 .dtor = _nvkm_dmaobj_dtor,
135 .init = _nvkm_dmaobj_init,
136 .fini = _nvkm_dmaobj_fini,
137};
138
139static struct nouveau_oclass
140nvd0_dmaeng_sclass[] = {
141 { NV_DMA_FROM_MEMORY_CLASS, &nvd0_dmaobj_ofuncs },
142 { NV_DMA_TO_MEMORY_CLASS, &nvd0_dmaobj_ofuncs },
143 { NV_DMA_IN_MEMORY_CLASS, &nvd0_dmaobj_ofuncs },
144 {}
145};
146
102struct nouveau_oclass * 147struct nouveau_oclass *
103nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { 148nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
104 .base.handle = NV_ENGINE(DMAOBJ, 0xd0), 149 .base.handle = NV_ENGINE(DMAOBJ, 0xd0),
@@ -108,5 +153,6 @@ nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
108 .init = _nvkm_dmaeng_init, 153 .init = _nvkm_dmaeng_init,
109 .fini = _nvkm_dmaeng_fini, 154 .fini = _nvkm_dmaeng_fini,
110 }, 155 },
156 .sclass = nvd0_dmaeng_sclass,
111 .bind = nvd0_dmaobj_bind, 157 .bind = nvd0_dmaobj_bind,
112}.base; 158}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h b/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
index f9aeea5564d9..36f743866937 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
@@ -3,6 +3,16 @@
3 3
4#include <engine/dmaobj.h> 4#include <engine/dmaobj.h>
5 5
6#define nvkm_dmaobj_create(p,e,c,pa,sa,d) \
7 nvkm_dmaobj_create_((p), (e), (c), (pa), (sa), sizeof(**d), (void **)d)
8
9int nvkm_dmaobj_create_(struct nouveau_object *, struct nouveau_object *,
10 struct nouveau_oclass *, void **, u32 *,
11 int, void **);
12#define _nvkm_dmaobj_dtor nouveau_object_destroy
13#define _nvkm_dmaobj_init nouveau_object_init
14#define _nvkm_dmaobj_fini nouveau_object_fini
15
6int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *, 16int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
7 struct nouveau_oclass *, void *, u32, 17 struct nouveau_oclass *, void *, u32,
8 struct nouveau_object **); 18 struct nouveau_object **);
@@ -12,8 +22,9 @@ int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
12 22
13struct nvkm_dmaeng_impl { 23struct nvkm_dmaeng_impl {
14 struct nouveau_oclass base; 24 struct nouveau_oclass base;
15 int (*bind)(struct nouveau_dmaeng *, struct nouveau_object *, 25 struct nouveau_oclass *sclass;
16 struct nouveau_dmaobj *, struct nouveau_gpuobj **); 26 int (*bind)(struct nouveau_dmaobj *, struct nouveau_object *,
27 struct nouveau_gpuobj **);
17}; 28};
18 29
19#endif 30#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
index 812d85dc9f52..2f81cbc4b472 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
@@ -83,7 +83,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
83 return -EINVAL; 83 return -EINVAL;
84 } 84 }
85 85
86 ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu); 86 ret = dmaeng->bind(chan->pushdma, parent, &chan->pushgpu);
87 if (ret) 87 if (ret)
88 return ret; 88 return ret;
89 89
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
index e09df667094b..f060b063d7de 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
@@ -19,9 +19,8 @@ struct nouveau_dmaeng {
19 struct nouveau_engine base; 19 struct nouveau_engine base;
20 20
21 /* creates a "physical" dma object from a struct nouveau_dmaobj */ 21 /* creates a "physical" dma object from a struct nouveau_dmaobj */
22 int (*bind)(struct nouveau_dmaeng *dmaeng, 22 int (*bind)(struct nouveau_dmaobj *dmaobj,
23 struct nouveau_object *parent, 23 struct nouveau_object *parent,
24 struct nouveau_dmaobj *dmaobj,
25 struct nouveau_gpuobj **); 24 struct nouveau_gpuobj **);
26}; 25};
27 26