Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'iommu-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull iommu fixes from Will Deacon:
"Three IOMMU fixes for -rc4.

The main one is a change to the Intel IOMMU driver to fix the handling
of unaligned addresses when invalidating the TLB.

The fix itself is a bit ugly (the caller does a bunch of shifting
which is then effectively undone later in the callchain), but Lu has
patches to clean all of this up in 5.12.

Summary:

- Fix address alignment handling for VT-D TLB invalidation

- Enable workarounds for buggy Qualcomm firmware on two more SoCs

- Drop duplicate #include"

* tag 'iommu-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
iommu/vt-d: Fix duplicate included linux/dma-map-ops.h
iommu: arm-smmu-qcom: Add sdm630/msm8998 compatibles for qcom quirks
iommu/vt-d: Fix unaligned addresses for intel_flush_svm_range_dev()

+22 -3
+2
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
··· 325 325 } 326 326 327 327 static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = { 328 + { .compatible = "qcom,msm8998-smmu-v2" }, 328 329 { .compatible = "qcom,sc7180-smmu-500" }, 330 + { .compatible = "qcom,sdm630-smmu-v2" }, 329 331 { .compatible = "qcom,sdm845-smmu-500" }, 330 332 { .compatible = "qcom,sm8150-smmu-500" }, 331 333 { .compatible = "qcom,sm8250-smmu-500" },
-1
drivers/iommu/intel/iommu.c
··· 38 38 #include <linux/dmi.h> 39 39 #include <linux/pci-ats.h> 40 40 #include <linux/memblock.h> 41 - #include <linux/dma-map-ops.h> 42 41 #include <linux/dma-direct.h> 43 42 #include <linux/crash_dump.h> 44 43 #include <linux/numa.h>
+20 -2
drivers/iommu/intel/svm.c
··· 118 118 iommu->flags |= VTD_FLAG_SVM_CAPABLE; 119 119 } 120 120 121 - static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev, 122 - unsigned long address, unsigned long pages, int ih) 121 + static void __flush_svm_range_dev(struct intel_svm *svm, 122 + struct intel_svm_dev *sdev, 123 + unsigned long address, 124 + unsigned long pages, int ih) 123 125 { 124 126 struct qi_desc desc; 125 127 ··· 169 167 desc.qw2 = 0; 170 168 desc.qw3 = 0; 171 169 qi_submit_sync(sdev->iommu, &desc, 1, 0); 170 + } 171 + } 172 + 173 + static void intel_flush_svm_range_dev(struct intel_svm *svm, 174 + struct intel_svm_dev *sdev, 175 + unsigned long address, 176 + unsigned long pages, int ih) 177 + { 178 + unsigned long shift = ilog2(__roundup_pow_of_two(pages)); 179 + unsigned long align = (1ULL << (VTD_PAGE_SHIFT + shift)); 180 + unsigned long start = ALIGN_DOWN(address, align); 181 + unsigned long end = ALIGN(address + (pages << VTD_PAGE_SHIFT), align); 182 + 183 + while (start < end) { 184 + __flush_svm_range_dev(svm, sdev, start, align >> VTD_PAGE_SHIFT, ih); 185 + start += align; 172 186 } 173 187 } 174 188