From: Ben Skeggs Date: Mon, 6 Dec 2010 05:28:54 +0000 (+1000) Subject: drm/nouveau: kick vram functions out into an "engine" X-Git-Tag: v3.12-rc1~7794^2~37^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=60d2a88ae896ae51c76f8b15c2f4b762d5b00864;p=kernel%2Fkernel-generic.git drm/nouveau: kick vram functions out into an "engine" NVC0 will be able to share some of nv50's paths this way. This also makes it the card-specific vram code responsible for deciding if a given set of tile_flags is valid, rather than duplicating the allowed types in nv50_vram.c and nouveau_gem.c Signed-off-by: Ben Skeggs --- diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 2cd87e6..f8931b2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -501,6 +501,15 @@ struct nouveau_crypt_engine { void (*tlb_flush)(struct drm_device *dev); }; +struct nouveau_vram_engine { + int (*init)(struct drm_device *); + int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, + u32 type, struct nouveau_vram **); + void (*put)(struct drm_device *, struct nouveau_vram **); + + bool (*flags_valid)(struct drm_device *, u32 tile_flags); +}; + struct nouveau_engine { struct nouveau_instmem_engine instmem; struct nouveau_mc_engine mc; @@ -512,6 +521,7 @@ struct nouveau_engine { struct nouveau_gpio_engine gpio; struct nouveau_pm_engine pm; struct nouveau_crypt_engine crypt; + struct nouveau_vram_engine vram; }; struct nouveau_pll_vals { @@ -821,6 +831,8 @@ extern void nouveau_mem_gart_fini(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *); extern int nouveau_mem_reset_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); +extern int nouveau_mem_detect(struct drm_device *); +extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); extern struct nouveau_tile_reg *nv10_mem_set_tiling( struct drm_device *dev, uint32_t addr, uint32_t size, uint32_t pitch, uint32_t flags); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 0adb2a8..506c508 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -103,32 +103,6 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) return 0; } -static bool -nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->card_type >= NV_50) { - switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { - case 0x0000: - case 0x1800: - case 0x2800: - case 0x4800: - case 0x7000: - case 0x7400: - case 0x7a00: - case 0xe000: - return true; - } - } else { - if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) - return true; - } - - NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); - return false; -} - int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -150,8 +124,10 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) flags |= TTM_PL_FLAG_SYSTEM; - if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) + if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { + NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; + } if (req->channel_hint) { chan = nouveau_channel_get(dev, file_priv, req->channel_hint); diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 5a18094..2241811 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -241,7 +241,7 @@ nouveau_mem_detect_nforce(struct drm_device *dev) return 0; } -static int +int nouveau_mem_detect(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -255,26 +255,25 @@ nouveau_mem_detect(struct drm_device *dev) if (dev_priv->card_type < NV_50) { dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - } else - if (dev_priv->card_type < NV_C0) { - if (nv50_vram_init(dev)) - return -ENOMEM; } else { dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; dev_priv->vram_size *= nv_rd32(dev, 0x121c74); } - 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", - dev_priv->vram_sys_base); - } - if (dev_priv->vram_size) return 0; return -ENOMEM; } +bool +nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) +{ + if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) + return true; + + return false; +} + #if __OS_HAS_AGP static unsigned long get_agp_mode(struct drm_device *dev, unsigned long mode) @@ -432,11 +431,16 @@ nouveau_mem_vram_init(struct drm_device *dev) else dev_priv->ramin_rsvd_vram = (512 * 1024); - /* initialise gpu-specific vram backend */ - ret = nouveau_mem_detect(dev); + 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", + dev_priv->vram_sys_base); + } + dev_priv->fb_available_size = dev_priv->vram_size; dev_priv->fb_mappable_pages = dev_priv->fb_available_size; if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) @@ -698,9 +702,10 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; - nv50_vram_del(dev, (struct nouveau_vram **)&mem->mm_node); + vram->put(dev, (struct nouveau_vram **)&mem->mm_node); } static int @@ -710,30 +715,30 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nouveau_vram *vram; + struct nouveau_vram *node; u32 size_nc = 0; int ret; if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->vma.node->type; - ret = nv50_vram_new(dev, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, - (nvbo->tile_flags >> 8) & 0x7f, &vram); + ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, + (nvbo->tile_flags >> 8) & 0xff, &node); if (ret) return ret; - mem->mm_node = vram; - mem->start = vram->offset >> PAGE_SHIFT; + mem->mm_node = node; + mem->start = node->offset >> PAGE_SHIFT; return 0; } void nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) { - struct ttm_bo_global *glob = man->bdev->glob; struct nouveau_mm *mm = man->priv; struct nouveau_mm_node *r; u64 total = 0, ttotal[3] = {}, tused[3] = {}, tfree[3] = {}; diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h index 7e8f8bd..250e642 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mm.h +++ b/drivers/gpu/drm/nouveau/nouveau_mm.h @@ -57,5 +57,6 @@ int nv50_vram_init(struct drm_device *); int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, u32 memtype, struct nouveau_vram **); void nv50_vram_del(struct drm_device *, struct nouveau_vram **); +bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index e0811f9..8eac943 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -100,6 +100,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clock_set = nv04_pm_clock_set; engine->crypt.init = nouveau_stub_init; engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x10: engine->instmem.init = nv04_instmem_init; @@ -157,6 +159,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clock_set = nv04_pm_clock_set; engine->crypt.init = nouveau_stub_init; engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x20: engine->instmem.init = nv04_instmem_init; @@ -214,6 +218,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clock_set = nv04_pm_clock_set; engine->crypt.init = nouveau_stub_init; engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x30: engine->instmem.init = nv04_instmem_init; @@ -273,6 +279,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.voltage_set = nouveau_voltage_gpio_set; engine->crypt.init = nouveau_stub_init; engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x40: case 0x60: @@ -334,6 +342,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv40_temp_get; engine->crypt.init = nouveau_stub_init; engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x50: case 0x80: /* gotta love NVIDIA's consistency.. */ @@ -444,6 +454,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->crypt.takedown = nouveau_stub_takedown; break; } + engine->vram.init = nv50_vram_init; + engine->vram.get = nv50_vram_new; + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nv50_vram_flags_valid; break; case 0xC0: engine->instmem.init = nvc0_instmem_init; @@ -495,6 +509,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->crypt.init = nouveau_stub_init; engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; default: NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index e2efd6f..38f3027 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -312,6 +312,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) { struct drm_device *dev = gpuobj->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node = NULL; int ret; @@ -323,7 +324,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) size = (size + 4095) & ~4095; align = max(align, (u32)4096); - ret = nv50_vram_new(dev, size, align, 0, 0, &node->vram); + ret = vram->get(dev, size, align, 0, 0, &node->vram); if (ret) { kfree(node); return ret; @@ -336,7 +337,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &node->chan_vma); if (ret) { - nv50_vram_del(dev, &node->vram); + vram->put(dev, &node->vram); kfree(node); return ret; } @@ -354,6 +355,8 @@ void nv50_instmem_put(struct nouveau_gpuobj *gpuobj) { struct drm_device *dev = gpuobj->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node; node = gpuobj->node; @@ -363,7 +366,7 @@ nv50_instmem_put(struct nouveau_gpuobj *gpuobj) nouveau_vm_unmap(&node->chan_vma); nouveau_vm_put(&node->chan_vma); } - nv50_vram_del(dev, &node->vram); + vram->put(dev, &node->vram); kfree(node); } diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c index 6e75335..47489ed 100644 --- a/drivers/gpu/drm/nouveau/nv50_vram.c +++ b/drivers/gpu/drm/nouveau/nv50_vram.c @@ -37,6 +37,16 @@ static int types[0x80] = { 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 }; +bool +nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) +{ + int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; + + if (likely(type < sizeof(types) && types[type])) + return true; + return false; +} + void nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) {