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 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 | ||
31 | static int | 35 | static int |
32 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | 36 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) |
@@ -60,11 +64,10 @@ static void | |||
60 | nouveau_vram_manager_del(struct ttm_mem_type_manager *man, | 64 | nouveau_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 | ||
70 | static int | 73 | static 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> | ||
191 | static int | 193 | static int |
192 | nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | 194 | nv04_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 | ||
200 | static int | 205 | static int |
@@ -260,13 +265,12 @@ int | |||
260 | nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) | 265 | nouveau_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 | ||
272 | static int | 276 | static int |
@@ -282,12 +286,12 @@ nouveau_ttm_mem_global_release(struct drm_global_reference *ref) | |||
282 | } | 286 | } |
283 | 287 | ||
284 | int | 288 | int |
285 | nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) | 289 | nouveau_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 | ||
321 | void | 325 | void |
322 | nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) | 326 | nouveau_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 | |||
336 | int | ||
337 | nouveau_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 | |||
409 | void | ||
410 | nouveau_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 | } |