aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-06-09 23:36:08 -0400
committerBen Skeggs <bskeggs@redhat.com>2011-06-23 02:03:46 -0400
commit24f246ac10ae6a6ae873045387d4501498869f74 (patch)
treeeb0c2dde2080898958e317c37ed87bb883653678 /drivers/gpu
parent15ba79ad44fed84a9dabf6996144789424abae5b (diff)
drm/nouveau: rework vram init/fini ordering a little
Commit "drm/nouveau: add some debug output if nouveau_mm busy at destroy time" revealed an issue where vram mm takedown would actually fail due to there still being nodes present, causing nouveau to leak a small amount of memory on module unload. This splits TTM/nouveau_mm a bit more cleanly and ensures nouveau_mm fini isn't done until all gpuobjs are also destroyed. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c22
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vram.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vram.c14
6 files changed, 59 insertions, 53 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index bbea0452dca7..d610edb044c4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -504,7 +504,10 @@ struct nouveau_pm_engine {
504}; 504};
505 505
506struct nouveau_vram_engine { 506struct nouveau_vram_engine {
507 struct nouveau_mm *mm;
508
507 int (*init)(struct drm_device *); 509 int (*init)(struct drm_device *);
510 void (*takedown)(struct drm_device *dev);
508 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, 511 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
509 u32 type, struct nouveau_mem **); 512 u32 type, struct nouveau_mem **);
510 void (*put)(struct drm_device *, struct nouveau_mem **); 513 void (*put)(struct drm_device *, struct nouveau_mem **);
@@ -717,7 +720,6 @@ struct drm_nouveau_private {
717 /* VRAM/fb configuration */ 720 /* VRAM/fb configuration */
718 uint64_t vram_size; 721 uint64_t vram_size;
719 uint64_t vram_sys_base; 722 uint64_t vram_sys_base;
720 u32 vram_rblock_size;
721 723
722 uint64_t fb_phys; 724 uint64_t fb_phys;
723 uint64_t fb_available_size; 725 uint64_t fb_available_size;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 976887dc2bab..765f0e57da78 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -451,10 +451,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
451 dev_priv->ramin_rsvd_vram = 512 * 1024; 451 dev_priv->ramin_rsvd_vram = 512 * 1024;
452 } 452 }
453 453
454 ret = dev_priv->engine.vram.init(dev);
455 if (ret)
456 return ret;
457
458 NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); 454 NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
459 if (dev_priv->vram_sys_base) { 455 if (dev_priv->vram_sys_base) {
460 NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", 456 NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
@@ -729,36 +725,16 @@ nouveau_mem_timing_fini(struct drm_device *dev)
729} 725}
730 726
731static int 727static int
732nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size) 728nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
733{ 729{
734 struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); 730 /* nothing to do */
735 struct nouveau_mm *mm;
736 u64 size, block, rsvd;
737 int ret;
738
739 rsvd = (256 * 1024); /* vga memory */
740 size = (p_size << PAGE_SHIFT) - rsvd;
741 block = dev_priv->vram_rblock_size;
742
743 ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
744 if (ret)
745 return ret;
746
747 man->priv = mm;
748 return 0; 731 return 0;
749} 732}
750 733
751static int 734static int
752nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) 735nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
753{ 736{
754 struct nouveau_mm *mm = man->priv; 737 /* nothing to do */
755 int ret;
756
757 ret = nouveau_mm_fini(&mm);
758 if (ret)
759 return ret;
760
761 man->priv = NULL;
762 return 0; 738 return 0;
763} 739}
764 740
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
index 1f7483aae9a4..b9c016d21553 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -52,6 +52,7 @@ int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
52void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); 52void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
53 53
54int nv50_vram_init(struct drm_device *); 54int nv50_vram_init(struct drm_device *);
55void nv50_vram_fini(struct drm_device *);
55int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, 56int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
56 u32 memtype, struct nouveau_mem **); 57 u32 memtype, struct nouveau_mem **);
57void nv50_vram_del(struct drm_device *, struct nouveau_mem **); 58void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 27d2a816d2c6..49196fa8ea21 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -91,6 +91,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
91 engine->pm.clock_pre = nv04_pm_clock_pre; 91 engine->pm.clock_pre = nv04_pm_clock_pre;
92 engine->pm.clock_set = nv04_pm_clock_set; 92 engine->pm.clock_set = nv04_pm_clock_set;
93 engine->vram.init = nouveau_mem_detect; 93 engine->vram.init = nouveau_mem_detect;
94 engine->vram.takedown = nouveau_stub_takedown;
94 engine->vram.flags_valid = nouveau_mem_flags_valid; 95 engine->vram.flags_valid = nouveau_mem_flags_valid;
95 break; 96 break;
96 case 0x10: 97 case 0x10:
@@ -139,6 +140,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
139 engine->pm.clock_pre = nv04_pm_clock_pre; 140 engine->pm.clock_pre = nv04_pm_clock_pre;
140 engine->pm.clock_set = nv04_pm_clock_set; 141 engine->pm.clock_set = nv04_pm_clock_set;
141 engine->vram.init = nouveau_mem_detect; 142 engine->vram.init = nouveau_mem_detect;
143 engine->vram.takedown = nouveau_stub_takedown;
142 engine->vram.flags_valid = nouveau_mem_flags_valid; 144 engine->vram.flags_valid = nouveau_mem_flags_valid;
143 break; 145 break;
144 case 0x20: 146 case 0x20:
@@ -187,6 +189,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
187 engine->pm.clock_pre = nv04_pm_clock_pre; 189 engine->pm.clock_pre = nv04_pm_clock_pre;
188 engine->pm.clock_set = nv04_pm_clock_set; 190 engine->pm.clock_set = nv04_pm_clock_set;
189 engine->vram.init = nouveau_mem_detect; 191 engine->vram.init = nouveau_mem_detect;
192 engine->vram.takedown = nouveau_stub_takedown;
190 engine->vram.flags_valid = nouveau_mem_flags_valid; 193 engine->vram.flags_valid = nouveau_mem_flags_valid;
191 break; 194 break;
192 case 0x30: 195 case 0x30:
@@ -237,6 +240,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
237 engine->pm.voltage_get = nouveau_voltage_gpio_get; 240 engine->pm.voltage_get = nouveau_voltage_gpio_get;
238 engine->pm.voltage_set = nouveau_voltage_gpio_set; 241 engine->pm.voltage_set = nouveau_voltage_gpio_set;
239 engine->vram.init = nouveau_mem_detect; 242 engine->vram.init = nouveau_mem_detect;
243 engine->vram.takedown = nouveau_stub_takedown;
240 engine->vram.flags_valid = nouveau_mem_flags_valid; 244 engine->vram.flags_valid = nouveau_mem_flags_valid;
241 break; 245 break;
242 case 0x40: 246 case 0x40:
@@ -289,6 +293,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
289 engine->pm.voltage_set = nouveau_voltage_gpio_set; 293 engine->pm.voltage_set = nouveau_voltage_gpio_set;
290 engine->pm.temp_get = nv40_temp_get; 294 engine->pm.temp_get = nv40_temp_get;
291 engine->vram.init = nouveau_mem_detect; 295 engine->vram.init = nouveau_mem_detect;
296 engine->vram.takedown = nouveau_stub_takedown;
292 engine->vram.flags_valid = nouveau_mem_flags_valid; 297 engine->vram.flags_valid = nouveau_mem_flags_valid;
293 break; 298 break;
294 case 0x50: 299 case 0x50:
@@ -366,6 +371,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
366 else 371 else
367 engine->pm.temp_get = nv40_temp_get; 372 engine->pm.temp_get = nv40_temp_get;
368 engine->vram.init = nv50_vram_init; 373 engine->vram.init = nv50_vram_init;
374 engine->vram.takedown = nv50_vram_fini;
369 engine->vram.get = nv50_vram_new; 375 engine->vram.get = nv50_vram_new;
370 engine->vram.put = nv50_vram_del; 376 engine->vram.put = nv50_vram_del;
371 engine->vram.flags_valid = nv50_vram_flags_valid; 377 engine->vram.flags_valid = nv50_vram_flags_valid;
@@ -412,6 +418,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
412 engine->gpio.irq_unregister = nv50_gpio_irq_unregister; 418 engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
413 engine->gpio.irq_enable = nv50_gpio_irq_enable; 419 engine->gpio.irq_enable = nv50_gpio_irq_enable;
414 engine->vram.init = nvc0_vram_init; 420 engine->vram.init = nvc0_vram_init;
421 engine->vram.takedown = nv50_vram_fini;
415 engine->vram.get = nvc0_vram_new; 422 engine->vram.get = nvc0_vram_new;
416 engine->vram.put = nv50_vram_del; 423 engine->vram.put = nv50_vram_del;
417 engine->vram.flags_valid = nvc0_vram_flags_valid; 424 engine->vram.flags_valid = nvc0_vram_flags_valid;
@@ -529,7 +536,7 @@ nouveau_card_init(struct drm_device *dev)
529 536
530 nouveau_pm_init(dev); 537 nouveau_pm_init(dev);
531 538
532 ret = nouveau_mem_vram_init(dev); 539 ret = engine->vram.init(dev);
533 if (ret) 540 if (ret)
534 goto out_bios; 541 goto out_bios;
535 542
@@ -541,10 +548,14 @@ nouveau_card_init(struct drm_device *dev)
541 if (ret) 548 if (ret)
542 goto out_gpuobj; 549 goto out_gpuobj;
543 550
544 ret = nouveau_mem_gart_init(dev); 551 ret = nouveau_mem_vram_init(dev);
545 if (ret) 552 if (ret)
546 goto out_instmem; 553 goto out_instmem;
547 554
555 ret = nouveau_mem_gart_init(dev);
556 if (ret)
557 goto out_ttmvram;
558
548 /* PMC */ 559 /* PMC */
549 ret = engine->mc.init(dev); 560 ret = engine->mc.init(dev);
550 if (ret) 561 if (ret)
@@ -698,12 +709,14 @@ out_mc:
698 engine->mc.takedown(dev); 709 engine->mc.takedown(dev);
699out_gart: 710out_gart:
700 nouveau_mem_gart_fini(dev); 711 nouveau_mem_gart_fini(dev);
712out_ttmvram:
713 nouveau_mem_vram_fini(dev);
701out_instmem: 714out_instmem:
702 engine->instmem.takedown(dev); 715 engine->instmem.takedown(dev);
703out_gpuobj: 716out_gpuobj:
704 nouveau_gpuobj_takedown(dev); 717 nouveau_gpuobj_takedown(dev);
705out_vram: 718out_vram:
706 nouveau_mem_vram_fini(dev); 719 engine->vram.takedown(dev);
707out_bios: 720out_bios:
708 nouveau_pm_fini(dev); 721 nouveau_pm_fini(dev);
709 nouveau_bios_takedown(dev); 722 nouveau_bios_takedown(dev);
@@ -755,10 +768,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
755 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); 768 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
756 mutex_unlock(&dev->struct_mutex); 769 mutex_unlock(&dev->struct_mutex);
757 nouveau_mem_gart_fini(dev); 770 nouveau_mem_gart_fini(dev);
771 nouveau_mem_vram_fini(dev);
758 772
759 engine->instmem.takedown(dev); 773 engine->instmem.takedown(dev);
760 nouveau_gpuobj_takedown(dev); 774 nouveau_gpuobj_takedown(dev);
761 nouveau_mem_vram_fini(dev); 775 engine->vram.takedown(dev);
762 776
763 nouveau_irq_fini(dev); 777 nouveau_irq_fini(dev);
764 drm_vblank_cleanup(dev); 778 drm_vblank_cleanup(dev);
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
index ffbc3d8cf5be..af32daecd1ed 100644
--- a/drivers/gpu/drm/nouveau/nv50_vram.c
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -51,9 +51,7 @@ void
51nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) 51nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
52{ 52{
53 struct drm_nouveau_private *dev_priv = dev->dev_private; 53 struct drm_nouveau_private *dev_priv = dev->dev_private;
54 struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; 54 struct nouveau_mm *mm = dev_priv->engine.vram.mm;
55 struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
56 struct nouveau_mm *mm = man->priv;
57 struct nouveau_mm_node *this; 55 struct nouveau_mm_node *this;
58 struct nouveau_mem *mem; 56 struct nouveau_mem *mem;
59 57
@@ -84,9 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
84 u32 memtype, struct nouveau_mem **pmem) 82 u32 memtype, struct nouveau_mem **pmem)
85{ 83{
86 struct drm_nouveau_private *dev_priv = dev->dev_private; 84 struct drm_nouveau_private *dev_priv = dev->dev_private;
87 struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; 85 struct nouveau_mm *mm = dev_priv->engine.vram.mm;
88 struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
89 struct nouveau_mm *mm = man->priv;
90 struct nouveau_mm_node *r; 86 struct nouveau_mm_node *r;
91 struct nouveau_mem *mem; 87 struct nouveau_mem *mem;
92 int comp = (memtype & 0x300) >> 8; 88 int comp = (memtype & 0x300) >> 8;
@@ -190,22 +186,35 @@ int
190nv50_vram_init(struct drm_device *dev) 186nv50_vram_init(struct drm_device *dev)
191{ 187{
192 struct drm_nouveau_private *dev_priv = dev->dev_private; 188 struct drm_nouveau_private *dev_priv = dev->dev_private;
189 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
190 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
191 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
192 u32 rblock, length;
193 193
194 dev_priv->vram_size = nv_rd32(dev, 0x10020c); 194 dev_priv->vram_size = nv_rd32(dev, 0x10020c);
195 dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; 195 dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
196 dev_priv->vram_size &= 0xffffffff00ULL; 196 dev_priv->vram_size &= 0xffffffff00ULL;
197 197
198 switch (dev_priv->chipset) { 198 /* IGPs, no funky reordering happens here, they don't have VRAM */
199 case 0xaa: 199 if (dev_priv->chipset == 0xaa ||
200 case 0xac: 200 dev_priv->chipset == 0xac ||
201 case 0xaf: 201 dev_priv->chipset == 0xaf) {
202 dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; 202 dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
203 dev_priv->vram_rblock_size = 4096; 203 rblock = 4096 >> 12;
204 break; 204 } else {
205 default: 205 rblock = nv50_vram_rblock(dev) >> 12;
206 dev_priv->vram_rblock_size = nv50_vram_rblock(dev);
207 break;
208 } 206 }
209 207
210 return 0; 208 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
209
210 return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
211}
212
213void
214nv50_vram_fini(struct drm_device *dev)
215{
216 struct drm_nouveau_private *dev_priv = dev->dev_private;
217 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
218
219 nouveau_mm_fini(&vram->mm);
211} 220}
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index 67c6ec6f34ea..e45a24d84e98 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -61,9 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
61 u32 type, struct nouveau_mem **pmem) 61 u32 type, struct nouveau_mem **pmem)
62{ 62{
63 struct drm_nouveau_private *dev_priv = dev->dev_private; 63 struct drm_nouveau_private *dev_priv = dev->dev_private;
64 struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; 64 struct nouveau_mm *mm = dev_priv->engine.vram.mm;
65 struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
66 struct nouveau_mm *mm = man->priv;
67 struct nouveau_mm_node *r; 65 struct nouveau_mm_node *r;
68 struct nouveau_mem *mem; 66 struct nouveau_mem *mem;
69 int ret; 67 int ret;
@@ -105,9 +103,15 @@ int
105nvc0_vram_init(struct drm_device *dev) 103nvc0_vram_init(struct drm_device *dev)
106{ 104{
107 struct drm_nouveau_private *dev_priv = dev->dev_private; 105 struct drm_nouveau_private *dev_priv = dev->dev_private;
106 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
107 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
108 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
109 u32 length;
108 110
109 dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; 111 dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
110 dev_priv->vram_size *= nv_rd32(dev, 0x121c74); 112 dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
111 dev_priv->vram_rblock_size = 4096; 113
112 return 0; 114 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
115
116 return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
113} 117}