aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_ttm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_ttm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c163
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 e729535e9b26..560e816138eb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -24,9 +24,13 @@
24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */ 25 */
26 26
27#include "drmP.h" 27#include <subdev/fb.h>
28#include <subdev/vm.h>
29#include <subdev/instmem.h>
28 30
29#include "nouveau_drv.h" 31#include "nouveau_drm.h"
32#include "nouveau_ttm.h"
33#include "nouveau_gem.h"
30 34
31static int 35static int
32nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) 36nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
@@ -60,11 +64,10 @@ static void
60nouveau_vram_manager_del(struct ttm_mem_type_manager *man, 64nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
61 struct ttm_mem_reg *mem) 65 struct ttm_mem_reg *mem)
62{ 66{
63 struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); 67 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
64 struct drm_device *dev = dev_priv->dev; 68 struct nouveau_fb *pfb = nouveau_fb(drm->device);
65
66 nouveau_mem_node_cleanup(mem->mm_node); 69 nouveau_mem_node_cleanup(mem->mm_node);
67 nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node); 70 pfb->ram.put(pfb, (struct nouveau_mem **)&mem->mm_node);
68} 71}
69 72
70static int 73static int
@@ -73,8 +76,8 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
73 struct ttm_placement *placement, 76 struct ttm_placement *placement,
74 struct ttm_mem_reg *mem) 77 struct ttm_mem_reg *mem)
75{ 78{
76 struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); 79 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
77 struct drm_device *dev = dev_priv->dev; 80 struct nouveau_fb *pfb = nouveau_fb(drm->device);
78 struct nouveau_bo *nvbo = nouveau_bo(bo); 81 struct nouveau_bo *nvbo = nouveau_bo(bo);
79 struct nouveau_mem *node; 82 struct nouveau_mem *node;
80 u32 size_nc = 0; 83 u32 size_nc = 0;
@@ -83,9 +86,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
83 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) 86 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
84 size_nc = 1 << nvbo->page_shift; 87 size_nc = 1 << nvbo->page_shift;
85 88
86 ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT, 89 ret = pfb->ram.get(pfb, mem->num_pages << PAGE_SHIFT,
87 mem->page_alignment << PAGE_SHIFT, size_nc, 90 mem->page_alignment << PAGE_SHIFT, size_nc,
88 (nvbo->tile_flags >> 8) & 0x3ff, &node); 91 (nvbo->tile_flags >> 8) & 0x3ff, &node);
89 if (ret) { 92 if (ret) {
90 mem->mm_node = NULL; 93 mem->mm_node = NULL;
91 return (ret == -ENOSPC) ? 0 : ret; 94 return (ret == -ENOSPC) ? 0 : ret;
@@ -158,11 +161,9 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
158 struct ttm_placement *placement, 161 struct ttm_placement *placement,
159 struct ttm_mem_reg *mem) 162 struct ttm_mem_reg *mem)
160{ 163{
161 struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
162 struct nouveau_mem *node; 164 struct nouveau_mem *node;
163 165
164 if (unlikely((mem->num_pages << PAGE_SHIFT) >= 166 if (unlikely((mem->num_pages << PAGE_SHIFT) >= 512 * 1024 * 1024))
165 dev_priv->gart_info.aper_size))
166 return -ENOMEM; 167 return -ENOMEM;
167 168
168 node = kzalloc(sizeof(*node), GFP_KERNEL); 169 node = kzalloc(sizeof(*node), GFP_KERNEL);
@@ -188,13 +189,17 @@ const struct ttm_mem_type_manager_func nouveau_gart_manager = {
188 nouveau_gart_manager_debug 189 nouveau_gart_manager_debug
189}; 190};
190 191
192#include <core/subdev/vm/nv04.h>
191static int 193static int
192nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) 194nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
193{ 195{
194 struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); 196 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
195 struct drm_device *dev = dev_priv->dev; 197 struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device);
196 man->priv = nv04vm_ref(dev); 198 struct nv04_vmmgr_priv *priv = (void *)vmm;
197 return (man->priv != NULL) ? 0 : -ENODEV; 199 struct nouveau_vm *vm = NULL;
200 nouveau_vm_ref(priv->vm, &vm, NULL);
201 man->priv = vm;
202 return 0;
198} 203}
199 204
200static int 205static int
@@ -260,13 +265,12 @@ int
260nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) 265nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
261{ 266{
262 struct drm_file *file_priv = filp->private_data; 267 struct drm_file *file_priv = filp->private_data;
263 struct drm_nouveau_private *dev_priv = 268 struct nouveau_drm *drm = nouveau_newpriv(file_priv->minor->dev);
264 file_priv->minor->dev->dev_private;
265 269
266 if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) 270 if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
267 return drm_mmap(filp, vma); 271 return drm_mmap(filp, vma);
268 272
269 return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); 273 return ttm_bo_mmap(filp, vma, &drm->ttm.bdev);
270} 274}
271 275
272static int 276static int
@@ -282,12 +286,12 @@ nouveau_ttm_mem_global_release(struct drm_global_reference *ref)
282} 286}
283 287
284int 288int
285nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) 289nouveau_ttm_global_init(struct nouveau_drm *drm)
286{ 290{
287 struct drm_global_reference *global_ref; 291 struct drm_global_reference *global_ref;
288 int ret; 292 int ret;
289 293
290 global_ref = &dev_priv->ttm.mem_global_ref; 294 global_ref = &drm->ttm.mem_global_ref;
291 global_ref->global_type = DRM_GLOBAL_TTM_MEM; 295 global_ref->global_type = DRM_GLOBAL_TTM_MEM;
292 global_ref->size = sizeof(struct ttm_mem_global); 296 global_ref->size = sizeof(struct ttm_mem_global);
293 global_ref->init = &nouveau_ttm_mem_global_init; 297 global_ref->init = &nouveau_ttm_mem_global_init;
@@ -296,12 +300,12 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
296 ret = drm_global_item_ref(global_ref); 300 ret = drm_global_item_ref(global_ref);
297 if (unlikely(ret != 0)) { 301 if (unlikely(ret != 0)) {
298 DRM_ERROR("Failed setting up TTM memory accounting\n"); 302 DRM_ERROR("Failed setting up TTM memory accounting\n");
299 dev_priv->ttm.mem_global_ref.release = NULL; 303 drm->ttm.mem_global_ref.release = NULL;
300 return ret; 304 return ret;
301 } 305 }
302 306
303 dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; 307 drm->ttm.bo_global_ref.mem_glob = global_ref->object;
304 global_ref = &dev_priv->ttm.bo_global_ref.ref; 308 global_ref = &drm->ttm.bo_global_ref.ref;
305 global_ref->global_type = DRM_GLOBAL_TTM_BO; 309 global_ref->global_type = DRM_GLOBAL_TTM_BO;
306 global_ref->size = sizeof(struct ttm_bo_global); 310 global_ref->size = sizeof(struct ttm_bo_global);
307 global_ref->init = &ttm_bo_global_init; 311 global_ref->init = &ttm_bo_global_init;
@@ -310,8 +314,8 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
310 ret = drm_global_item_ref(global_ref); 314 ret = drm_global_item_ref(global_ref);
311 if (unlikely(ret != 0)) { 315 if (unlikely(ret != 0)) {
312 DRM_ERROR("Failed setting up TTM BO subsystem\n"); 316 DRM_ERROR("Failed setting up TTM BO subsystem\n");
313 drm_global_item_unref(&dev_priv->ttm.mem_global_ref); 317 drm_global_item_unref(&drm->ttm.mem_global_ref);
314 dev_priv->ttm.mem_global_ref.release = NULL; 318 drm->ttm.mem_global_ref.release = NULL;
315 return ret; 319 return ret;
316 } 320 }
317 321
@@ -319,12 +323,105 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
319} 323}
320 324
321void 325void
322nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) 326nouveau_ttm_global_release(struct nouveau_drm *drm)
323{ 327{
324 if (dev_priv->ttm.mem_global_ref.release == NULL) 328 if (drm->ttm.mem_global_ref.release == NULL)
325 return; 329 return;
326 330
327 drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); 331 drm_global_item_unref(&drm->ttm.bo_global_ref.ref);
328 drm_global_item_unref(&dev_priv->ttm.mem_global_ref); 332 drm_global_item_unref(&drm->ttm.mem_global_ref);
329 dev_priv->ttm.mem_global_ref.release = NULL; 333 drm->ttm.mem_global_ref.release = NULL;
334}
335
336int
337nouveau_ttm_init(struct nouveau_drm *drm)
338{
339 struct drm_device *dev = drm->dev;
340 u32 bits;
341 int ret;
342
343 if (nv_device(drm->device)->card_type >= NV_50) {
344 if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
345 bits = 40;
346 else
347 bits = 32;
348 } else {
349 bits = 32;
350 }
351
352 ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
353 if (ret)
354 return ret;
355
356 ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
357 if (ret)
358 pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32));
359
360 ret = nouveau_ttm_global_init(drm);
361 if (ret)
362 return ret;
363
364 ret = ttm_bo_device_init(&drm->ttm.bdev,
365 drm->ttm.bo_global_ref.ref.object,
366 &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET,
367 bits <= 32 ? true : false);
368 if (ret) {
369 NV_ERROR(drm, "error initialising bo driver, %d\n", ret);
370 return ret;
371 }
372
373 /* VRAM init */
374 drm->gem.vram_available = nouveau_fb(drm->device)->ram.size;
375 drm->gem.vram_available -= nouveau_instmem(drm->device)->reserved;
376
377 ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM,
378 drm->gem.vram_available >> PAGE_SHIFT);
379 if (ret) {
380 NV_ERROR(drm, "VRAM mm init failed, %d\n", ret);
381 return ret;
382 }
383
384 drm->ttm.mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
385 pci_resource_len(dev->pdev, 1),
386 DRM_MTRR_WC);
387
388 /* GART init */
389 if (drm->agp.stat != ENABLED) {
390 drm->gem.gart_available = nouveau_vmmgr(drm->device)->limit;
391 if (drm->gem.gart_available > 512 * 1024 * 1024)
392 drm->gem.gart_available = 512 * 1024 * 1024;
393 } else {
394 drm->gem.gart_available = drm->agp.size;
395 }
396
397 ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_TT,
398 drm->gem.gart_available >> PAGE_SHIFT);
399 if (ret) {
400 NV_ERROR(drm, "GART mm init failed, %d\n", ret);
401 return ret;
402 }
403
404 NV_INFO(drm, "VRAM: %d MiB\n", (u32)(drm->gem.vram_available >> 20));
405 NV_INFO(drm, "GART: %d MiB\n", (u32)(drm->gem.gart_available >> 20));
406 return 0;
407}
408
409void
410nouveau_ttm_fini(struct nouveau_drm *drm)
411{
412 mutex_lock(&drm->dev->struct_mutex);
413 ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM);
414 ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT);
415 mutex_unlock(&drm->dev->struct_mutex);
416
417 ttm_bo_device_release(&drm->ttm.bdev);
418
419 nouveau_ttm_global_release(drm);
420
421 if (drm->ttm.mtrr >= 0) {
422 drm_mtrr_del(drm->ttm.mtrr,
423 pci_resource_start(drm->dev->pdev, 1),
424 pci_resource_len(drm->dev->pdev, 1), DRM_MTRR_WC);
425 drm->ttm.mtrr = -1;
426 }
330} 427}