diff options
Diffstat (limited to 'drivers/staging/media/tegra-vde/iommu.c')
-rw-r--r-- | drivers/staging/media/tegra-vde/iommu.c | 157 |
1 files changed, 0 insertions, 157 deletions
diff --git a/drivers/staging/media/tegra-vde/iommu.c b/drivers/staging/media/tegra-vde/iommu.c deleted file mode 100644 index adf8dc7ee25c..000000000000 --- a/drivers/staging/media/tegra-vde/iommu.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * NVIDIA Tegra Video decoder driver - * - * Copyright (C) 2016-2019 GRATE-DRIVER project - */ - -#include <linux/iommu.h> -#include <linux/iova.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> - -#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) -#include <asm/dma-iommu.h> -#endif - -#include "vde.h" - -int tegra_vde_iommu_map(struct tegra_vde *vde, - struct sg_table *sgt, - struct iova **iovap, - size_t size) -{ - struct iova *iova; - unsigned long shift; - unsigned long end; - dma_addr_t addr; - - end = vde->domain->geometry.aperture_end; - size = iova_align(&vde->iova, size); - shift = iova_shift(&vde->iova); - - iova = alloc_iova(&vde->iova, size >> shift, end >> shift, true); - if (!iova) - return -ENOMEM; - - addr = iova_dma_addr(&vde->iova, iova); - - size = iommu_map_sgtable(vde->domain, addr, sgt, - IOMMU_READ | IOMMU_WRITE); - if (!size) { - __free_iova(&vde->iova, iova); - return -ENXIO; - } - - *iovap = iova; - - return 0; -} - -void tegra_vde_iommu_unmap(struct tegra_vde *vde, struct iova *iova) -{ - unsigned long shift = iova_shift(&vde->iova); - unsigned long size = iova_size(iova) << shift; - dma_addr_t addr = iova_dma_addr(&vde->iova, iova); - - iommu_unmap(vde->domain, addr, size); - __free_iova(&vde->iova, iova); -} - -int tegra_vde_iommu_init(struct tegra_vde *vde) -{ - struct device *dev = vde->miscdev.parent; - struct iova *iova; - unsigned long order; - unsigned long shift; - int err; - - vde->group = iommu_group_get(dev); - if (!vde->group) - return 0; - -#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) - if (dev->archdata.mapping) { - struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); - - arm_iommu_detach_device(dev); - arm_iommu_release_mapping(mapping); - } -#endif - vde->domain = iommu_domain_alloc(&platform_bus_type); - if (!vde->domain) { - err = -ENOMEM; - goto put_group; - } - - err = iova_cache_get(); - if (err) - goto free_domain; - - order = __ffs(vde->domain->pgsize_bitmap); - init_iova_domain(&vde->iova, 1UL << order, 0); - - err = iommu_attach_group(vde->domain, vde->group); - if (err) - goto put_iova; - - /* - * We're using some static addresses that are not accessible by VDE - * to trap invalid memory accesses. - */ - shift = iova_shift(&vde->iova); - iova = reserve_iova(&vde->iova, 0x60000000 >> shift, - 0x70000000 >> shift); - if (!iova) { - err = -ENOMEM; - goto detach_group; - } - - vde->iova_resv_static_addresses = iova; - - /* - * BSEV's end-address wraps around due to integer overflow during - * of hardware context preparation if IOVA is allocated at the end - * of address space and VDE can't handle that. Hence simply reserve - * the last page to avoid the problem. - */ - iova = reserve_iova(&vde->iova, 0xffffffff >> shift, - (0xffffffff >> shift) + 1); - if (!iova) { - err = -ENOMEM; - goto unreserve_iova; - } - - vde->iova_resv_last_page = iova; - - return 0; - -unreserve_iova: - __free_iova(&vde->iova, vde->iova_resv_static_addresses); -detach_group: - iommu_detach_group(vde->domain, vde->group); -put_iova: - put_iova_domain(&vde->iova); - iova_cache_put(); -free_domain: - iommu_domain_free(vde->domain); -put_group: - iommu_group_put(vde->group); - - return err; -} - -void tegra_vde_iommu_deinit(struct tegra_vde *vde) -{ - if (vde->domain) { - __free_iova(&vde->iova, vde->iova_resv_last_page); - __free_iova(&vde->iova, vde->iova_resv_static_addresses); - iommu_detach_group(vde->domain, vde->group); - put_iova_domain(&vde->iova); - iova_cache_put(); - iommu_domain_free(vde->domain); - iommu_group_put(vde->group); - - vde->domain = NULL; - } -} |