diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-07-27 15:29:36 +0300 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2015-08-13 17:06:40 +0300 |
commit | 4b3c7d10765403ab19628fb7d530b8ce1c50b81d (patch) | |
tree | d0dff12de7f9a34aa2b86479cc6d0180b6d7d642 /drivers/iommu/tegra-smmu.c | |
parent | 32924c76b0cbc67aa4cf0741f7bc6c37f097aaf3 (diff) | |
download | linux-4b3c7d10765403ab19628fb7d530b8ce1c50b81d.tar.xz |
iommu/tegra-smmu: Move flush_dcache to tegra-smmu.c
Drivers should not be using __cpuc_* functions nor outer_cache_flush()
directly. This change partly cleans up tegra-smmu.c.
The only difference between cache handling of the tegra variants is
Denver, which omits the call to outer_cache_flush(). This is due to
Denver being an ARM64 CPU, and the ARM64 architecture does not provide
this function. (This, in itself, is a good reason why these should not
be used.)
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
[treding@nvidia.com: fix build failure on 64-bit ARM]
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/iommu/tegra-smmu.c')
-rw-r--r-- | drivers/iommu/tegra-smmu.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index d649b06cc4ca..42b13c07aeef 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -16,6 +16,8 @@ #include <linux/platform_device.h> #include <linux/slab.h> +#include <asm/cacheflush.h> + #include <soc/tegra/ahb.h> #include <soc/tegra/mc.h> @@ -145,6 +147,24 @@ static unsigned int iova_pt_index(unsigned long iova) return (iova >> SMMU_PTE_SHIFT) & (SMMU_NUM_PTE - 1); } +static void smmu_flush_dcache(struct page *page, unsigned long offset, + size_t size) +{ +#ifdef CONFIG_ARM + phys_addr_t phys = page_to_phys(page) + offset; +#endif + void *virt = page_address(page) + offset; + +#ifdef CONFIG_ARM + __cpuc_flush_dcache_area(virt, size); + outer_flush_range(phys, phys + size); +#endif + +#ifdef CONFIG_ARM64 + __flush_dcache_area(virt, size); +#endif +} + static inline void smmu_flush_ptc(struct tegra_smmu *smmu, struct page *page, unsigned long offset) { @@ -392,7 +412,7 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, if (err < 0) return err; - smmu->soc->ops->flush_dcache(as->pd, 0, SMMU_SIZE_PD); + smmu_flush_dcache(as->pd, 0, SMMU_SIZE_PD); smmu_flush_ptc(smmu, as->pd, 0); smmu_flush_tlb_asid(smmu, as->id); @@ -521,11 +541,11 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova, as->pts[pde] = page; - smmu->soc->ops->flush_dcache(page, 0, SMMU_SIZE_PT); + smmu_flush_dcache(page, 0, SMMU_SIZE_PT); pd[pde] = SMMU_MK_PDE(page, SMMU_PDE_ATTR | SMMU_PDE_NEXT); - smmu->soc->ops->flush_dcache(as->pd, pde << 2, 4); + smmu_flush_dcache(as->pd, pde << 2, 4); smmu_flush_ptc(smmu, as->pd, pde << 2); smmu_flush_tlb_section(smmu, as->id, iova); smmu_flush(smmu); @@ -562,7 +582,7 @@ static void tegra_smmu_pte_put_use(struct tegra_smmu_as *as, unsigned long iova) pd[pde] = 0; /* Flush the page directory entry */ - smmu->soc->ops->flush_dcache(as->pd, offset, sizeof(*pd)); + smmu_flush_dcache(as->pd, offset, sizeof(*pd)); smmu_flush_ptc(smmu, as->pd, offset); smmu_flush_tlb_section(smmu, as->id, iova); smmu_flush(smmu); @@ -582,7 +602,7 @@ static void tegra_smmu_set_pte(struct tegra_smmu_as *as, unsigned long iova, *pte = val; - smmu->soc->ops->flush_dcache(pte_page, offset, 4); + smmu_flush_dcache(pte_page, offset, 4); smmu_flush_ptc(smmu, pte_page, offset); smmu_flush_tlb_group(smmu, as->id, iova); smmu_flush(smmu); |