aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c215
1 files changed, 171 insertions, 44 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 5158a12f7844..2dc09dbd817d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -192,6 +192,92 @@ void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
192} 192}
193 193
194/* 194/*
195 * NV10-NV40 tiling helpers
196 */
197
198static void
199nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
200 uint32_t size, uint32_t pitch)
201{
202 struct drm_nouveau_private *dev_priv = dev->dev_private;
203 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
204 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
205 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
206 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
207
208 tile->addr = addr;
209 tile->size = size;
210 tile->used = !!pitch;
211 nouveau_fence_unref((void **)&tile->fence);
212
213 if (!pfifo->cache_flush(dev))
214 return;
215
216 pfifo->reassign(dev, false);
217 pfifo->cache_flush(dev);
218 pfifo->cache_pull(dev, false);
219
220 nouveau_wait_for_idle(dev);
221
222 pgraph->set_region_tiling(dev, i, addr, size, pitch);
223 pfb->set_region_tiling(dev, i, addr, size, pitch);
224
225 pfifo->cache_pull(dev, true);
226 pfifo->reassign(dev, true);
227}
228
229struct nouveau_tile_reg *
230nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
231 uint32_t pitch)
232{
233 struct drm_nouveau_private *dev_priv = dev->dev_private;
234 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
235 struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL;
236 int i;
237
238 spin_lock(&dev_priv->tile.lock);
239
240 for (i = 0; i < pfb->num_tiles; i++) {
241 if (tile[i].used)
242 /* Tile region in use. */
243 continue;
244
245 if (tile[i].fence &&
246 !nouveau_fence_signalled(tile[i].fence, NULL))
247 /* Pending tile region. */
248 continue;
249
250 if (max(tile[i].addr, addr) <
251 min(tile[i].addr + tile[i].size, addr + size))
252 /* Kill an intersecting tile region. */
253 nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
254
255 if (pitch && !found) {
256 /* Free tile region. */
257 nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
258 found = &tile[i];
259 }
260 }
261
262 spin_unlock(&dev_priv->tile.lock);
263
264 return found;
265}
266
267void
268nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
269 struct nouveau_fence *fence)
270{
271 if (fence) {
272 /* Mark it as pending. */
273 tile->fence = fence;
274 nouveau_fence_ref(fence);
275 }
276
277 tile->used = false;
278}
279
280/*
195 * NV50 VM helpers 281 * NV50 VM helpers
196 */ 282 */
197int 283int
@@ -199,53 +285,50 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
199 uint32_t flags, uint64_t phys) 285 uint32_t flags, uint64_t phys)
200{ 286{
201 struct drm_nouveau_private *dev_priv = dev->dev_private; 287 struct drm_nouveau_private *dev_priv = dev->dev_private;
202 struct nouveau_gpuobj **pgt; 288 struct nouveau_gpuobj *pgt;
203 unsigned psz, pfl, pages; 289 unsigned block;
204 290 int i;
205 if (virt >= dev_priv->vm_gart_base && 291
206 (virt + size) < (dev_priv->vm_gart_base + dev_priv->vm_gart_size)) { 292 virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
207 psz = 12; 293 size = (size >> 16) << 1;
208 pgt = &dev_priv->gart_info.sg_ctxdma; 294
209 pfl = 0x21; 295 phys |= ((uint64_t)flags << 32);
210 virt -= dev_priv->vm_gart_base; 296 phys |= 1;
211 } else 297 if (dev_priv->vram_sys_base) {
212 if (virt >= dev_priv->vm_vram_base && 298 phys += dev_priv->vram_sys_base;
213 (virt + size) < (dev_priv->vm_vram_base + dev_priv->vm_vram_size)) { 299 phys |= 0x30;
214 psz = 16;
215 pgt = dev_priv->vm_vram_pt;
216 pfl = 0x01;
217 virt -= dev_priv->vm_vram_base;
218 } else {
219 NV_ERROR(dev, "Invalid address: 0x%16llx-0x%16llx\n",
220 virt, virt + size - 1);
221 return -EINVAL;
222 } 300 }
223 301
224 pages = size >> psz;
225
226 dev_priv->engine.instmem.prepare_access(dev, true); 302 dev_priv->engine.instmem.prepare_access(dev, true);
227 if (flags & 0x80000000) { 303 while (size) {
228 while (pages--) { 304 unsigned offset_h = upper_32_bits(phys);
229 struct nouveau_gpuobj *pt = pgt[virt >> 29]; 305 unsigned offset_l = lower_32_bits(phys);
230 unsigned pte = ((virt & 0x1fffffffULL) >> psz) << 1; 306 unsigned pte, end;
307
308 for (i = 7; i >= 0; i--) {
309 block = 1 << (i + 1);
310 if (size >= block && !(virt & (block - 1)))
311 break;
312 }
313 offset_l |= (i << 7);
231 314
232 nv_wo32(dev, pt, pte++, 0x00000000); 315 phys += block << 15;
233 nv_wo32(dev, pt, pte++, 0x00000000); 316 size -= block;
234 317
235 virt += (1 << psz); 318 while (block) {
236 } 319 pgt = dev_priv->vm_vram_pt[virt >> 14];
237 } else { 320 pte = virt & 0x3ffe;
238 while (pages--) {
239 struct nouveau_gpuobj *pt = pgt[virt >> 29];
240 unsigned pte = ((virt & 0x1fffffffULL) >> psz) << 1;
241 unsigned offset_h = upper_32_bits(phys) & 0xff;
242 unsigned offset_l = lower_32_bits(phys);
243 321
244 nv_wo32(dev, pt, pte++, offset_l | pfl); 322 end = pte + block;
245 nv_wo32(dev, pt, pte++, offset_h | flags); 323 if (end > 16384)
324 end = 16384;
325 block -= (end - pte);
326 virt += (end - pte);
246 327
247 phys += (1 << psz); 328 while (pte < end) {
248 virt += (1 << psz); 329 nv_wo32(dev, pgt, pte++, offset_l);
330 nv_wo32(dev, pgt, pte++, offset_h);
331 }
249 } 332 }
250 } 333 }
251 dev_priv->engine.instmem.finish_access(dev); 334 dev_priv->engine.instmem.finish_access(dev);
@@ -270,7 +353,41 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
270void 353void
271nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) 354nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
272{ 355{
273 nv50_mem_vm_bind_linear(dev, virt, size, 0x80000000, 0); 356 struct drm_nouveau_private *dev_priv = dev->dev_private;
357 struct nouveau_gpuobj *pgt;
358 unsigned pages, pte, end;
359
360 virt -= dev_priv->vm_vram_base;
361 pages = (size >> 16) << 1;
362
363 dev_priv->engine.instmem.prepare_access(dev, true);
364 while (pages) {
365 pgt = dev_priv->vm_vram_pt[virt >> 29];
366 pte = (virt & 0x1ffe0000ULL) >> 15;
367
368 end = pte + pages;
369 if (end > 16384)
370 end = 16384;
371 pages -= (end - pte);
372 virt += (end - pte) << 15;
373
374 while (pte < end)
375 nv_wo32(dev, pgt, pte++, 0);
376 }
377 dev_priv->engine.instmem.finish_access(dev);
378
379 nv_wr32(dev, 0x100c80, 0x00050001);
380 if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
381 NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
382 NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
383 return;
384 }
385
386 nv_wr32(dev, 0x100c80, 0x00000001);
387 if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
388 NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
389 NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
390 }
274} 391}
275 392
276/* 393/*
@@ -297,9 +414,8 @@ void nouveau_mem_close(struct drm_device *dev)
297{ 414{
298 struct drm_nouveau_private *dev_priv = dev->dev_private; 415 struct drm_nouveau_private *dev_priv = dev->dev_private;
299 416
300 if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type) 417 nouveau_bo_unpin(dev_priv->vga_ram);
301 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0); 418 nouveau_bo_ref(NULL, &dev_priv->vga_ram);
302 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
303 419
304 ttm_bo_device_release(&dev_priv->ttm.bdev); 420 ttm_bo_device_release(&dev_priv->ttm.bdev);
305 421
@@ -513,6 +629,7 @@ nouveau_mem_init(struct drm_device *dev)
513 629
514 INIT_LIST_HEAD(&dev_priv->ttm.bo_list); 630 INIT_LIST_HEAD(&dev_priv->ttm.bo_list);
515 spin_lock_init(&dev_priv->ttm.bo_list_lock); 631 spin_lock_init(&dev_priv->ttm.bo_list_lock);
632 spin_lock_init(&dev_priv->tile.lock);
516 633
517 dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); 634 dev_priv->fb_available_size = nouveau_mem_fb_amount(dev);
518 635
@@ -535,6 +652,15 @@ nouveau_mem_init(struct drm_device *dev)
535 return ret; 652 return ret;
536 } 653 }
537 654
655 ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
656 0, 0, true, true, &dev_priv->vga_ram);
657 if (ret == 0)
658 ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
659 if (ret) {
660 NV_WARN(dev, "failed to reserve VGA memory\n");
661 nouveau_bo_ref(NULL, &dev_priv->vga_ram);
662 }
663
538 /* GART */ 664 /* GART */
539#if !defined(__powerpc__) && !defined(__ia64__) 665#if !defined(__powerpc__) && !defined(__ia64__)
540 if (drm_device_is_agp(dev) && dev->agp) { 666 if (drm_device_is_agp(dev) && dev->agp) {
@@ -566,6 +692,7 @@ nouveau_mem_init(struct drm_device *dev)
566 dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), 692 dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
567 drm_get_resource_len(dev, 1), 693 drm_get_resource_len(dev, 1),
568 DRM_MTRR_WC); 694 DRM_MTRR_WC);
695
569 return 0; 696 return 0;
570} 697}
571 698