diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 296e985d0b65..b67e94e25cfc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -1613,6 +1613,105 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, | |||
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | /** | 1615 | /** |
1616 | * amdgpu_vm_bo_clear_mappings - remove all mappings in a specific range | ||
1617 | * | ||
1618 | * @adev: amdgpu_device pointer | ||
1619 | * @vm: VM structure to use | ||
1620 | * @saddr: start of the range | ||
1621 | * @size: size of the range | ||
1622 | * | ||
1623 | * Remove all mappings in a range, split them as appropriate. | ||
1624 | * Returns 0 for success, error for failure. | ||
1625 | */ | ||
1626 | int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, | ||
1627 | struct amdgpu_vm *vm, | ||
1628 | uint64_t saddr, uint64_t size) | ||
1629 | { | ||
1630 | struct amdgpu_bo_va_mapping *before, *after, *tmp, *next; | ||
1631 | struct interval_tree_node *it; | ||
1632 | LIST_HEAD(removed); | ||
1633 | uint64_t eaddr; | ||
1634 | |||
1635 | eaddr = saddr + size - 1; | ||
1636 | saddr /= AMDGPU_GPU_PAGE_SIZE; | ||
1637 | eaddr /= AMDGPU_GPU_PAGE_SIZE; | ||
1638 | |||
1639 | /* Allocate all the needed memory */ | ||
1640 | before = kzalloc(sizeof(*before), GFP_KERNEL); | ||
1641 | if (!before) | ||
1642 | return -ENOMEM; | ||
1643 | |||
1644 | after = kzalloc(sizeof(*after), GFP_KERNEL); | ||
1645 | if (!after) { | ||
1646 | kfree(before); | ||
1647 | return -ENOMEM; | ||
1648 | } | ||
1649 | |||
1650 | /* Now gather all removed mappings */ | ||
1651 | it = interval_tree_iter_first(&vm->va, saddr, eaddr); | ||
1652 | while (it) { | ||
1653 | tmp = container_of(it, struct amdgpu_bo_va_mapping, it); | ||
1654 | it = interval_tree_iter_next(it, saddr, eaddr); | ||
1655 | |||
1656 | /* Remember mapping split at the start */ | ||
1657 | if (tmp->it.start < saddr) { | ||
1658 | before->it.start = tmp->it.start;; | ||
1659 | before->it.last = saddr - 1; | ||
1660 | before->offset = tmp->offset; | ||
1661 | before->flags = tmp->flags; | ||
1662 | list_add(&before->list, &tmp->list); | ||
1663 | } | ||
1664 | |||
1665 | /* Remember mapping split at the end */ | ||
1666 | if (tmp->it.last > eaddr) { | ||
1667 | after->it.start = eaddr + 1; | ||
1668 | after->it.last = tmp->it.last; | ||
1669 | after->offset = tmp->offset; | ||
1670 | after->offset += after->it.start - tmp->it.start; | ||
1671 | after->flags = tmp->flags; | ||
1672 | list_add(&after->list, &tmp->list); | ||
1673 | } | ||
1674 | |||
1675 | list_del(&tmp->list); | ||
1676 | list_add(&tmp->list, &removed); | ||
1677 | } | ||
1678 | |||
1679 | /* And free them up */ | ||
1680 | list_for_each_entry_safe(tmp, next, &removed, list) { | ||
1681 | interval_tree_remove(&tmp->it, &vm->va); | ||
1682 | list_del(&tmp->list); | ||
1683 | |||
1684 | if (tmp->it.start < saddr) | ||
1685 | tmp->it.start = saddr; | ||
1686 | if (tmp->it.last > eaddr) | ||
1687 | tmp->it.last = eaddr; | ||
1688 | |||
1689 | list_add(&tmp->list, &vm->freed); | ||
1690 | trace_amdgpu_vm_bo_unmap(NULL, tmp); | ||
1691 | } | ||
1692 | |||
1693 | /* Insert partial mapping before the range*/ | ||
1694 | if (before->it.start != before->it.last) { | ||
1695 | interval_tree_insert(&before->it, &vm->va); | ||
1696 | if (before->flags & AMDGPU_PTE_PRT) | ||
1697 | amdgpu_vm_prt_get(adev); | ||
1698 | } else { | ||
1699 | kfree(before); | ||
1700 | } | ||
1701 | |||
1702 | /* Insert partial mapping after the range */ | ||
1703 | if (after->it.start != after->it.last) { | ||
1704 | interval_tree_insert(&after->it, &vm->va); | ||
1705 | if (after->flags & AMDGPU_PTE_PRT) | ||
1706 | amdgpu_vm_prt_get(adev); | ||
1707 | } else { | ||
1708 | kfree(after); | ||
1709 | } | ||
1710 | |||
1711 | return 0; | ||
1712 | } | ||
1713 | |||
1714 | /** | ||
1616 | * amdgpu_vm_bo_rmv - remove a bo to a specific vm | 1715 | * amdgpu_vm_bo_rmv - remove a bo to a specific vm |
1617 | * | 1716 | * |
1618 | * @adev: amdgpu_device pointer | 1717 | * @adev: amdgpu_device pointer |