Commit 7aec71cd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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()
parents 02c06dc3 694a1c0a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -325,7 +325,9 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
}

static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = {
	{ .compatible = "qcom,msm8998-smmu-v2" },
	{ .compatible = "qcom,sc7180-smmu-500" },
	{ .compatible = "qcom,sdm630-smmu-v2" },
	{ .compatible = "qcom,sdm845-smmu-500" },
	{ .compatible = "qcom,sm8150-smmu-500" },
	{ .compatible = "qcom,sm8250-smmu-500" },
+0 −1
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@
#include <linux/dmi.h>
#include <linux/pci-ats.h>
#include <linux/memblock.h>
#include <linux/dma-map-ops.h>
#include <linux/dma-direct.h>
#include <linux/crash_dump.h>
#include <linux/numa.h>
+20 −2
Original line number Diff line number Diff line
@@ -118,8 +118,10 @@ void intel_svm_check(struct intel_iommu *iommu)
	iommu->flags |= VTD_FLAG_SVM_CAPABLE;
}

static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev,
				unsigned long address, unsigned long pages, int ih)
static void __flush_svm_range_dev(struct intel_svm *svm,
				  struct intel_svm_dev *sdev,
				  unsigned long address,
				  unsigned long pages, int ih)
{
	struct qi_desc desc;

@@ -170,6 +172,22 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
	}
}

static void intel_flush_svm_range_dev(struct intel_svm *svm,
				      struct intel_svm_dev *sdev,
				      unsigned long address,
				      unsigned long pages, int ih)
{
	unsigned long shift = ilog2(__roundup_pow_of_two(pages));
	unsigned long align = (1ULL << (VTD_PAGE_SHIFT + shift));
	unsigned long start = ALIGN_DOWN(address, align);
	unsigned long end = ALIGN(address + (pages << VTD_PAGE_SHIFT), align);

	while (start < end) {
		__flush_svm_range_dev(svm, sdev, start, align >> VTD_PAGE_SHIFT, ih);
		start += align;
	}
}

static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
				unsigned long pages, int ih)
{