aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvc0_instmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvc0_instmem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_instmem.c317
1 files changed, 159 insertions, 158 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c
index 13a0f78a9088..c09091749054 100644
--- a/drivers/gpu/drm/nouveau/nvc0_instmem.c
+++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c
@@ -25,206 +25,207 @@
25#include "drmP.h" 25#include "drmP.h"
26 26
27#include "nouveau_drv.h" 27#include "nouveau_drv.h"
28#include "nouveau_vm.h"
29
30struct nvc0_instmem_priv {
31 struct nouveau_gpuobj *bar1_pgd;
32 struct nouveau_channel *bar1;
33 struct nouveau_gpuobj *bar3_pgd;
34 struct nouveau_channel *bar3;
35 struct nouveau_gpuobj *chan_pgd;
36};
28 37
29int 38int
30nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, 39nvc0_instmem_suspend(struct drm_device *dev)
31 uint32_t *size)
32{ 40{
33 int ret; 41 struct drm_nouveau_private *dev_priv = dev->dev_private;
34
35 *size = ALIGN(*size, 4096);
36 if (*size == 0)
37 return -EINVAL;
38
39 ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000,
40 true, false, &gpuobj->im_backing);
41 if (ret) {
42 NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret);
43 return ret;
44 }
45
46 ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM);
47 if (ret) {
48 NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret);
49 nouveau_bo_ref(NULL, &gpuobj->im_backing);
50 return ret;
51 }
52 42
53 gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; 43 dev_priv->ramin_available = false;
54 return 0; 44 return 0;
55} 45}
56 46
57void 47void
58nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) 48nvc0_instmem_resume(struct drm_device *dev)
59{ 49{
60 struct drm_nouveau_private *dev_priv = dev->dev_private; 50 struct drm_nouveau_private *dev_priv = dev->dev_private;
51 struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
61 52
62 if (gpuobj && gpuobj->im_backing) { 53 nv_mask(dev, 0x100c80, 0x00000001, 0x00000000);
63 if (gpuobj->im_bound) 54 nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12);
64 dev_priv->engine.instmem.unbind(dev, gpuobj); 55 nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12);
65 nouveau_bo_unpin(gpuobj->im_backing); 56 dev_priv->ramin_available = true;
66 nouveau_bo_ref(NULL, &gpuobj->im_backing);
67 gpuobj->im_backing = NULL;
68 }
69} 57}
70 58
71int 59static void
72nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) 60nvc0_channel_del(struct nouveau_channel **pchan)
73{ 61{
74 struct drm_nouveau_private *dev_priv = dev->dev_private; 62 struct nouveau_channel *chan;
75 uint32_t pte, pte_end; 63
76 uint64_t vram; 64 chan = *pchan;
77 65 *pchan = NULL;
78 if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) 66 if (!chan)
79 return -EINVAL; 67 return;
80 68
81 NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", 69 nouveau_vm_ref(NULL, &chan->vm, NULL);
82 gpuobj->im_pramin->start, gpuobj->im_pramin->size); 70 if (chan->ramin_heap.free_stack.next)
71 drm_mm_takedown(&chan->ramin_heap);
72 nouveau_gpuobj_ref(NULL, &chan->ramin);
73 kfree(chan);
74}
83 75
84 pte = gpuobj->im_pramin->start >> 12; 76static int
85 pte_end = (gpuobj->im_pramin->size >> 12) + pte; 77nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
86 vram = gpuobj->vinst; 78 struct nouveau_channel **pchan,
79 struct nouveau_gpuobj *pgd, u64 vm_size)
80{
81 struct nouveau_channel *chan;
82 int ret;
87 83
88 NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", 84 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
89 gpuobj->im_pramin->start, pte, pte_end); 85 if (!chan)
90 NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); 86 return -ENOMEM;
87 chan->dev = dev;
91 88
92 while (pte < pte_end) { 89 ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
93 nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); 90 if (ret) {
94 nv_wr32(dev, 0x702004 + (pte * 8), 0); 91 nvc0_channel_del(&chan);
95 vram += 4096; 92 return ret;
96 pte++;
97 } 93 }
98 dev_priv->engine.instmem.flush(dev);
99 94
100 if (1) { 95 ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000);
101 u32 chan = nv_rd32(dev, 0x1700) << 16; 96 if (ret) {
102 nv_wr32(dev, 0x100cb8, (chan + 0x1000) >> 8); 97 nvc0_channel_del(&chan);
103 nv_wr32(dev, 0x100cbc, 0x80000005); 98 return ret;
104 } 99 }
105 100
106 gpuobj->im_bound = 1; 101 ret = nouveau_vm_ref(vm, &chan->vm, NULL);
107 return 0; 102 if (ret) {
108} 103 nvc0_channel_del(&chan);
109 104 return ret;
110int
111nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
112{
113 struct drm_nouveau_private *dev_priv = dev->dev_private;
114 uint32_t pte, pte_end;
115
116 if (gpuobj->im_bound == 0)
117 return -EINVAL;
118
119 pte = gpuobj->im_pramin->start >> 12;
120 pte_end = (gpuobj->im_pramin->size >> 12) + pte;
121 while (pte < pte_end) {
122 nv_wr32(dev, 0x702000 + (pte * 8), 0);
123 nv_wr32(dev, 0x702004 + (pte * 8), 0);
124 pte++;
125 } 105 }
126 dev_priv->engine.instmem.flush(dev);
127 106
128 gpuobj->im_bound = 0; 107 nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst));
129 return 0; 108 nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst));
130} 109 nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1));
110 nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1));
131 111
132void 112 *pchan = chan;
133nvc0_instmem_flush(struct drm_device *dev) 113 return 0;
134{
135 nv_wr32(dev, 0x070000, 1);
136 if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000))
137 NV_ERROR(dev, "PRAMIN flush timeout\n");
138} 114}
139 115
140int 116int
141nvc0_instmem_suspend(struct drm_device *dev) 117nvc0_instmem_init(struct drm_device *dev)
142{ 118{
143 struct drm_nouveau_private *dev_priv = dev->dev_private; 119 struct drm_nouveau_private *dev_priv = dev->dev_private;
144 u32 *buf; 120 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
145 int i; 121 struct pci_dev *pdev = dev->pdev;
122 struct nvc0_instmem_priv *priv;
123 struct nouveau_vm *vm = NULL;
124 int ret;
146 125
147 dev_priv->susres.ramin_copy = vmalloc(65536); 126 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
148 if (!dev_priv->susres.ramin_copy) 127 if (!priv)
149 return -ENOMEM; 128 return -ENOMEM;
150 buf = dev_priv->susres.ramin_copy; 129 pinstmem->priv = priv;
151 130
152 for (i = 0; i < 65536; i += 4) 131 /* BAR3 VM */
153 buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i); 132 ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0,
133 &dev_priv->bar3_vm);
134 if (ret)
135 goto error;
136
137 ret = nouveau_gpuobj_new(dev, NULL,
138 (pci_resource_len(pdev, 3) >> 12) * 8, 0,
139 NVOBJ_FLAG_DONT_MAP |
140 NVOBJ_FLAG_ZERO_ALLOC,
141 &dev_priv->bar3_vm->pgt[0].obj[0]);
142 if (ret)
143 goto error;
144 dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
145
146 nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
147
148 ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
149 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd);
150 if (ret)
151 goto error;
152
153 ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd);
154 if (ret)
155 goto error;
156 nouveau_vm_ref(NULL, &vm, NULL);
157
158 ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3,
159 priv->bar3_pgd, pci_resource_len(dev->pdev, 3));
160 if (ret)
161 goto error;
162
163 /* BAR1 VM */
164 ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm);
165 if (ret)
166 goto error;
167
168 ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
169 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd);
170 if (ret)
171 goto error;
172
173 ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd);
174 if (ret)
175 goto error;
176 nouveau_vm_ref(NULL, &vm, NULL);
177
178 ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1,
179 priv->bar1_pgd, pci_resource_len(dev->pdev, 1));
180 if (ret)
181 goto error;
182
183 /* channel vm */
184 ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
185 if (ret)
186 goto error;
187
188 ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
189 if (ret)
190 goto error;
191
192 nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
193 nouveau_vm_ref(NULL, &vm, NULL);
194
195 nvc0_instmem_resume(dev);
154 return 0; 196 return 0;
197error:
198 nvc0_instmem_takedown(dev);
199 return ret;
155} 200}
156 201
157void 202void
158nvc0_instmem_resume(struct drm_device *dev) 203nvc0_instmem_takedown(struct drm_device *dev)
159{ 204{
160 struct drm_nouveau_private *dev_priv = dev->dev_private; 205 struct drm_nouveau_private *dev_priv = dev->dev_private;
161 u32 *buf = dev_priv->susres.ramin_copy; 206 struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
162 u64 chan; 207 struct nouveau_vm *vm = NULL;
163 int i;
164 208
165 chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; 209 nvc0_instmem_suspend(dev);
166 nv_wr32(dev, 0x001700, chan >> 16);
167 210
168 for (i = 0; i < 65536; i += 4) 211 nv_wr32(dev, 0x1704, 0x00000000);
169 nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]); 212 nv_wr32(dev, 0x1714, 0x00000000);
170 vfree(dev_priv->susres.ramin_copy);
171 dev_priv->susres.ramin_copy = NULL;
172 213
173 nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); 214 nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
174} 215 nouveau_gpuobj_ref(NULL, &priv->chan_pgd);
175 216
176int 217 nvc0_channel_del(&priv->bar1);
177nvc0_instmem_init(struct drm_device *dev) 218 nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
178{ 219 nouveau_gpuobj_ref(NULL, &priv->bar1_pgd);
179 struct drm_nouveau_private *dev_priv = dev->dev_private;
180 u64 chan, pgt3, imem, lim3 = dev_priv->ramin_size - 1;
181 int ret, i;
182
183 dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
184 chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
185 imem = 4096 + 4096 + 32768;
186
187 nv_wr32(dev, 0x001700, chan >> 16);
188
189 /* channel setup */
190 nv_wr32(dev, 0x700200, lower_32_bits(chan + 0x1000));
191 nv_wr32(dev, 0x700204, upper_32_bits(chan + 0x1000));
192 nv_wr32(dev, 0x700208, lower_32_bits(lim3));
193 nv_wr32(dev, 0x70020c, upper_32_bits(lim3));
194
195 /* point pgd -> pgt */
196 nv_wr32(dev, 0x701000, 0);
197 nv_wr32(dev, 0x701004, ((chan + 0x2000) >> 8) | 1);
198
199 /* point pgt -> physical vram for channel */
200 pgt3 = 0x2000;
201 for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4096, pgt3 += 8) {
202 nv_wr32(dev, 0x700000 + pgt3, ((chan + i) >> 8) | 1);
203 nv_wr32(dev, 0x700004 + pgt3, 0);
204 }
205
206 /* clear rest of pgt */
207 for (; i < dev_priv->ramin_size; i += 4096, pgt3 += 8) {
208 nv_wr32(dev, 0x700000 + pgt3, 0);
209 nv_wr32(dev, 0x700004 + pgt3, 0);
210 }
211
212 /* point bar3 at the channel */
213 nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12));
214
215 /* Global PRAMIN heap */
216 ret = drm_mm_init(&dev_priv->ramin_heap, imem,
217 dev_priv->ramin_size - imem);
218 if (ret) {
219 NV_ERROR(dev, "Failed to init RAMIN heap\n");
220 return -ENOMEM;
221 }
222 220
223 return 0; 221 nvc0_channel_del(&priv->bar3);
224} 222 nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL);
223 nouveau_vm_ref(NULL, &vm, priv->bar3_pgd);
224 nouveau_gpuobj_ref(NULL, &priv->bar3_pgd);
225 nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
226 nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
225 227
226void 228 dev_priv->engine.instmem.priv = NULL;
227nvc0_instmem_takedown(struct drm_device *dev) 229 kfree(priv);
228{
229} 230}
230 231