aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-03-17 19:45:20 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-04-08 20:12:02 -0400
commita76fb4e8ffe42144529e21fe1e609b762e8eb5cc (patch)
tree3215f63360ffb93d685582edeca2e48ee7646170 /drivers/gpu
parent952eb63543552deb1bf1113739d59d29172d7755 (diff)
drm/nouveau: detect vram amount once, and save the value
As opposed to repeatedly reading the amount back from the GPU every time we need to know the VRAM size. We should now fail to load gracefully on detecting no VRAM, rather than something potentially messy happening. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h22
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c96
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c6
-rw-r--r--drivers/gpu/drm/nouveau/nv40_fifo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c4
-rw-r--r--drivers/gpu/drm/nouveau/nv50_instmem.c9
8 files changed, 74 insertions, 76 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 418d881050a0..eeab3fb27083 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -71,7 +71,7 @@ nouveau_bo_fixup_align(struct drm_device *dev,
71 * many small buffers. 71 * many small buffers.
72 */ 72 */
73 if (dev_priv->card_type == NV_50) { 73 if (dev_priv->card_type == NV_50) {
74 uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15; 74 uint32_t block_size = dev_priv->vram_size >> 15;
75 int i; 75 int i;
76 76
77 switch (tile_flags) { 77 switch (tile_flags) {
@@ -399,8 +399,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
399 man->io_addr = NULL; 399 man->io_addr = NULL;
400 man->io_offset = drm_get_resource_start(dev, 1); 400 man->io_offset = drm_get_resource_start(dev, 1);
401 man->io_size = drm_get_resource_len(dev, 1); 401 man->io_size = drm_get_resource_len(dev, 1);
402 if (man->io_size > nouveau_mem_fb_amount(dev)) 402 if (man->io_size > dev_priv->vram_size)
403 man->io_size = nouveau_mem_fb_amount(dev); 403 man->io_size = dev_priv->vram_size;
404 404
405 man->gpu_offset = dev_priv->vm_vram_base; 405 man->gpu_offset = dev_priv->vm_vram_base;
406 break; 406 break;
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
index 8ff9ef5d4b47..a251886a0ce6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -137,10 +137,9 @@ nouveau_debugfs_memory_info(struct seq_file *m, void *data)
137{ 137{
138 struct drm_info_node *node = (struct drm_info_node *) m->private; 138 struct drm_info_node *node = (struct drm_info_node *) m->private;
139 struct drm_minor *minor = node->minor; 139 struct drm_minor *minor = node->minor;
140 struct drm_device *dev = minor->dev; 140 struct drm_nouveau_private *dev_priv = minor->dev->dev_private;
141 141
142 seq_printf(m, "VRAM total: %dKiB\n", 142 seq_printf(m, "VRAM total: %dKiB\n", (int)(dev_priv->vram_size >> 10));
143 (int)(nouveau_mem_fb_amount(dev) >> 10));
144 return 0; 143 return 0;
145} 144}
146 145
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 5d3618e4520d..f7d4d2a10052 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -553,12 +553,6 @@ struct drm_nouveau_private {
553 uint32_t ramro_offset; 553 uint32_t ramro_offset;
554 uint32_t ramro_size; 554 uint32_t ramro_size;
555 555
556 /* base physical addresses */
557 uint64_t fb_phys;
558 uint64_t fb_available_size;
559 uint64_t fb_mappable_pages;
560 uint64_t fb_aper_free;
561
562 struct { 556 struct {
563 enum { 557 enum {
564 NOUVEAU_GART_NONE = 0, 558 NOUVEAU_GART_NONE = 0,
@@ -580,6 +574,16 @@ struct drm_nouveau_private {
580 spinlock_t lock; 574 spinlock_t lock;
581 } tile; 575 } tile;
582 576
577 /* VRAM/fb configuration */
578 uint64_t vram_size;
579 uint64_t vram_sys_base;
580
581 uint64_t fb_phys;
582 uint64_t fb_available_size;
583 uint64_t fb_mappable_pages;
584 uint64_t fb_aper_free;
585 int fb_mtrr;
586
583 /* G8x/G9x virtual address space */ 587 /* G8x/G9x virtual address space */
584 uint64_t vm_gart_base; 588 uint64_t vm_gart_base;
585 uint64_t vm_gart_size; 589 uint64_t vm_gart_size;
@@ -588,10 +592,6 @@ struct drm_nouveau_private {
588 uint64_t vm_end; 592 uint64_t vm_end;
589 struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; 593 struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
590 int vm_vram_pt_nr; 594 int vm_vram_pt_nr;
591 uint64_t vram_sys_base;
592
593 /* the mtrr covering the FB */
594 int fb_mtrr;
595 595
596 struct mem_block *ramin_heap; 596 struct mem_block *ramin_heap;
597 597
@@ -709,7 +709,7 @@ extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,
709 struct drm_file *, int tail); 709 struct drm_file *, int tail);
710extern void nouveau_mem_takedown(struct mem_block **heap); 710extern void nouveau_mem_takedown(struct mem_block **heap);
711extern void nouveau_mem_free_block(struct mem_block *); 711extern void nouveau_mem_free_block(struct mem_block *);
712extern uint64_t nouveau_mem_fb_amount(struct drm_device *); 712extern int nouveau_mem_detect(struct drm_device *dev);
713extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); 713extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
714extern int nouveau_mem_init(struct drm_device *); 714extern int nouveau_mem_init(struct drm_device *);
715extern int nouveau_mem_init_agp(struct drm_device *); 715extern int nouveau_mem_init_agp(struct drm_device *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index a4d5ecc6ed5a..775a7017af64 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -477,9 +477,30 @@ void nouveau_mem_close(struct drm_device *dev)
477 } 477 }
478} 478}
479 479
480/*XXX won't work on BSD because of pci_read_config_dword */
481static uint32_t 480static uint32_t
482nouveau_mem_fb_amount_igp(struct drm_device *dev) 481nouveau_mem_detect_nv04(struct drm_device *dev)
482{
483 uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0);
484
485 if (boot0 & 0x00000100)
486 return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;
487
488 switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) {
489 case NV04_BOOT_0_RAM_AMOUNT_32MB:
490 return 32 * 1024 * 1024;
491 case NV04_BOOT_0_RAM_AMOUNT_16MB:
492 return 16 * 1024 * 1024;
493 case NV04_BOOT_0_RAM_AMOUNT_8MB:
494 return 8 * 1024 * 1024;
495 case NV04_BOOT_0_RAM_AMOUNT_4MB:
496 return 4 * 1024 * 1024;
497 }
498
499 return 0;
500}
501
502static uint32_t
503nouveau_mem_detect_nforce(struct drm_device *dev)
483{ 504{
484 struct drm_nouveau_private *dev_priv = dev->dev_private; 505 struct drm_nouveau_private *dev_priv = dev->dev_private;
485 struct pci_dev *bridge; 506 struct pci_dev *bridge;
@@ -491,11 +512,11 @@ nouveau_mem_fb_amount_igp(struct drm_device *dev)
491 return 0; 512 return 0;
492 } 513 }
493 514
494 if (dev_priv->flags&NV_NFORCE) { 515 if (dev_priv->flags & NV_NFORCE) {
495 pci_read_config_dword(bridge, 0x7C, &mem); 516 pci_read_config_dword(bridge, 0x7C, &mem);
496 return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; 517 return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
497 } else 518 } else
498 if (dev_priv->flags&NV_NFORCE2) { 519 if (dev_priv->flags & NV_NFORCE2) {
499 pci_read_config_dword(bridge, 0x84, &mem); 520 pci_read_config_dword(bridge, 0x84, &mem);
500 return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; 521 return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
501 } 522 }
@@ -505,50 +526,32 @@ nouveau_mem_fb_amount_igp(struct drm_device *dev)
505} 526}
506 527
507/* returns the amount of FB ram in bytes */ 528/* returns the amount of FB ram in bytes */
508uint64_t nouveau_mem_fb_amount(struct drm_device *dev) 529int
530nouveau_mem_detect(struct drm_device *dev)
509{ 531{
510 struct drm_nouveau_private *dev_priv = dev->dev_private; 532 struct drm_nouveau_private *dev_priv = dev->dev_private;
511 uint32_t boot0; 533
512 534 if (dev_priv->card_type == NV_04) {
513 switch (dev_priv->card_type) { 535 dev_priv->vram_size = nouveau_mem_detect_nv04(dev);
514 case NV_04: 536 } else
515 boot0 = nv_rd32(dev, NV03_BOOT_0); 537 if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
516 if (boot0 & 0x00000100) 538 dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
517 return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; 539 } else {
518 540 dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
519 switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { 541 dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
520 case NV04_BOOT_0_RAM_AMOUNT_32MB: 542 if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
521 return 32 * 1024 * 1024; 543 dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
522 case NV04_BOOT_0_RAM_AMOUNT_16MB:
523 return 16 * 1024 * 1024;
524 case NV04_BOOT_0_RAM_AMOUNT_8MB:
525 return 8 * 1024 * 1024;
526 case NV04_BOOT_0_RAM_AMOUNT_4MB:
527 return 4 * 1024 * 1024;
528 }
529 break;
530 case NV_10:
531 case NV_20:
532 case NV_30:
533 case NV_40:
534 case NV_50:
535 default:
536 if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
537 return nouveau_mem_fb_amount_igp(dev);
538 } else {
539 uint64_t mem;
540 mem = (nv_rd32(dev, NV04_FIFO_DATA) &
541 NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >>
542 NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT;
543 return mem * 1024 * 1024;
544 }
545 break;
546 } 544 }
547 545
548 NV_ERROR(dev, 546 NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
549 "Unable to detect video ram size. Please report your setup to " 547 if (dev_priv->vram_sys_base) {
550 DRIVER_EMAIL "\n"); 548 NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
551 return 0; 549 dev_priv->vram_sys_base);
550 }
551
552 if (dev_priv->vram_size)
553 return 0;
554 return -ENOMEM;
552} 555}
553 556
554#if __OS_HAS_AGP 557#if __OS_HAS_AGP
@@ -659,15 +662,12 @@ nouveau_mem_init(struct drm_device *dev)
659 spin_lock_init(&dev_priv->ttm.bo_list_lock); 662 spin_lock_init(&dev_priv->ttm.bo_list_lock);
660 spin_lock_init(&dev_priv->tile.lock); 663 spin_lock_init(&dev_priv->tile.lock);
661 664
662 dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); 665 dev_priv->fb_available_size = dev_priv->vram_size;
663
664 dev_priv->fb_mappable_pages = dev_priv->fb_available_size; 666 dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
665 if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1)) 667 if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1))
666 dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1); 668 dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1);
667 dev_priv->fb_mappable_pages >>= PAGE_SHIFT; 669 dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
668 670
669 NV_INFO(dev, "%d MiB VRAM\n", (int)(dev_priv->fb_available_size >> 20));
670
671 /* remove reserved space at end of vram from available amount */ 671 /* remove reserved space at end of vram from available amount */
672 dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; 672 dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
673 dev_priv->fb_aper_free = dev_priv->fb_available_size; 673 dev_priv->fb_aper_free = dev_priv->fb_available_size;
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 58b46807de23..1ee2b65d72e9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -340,7 +340,7 @@ nouveau_card_init_channel(struct drm_device *dev)
340 340
341 gpuobj = NULL; 341 gpuobj = NULL;
342 ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, 342 ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
343 0, nouveau_mem_fb_amount(dev), 343 0, dev_priv->vram_size,
344 NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, 344 NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
345 &gpuobj); 345 &gpuobj);
346 if (ret) 346 if (ret)
@@ -426,6 +426,10 @@ nouveau_card_init(struct drm_device *dev)
426 goto out; 426 goto out;
427 } 427 }
428 428
429 ret = nouveau_mem_detect(dev);
430 if (ret)
431 goto out_bios;
432
429 ret = nouveau_gpuobj_early_init(dev); 433 ret = nouveau_gpuobj_early_init(dev);
430 if (ret) 434 if (ret)
431 goto out_bios; 435 goto out_bios;
diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c
index 6b2ef4a9fce1..500ccfd3a0b8 100644
--- a/drivers/gpu/drm/nouveau/nv40_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv40_fifo.c
@@ -278,7 +278,7 @@ nv40_fifo_init_ramxx(struct drm_device *dev)
278 default: 278 default:
279 nv_wr32(dev, 0x2230, 0); 279 nv_wr32(dev, 0x2230, 0);
280 nv_wr32(dev, NV40_PFIFO_RAMFC, 280 nv_wr32(dev, NV40_PFIFO_RAMFC,
281 ((nouveau_mem_fb_amount(dev) - 512 * 1024 + 281 ((dev_priv->vram_size - 512 * 1024 +
282 dev_priv->ramfc_offset) >> 16) | (3 << 16)); 282 dev_priv->ramfc_offset) >> 16) | (3 << 16));
283 break; 283 break;
284 } 284 }
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index fac6c88a2b1f..bd99986a1146 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -143,7 +143,7 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)
143 } 143 }
144 144
145 ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, 145 ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19,
146 0, nouveau_mem_fb_amount(dev)); 146 0, dev_priv->vram_size);
147 if (ret) { 147 if (ret) {
148 nv50_evo_channel_del(pchan); 148 nv50_evo_channel_del(pchan);
149 return ret; 149 return ret;
@@ -231,7 +231,7 @@ nv50_display_init(struct drm_device *dev)
231 /* This used to be in crtc unblank, but seems out of place there. */ 231 /* This used to be in crtc unblank, but seems out of place there. */
232 nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); 232 nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0);
233 /* RAM is clamped to 256 MiB. */ 233 /* RAM is clamped to 256 MiB. */
234 ram_amount = nouveau_mem_fb_amount(dev); 234 ram_amount = dev_priv->vram_size;
235 NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); 235 NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount);
236 if (ram_amount > 256*1024*1024) 236 if (ram_amount > 256*1024*1024)
237 ram_amount = 256*1024*1024; 237 ram_amount = 256*1024*1024;
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
index de1f5b0062c5..34280eb31df3 100644
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -76,17 +76,12 @@ nv50_instmem_init(struct drm_device *dev)
76 for (i = 0x1700; i <= 0x1710; i += 4) 76 for (i = 0x1700; i <= 0x1710; i += 4)
77 priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); 77 priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i);
78 78
79 if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
80 dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
81 else
82 dev_priv->vram_sys_base = 0;
83
84 /* Reserve the last MiB of VRAM, we should probably try to avoid 79 /* Reserve the last MiB of VRAM, we should probably try to avoid
85 * setting up the below tables over the top of the VBIOS image at 80 * setting up the below tables over the top of the VBIOS image at
86 * some point. 81 * some point.
87 */ 82 */
88 dev_priv->ramin_rsvd_vram = 1 << 20; 83 dev_priv->ramin_rsvd_vram = 1 << 20;
89 c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram; 84 c_offset = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
90 c_size = 128 << 10; 85 c_size = 128 << 10;
91 c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200; 86 c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200;
92 c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; 87 c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20;
@@ -106,7 +101,7 @@ nv50_instmem_init(struct drm_device *dev)
106 dev_priv->vm_gart_size = NV50_VM_BLOCK; 101 dev_priv->vm_gart_size = NV50_VM_BLOCK;
107 102
108 dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; 103 dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size;
109 dev_priv->vm_vram_size = nouveau_mem_fb_amount(dev); 104 dev_priv->vm_vram_size = dev_priv->vram_size;
110 if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) 105 if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM)
111 dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; 106 dev_priv->vm_vram_size = NV50_VM_MAX_VRAM;
112 dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); 107 dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK);