diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_ttm.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_ttm.c | 163 |
1 files changed, 130 insertions, 33 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index e729535e9b2..560e816138e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -24,9 +24,13 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" +#include <subdev/fb.h> +#include <subdev/vm.h> +#include <subdev/instmem.h> -#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_ttm.h" +#include "nouveau_gem.h" static int nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) @@ -60,11 +64,10 @@ static void 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 drm_device *dev = dev_priv->dev; - + struct nouveau_drm *drm = nouveau_bdev(man->bdev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); nouveau_mem_node_cleanup(mem->mm_node); - nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); + pfb->ram.put(pfb, (struct nouveau_mem **)&mem->mm_node); } static int @@ -73,8 +76,8 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_placement *placement, struct ttm_mem_reg *mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; + struct nouveau_drm *drm = nouveau_bdev(man->bdev); + struct nouveau_fb *pfb = nouveau_fb(drm->device); struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_mem *node; u32 size_nc = 0; @@ -83,9 +86,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->page_shift; - ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, - (nvbo->tile_flags >> 8) & 0x3ff, &node); + ret = pfb->ram.get(pfb, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, + (nvbo->tile_flags >> 8) & 0x3ff, &node); if (ret) { mem->mm_node = NULL; return (ret == -ENOSPC) ? 0 : ret; @@ -158,11 +161,9 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, struct ttm_placement *placement, struct ttm_mem_reg *mem) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct nouveau_mem *node; - if (unlikely((mem->num_pages << PAGE_SHIFT) >= - dev_priv->gart_info.aper_size)) + if (unlikely((mem->num_pages << PAGE_SHIFT) >= 512 * 1024 * 1024)) return -ENOMEM; node = kzalloc(sizeof(*node), GFP_KERNEL); @@ -188,13 +189,17 @@ const struct ttm_mem_type_manager_func nouveau_gart_manager = { nouveau_gart_manager_debug }; +#include <core/subdev/vm/nv04.h> static int nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct drm_device *dev = dev_priv->dev; - man->priv = nv04vm_ref(dev); - return (man->priv != NULL) ? 0 : -ENODEV; + struct nouveau_drm *drm = nouveau_bdev(man->bdev); + struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device); + struct nv04_vmmgr_priv *priv = (void *)vmm; + struct nouveau_vm *vm = NULL; + nouveau_vm_ref(priv->vm, &vm, NULL); + man->priv = vm; + return 0; } static int @@ -260,13 +265,12 @@ int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; - struct drm_nouveau_private *dev_priv = - file_priv->minor->dev->dev_private; + struct nouveau_drm *drm = nouveau_newpriv(file_priv->minor->dev); if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) return drm_mmap(filp, vma); - return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); + return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); } static int @@ -282,12 +286,12 @@ nouveau_ttm_mem_global_release(struct drm_global_reference *ref) } int -nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) +nouveau_ttm_global_init(struct nouveau_drm *drm) { struct drm_global_reference *global_ref; int ret; - global_ref = &dev_priv->ttm.mem_global_ref; + global_ref = &drm->ttm.mem_global_ref; global_ref->global_type = DRM_GLOBAL_TTM_MEM; global_ref->size = sizeof(struct ttm_mem_global); global_ref->init = &nouveau_ttm_mem_global_init; @@ -296,12 +300,12 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM memory accounting\n"); - dev_priv->ttm.mem_global_ref.release = NULL; + drm->ttm.mem_global_ref.release = NULL; return ret; } - dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; - global_ref = &dev_priv->ttm.bo_global_ref.ref; + drm->ttm.bo_global_ref.mem_glob = global_ref->object; + global_ref = &drm->ttm.bo_global_ref.ref; global_ref->global_type = DRM_GLOBAL_TTM_BO; global_ref->size = sizeof(struct ttm_bo_global); global_ref->init = &ttm_bo_global_init; @@ -310,8 +314,8 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM BO subsystem\n"); - drm_global_item_unref(&dev_priv->ttm.mem_global_ref); - dev_priv->ttm.mem_global_ref.release = NULL; + drm_global_item_unref(&drm->ttm.mem_global_ref); + drm->ttm.mem_global_ref.release = NULL; return ret; } @@ -319,12 +323,105 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) } void -nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) +nouveau_ttm_global_release(struct nouveau_drm *drm) { - if (dev_priv->ttm.mem_global_ref.release == NULL) + if (drm->ttm.mem_global_ref.release == NULL) return; - drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); - drm_global_item_unref(&dev_priv->ttm.mem_global_ref); - dev_priv->ttm.mem_global_ref.release = NULL; + drm_global_item_unref(&drm->ttm.bo_global_ref.ref); + drm_global_item_unref(&drm->ttm.mem_global_ref); + drm->ttm.mem_global_ref.release = NULL; +} + +int +nouveau_ttm_init(struct nouveau_drm *drm) +{ + struct drm_device *dev = drm->dev; + u32 bits; + int ret; + + if (nv_device(drm->device)->card_type >= NV_50) { + if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) + bits = 40; + else + bits = 32; + } else { + bits = 32; + } + + ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); + if (ret) + return ret; + + ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); + if (ret) + pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); + + ret = nouveau_ttm_global_init(drm); + if (ret) + return ret; + + ret = ttm_bo_device_init(&drm->ttm.bdev, + drm->ttm.bo_global_ref.ref.object, + &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET, + bits <= 32 ? true : false); + if (ret) { + NV_ERROR(drm, "error initialising bo driver, %d\n", ret); + return ret; + } + + /* VRAM init */ + drm->gem.vram_available = nouveau_fb(drm->device)->ram.size; + drm->gem.vram_available -= nouveau_instmem(drm->device)->reserved; + + ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM, + drm->gem.vram_available >> PAGE_SHIFT); + if (ret) { + NV_ERROR(drm, "VRAM mm init failed, %d\n", ret); + return ret; + } + + drm->ttm.mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), + pci_resource_len(dev->pdev, 1), + DRM_MTRR_WC); + + /* GART init */ + if (drm->agp.stat != ENABLED) { + drm->gem.gart_available = nouveau_vmmgr(drm->device)->limit; + if (drm->gem.gart_available > 512 * 1024 * 1024) + drm->gem.gart_available = 512 * 1024 * 1024; + } else { + drm->gem.gart_available = drm->agp.size; + } + + ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_TT, + drm->gem.gart_available >> PAGE_SHIFT); + if (ret) { + NV_ERROR(drm, "GART mm init failed, %d\n", ret); + return ret; + } + + NV_INFO(drm, "VRAM: %d MiB\n", (u32)(drm->gem.vram_available >> 20)); + NV_INFO(drm, "GART: %d MiB\n", (u32)(drm->gem.gart_available >> 20)); + return 0; +} + +void +nouveau_ttm_fini(struct nouveau_drm *drm) +{ + mutex_lock(&drm->dev->struct_mutex); + ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM); + ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT); + mutex_unlock(&drm->dev->struct_mutex); + + ttm_bo_device_release(&drm->ttm.bdev); + + nouveau_ttm_global_release(drm); + + if (drm->ttm.mtrr >= 0) { + drm_mtrr_del(drm->ttm.mtrr, + pci_resource_start(drm->dev->pdev, 1), + pci_resource_len(drm->dev->pdev, 1), DRM_MTRR_WC); + drm->ttm.mtrr = -1; + } } |