From c4e398bbc8aa40b09010bb3b01b167b7936e2549 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Tue, 20 Dec 2016 11:34:04 -0800 Subject: [PATCH] iommu/io-pgtable-arm: Set page table coherency Currently the coherency of an iommu's page table is dictated by the coherency of the iommu device. Support being able to configure iommu page tables as being coherent or not. Change-Id: I311d535b673cc476edb431145bfdb85015361ab7 Signed-off-by: Liam Mark --- drivers/iommu/io-pgtable-arm.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 3f9825a9addb..0d057ca92972 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -290,6 +290,16 @@ static dma_addr_t __arm_lpae_dma_addr(void *pages) return (dma_addr_t)virt_to_phys(pages); } +static inline void pgtable_dma_sync_single_for_device( + struct io_pgtable_cfg *cfg, + dma_addr_t addr, size_t size, + enum dma_data_direction dir) +{ + if (!(cfg->quirks & IO_PGTABLE_QUIRK_PAGE_TABLE_COHERENT)) + dma_sync_single_for_device(cfg->iommu_dev, addr, size, + dir); +} + static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp, struct io_pgtable_cfg *cfg, void *cookie) @@ -340,7 +350,7 @@ static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte, *ptep = pte; if (!selftest_running) - dma_sync_single_for_device(cfg->iommu_dev, + pgtable_dma_sync_single_for_device(cfg, __arm_lpae_dma_addr(ptep), sizeof(pte), DMA_TO_DEVICE); } @@ -415,7 +425,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova, if (lvl == MAP_STATE_LVL) { if (ms->pgtable) - dma_sync_single_for_device(cfg->iommu_dev, + pgtable_dma_sync_single_for_device(cfg, __arm_lpae_dma_addr(ms->pte_start), ms->num_pte * sizeof(*ptep), DMA_TO_DEVICE); @@ -433,7 +443,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova, * mapping. Flush out the previous page mappings. */ if (ms->pgtable) - dma_sync_single_for_device(cfg->iommu_dev, + pgtable_dma_sync_single_for_device(cfg, __arm_lpae_dma_addr(ms->pte_start), ms->num_pte * sizeof(*ptep), DMA_TO_DEVICE); @@ -603,7 +613,7 @@ static int arm_lpae_map_sg(struct io_pgtable_ops *ops, unsigned long iova, } if (ms.pgtable) - dma_sync_single_for_device(cfg->iommu_dev, + pgtable_dma_sync_single_for_device(cfg, __arm_lpae_dma_addr(ms.pte_start), ms.num_pte * sizeof(*ms.pte_start), DMA_TO_DEVICE); @@ -753,7 +763,7 @@ static int __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, table += tl_offset; memset(table, 0, table_len); - dma_sync_single_for_device(cfg->iommu_dev, + pgtable_dma_sync_single_for_device(cfg, __arm_lpae_dma_addr(table), table_len, DMA_TO_DEVICE); @@ -994,7 +1004,7 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) return NULL; /* TCR */ - if (cfg->iommu_dev && cfg->iommu_dev->archdata.dma_coherent) + if (cfg->quirks & IO_PGTABLE_QUIRK_PAGE_TABLE_COHERENT) reg = (ARM_LPAE_TCR_SH_OS << ARM_LPAE_TCR_SH0_SHIFT) | (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) | (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);