diff options
author | Alex Waterman <alexw@nvidia.com> | 2017-09-07 19:45:07 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-10-18 19:00:37 -0400 |
commit | 0853109c9994d1375a10d13ae254690a4a4c9610 (patch) | |
tree | 339adb7e8e74c8e0085b24ed9e50181a9aafa3ee /drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |
parent | b3446bc0b6fca6cb992667f80a95f8503b6a652a (diff) |
gpu: nvgpu: Refactoring nvgpu_vm functions
Refactor the last nvgpu_vm functions from the mm_gk20a.c code. This
removes some usages of dma_buf from the mm_gk20a.c code, too, which
helps make mm_gk20a.c less Linux specific.
Also delete some header files that are no longer necessary in
gk20a/mm_gk20a.c which are Linux specific. The mm_gk20a.c code is now
quite close to being Linux free.
JIRA NVGPU-30
JIRA NVGPU-138
Change-Id: I72b370bd85a7b029768b0fb4827d6abba42007c3
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1566629
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 348 |
1 files changed, 0 insertions, 348 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 69d9e983..687951a9 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -22,11 +22,6 @@ | |||
22 | * DEALINGS IN THE SOFTWARE. | 22 | * DEALINGS IN THE SOFTWARE. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/dma-buf.h> | ||
26 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/dma-attrs.h> | ||
28 | #include <linux/lcm.h> | ||
29 | #include <uapi/linux/nvgpu.h> | ||
30 | #include <trace/events/gk20a.h> | 25 | #include <trace/events/gk20a.h> |
31 | 26 | ||
32 | #include <nvgpu/vm.h> | 27 | #include <nvgpu/vm.h> |
@@ -46,8 +41,6 @@ | |||
46 | #include <nvgpu/enabled.h> | 41 | #include <nvgpu/enabled.h> |
47 | #include <nvgpu/vidmem.h> | 42 | #include <nvgpu/vidmem.h> |
48 | 43 | ||
49 | #include <nvgpu/linux/dma.h> | ||
50 | |||
51 | #include "gk20a.h" | 44 | #include "gk20a.h" |
52 | #include "platform_gk20a.h" | 45 | #include "platform_gk20a.h" |
53 | #include "mm_gk20a.h" | 46 | #include "mm_gk20a.h" |
@@ -65,13 +58,6 @@ | |||
65 | #include <nvgpu/hw/gk20a/hw_ltc_gk20a.h> | 58 | #include <nvgpu/hw/gk20a/hw_ltc_gk20a.h> |
66 | 59 | ||
67 | /* | 60 | /* |
68 | * Necessary while transitioning to less coupled code. Will be removed once | ||
69 | * all the common APIs no longers have Linux stuff in them. | ||
70 | */ | ||
71 | #include "common/linux/vm_priv.h" | ||
72 | #include "common/linux/dmabuf.h" | ||
73 | |||
74 | /* | ||
75 | * GPU mapping life cycle | 61 | * GPU mapping life cycle |
76 | * ====================== | 62 | * ====================== |
77 | * | 63 | * |
@@ -330,209 +316,6 @@ int gk20a_mm_pde_coverage_bit_count(struct vm_gk20a *vm) | |||
330 | return vm->mmu_levels[0].lo_bit[0]; | 316 | return vm->mmu_levels[0].lo_bit[0]; |
331 | } | 317 | } |
332 | 318 | ||
333 | int nvgpu_vm_get_buffers(struct vm_gk20a *vm, | ||
334 | struct nvgpu_mapped_buf ***mapped_buffers, | ||
335 | int *num_buffers) | ||
336 | { | ||
337 | struct nvgpu_mapped_buf *mapped_buffer; | ||
338 | struct nvgpu_mapped_buf **buffer_list; | ||
339 | struct nvgpu_rbtree_node *node = NULL; | ||
340 | int i = 0; | ||
341 | |||
342 | if (vm->userspace_managed) { | ||
343 | *mapped_buffers = NULL; | ||
344 | *num_buffers = 0; | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | nvgpu_mutex_acquire(&vm->update_gmmu_lock); | ||
349 | |||
350 | buffer_list = nvgpu_big_zalloc(vm->mm->g, sizeof(*buffer_list) * | ||
351 | vm->num_user_mapped_buffers); | ||
352 | if (!buffer_list) { | ||
353 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
354 | return -ENOMEM; | ||
355 | } | ||
356 | |||
357 | nvgpu_rbtree_enum_start(0, &node, vm->mapped_buffers); | ||
358 | while (node) { | ||
359 | mapped_buffer = mapped_buffer_from_rbtree_node(node); | ||
360 | if (mapped_buffer->user_mapped) { | ||
361 | buffer_list[i] = mapped_buffer; | ||
362 | nvgpu_ref_get(&mapped_buffer->ref); | ||
363 | i++; | ||
364 | } | ||
365 | nvgpu_rbtree_enum_next(&node, node); | ||
366 | } | ||
367 | |||
368 | BUG_ON(i != vm->num_user_mapped_buffers); | ||
369 | |||
370 | *num_buffers = vm->num_user_mapped_buffers; | ||
371 | *mapped_buffers = buffer_list; | ||
372 | |||
373 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | void gk20a_vm_unmap_locked_ref(struct nvgpu_ref *ref) | ||
379 | { | ||
380 | struct nvgpu_mapped_buf *mapped_buffer = | ||
381 | container_of(ref, struct nvgpu_mapped_buf, ref); | ||
382 | nvgpu_vm_unmap_locked(mapped_buffer, mapped_buffer->vm->kref_put_batch); | ||
383 | } | ||
384 | |||
385 | void nvgpu_vm_put_buffers(struct vm_gk20a *vm, | ||
386 | struct nvgpu_mapped_buf **mapped_buffers, | ||
387 | int num_buffers) | ||
388 | { | ||
389 | int i; | ||
390 | struct vm_gk20a_mapping_batch batch; | ||
391 | |||
392 | if (num_buffers == 0) | ||
393 | return; | ||
394 | |||
395 | nvgpu_mutex_acquire(&vm->update_gmmu_lock); | ||
396 | nvgpu_vm_mapping_batch_start(&batch); | ||
397 | vm->kref_put_batch = &batch; | ||
398 | |||
399 | for (i = 0; i < num_buffers; ++i) | ||
400 | nvgpu_ref_put(&mapped_buffers[i]->ref, | ||
401 | gk20a_vm_unmap_locked_ref); | ||
402 | |||
403 | vm->kref_put_batch = NULL; | ||
404 | nvgpu_vm_mapping_batch_finish_locked(vm, &batch); | ||
405 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
406 | |||
407 | nvgpu_big_free(vm->mm->g, mapped_buffers); | ||
408 | } | ||
409 | |||
410 | static void nvgpu_vm_unmap_user(struct vm_gk20a *vm, u64 offset, | ||
411 | struct vm_gk20a_mapping_batch *batch) | ||
412 | { | ||
413 | struct gk20a *g = vm->mm->g; | ||
414 | struct nvgpu_mapped_buf *mapped_buffer; | ||
415 | |||
416 | nvgpu_mutex_acquire(&vm->update_gmmu_lock); | ||
417 | |||
418 | mapped_buffer = __nvgpu_vm_find_mapped_buf(vm, offset); | ||
419 | if (!mapped_buffer) { | ||
420 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
421 | nvgpu_err(g, "invalid addr to unmap 0x%llx", offset); | ||
422 | return; | ||
423 | } | ||
424 | |||
425 | if (mapped_buffer->flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) { | ||
426 | struct nvgpu_timeout timeout; | ||
427 | |||
428 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
429 | |||
430 | nvgpu_timeout_init(vm->mm->g, &timeout, 10000, | ||
431 | NVGPU_TIMER_RETRY_TIMER); | ||
432 | do { | ||
433 | if (nvgpu_atomic_read( | ||
434 | &mapped_buffer->ref.refcount) == 1) | ||
435 | break; | ||
436 | nvgpu_udelay(5); | ||
437 | } while (!nvgpu_timeout_expired_msg(&timeout, | ||
438 | "sync-unmap failed on 0x%llx")); | ||
439 | |||
440 | nvgpu_mutex_acquire(&vm->update_gmmu_lock); | ||
441 | } | ||
442 | |||
443 | if (mapped_buffer->user_mapped == 0) { | ||
444 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
445 | nvgpu_err(g, "addr already unmapped from user 0x%llx", offset); | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | mapped_buffer->user_mapped--; | ||
450 | if (mapped_buffer->user_mapped == 0) | ||
451 | vm->num_user_mapped_buffers--; | ||
452 | |||
453 | vm->kref_put_batch = batch; | ||
454 | nvgpu_ref_put(&mapped_buffer->ref, gk20a_vm_unmap_locked_ref); | ||
455 | vm->kref_put_batch = NULL; | ||
456 | |||
457 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
458 | } | ||
459 | |||
460 | static int setup_kind_legacy(struct vm_gk20a *vm, struct buffer_attrs *bfr, | ||
461 | bool *pkind_compressible) | ||
462 | { | ||
463 | struct gk20a *g = gk20a_from_vm(vm); | ||
464 | bool kind_compressible; | ||
465 | |||
466 | if (unlikely(bfr->kind_v == gmmu_pte_kind_invalid_v())) | ||
467 | bfr->kind_v = gmmu_pte_kind_pitch_v(); | ||
468 | |||
469 | if (unlikely(!gk20a_kind_is_supported(bfr->kind_v))) { | ||
470 | nvgpu_err(g, "kind 0x%x not supported", bfr->kind_v); | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | bfr->uc_kind_v = gmmu_pte_kind_invalid_v(); | ||
475 | /* find a suitable incompressible kind if it becomes necessary later */ | ||
476 | kind_compressible = gk20a_kind_is_compressible(bfr->kind_v); | ||
477 | if (kind_compressible) { | ||
478 | bfr->uc_kind_v = gk20a_get_uncompressed_kind(bfr->kind_v); | ||
479 | if (unlikely(bfr->uc_kind_v == gmmu_pte_kind_invalid_v())) { | ||
480 | /* shouldn't happen, but it is worth cross-checking */ | ||
481 | nvgpu_err(g, "comptag kind 0x%x can't be" | ||
482 | " downgraded to uncompressed kind", | ||
483 | bfr->kind_v); | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | *pkind_compressible = kind_compressible; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | int setup_buffer_kind_and_compression(struct vm_gk20a *vm, | ||
493 | u32 flags, | ||
494 | struct buffer_attrs *bfr, | ||
495 | enum gmmu_pgsz_gk20a pgsz_idx) | ||
496 | { | ||
497 | bool kind_compressible; | ||
498 | struct gk20a *g = gk20a_from_vm(vm); | ||
499 | int ctag_granularity = g->ops.fb.compression_page_size(g); | ||
500 | |||
501 | if (!bfr->use_kind_v) | ||
502 | bfr->kind_v = gmmu_pte_kind_invalid_v(); | ||
503 | if (!bfr->use_uc_kind_v) | ||
504 | bfr->uc_kind_v = gmmu_pte_kind_invalid_v(); | ||
505 | |||
506 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { | ||
507 | kind_compressible = (bfr->kind_v != gmmu_pte_kind_invalid_v()); | ||
508 | if (!kind_compressible) | ||
509 | bfr->kind_v = bfr->uc_kind_v; | ||
510 | } else { | ||
511 | int err = setup_kind_legacy(vm, bfr, &kind_compressible); | ||
512 | |||
513 | if (err) | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | /* comptags only supported for suitable kinds, 128KB pagesize */ | ||
518 | if (kind_compressible && | ||
519 | vm->gmmu_page_sizes[pgsz_idx] < g->ops.fb.compressible_page_size(g)) { | ||
520 | /* it is safe to fall back to uncompressed as | ||
521 | functionality is not harmed */ | ||
522 | bfr->kind_v = bfr->uc_kind_v; | ||
523 | kind_compressible = false; | ||
524 | } | ||
525 | if (kind_compressible) | ||
526 | bfr->ctag_lines = DIV_ROUND_UP_ULL(bfr->size, ctag_granularity); | ||
527 | else | ||
528 | bfr->ctag_lines = 0; | ||
529 | |||
530 | bfr->use_kind_v = (bfr->kind_v != gmmu_pte_kind_invalid_v()); | ||
531 | bfr->use_uc_kind_v = (bfr->uc_kind_v != gmmu_pte_kind_invalid_v()); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | /* for gk20a the "video memory" apertures here are misnomers. */ | 319 | /* for gk20a the "video memory" apertures here are misnomers. */ |
537 | static inline u32 big_valid_pde0_bits(struct gk20a *g, | 320 | static inline u32 big_valid_pde0_bits(struct gk20a *g, |
538 | struct nvgpu_gmmu_pd *pd, u64 addr) | 321 | struct nvgpu_gmmu_pd *pd, u64 addr) |
@@ -698,43 +481,6 @@ static void update_gmmu_pte_locked(struct vm_gk20a *vm, | |||
698 | pd_write(g, pd, pd_offset + 1, pte_w[1]); | 481 | pd_write(g, pd, pd_offset + 1, pte_w[1]); |
699 | } | 482 | } |
700 | 483 | ||
701 | /* NOTE! mapped_buffers lock must be held */ | ||
702 | void nvgpu_vm_unmap_locked(struct nvgpu_mapped_buf *mapped_buffer, | ||
703 | struct vm_gk20a_mapping_batch *batch) | ||
704 | { | ||
705 | struct vm_gk20a *vm = mapped_buffer->vm; | ||
706 | struct gk20a *g = vm->mm->g; | ||
707 | |||
708 | g->ops.mm.gmmu_unmap(vm, | ||
709 | mapped_buffer->addr, | ||
710 | mapped_buffer->size, | ||
711 | mapped_buffer->pgsz_idx, | ||
712 | mapped_buffer->va_allocated, | ||
713 | gk20a_mem_flag_none, | ||
714 | mapped_buffer->vm_area ? | ||
715 | mapped_buffer->vm_area->sparse : false, | ||
716 | batch); | ||
717 | |||
718 | gk20a_mm_unpin(dev_from_vm(vm), mapped_buffer->dmabuf, | ||
719 | mapped_buffer->sgt); | ||
720 | |||
721 | /* remove from mapped buffer tree and remove list, free */ | ||
722 | nvgpu_remove_mapped_buf(vm, mapped_buffer); | ||
723 | if (!nvgpu_list_empty(&mapped_buffer->buffer_list)) | ||
724 | nvgpu_list_del(&mapped_buffer->buffer_list); | ||
725 | |||
726 | /* keep track of mapped buffers */ | ||
727 | if (mapped_buffer->user_mapped) | ||
728 | vm->num_user_mapped_buffers--; | ||
729 | |||
730 | if (mapped_buffer->own_mem_ref) | ||
731 | dma_buf_put(mapped_buffer->dmabuf); | ||
732 | |||
733 | nvgpu_kfree(g, mapped_buffer); | ||
734 | |||
735 | return; | ||
736 | } | ||
737 | |||
738 | const struct gk20a_mmu_level gk20a_mm_levels_64k[] = { | 484 | const struct gk20a_mmu_level gk20a_mm_levels_64k[] = { |
739 | {.hi_bit = {NV_GMMU_VA_RANGE-1, NV_GMMU_VA_RANGE-1}, | 485 | {.hi_bit = {NV_GMMU_VA_RANGE-1, NV_GMMU_VA_RANGE-1}, |
740 | .lo_bit = {26, 26}, | 486 | .lo_bit = {26, 26}, |
@@ -853,76 +599,6 @@ int gk20a_vm_bind_channel(struct gk20a_as_share *as_share, | |||
853 | return __gk20a_vm_bind_channel(as_share->vm, ch); | 599 | return __gk20a_vm_bind_channel(as_share->vm, ch); |
854 | } | 600 | } |
855 | 601 | ||
856 | int nvgpu_vm_map_buffer(struct vm_gk20a *vm, | ||
857 | int dmabuf_fd, | ||
858 | u64 *offset_align, | ||
859 | u32 flags, /*NVGPU_AS_MAP_BUFFER_FLAGS_*/ | ||
860 | s16 compr_kind, | ||
861 | s16 incompr_kind, | ||
862 | u64 buffer_offset, | ||
863 | u64 mapping_size, | ||
864 | struct vm_gk20a_mapping_batch *batch) | ||
865 | { | ||
866 | int err = 0; | ||
867 | struct dma_buf *dmabuf; | ||
868 | u64 ret_va; | ||
869 | |||
870 | gk20a_dbg_fn(""); | ||
871 | |||
872 | /* get ref to the mem handle (released on unmap_locked) */ | ||
873 | dmabuf = dma_buf_get(dmabuf_fd); | ||
874 | if (IS_ERR(dmabuf)) { | ||
875 | nvgpu_warn(gk20a_from_vm(vm), "%s: fd %d is not a dmabuf", | ||
876 | __func__, dmabuf_fd); | ||
877 | return PTR_ERR(dmabuf); | ||
878 | } | ||
879 | |||
880 | /* verify that we're not overflowing the buffer, i.e. | ||
881 | * (buffer_offset + mapping_size)> dmabuf->size. | ||
882 | * | ||
883 | * Since buffer_offset + mapping_size could overflow, first check | ||
884 | * that mapping size < dmabuf_size, at which point we can subtract | ||
885 | * mapping_size from both sides for the final comparison. | ||
886 | */ | ||
887 | if ((mapping_size > dmabuf->size) || | ||
888 | (buffer_offset > (dmabuf->size - mapping_size))) { | ||
889 | nvgpu_err(gk20a_from_vm(vm), | ||
890 | "buf size %llx < (offset(%llx) + map_size(%llx))\n", | ||
891 | (u64)dmabuf->size, buffer_offset, mapping_size); | ||
892 | return -EINVAL; | ||
893 | } | ||
894 | |||
895 | err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev_from_vm(vm)); | ||
896 | if (err) { | ||
897 | dma_buf_put(dmabuf); | ||
898 | return err; | ||
899 | } | ||
900 | |||
901 | ret_va = nvgpu_vm_map(vm, dmabuf, *offset_align, | ||
902 | flags, compr_kind, incompr_kind, true, | ||
903 | gk20a_mem_flag_none, | ||
904 | buffer_offset, | ||
905 | mapping_size, | ||
906 | batch); | ||
907 | |||
908 | *offset_align = ret_va; | ||
909 | if (!ret_va) { | ||
910 | dma_buf_put(dmabuf); | ||
911 | err = -EINVAL; | ||
912 | } | ||
913 | |||
914 | return err; | ||
915 | } | ||
916 | |||
917 | int nvgpu_vm_unmap_buffer(struct vm_gk20a *vm, u64 offset, | ||
918 | struct vm_gk20a_mapping_batch *batch) | ||
919 | { | ||
920 | gk20a_dbg_fn(""); | ||
921 | |||
922 | nvgpu_vm_unmap_user(vm, offset, batch); | ||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | int gk20a_alloc_inst_block(struct gk20a *g, struct nvgpu_mem *inst_block) | 602 | int gk20a_alloc_inst_block(struct gk20a *g, struct nvgpu_mem *inst_block) |
927 | { | 603 | { |
928 | int err; | 604 | int err; |
@@ -1298,30 +974,6 @@ hw_was_off: | |||
1298 | gk20a_idle_nosuspend(g); | 974 | gk20a_idle_nosuspend(g); |
1299 | } | 975 | } |
1300 | 976 | ||
1301 | int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, | ||
1302 | struct dma_buf **dmabuf, | ||
1303 | u64 *offset) | ||
1304 | { | ||
1305 | struct nvgpu_mapped_buf *mapped_buffer; | ||
1306 | |||
1307 | gk20a_dbg_fn("gpu_va=0x%llx", gpu_va); | ||
1308 | |||
1309 | nvgpu_mutex_acquire(&vm->update_gmmu_lock); | ||
1310 | |||
1311 | mapped_buffer = __nvgpu_vm_find_mapped_buf_range(vm, gpu_va); | ||
1312 | if (!mapped_buffer) { | ||
1313 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
1314 | return -EINVAL; | ||
1315 | } | ||
1316 | |||
1317 | *dmabuf = mapped_buffer->dmabuf; | ||
1318 | *offset = gpu_va - mapped_buffer->addr; | ||
1319 | |||
1320 | nvgpu_mutex_release(&vm->update_gmmu_lock); | ||
1321 | |||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | int gk20a_mm_suspend(struct gk20a *g) | 977 | int gk20a_mm_suspend(struct gk20a *g) |
1326 | { | 978 | { |
1327 | gk20a_dbg_fn(""); | 979 | gk20a_dbg_fn(""); |