diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-10-07 06:23:24 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-10-07 06:23:24 -0400 |
commit | 02685b1df0461ce4c23d263b66ea0aac66450d13 (patch) | |
tree | bea4402e96bb54b6813971bfb48784bcefb875c6 /drivers/iommu | |
parent | 499f3aa4323775d5320bdf7ccc26576c54a54169 (diff) | |
parent | 1c27df1c0a82b938d8073a60243ff62eff8056b5 (diff) |
Merge branch 'for-joerg/arm-smmu/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into iommu/fixes
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/Kconfig | 3 | ||||
-rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 21 | ||||
-rw-r--r-- | drivers/iommu/io-pgtable-arm.c | 24 |
3 files changed, 29 insertions, 19 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 4664c2a96c67..3dc1bcb0d01d 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -23,8 +23,7 @@ config IOMMU_IO_PGTABLE | |||
23 | config IOMMU_IO_PGTABLE_LPAE | 23 | config IOMMU_IO_PGTABLE_LPAE |
24 | bool "ARMv7/v8 Long Descriptor Format" | 24 | bool "ARMv7/v8 Long Descriptor Format" |
25 | select IOMMU_IO_PGTABLE | 25 | select IOMMU_IO_PGTABLE |
26 | # SWIOTLB guarantees a dma_to_phys() implementation | 26 | depends on HAS_DMA && (ARM || ARM64 || COMPILE_TEST) |
27 | depends on ARM || ARM64 || (COMPILE_TEST && SWIOTLB) | ||
28 | help | 27 | help |
29 | Enable support for the ARM long descriptor pagetable format. | 28 | Enable support for the ARM long descriptor pagetable format. |
30 | This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page | 29 | This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page |
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index dafaf59dc3b8..286e890e7d64 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #define IDR0_TTF_SHIFT 2 | 56 | #define IDR0_TTF_SHIFT 2 |
57 | #define IDR0_TTF_MASK 0x3 | 57 | #define IDR0_TTF_MASK 0x3 |
58 | #define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT) | 58 | #define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT) |
59 | #define IDR0_TTF_AARCH32_64 (3 << IDR0_TTF_SHIFT) | ||
59 | #define IDR0_S1P (1 << 1) | 60 | #define IDR0_S1P (1 << 1) |
60 | #define IDR0_S2P (1 << 0) | 61 | #define IDR0_S2P (1 << 0) |
61 | 62 | ||
@@ -342,7 +343,8 @@ | |||
342 | #define CMDQ_TLBI_0_VMID_SHIFT 32 | 343 | #define CMDQ_TLBI_0_VMID_SHIFT 32 |
343 | #define CMDQ_TLBI_0_ASID_SHIFT 48 | 344 | #define CMDQ_TLBI_0_ASID_SHIFT 48 |
344 | #define CMDQ_TLBI_1_LEAF (1UL << 0) | 345 | #define CMDQ_TLBI_1_LEAF (1UL << 0) |
345 | #define CMDQ_TLBI_1_ADDR_MASK ~0xfffUL | 346 | #define CMDQ_TLBI_1_VA_MASK ~0xfffUL |
347 | #define CMDQ_TLBI_1_IPA_MASK 0xfffffffff000UL | ||
346 | 348 | ||
347 | #define CMDQ_PRI_0_SSID_SHIFT 12 | 349 | #define CMDQ_PRI_0_SSID_SHIFT 12 |
348 | #define CMDQ_PRI_0_SSID_MASK 0xfffffUL | 350 | #define CMDQ_PRI_0_SSID_MASK 0xfffffUL |
@@ -770,11 +772,13 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) | |||
770 | break; | 772 | break; |
771 | case CMDQ_OP_TLBI_NH_VA: | 773 | case CMDQ_OP_TLBI_NH_VA: |
772 | cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT; | 774 | cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT; |
773 | /* Fallthrough */ | 775 | cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0; |
776 | cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK; | ||
777 | break; | ||
774 | case CMDQ_OP_TLBI_S2_IPA: | 778 | case CMDQ_OP_TLBI_S2_IPA: |
775 | cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT; | 779 | cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT; |
776 | cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0; | 780 | cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0; |
777 | cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_ADDR_MASK; | 781 | cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK; |
778 | break; | 782 | break; |
779 | case CMDQ_OP_TLBI_NH_ASID: | 783 | case CMDQ_OP_TLBI_NH_ASID: |
780 | cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT; | 784 | cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT; |
@@ -2460,7 +2464,13 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu) | |||
2460 | } | 2464 | } |
2461 | 2465 | ||
2462 | /* We only support the AArch64 table format at present */ | 2466 | /* We only support the AArch64 table format at present */ |
2463 | if ((reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) < IDR0_TTF_AARCH64) { | 2467 | switch (reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) { |
2468 | case IDR0_TTF_AARCH32_64: | ||
2469 | smmu->ias = 40; | ||
2470 | /* Fallthrough */ | ||
2471 | case IDR0_TTF_AARCH64: | ||
2472 | break; | ||
2473 | default: | ||
2464 | dev_err(smmu->dev, "AArch64 table format not supported!\n"); | 2474 | dev_err(smmu->dev, "AArch64 table format not supported!\n"); |
2465 | return -ENXIO; | 2475 | return -ENXIO; |
2466 | } | 2476 | } |
@@ -2541,8 +2551,7 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu) | |||
2541 | dev_warn(smmu->dev, | 2551 | dev_warn(smmu->dev, |
2542 | "failed to set DMA mask for table walker\n"); | 2552 | "failed to set DMA mask for table walker\n"); |
2543 | 2553 | ||
2544 | if (!smmu->ias) | 2554 | smmu->ias = max(smmu->ias, smmu->oas); |
2545 | smmu->ias = smmu->oas; | ||
2546 | 2555 | ||
2547 | dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n", | 2556 | dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n", |
2548 | smmu->ias, smmu->oas, smmu->features); | 2557 | smmu->ias, smmu->oas, smmu->features); |
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 73c07482f487..7df97777662d 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c | |||
@@ -202,9 +202,9 @@ typedef u64 arm_lpae_iopte; | |||
202 | 202 | ||
203 | static bool selftest_running = false; | 203 | static bool selftest_running = false; |
204 | 204 | ||
205 | static dma_addr_t __arm_lpae_dma_addr(struct device *dev, void *pages) | 205 | static dma_addr_t __arm_lpae_dma_addr(void *pages) |
206 | { | 206 | { |
207 | return phys_to_dma(dev, virt_to_phys(pages)); | 207 | return (dma_addr_t)virt_to_phys(pages); |
208 | } | 208 | } |
209 | 209 | ||
210 | static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp, | 210 | static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp, |
@@ -223,10 +223,10 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp, | |||
223 | goto out_free; | 223 | goto out_free; |
224 | /* | 224 | /* |
225 | * We depend on the IOMMU being able to work with any physical | 225 | * We depend on the IOMMU being able to work with any physical |
226 | * address directly, so if the DMA layer suggests it can't by | 226 | * address directly, so if the DMA layer suggests otherwise by |
227 | * giving us back some translation, that bodes very badly... | 227 | * translating or truncating them, that bodes very badly... |
228 | */ | 228 | */ |
229 | if (dma != __arm_lpae_dma_addr(dev, pages)) | 229 | if (dma != virt_to_phys(pages)) |
230 | goto out_unmap; | 230 | goto out_unmap; |
231 | } | 231 | } |
232 | 232 | ||
@@ -243,10 +243,8 @@ out_free: | |||
243 | static void __arm_lpae_free_pages(void *pages, size_t size, | 243 | static void __arm_lpae_free_pages(void *pages, size_t size, |
244 | struct io_pgtable_cfg *cfg) | 244 | struct io_pgtable_cfg *cfg) |
245 | { | 245 | { |
246 | struct device *dev = cfg->iommu_dev; | ||
247 | |||
248 | if (!selftest_running) | 246 | if (!selftest_running) |
249 | dma_unmap_single(dev, __arm_lpae_dma_addr(dev, pages), | 247 | dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages), |
250 | size, DMA_TO_DEVICE); | 248 | size, DMA_TO_DEVICE); |
251 | free_pages_exact(pages, size); | 249 | free_pages_exact(pages, size); |
252 | } | 250 | } |
@@ -254,12 +252,11 @@ static void __arm_lpae_free_pages(void *pages, size_t size, | |||
254 | static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte, | 252 | static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte, |
255 | struct io_pgtable_cfg *cfg) | 253 | struct io_pgtable_cfg *cfg) |
256 | { | 254 | { |
257 | struct device *dev = cfg->iommu_dev; | ||
258 | |||
259 | *ptep = pte; | 255 | *ptep = pte; |
260 | 256 | ||
261 | if (!selftest_running) | 257 | if (!selftest_running) |
262 | dma_sync_single_for_device(dev, __arm_lpae_dma_addr(dev, ptep), | 258 | dma_sync_single_for_device(cfg->iommu_dev, |
259 | __arm_lpae_dma_addr(ptep), | ||
263 | sizeof(pte), DMA_TO_DEVICE); | 260 | sizeof(pte), DMA_TO_DEVICE); |
264 | } | 261 | } |
265 | 262 | ||
@@ -629,6 +626,11 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg) | |||
629 | if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS) | 626 | if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS) |
630 | return NULL; | 627 | return NULL; |
631 | 628 | ||
629 | if (!selftest_running && cfg->iommu_dev->dma_pfn_offset) { | ||
630 | dev_err(cfg->iommu_dev, "Cannot accommodate DMA offset for IOMMU page tables\n"); | ||
631 | return NULL; | ||
632 | } | ||
633 | |||
632 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 634 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
633 | if (!data) | 635 | if (!data) |
634 | return NULL; | 636 | return NULL; |