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>
This commit is contained in:
parent
15ba79ad44
commit
24f246ac10
|
@ -504,7 +504,10 @@ struct nouveau_pm_engine {
|
|||
};
|
||||
|
||||
struct nouveau_vram_engine {
|
||||
struct nouveau_mm *mm;
|
||||
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
|
||||
u32 type, struct nouveau_mem **);
|
||||
void (*put)(struct drm_device *, struct nouveau_mem **);
|
||||
|
@ -717,7 +720,6 @@ struct drm_nouveau_private {
|
|||
/* VRAM/fb configuration */
|
||||
uint64_t vram_size;
|
||||
uint64_t vram_sys_base;
|
||||
u32 vram_rblock_size;
|
||||
|
||||
uint64_t fb_phys;
|
||||
uint64_t fb_available_size;
|
||||
|
|
|
@ -451,10 +451,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
|
|||
dev_priv->ramin_rsvd_vram = 512 * 1024;
|
||||
}
|
||||
|
||||
ret = dev_priv->engine.vram.init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
|
||||
if (dev_priv->vram_sys_base) {
|
||||
NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
|
||||
|
@ -729,36 +725,16 @@ nouveau_mem_timing_fini(struct drm_device *dev)
|
|||
}
|
||||
|
||||
static int
|
||||
nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
|
||||
nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
|
||||
struct nouveau_mm *mm;
|
||||
u64 size, block, rsvd;
|
||||
int ret;
|
||||
|
||||
rsvd = (256 * 1024); /* vga memory */
|
||||
size = (p_size << PAGE_SHIFT) - rsvd;
|
||||
block = dev_priv->vram_rblock_size;
|
||||
|
||||
ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
man->priv = mm;
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
|
||||
{
|
||||
struct nouveau_mm *mm = man->priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_mm_fini(&mm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
man->priv = NULL;
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
|
|||
void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
|
||||
|
||||
int nv50_vram_init(struct drm_device *);
|
||||
void nv50_vram_fini(struct drm_device *);
|
||||
int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
|
||||
u32 memtype, struct nouveau_mem **);
|
||||
void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
|
||||
|
|
|
@ -91,6 +91,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clock_pre = nv04_pm_clock_pre;
|
||||
engine->pm.clock_set = nv04_pm_clock_set;
|
||||
engine->vram.init = nouveau_mem_detect;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x10:
|
||||
|
@ -139,6 +140,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clock_pre = nv04_pm_clock_pre;
|
||||
engine->pm.clock_set = nv04_pm_clock_set;
|
||||
engine->vram.init = nouveau_mem_detect;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x20:
|
||||
|
@ -187,6 +189,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clock_pre = nv04_pm_clock_pre;
|
||||
engine->pm.clock_set = nv04_pm_clock_set;
|
||||
engine->vram.init = nouveau_mem_detect;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x30:
|
||||
|
@ -237,6 +240,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.voltage_get = nouveau_voltage_gpio_get;
|
||||
engine->pm.voltage_set = nouveau_voltage_gpio_set;
|
||||
engine->vram.init = nouveau_mem_detect;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x40:
|
||||
|
@ -289,6 +293,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.voltage_set = nouveau_voltage_gpio_set;
|
||||
engine->pm.temp_get = nv40_temp_get;
|
||||
engine->vram.init = nouveau_mem_detect;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x50:
|
||||
|
@ -366,6 +371,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
else
|
||||
engine->pm.temp_get = nv40_temp_get;
|
||||
engine->vram.init = nv50_vram_init;
|
||||
engine->vram.takedown = nv50_vram_fini;
|
||||
engine->vram.get = nv50_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nv50_vram_flags_valid;
|
||||
|
@ -412,6 +418,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
|
||||
engine->gpio.irq_enable = nv50_gpio_irq_enable;
|
||||
engine->vram.init = nvc0_vram_init;
|
||||
engine->vram.takedown = nv50_vram_fini;
|
||||
engine->vram.get = nvc0_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nvc0_vram_flags_valid;
|
||||
|
@ -529,7 +536,7 @@ nouveau_card_init(struct drm_device *dev)
|
|||
|
||||
nouveau_pm_init(dev);
|
||||
|
||||
ret = nouveau_mem_vram_init(dev);
|
||||
ret = engine->vram.init(dev);
|
||||
if (ret)
|
||||
goto out_bios;
|
||||
|
||||
|
@ -541,10 +548,14 @@ nouveau_card_init(struct drm_device *dev)
|
|||
if (ret)
|
||||
goto out_gpuobj;
|
||||
|
||||
ret = nouveau_mem_gart_init(dev);
|
||||
ret = nouveau_mem_vram_init(dev);
|
||||
if (ret)
|
||||
goto out_instmem;
|
||||
|
||||
ret = nouveau_mem_gart_init(dev);
|
||||
if (ret)
|
||||
goto out_ttmvram;
|
||||
|
||||
/* PMC */
|
||||
ret = engine->mc.init(dev);
|
||||
if (ret)
|
||||
|
@ -698,12 +709,14 @@ out_mc:
|
|||
engine->mc.takedown(dev);
|
||||
out_gart:
|
||||
nouveau_mem_gart_fini(dev);
|
||||
out_ttmvram:
|
||||
nouveau_mem_vram_fini(dev);
|
||||
out_instmem:
|
||||
engine->instmem.takedown(dev);
|
||||
out_gpuobj:
|
||||
nouveau_gpuobj_takedown(dev);
|
||||
out_vram:
|
||||
nouveau_mem_vram_fini(dev);
|
||||
engine->vram.takedown(dev);
|
||||
out_bios:
|
||||
nouveau_pm_fini(dev);
|
||||
nouveau_bios_takedown(dev);
|
||||
|
@ -755,10 +768,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
|||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
nouveau_mem_gart_fini(dev);
|
||||
nouveau_mem_vram_fini(dev);
|
||||
|
||||
engine->instmem.takedown(dev);
|
||||
nouveau_gpuobj_takedown(dev);
|
||||
nouveau_mem_vram_fini(dev);
|
||||
engine->vram.takedown(dev);
|
||||
|
||||
nouveau_irq_fini(dev);
|
||||
drm_vblank_cleanup(dev);
|
||||
|
|
|
@ -51,9 +51,7 @@ void
|
|||
nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
|
||||
struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
|
||||
struct nouveau_mm *mm = man->priv;
|
||||
struct nouveau_mm *mm = dev_priv->engine.vram.mm;
|
||||
struct nouveau_mm_node *this;
|
||||
struct nouveau_mem *mem;
|
||||
|
||||
|
@ -84,9 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
|
|||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
|
||||
struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
|
||||
struct nouveau_mm *mm = man->priv;
|
||||
struct nouveau_mm *mm = dev_priv->engine.vram.mm;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int comp = (memtype & 0x300) >> 8;
|
||||
|
@ -190,22 +186,35 @@ int
|
|||
nv50_vram_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 rblock, length;
|
||||
|
||||
dev_priv->vram_size = nv_rd32(dev, 0x10020c);
|
||||
dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
|
||||
dev_priv->vram_size &= 0xffffffff00ULL;
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case 0xaa:
|
||||
case 0xac:
|
||||
case 0xaf:
|
||||
/* IGPs, no funky reordering happens here, they don't have VRAM */
|
||||
if (dev_priv->chipset == 0xaa ||
|
||||
dev_priv->chipset == 0xac ||
|
||||
dev_priv->chipset == 0xaf) {
|
||||
dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
|
||||
dev_priv->vram_rblock_size = 4096;
|
||||
break;
|
||||
default:
|
||||
dev_priv->vram_rblock_size = nv50_vram_rblock(dev);
|
||||
break;
|
||||
rblock = 4096 >> 12;
|
||||
} else {
|
||||
rblock = nv50_vram_rblock(dev) >> 12;
|
||||
}
|
||||
|
||||
return 0;
|
||||
length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
|
||||
|
||||
return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_vram_fini(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
|
||||
nouveau_mm_fini(&vram->mm);
|
||||
}
|
||||
|
|
|
@ -61,9 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
|
|||
u32 type, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
|
||||
struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
|
||||
struct nouveau_mm *mm = man->priv;
|
||||
struct nouveau_mm *mm = dev_priv->engine.vram.mm;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int ret;
|
||||
|
@ -105,9 +103,15 @@ int
|
|||
nvc0_vram_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 length;
|
||||
|
||||
dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
|
||||
dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
|
||||
dev_priv->vram_rblock_size = 4096;
|
||||
return 0;
|
||||
|
||||
length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
|
||||
|
||||
return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue