diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 19:43:27 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 19:43:27 -0500 |
| commit | 2cd83ba5bede2f72cc6c79a19a1bddf576b50e88 (patch) | |
| tree | 6a02f6f93f90f3fea419c3a283ced0543b603fd4 | |
| parent | 670ffccb2f9183eb6cb32fe92257aea52b3f8a7d (diff) | |
| parent | 56f19441da39e5f27824bcbdf3f60980414b5bd0 (diff) | |
Merge tag 'iommu-v4.15-rc1' of git://github.com/awilliam/linux-vfio
Pull IOMMU updates from Alex Williamson:
"As Joerg mentioned[1], he's out on paternity leave through the end of
the year and I'm filling in for him in the interim:
- Enforce MSI multiple IRQ alignment in AMD IOMMU
- VT-d PASID error handling fixes
- Add r8a7795 IPMMU support
- Manage runtime PM links on exynos at {add,remove}_device callbacks
- Fix Mediatek driver name to avoid conflict
- Add terminate support to qcom fault handler
- 64-bit IOVA optimizations
- Simplfy IOVA domain destruction, better use of rcache, and skip
anchor nodes on copy
- Convert to IOMMU TLB sync API in io-pgtable-arm{-v7s}
- Drop command queue lock when waiting for CMD_SYNC completion on ARM
SMMU implementations supporting MSI to cacheable memory
- iomu-vmsa cleanup inspired by missed IOTLB sync callbacks
- Fix sleeping lock with preemption disabled for RT
- Dual MMU support for TI DRA7xx DSPs
- Optional flush option on IOVA allocation avoiding overhead when
caller can try other options
[1] https://lkml.org/lkml/2017/10/22/72"
* tag 'iommu-v4.15-rc1' of git://github.com/awilliam/linux-vfio: (54 commits)
iommu/iova: Use raw_cpu_ptr() instead of get_cpu_ptr() for ->fq
iommu/mediatek: Fix driver name
iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code
iommu/ipmmu-vmsa: Allow two bit SL0
iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
iommu/ipmmu-vmsa: Write IMCTR twice
iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
iommu/ipmmu-vmsa: Enable multi context support
iommu/ipmmu-vmsa: Add optional root device feature
iommu/ipmmu-vmsa: Introduce features, break out alias
iommu/ipmmu-vmsa: Unify ipmmu_ops
iommu/ipmmu-vmsa: Clean up struct ipmmu_vmsa_iommu_priv
iommu/ipmmu-vmsa: Simplify group allocation
iommu/ipmmu-vmsa: Unify domain alloc/free
iommu/ipmmu-vmsa: Fix return value check in ipmmu_find_group_dma()
iommu/vt-d: Clear pasid table entry when memory unbound
iommu/vt-d: Clear Page Request Overflow fault bit
iommu/vt-d: Missing checks for pasid tables if allocation fails
iommu/amd: Limit the IOVA page range to the specified addresses
...
| -rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/host1x/dev.c | 3 | ||||
| -rw-r--r-- | drivers/iommu/amd_iommu.c | 43 | ||||
| -rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 214 | ||||
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 31 | ||||
| -rw-r--r-- | drivers/iommu/dma-iommu.c | 24 | ||||
| -rw-r--r-- | drivers/iommu/dmar.c | 10 | ||||
| -rw-r--r-- | drivers/iommu/exynos-iommu.c | 23 | ||||
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 28 | ||||
| -rw-r--r-- | drivers/iommu/intel-svm.c | 4 | ||||
| -rw-r--r-- | drivers/iommu/io-pgtable-arm-v7s.c | 7 | ||||
| -rw-r--r-- | drivers/iommu/io-pgtable-arm.c | 7 | ||||
| -rw-r--r-- | drivers/iommu/iova.c | 220 | ||||
| -rw-r--r-- | drivers/iommu/ipmmu-vmsa.c | 527 | ||||
| -rw-r--r-- | drivers/iommu/mtk_iommu.c | 7 | ||||
| -rw-r--r-- | drivers/iommu/mtk_iommu_v1.c | 2 | ||||
| -rw-r--r-- | drivers/iommu/omap-iommu.c | 375 | ||||
| -rw-r--r-- | drivers/iommu/omap-iommu.h | 30 | ||||
| -rw-r--r-- | drivers/iommu/qcom_iommu.c | 33 | ||||
| -rw-r--r-- | drivers/misc/mic/scif/scif_rma.c | 3 | ||||
| -rw-r--r-- | include/linux/dmar.h | 1 | ||||
| -rw-r--r-- | include/linux/intel-iommu.h | 1 | ||||
| -rw-r--r-- | include/linux/iova.h | 14 |
23 files changed, 983 insertions, 627 deletions
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 597d563d636a..b822e484b7e5 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -155,8 +155,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
| 155 | 155 | ||
| 156 | order = __ffs(tegra->domain->pgsize_bitmap); | 156 | order = __ffs(tegra->domain->pgsize_bitmap); |
| 157 | init_iova_domain(&tegra->carveout.domain, 1UL << order, | 157 | init_iova_domain(&tegra->carveout.domain, 1UL << order, |
| 158 | carveout_start >> order, | 158 | carveout_start >> order); |
| 159 | carveout_end >> order); | ||
| 160 | 159 | ||
| 161 | tegra->carveout.shift = iova_shift(&tegra->carveout.domain); | 160 | tegra->carveout.shift = iova_shift(&tegra->carveout.domain); |
| 162 | tegra->carveout.limit = carveout_end >> tegra->carveout.shift; | 161 | tegra->carveout.limit = carveout_end >> tegra->carveout.shift; |
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 7f22c5c37660..5267c62e8896 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c | |||
| @@ -198,8 +198,7 @@ static int host1x_probe(struct platform_device *pdev) | |||
| 198 | 198 | ||
| 199 | order = __ffs(host->domain->pgsize_bitmap); | 199 | order = __ffs(host->domain->pgsize_bitmap); |
| 200 | init_iova_domain(&host->iova, 1UL << order, | 200 | init_iova_domain(&host->iova, 1UL << order, |
| 201 | geometry->aperture_start >> order, | 201 | geometry->aperture_start >> order); |
| 202 | geometry->aperture_end >> order); | ||
| 203 | host->iova_end = geometry->aperture_end; | 202 | host->iova_end = geometry->aperture_end; |
| 204 | } | 203 | } |
| 205 | 204 | ||
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 9c848e36f209..7d5eb004091d 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
| @@ -63,7 +63,6 @@ | |||
| 63 | /* IO virtual address start page frame number */ | 63 | /* IO virtual address start page frame number */ |
| 64 | #define IOVA_START_PFN (1) | 64 | #define IOVA_START_PFN (1) |
| 65 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) | 65 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) |
| 66 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) | ||
| 67 | 66 | ||
| 68 | /* Reserved IOVA ranges */ | 67 | /* Reserved IOVA ranges */ |
| 69 | #define MSI_RANGE_START (0xfee00000) | 68 | #define MSI_RANGE_START (0xfee00000) |
| @@ -1547,10 +1546,11 @@ static unsigned long dma_ops_alloc_iova(struct device *dev, | |||
| 1547 | 1546 | ||
| 1548 | if (dma_mask > DMA_BIT_MASK(32)) | 1547 | if (dma_mask > DMA_BIT_MASK(32)) |
| 1549 | pfn = alloc_iova_fast(&dma_dom->iovad, pages, | 1548 | pfn = alloc_iova_fast(&dma_dom->iovad, pages, |
| 1550 | IOVA_PFN(DMA_BIT_MASK(32))); | 1549 | IOVA_PFN(DMA_BIT_MASK(32)), false); |
| 1551 | 1550 | ||
| 1552 | if (!pfn) | 1551 | if (!pfn) |
| 1553 | pfn = alloc_iova_fast(&dma_dom->iovad, pages, IOVA_PFN(dma_mask)); | 1552 | pfn = alloc_iova_fast(&dma_dom->iovad, pages, |
| 1553 | IOVA_PFN(dma_mask), true); | ||
| 1554 | 1554 | ||
| 1555 | return (pfn << PAGE_SHIFT); | 1555 | return (pfn << PAGE_SHIFT); |
| 1556 | } | 1556 | } |
| @@ -1788,8 +1788,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void) | |||
| 1788 | if (!dma_dom->domain.pt_root) | 1788 | if (!dma_dom->domain.pt_root) |
| 1789 | goto free_dma_dom; | 1789 | goto free_dma_dom; |
| 1790 | 1790 | ||
| 1791 | init_iova_domain(&dma_dom->iovad, PAGE_SIZE, | 1791 | init_iova_domain(&dma_dom->iovad, PAGE_SIZE, IOVA_START_PFN); |
| 1792 | IOVA_START_PFN, DMA_32BIT_PFN); | ||
| 1793 | 1792 | ||
| 1794 | if (init_iova_flush_queue(&dma_dom->iovad, iova_domain_flush_tlb, NULL)) | 1793 | if (init_iova_flush_queue(&dma_dom->iovad, iova_domain_flush_tlb, NULL)) |
| 1795 | goto free_dma_dom; | 1794 | goto free_dma_dom; |
| @@ -2383,11 +2382,9 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, | |||
| 2383 | size_t size, | 2382 | size_t size, |
| 2384 | int dir) | 2383 | int dir) |
| 2385 | { | 2384 | { |
| 2386 | dma_addr_t flush_addr; | ||
| 2387 | dma_addr_t i, start; | 2385 | dma_addr_t i, start; |
| 2388 | unsigned int pages; | 2386 | unsigned int pages; |
| 2389 | 2387 | ||
| 2390 | flush_addr = dma_addr; | ||
| 2391 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); | 2388 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); |
| 2392 | dma_addr &= PAGE_MASK; | 2389 | dma_addr &= PAGE_MASK; |
| 2393 | start = dma_addr; | 2390 | start = dma_addr; |
| @@ -2696,8 +2693,7 @@ static int init_reserved_iova_ranges(void) | |||
| 2696 | struct pci_dev *pdev = NULL; | 2693 | struct pci_dev *pdev = NULL; |
| 2697 | struct iova *val; | 2694 | struct iova *val; |
| 2698 | 2695 | ||
| 2699 | init_iova_domain(&reserved_iova_ranges, PAGE_SIZE, | 2696 | init_iova_domain(&reserved_iova_ranges, PAGE_SIZE, IOVA_START_PFN); |
| 2700 | IOVA_START_PFN, DMA_32BIT_PFN); | ||
| 2701 | 2697 | ||
| 2702 | lockdep_set_class(&reserved_iova_ranges.iova_rbtree_lock, | 2698 | lockdep_set_class(&reserved_iova_ranges.iova_rbtree_lock, |
| 2703 | &reserved_rbtree_key); | 2699 | &reserved_rbtree_key); |
| @@ -3155,7 +3151,7 @@ static void amd_iommu_apply_resv_region(struct device *dev, | |||
| 3155 | unsigned long start, end; | 3151 | unsigned long start, end; |
| 3156 | 3152 | ||
| 3157 | start = IOVA_PFN(region->start); | 3153 | start = IOVA_PFN(region->start); |
| 3158 | end = IOVA_PFN(region->start + region->length); | 3154 | end = IOVA_PFN(region->start + region->length - 1); |
| 3159 | 3155 | ||
| 3160 | WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL); | 3156 | WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL); |
| 3161 | } | 3157 | } |
| @@ -3663,11 +3659,11 @@ out_unlock: | |||
| 3663 | return table; | 3659 | return table; |
| 3664 | } | 3660 | } |
| 3665 | 3661 | ||
| 3666 | static int alloc_irq_index(u16 devid, int count) | 3662 | static int alloc_irq_index(u16 devid, int count, bool align) |
| 3667 | { | 3663 | { |
| 3668 | struct irq_remap_table *table; | 3664 | struct irq_remap_table *table; |
| 3665 | int index, c, alignment = 1; | ||
| 3669 | unsigned long flags; | 3666 | unsigned long flags; |
| 3670 | int index, c; | ||
| 3671 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; | 3667 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; |
| 3672 | 3668 | ||
| 3673 | if (!iommu) | 3669 | if (!iommu) |
| @@ -3677,16 +3673,21 @@ static int alloc_irq_index(u16 devid, int count) | |||
| 3677 | if (!table) | 3673 | if (!table) |
| 3678 | return -ENODEV; | 3674 | return -ENODEV; |
| 3679 | 3675 | ||
| 3676 | if (align) | ||
| 3677 | alignment = roundup_pow_of_two(count); | ||
| 3678 | |||
| 3680 | spin_lock_irqsave(&table->lock, flags); | 3679 | spin_lock_irqsave(&table->lock, flags); |
| 3681 | 3680 | ||
| 3682 | /* Scan table for free entries */ | 3681 | /* Scan table for free entries */ |
| 3683 | for (c = 0, index = table->min_index; | 3682 | for (index = ALIGN(table->min_index, alignment), c = 0; |
| 3684 | index < MAX_IRQS_PER_TABLE; | 3683 | index < MAX_IRQS_PER_TABLE;) { |
| 3685 | ++index) { | 3684 | if (!iommu->irte_ops->is_allocated(table, index)) { |
| 3686 | if (!iommu->irte_ops->is_allocated(table, index)) | ||
| 3687 | c += 1; | 3685 | c += 1; |
| 3688 | else | 3686 | } else { |
| 3689 | c = 0; | 3687 | c = 0; |
| 3688 | index = ALIGN(index + 1, alignment); | ||
| 3689 | continue; | ||
| 3690 | } | ||
| 3690 | 3691 | ||
| 3691 | if (c == count) { | 3692 | if (c == count) { |
| 3692 | for (; c != 0; --c) | 3693 | for (; c != 0; --c) |
| @@ -3695,6 +3696,8 @@ static int alloc_irq_index(u16 devid, int count) | |||
| 3695 | index -= count - 1; | 3696 | index -= count - 1; |
| 3696 | goto out; | 3697 | goto out; |
| 3697 | |||
