Commit 4b205766 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'iommu-fixes-v5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull iommu fixes from Joerg Roedel:

 - Compile warning fix for the Intel IOMMU driver

 - Fix kdump boot with Intel IOMMU enabled and in passthrough mode

 - Disable AMD IOMMU on a Laptop/Embedded platform because the delay it
   introduces in DMA transactions causes screen flickering there with 4k
   monitors

 - Make domain_free function in QCOM IOMMU driver robust and not leak
   memory/dereference NULL pointers

 - Fix ARM-SMMU module parameter prefix names

* tag 'iommu-fixes-v5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu/arm-smmu: Restore naming of driver parameter prefix
  iommu/qcom: Fix bogus detach logic
  iommu/amd: Disable IOMMU on Stoney Ridge systems
  iommu/vt-d: Simplify check in identity_mapping()
  iommu/vt-d: Remove deferred_attach_domain()
  iommu/vt-d: Do deferred attachment in iommu_need_mapping()
  iommu/vt-d: Move deferred device attachment into helper function
  iommu/vt-d: Add attach_deferred() helper
  iommu/vt-d: Fix compile warning from intel-svm.h
parents fa079ba8 ab362fff
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -14,8 +14,8 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
obj-$(CONFIG_ARM_SMMU) += arm-smmu-mod.o
arm-smmu-mod-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
obj-$(CONFIG_ARM_SMMU) += arm_smmu.o
arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
obj-$(CONFIG_DMAR_TABLE) += dmar.o
obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
+12 −1
Original line number Diff line number Diff line
@@ -2523,6 +2523,7 @@ static int __init early_amd_iommu_init(void)
	struct acpi_table_header *ivrs_base;
	acpi_status status;
	int i, remap_cache_sz, ret = 0;
	u32 pci_id;

	if (!amd_iommu_detected)
		return -ENODEV;
@@ -2610,6 +2611,16 @@ static int __init early_amd_iommu_init(void)
	if (ret)
		goto out;

	/* Disable IOMMU if there's Stoney Ridge graphics */
	for (i = 0; i < 32; i++) {
		pci_id = read_pci_config(0, i, 0, 0);
		if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) {
			pr_info("Disable IOMMU on Stoney Ridge\n");
			amd_iommu_disabled = true;
			break;
		}
	}

	/* Disable any previously enabled IOMMUs */
	if (!is_kdump_kernel() || amd_iommu_disabled)
		disable_iommus();
@@ -2718,7 +2729,7 @@ static int __init state_next(void)
		ret = early_amd_iommu_init();
		init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
		if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) {
			pr_info("AMD IOMMU disabled on kernel command-line\n");
			pr_info("AMD IOMMU disabled\n");
			init_state = IOMMU_CMDLINE_DISABLED;
			ret = -EINVAL;
		}
+24 −17
Original line number Diff line number Diff line
@@ -762,6 +762,11 @@ static int iommu_dummy(struct device *dev)
	return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
}

static bool attach_deferred(struct device *dev)
{
	return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
}

/**
 * is_downstream_to_pci_bridge - test if a device belongs to the PCI
 *				 sub-hierarchy of a candidate PCI-PCI bridge
@@ -2510,8 +2515,7 @@ struct dmar_domain *find_domain(struct device *dev)
{
	struct device_domain_info *info;

	if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO ||
		     dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO))
	if (unlikely(attach_deferred(dev) || iommu_dummy(dev)))
		return NULL;

	if (dev_is_pci(dev))
@@ -2525,9 +2529,8 @@ struct dmar_domain *find_domain(struct device *dev)
	return NULL;
}

static struct dmar_domain *deferred_attach_domain(struct device *dev)
static void do_deferred_attach(struct device *dev)
{
	if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
	struct iommu_domain *domain;

	dev->archdata.iommu = NULL;
@@ -2536,9 +2539,6 @@ static struct dmar_domain *deferred_attach_domain(struct device *dev)
		intel_iommu_attach_device(domain, dev);
}

	return find_domain(dev);
}

static inline struct device_domain_info *
dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
{
@@ -2916,7 +2916,7 @@ static int identity_mapping(struct device *dev)
	struct device_domain_info *info;

	info = dev->archdata.iommu;
	if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO)
	if (info)
		return (info->domain == si_domain);

	return 0;
@@ -3587,6 +3587,9 @@ static bool iommu_need_mapping(struct device *dev)
	if (iommu_dummy(dev))
		return false;

	if (unlikely(attach_deferred(dev)))
		do_deferred_attach(dev);

	ret = identity_mapping(dev);
	if (ret) {
		u64 dma_mask = *dev->dma_mask;
@@ -3635,7 +3638,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,

	BUG_ON(dir == DMA_NONE);

	domain = deferred_attach_domain(dev);
	domain = find_domain(dev);
	if (!domain)
		return DMA_MAPPING_ERROR;

@@ -3855,7 +3858,7 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
	if (!iommu_need_mapping(dev))
		return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);

	domain = deferred_attach_domain(dev);
	domain = find_domain(dev);
	if (!domain)
		return 0;

@@ -3950,7 +3953,11 @@ bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
	int prot = 0;
	int ret;

	domain = deferred_attach_domain(dev);
	if (unlikely(attach_deferred(dev)))
		do_deferred_attach(dev);

	domain = find_domain(dev);

	if (WARN_ON(dir == DMA_NONE || !domain))
		return DMA_MAPPING_ERROR;

@@ -6133,7 +6140,7 @@ intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
					   struct device *dev)
{
	return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
	return attach_deferred(dev);
}

static int
+12 −16
Original line number Diff line number Diff line
@@ -344,21 +344,19 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain)
{
	struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);

	if (WARN_ON(qcom_domain->iommu))    /* forgot to detach? */
		return;

	iommu_put_dma_cookie(domain);

	/* NOTE: unmap can be called after client device is powered off,
	 * for example, with GPUs or anything involving dma-buf.  So we
	 * cannot rely on the device_link.  Make sure the IOMMU is on to
	 * avoid unclocked accesses in the TLB inv path:
	if (qcom_domain->iommu) {
		/*
		 * NOTE: unmap can be called after client device is powered
		 * off, for example, with GPUs or anything involving dma-buf.
		 * So we cannot rely on the device_link.  Make sure the IOMMU
		 * is on to avoid unclocked accesses in the TLB inv path:
		 */
		pm_runtime_get_sync(qcom_domain->iommu->dev);

		free_io_pgtable_ops(qcom_domain->pgtbl_ops);

		pm_runtime_put_sync(qcom_domain->iommu->dev);
	}

	kfree(qcom_domain);
}
@@ -404,7 +402,7 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
	struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
	unsigned i;

	if (!qcom_domain->iommu)
	if (WARN_ON(!qcom_domain->iommu))
		return;

	pm_runtime_get_sync(qcom_iommu->dev);
@@ -417,8 +415,6 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
		ctx->domain = NULL;
	}
	pm_runtime_put_sync(qcom_iommu->dev);

	qcom_domain->iommu = NULL;
}

static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
+1 −1
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ static inline int intel_svm_unbind_mm(struct device *dev, int pasid)
	BUG();
}

static int intel_svm_is_pasid_valid(struct device *dev, int pasid)
static inline int intel_svm_is_pasid_valid(struct device *dev, int pasid)
{
	return -EINVAL;
}