Rev 5271 | Rev 6321 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6104 | ||
---|---|---|---|
Line 329... | Line 329... | ||
329 | bo_va->vm = vm; |
329 | bo_va->vm = vm; |
330 | bo_va->bo = bo; |
330 | bo_va->bo = bo; |
331 | bo_va->it.start = 0; |
331 | bo_va->it.start = 0; |
332 | bo_va->it.last = 0; |
332 | bo_va->it.last = 0; |
333 | bo_va->flags = 0; |
333 | bo_va->flags = 0; |
334 | bo_va->addr = 0; |
- | |
335 | bo_va->ref_count = 1; |
334 | bo_va->ref_count = 1; |
336 | INIT_LIST_HEAD(&bo_va->bo_list); |
335 | INIT_LIST_HEAD(&bo_va->bo_list); |
337 | INIT_LIST_HEAD(&bo_va->vm_status); |
336 | INIT_LIST_HEAD(&bo_va->vm_status); |
Line 338... | Line 337... | ||
338 | 337 | ||
Line 456... | Line 455... | ||
456 | 455 | ||
457 | if (soffset) { |
456 | if (soffset) { |
458 | /* make sure object fit at this offset */ |
457 | /* make sure object fit at this offset */ |
459 | eoffset = soffset + size; |
458 | eoffset = soffset + size; |
460 | if (soffset >= eoffset) { |
459 | if (soffset >= eoffset) { |
- | 460 | r = -EINVAL; |
|
461 | return -EINVAL; |
461 | goto error_unreserve; |
Line 462... | Line 462... | ||
462 | } |
462 | } |
463 | 463 | ||
464 | last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; |
464 | last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; |
465 | if (last_pfn > rdev->vm_manager.max_pfn) { |
465 | if (last_pfn > rdev->vm_manager.max_pfn) { |
466 | dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", |
466 | dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", |
- | 467 | last_pfn, rdev->vm_manager.max_pfn); |
|
467 | last_pfn, rdev->vm_manager.max_pfn); |
468 | r = -EINVAL; |
Line 468... | Line 469... | ||
468 | return -EINVAL; |
469 | goto error_unreserve; |
469 | } |
470 | } |
470 | 471 | ||
Line 471... | Line 472... | ||
471 | } else { |
472 | } else { |
- | 473 | eoffset = last_pfn = 0; |
|
- | 474 | } |
|
- | 475 | ||
- | 476 | mutex_lock(&vm->mutex); |
|
- | 477 | soffset /= RADEON_GPU_PAGE_SIZE; |
|
- | 478 | eoffset /= RADEON_GPU_PAGE_SIZE; |
|
- | 479 | if (soffset || eoffset) { |
|
- | 480 | struct interval_tree_node *it; |
|
- | 481 | it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1); |
|
- | 482 | if (it && it != &bo_va->it) { |
|
- | 483 | struct radeon_bo_va *tmp; |
|
- | 484 | tmp = container_of(it, struct radeon_bo_va, it); |
|
- | 485 | /* bo and tmp overlap, invalid offset */ |
|
- | 486 | dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with " |
|
- | 487 | "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo, |
|
- | 488 | soffset, tmp->bo, tmp->it.start, tmp->it.last); |
|
- | 489 | mutex_unlock(&vm->mutex); |
|
- | 490 | r = -EINVAL; |
|
472 | eoffset = last_pfn = 0; |
491 | goto error_unreserve; |
473 | } |
- | |
474 | 492 | } |
|
475 | mutex_lock(&vm->mutex); |
493 | } |
476 | if (bo_va->it.start || bo_va->it.last) { |
494 | |
477 | if (bo_va->addr) { |
495 | if (bo_va->it.start || bo_va->it.last) { |
478 | /* add a clone of the bo_va to clear the old address */ |
496 | /* add a clone of the bo_va to clear the old address */ |
479 | struct radeon_bo_va *tmp; |
497 | struct radeon_bo_va *tmp; |
- | 498 | tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); |
|
480 | tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); |
499 | if (!tmp) { |
481 | if (!tmp) { |
500 | mutex_unlock(&vm->mutex); |
482 | mutex_unlock(&vm->mutex); |
501 | r = -ENOMEM; |
483 | return -ENOMEM; |
502 | goto error_unreserve; |
484 | } |
- | |
485 | tmp->it.start = bo_va->it.start; |
503 | } |
486 | tmp->it.last = bo_va->it.last; |
- | |
487 | tmp->vm = vm; |
- | |
488 | tmp->addr = bo_va->addr; |
- | |
489 | tmp->bo = radeon_bo_ref(bo_va->bo); |
- | |
Line 490... | Line 504... | ||
490 | spin_lock(&vm->status_lock); |
504 | tmp->it.start = bo_va->it.start; |
- | 505 | tmp->it.last = bo_va->it.last; |
|
491 | list_add(&tmp->vm_status, &vm->freed); |
506 | tmp->vm = vm; |
492 | spin_unlock(&vm->status_lock); |
507 | tmp->bo = radeon_bo_ref(bo_va->bo); |
- | 508 | ||
- | 509 | interval_tree_remove(&bo_va->it, &vm->va); |
|
- | 510 | spin_lock(&vm->status_lock); |
|
493 | } |
511 | bo_va->it.start = 0; |
Line 494... | Line -... | ||
494 | - | ||
495 | interval_tree_remove(&bo_va->it, &vm->va); |
- | |
496 | bo_va->it.start = 0; |
512 | bo_va->it.last = 0; |
497 | bo_va->it.last = 0; |
- | |
498 | } |
- | |
499 | - | ||
500 | soffset /= RADEON_GPU_PAGE_SIZE; |
- | |
501 | eoffset /= RADEON_GPU_PAGE_SIZE; |
- | |
502 | if (soffset || eoffset) { |
- | |
503 | struct interval_tree_node *it; |
- | |
504 | it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1); |
- | |
505 | if (it) { |
- | |
506 | struct radeon_bo_va *tmp; |
513 | list_del_init(&bo_va->vm_status); |
507 | tmp = container_of(it, struct radeon_bo_va, it); |
- | |
508 | /* bo and tmp overlap, invalid offset */ |
- | |
509 | dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with " |
514 | list_add(&tmp->vm_status, &vm->freed); |
510 | "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo, |
515 | spin_unlock(&vm->status_lock); |
- | 516 | } |
|
- | 517 | ||
511 | soffset, tmp->bo, tmp->it.start, tmp->it.last); |
518 | if (soffset || eoffset) { |
512 | mutex_unlock(&vm->mutex); |
519 | spin_lock(&vm->status_lock); |
Line 513... | Line 520... | ||
513 | return -EINVAL; |
520 | bo_va->it.start = soffset; |
514 | } |
- | |
Line 515... | Line 521... | ||
515 | bo_va->it.start = soffset; |
521 | bo_va->it.last = eoffset - 1; |
516 | bo_va->it.last = eoffset - 1; |
522 | list_add(&bo_va->vm_status, &vm->cleared); |
Line 517... | Line 523... | ||
517 | interval_tree_insert(&bo_va->it, &vm->va); |
523 | spin_unlock(&vm->status_lock); |
Line 548... | Line 554... | ||
548 | return r; |
554 | return r; |
Line 549... | Line 555... | ||
549 | 555 | ||
550 | r = radeon_vm_clear_bo(rdev, pt); |
556 | r = radeon_vm_clear_bo(rdev, pt); |
551 | if (r) { |
557 | if (r) { |
552 | radeon_bo_unref(&pt); |
- | |
553 | radeon_bo_reserve(bo_va->bo, false); |
558 | radeon_bo_unref(&pt); |
554 | return r; |
559 | return r; |
Line 555... | Line 560... | ||
555 | } |
560 | } |
556 | 561 | ||
Line 568... | Line 573... | ||
568 | vm->page_tables[pt_idx].bo = pt; |
573 | vm->page_tables[pt_idx].bo = pt; |
569 | } |
574 | } |
Line 570... | Line 575... | ||
570 | 575 | ||
571 | mutex_unlock(&vm->mutex); |
576 | mutex_unlock(&vm->mutex); |
- | 577 | return 0; |
|
- | 578 | ||
- | 579 | error_unreserve: |
|
- | 580 | radeon_bo_unreserve(bo_va->bo); |
|
572 | return 0; |
581 | return r; |
Line 573... | Line 582... | ||
573 | } |
582 | } |
574 | 583 | ||
575 | /** |
584 | /** |
Line 585... | Line 594... | ||
585 | uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr) |
594 | uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr) |
586 | { |
595 | { |
587 | uint64_t result; |
596 | uint64_t result; |
Line 588... | Line 597... | ||
588 | 597 | ||
589 | /* page table offset */ |
598 | /* page table offset */ |
590 | result = rdev->gart.pages_addr[addr >> PAGE_SHIFT]; |
- | |
591 | - | ||
592 | /* in case cpu page size != gpu page size*/ |
599 | result = rdev->gart.pages_entry[addr >> RADEON_GPU_PAGE_SHIFT]; |
Line 593... | Line 600... | ||
593 | result |= addr & (~PAGE_MASK); |
600 | result &= ~RADEON_GPU_PAGE_MASK; |
594 | 601 | ||
Line 595... | Line 602... | ||
595 | return result; |
602 | return result; |
Line 743... | Line 750... | ||
743 | * Userspace can support this by aligning virtual base address and |
750 | * Userspace can support this by aligning virtual base address and |
744 | * allocation size to the fragment size. |
751 | * allocation size to the fragment size. |
745 | */ |
752 | */ |
Line 746... | Line 753... | ||
746 | 753 | ||
747 | /* NI is optimized for 256KB fragments, SI and newer for 64KB */ |
754 | /* NI is optimized for 256KB fragments, SI and newer for 64KB */ |
- | 755 | uint64_t frag_flags = ((rdev->family == CHIP_CAYMAN) || |
|
748 | uint64_t frag_flags = rdev->family == CHIP_CAYMAN ? |
756 | (rdev->family == CHIP_ARUBA)) ? |
749 | R600_PTE_FRAG_256KB : R600_PTE_FRAG_64KB; |
757 | R600_PTE_FRAG_256KB : R600_PTE_FRAG_64KB; |
- | 758 | uint64_t frag_align = ((rdev->family == CHIP_CAYMAN) || |
|
Line 750... | Line 759... | ||
750 | uint64_t frag_align = rdev->family == CHIP_CAYMAN ? 0x200 : 0x80; |
759 | (rdev->family == CHIP_ARUBA)) ? 0x200 : 0x80; |
751 | 760 | ||
Line 752... | Line 761... | ||
752 | uint64_t frag_start = ALIGN(pe_start, frag_align); |
761 | uint64_t frag_start = ALIGN(pe_start, frag_align); |
Line 914... | Line 923... | ||
914 | bo_va->bo, vm); |
923 | bo_va->bo, vm); |
915 | return -EINVAL; |
924 | return -EINVAL; |
916 | } |
925 | } |
Line 917... | Line 926... | ||
917 | 926 | ||
- | 927 | spin_lock(&vm->status_lock); |
|
- | 928 | if (mem) { |
|
- | 929 | if (list_empty(&bo_va->vm_status)) { |
|
- | 930 | spin_unlock(&vm->status_lock); |
|
- | 931 | return 0; |
|
918 | spin_lock(&vm->status_lock); |
932 | } |
- | 933 | list_del_init(&bo_va->vm_status); |
|
- | 934 | } else { |
|
- | 935 | list_del(&bo_va->vm_status); |
|
- | 936 | list_add(&bo_va->vm_status, &vm->cleared); |
|
919 | list_del_init(&bo_va->vm_status); |
937 | } |
Line 920... | Line 938... | ||
920 | spin_unlock(&vm->status_lock); |
938 | spin_unlock(&vm->status_lock); |
921 | 939 | ||
922 | bo_va->flags &= ~RADEON_VM_PAGE_VALID; |
940 | bo_va->flags &= ~RADEON_VM_PAGE_VALID; |
Line 940... | Line 958... | ||
940 | } |
958 | } |
941 | } else { |
959 | } else { |
942 | addr = 0; |
960 | addr = 0; |
943 | } |
961 | } |
Line 944... | Line -... | ||
944 | - | ||
945 | if (addr == bo_va->addr) |
- | |
946 | return 0; |
- | |
947 | bo_va->addr = addr; |
- | |
948 | 962 | ||
Line 949... | Line 963... | ||
949 | trace_radeon_vm_bo_update(bo_va); |
963 | trace_radeon_vm_bo_update(bo_va); |
Line 950... | Line 964... | ||
950 | 964 | ||
Line 1031... | Line 1045... | ||
1031 | */ |
1045 | */ |
1032 | int radeon_vm_clear_freed(struct radeon_device *rdev, |
1046 | int radeon_vm_clear_freed(struct radeon_device *rdev, |
1033 | struct radeon_vm *vm) |
1047 | struct radeon_vm *vm) |
1034 | { |
1048 | { |
1035 | struct radeon_bo_va *bo_va; |
1049 | struct radeon_bo_va *bo_va; |
1036 | int r; |
1050 | int r = 0; |
Line 1037... | Line 1051... | ||
1037 | 1051 | ||
1038 | spin_lock(&vm->status_lock); |
1052 | spin_lock(&vm->status_lock); |
1039 | while (!list_empty(&vm->freed)) { |
1053 | while (!list_empty(&vm->freed)) { |
1040 | bo_va = list_first_entry(&vm->freed, |
1054 | bo_va = list_first_entry(&vm->freed, |
1041 | struct radeon_bo_va, vm_status); |
1055 | struct radeon_bo_va, vm_status); |
Line 1042... | Line 1056... | ||
1042 | spin_unlock(&vm->status_lock); |
1056 | spin_unlock(&vm->status_lock); |
1043 | 1057 | ||
1044 | r = radeon_vm_bo_update(rdev, bo_va, NULL); |
1058 | r = radeon_vm_bo_update(rdev, bo_va, NULL); |
- | 1059 | radeon_bo_unref(&bo_va->bo); |
|
- | 1060 | radeon_fence_unref(&bo_va->last_pt_update); |
|
1045 | radeon_bo_unref(&bo_va->bo); |
1061 | spin_lock(&vm->status_lock); |
1046 | radeon_fence_unref(&bo_va->last_pt_update); |
1062 | list_del(&bo_va->vm_status); |
1047 | kfree(bo_va); |
1063 | kfree(bo_va); |
Line 1048... | Line -... | ||
1048 | if (r) |
- | |
1049 | return r; |
1064 | if (r) |
1050 | 1065 | break; |
|
1051 | spin_lock(&vm->status_lock); |
1066 | |
Line 1052... | Line 1067... | ||
1052 | } |
1067 | } |
Line 1053... | Line 1068... | ||
1053 | spin_unlock(&vm->status_lock); |
1068 | spin_unlock(&vm->status_lock); |
1054 | return 0; |
1069 | return r; |
Line 1105... | Line 1120... | ||
1105 | struct radeon_vm *vm = bo_va->vm; |
1120 | struct radeon_vm *vm = bo_va->vm; |
Line 1106... | Line 1121... | ||
1106 | 1121 | ||
Line 1107... | Line 1122... | ||
1107 | list_del(&bo_va->bo_list); |
1122 | list_del(&bo_va->bo_list); |
- | 1123 | ||
1108 | 1124 | mutex_lock(&vm->mutex); |
|
- | 1125 | if (bo_va->it.start || bo_va->it.last) |
|
1109 | mutex_lock(&vm->mutex); |
1126 | interval_tree_remove(&bo_va->it, &vm->va); |
1110 | interval_tree_remove(&bo_va->it, &vm->va); |
1127 | |
1111 | spin_lock(&vm->status_lock); |
- | |
1112 | list_del(&bo_va->vm_status); |
1128 | spin_lock(&vm->status_lock); |
1113 | 1129 | list_del(&bo_va->vm_status); |
|
1114 | if (bo_va->addr) { |
1130 | if (bo_va->it.start || bo_va->it.last) { |
1115 | bo_va->bo = radeon_bo_ref(bo_va->bo); |
1131 | bo_va->bo = radeon_bo_ref(bo_va->bo); |
1116 | list_add(&bo_va->vm_status, &vm->freed); |
1132 | list_add(&bo_va->vm_status, &vm->freed); |
1117 | } else { |
1133 | } else { |
Line 1136... | Line 1152... | ||
1136 | struct radeon_bo *bo) |
1152 | struct radeon_bo *bo) |
1137 | { |
1153 | { |
1138 | struct radeon_bo_va *bo_va; |
1154 | struct radeon_bo_va *bo_va; |
Line 1139... | Line 1155... | ||
1139 | 1155 | ||
1140 | list_for_each_entry(bo_va, &bo->va, bo_list) { |
- | |
1141 | if (bo_va->addr) { |
1156 | list_for_each_entry(bo_va, &bo->va, bo_list) { |
1142 | spin_lock(&bo_va->vm->status_lock); |
1157 | spin_lock(&bo_va->vm->status_lock); |
- | 1158 | if (list_empty(&bo_va->vm_status) && |
|
1143 | list_del(&bo_va->vm_status); |
1159 | (bo_va->it.start || bo_va->it.last)) |
1144 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); |
1160 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); |
1145 | spin_unlock(&bo_va->vm->status_lock); |
1161 | spin_unlock(&bo_va->vm->status_lock); |
1146 | } |
1162 | } |
1147 | } |
- | |
Line 1148... | Line 1163... | ||
1148 | } |
1163 | } |
1149 | 1164 | ||
1150 | /** |
1165 | /** |
1151 | * radeon_vm_init - initialize a vm instance |
1166 | * radeon_vm_init - initialize a vm instance |
Line 1171... | Line 1186... | ||
1171 | mutex_init(&vm->mutex); |
1186 | mutex_init(&vm->mutex); |
1172 | vm->va = RB_ROOT; |
1187 | vm->va = RB_ROOT; |
1173 | spin_lock_init(&vm->status_lock); |
1188 | spin_lock_init(&vm->status_lock); |
1174 | INIT_LIST_HEAD(&vm->invalidated); |
1189 | INIT_LIST_HEAD(&vm->invalidated); |
1175 | INIT_LIST_HEAD(&vm->freed); |
1190 | INIT_LIST_HEAD(&vm->freed); |
- | 1191 | INIT_LIST_HEAD(&vm->cleared); |
|
Line 1176... | Line 1192... | ||
1176 | 1192 | ||
1177 | pd_size = radeon_vm_directory_size(rdev); |
1193 | pd_size = radeon_vm_directory_size(rdev); |
Line 1178... | Line 1194... | ||
1178 | pd_entries = radeon_vm_num_pdes(rdev); |
1194 | pd_entries = radeon_vm_num_pdes(rdev); |