Commit f3523a22 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull iommu fixes from Joerg Roedel:

 - Revert a patch which caused boot failures with QCOM IOMMU

 - Two fixes for Intel VT-d context table handling

 - Physical address decoding fix for Rockchip IOMMU

 - Add a reviewer for AMD IOMMU

* tag 'iommu-fixes-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  MAINTAINERS: Add Suravee Suthikulpanit as Reviewer for AMD IOMMU (AMD-Vi)
  iommu/rockchip: Fix physical address decoding
  iommu/vt-d: Fix clearing real DMA device's scalable-mode context entries
  iommu/vt-d: Global devTLB flush when present context entry changed
  iommu/qcom: Revert "iommu/arm: Cleanup resources in case of probe error path"
parents 8096acd7 4a5c155a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -933,6 +933,7 @@ F: drivers/video/fbdev/geode/
AMD IOMMU (AMD-VI)
M:	Joerg Roedel <joro@8bytes.org>
R:	Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
L:	iommu@lists.linux-foundation.org
S:	Maintained
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
+2 −11
Original line number Diff line number Diff line
@@ -849,12 +849,10 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
	ret = iommu_device_register(&qcom_iommu->iommu, &qcom_iommu_ops, dev);
	if (ret) {
		dev_err(dev, "Failed to register iommu\n");
		goto err_sysfs_remove;
		return ret;
	}

	ret = bus_set_iommu(&platform_bus_type, &qcom_iommu_ops);
	if (ret)
		goto err_unregister_device;
	bus_set_iommu(&platform_bus_type, &qcom_iommu_ops);

	if (qcom_iommu->local_base) {
		pm_runtime_get_sync(dev);
@@ -863,13 +861,6 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
	}

	return 0;

err_unregister_device:
	iommu_device_unregister(&qcom_iommu->iommu);

err_sysfs_remove:
	iommu_device_sysfs_remove(&qcom_iommu->iommu);
	return ret;
}

static int qcom_iommu_device_remove(struct platform_device *pdev)
+23 −11
Original line number Diff line number Diff line
@@ -2429,10 +2429,11 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
	return 0;
}

static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8 devfn)
{
	unsigned long flags;
	struct intel_iommu *iommu = info->iommu;
	struct context_entry *context;
	unsigned long flags;
	u16 did_old;

	if (!iommu)
@@ -2444,7 +2445,16 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn
		spin_unlock_irqrestore(&iommu->lock, flags);
		return;
	}

	if (sm_supported(iommu)) {
		if (hw_pass_through && domain_type_is_si(info->domain))
			did_old = FLPT_DEFAULT_DID;
		else
			did_old = info->domain->iommu_did[iommu->seq_id];
	} else {
		did_old = context_domain_id(context);
	}

	context_clear_entry(context);
	__iommu_flush_cache(iommu, context, sizeof(*context));
	spin_unlock_irqrestore(&iommu->lock, flags);
@@ -2462,6 +2472,8 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn
				 0,
				 0,
				 DMA_TLB_DSI_FLUSH);

	__iommu_flush_dev_iotlb(info, 0, MAX_AGAW_PFN_WIDTH);
}

static inline void unlink_domain_info(struct device_domain_info *info)
@@ -4425,9 +4437,9 @@ int __init intel_iommu_init(void)

static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
{
	struct intel_iommu *iommu = opaque;
	struct device_domain_info *info = opaque;

	domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
	domain_context_clear_one(info, PCI_BUS_NUM(alias), alias & 0xff);
	return 0;
}

@@ -4437,12 +4449,13 @@ static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *op
 * devices, unbinding the driver from any one of them will possibly leave
 * the others unable to operate.
 */
static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
static void domain_context_clear(struct device_domain_info *info)
{
	if (!iommu || !dev || !dev_is_pci(dev))
	if (!info->iommu || !info->dev || !dev_is_pci(info->dev))
		return;

	pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
	pci_for_each_dma_alias(to_pci_dev(info->dev),
			       &domain_context_clear_one_cb, info);
}

static void __dmar_remove_one_dev_info(struct device_domain_info *info)
@@ -4459,14 +4472,13 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
	iommu = info->iommu;
	domain = info->domain;

	if (info->dev) {
	if (info->dev && !dev_is_real_dma_subdevice(info->dev)) {
		if (dev_is_pci(info->dev) && sm_supported(iommu))
			intel_pasid_tear_down_entry(iommu, info->dev,
					PASID_RID2PASID, false);

		iommu_disable_dev_iotlb(info);
		if (!dev_is_real_dma_subdevice(info->dev))
			domain_context_clear(iommu, info->dev);
		domain_context_clear(info);
		intel_pasid_free_table(info->dev);
	}

+4 −2
Original line number Diff line number Diff line
@@ -544,12 +544,14 @@ static inline u32 rk_dma_addr_dte(dma_addr_t dt_dma)
}

#define DT_HI_MASK GENMASK_ULL(39, 32)
#define DTE_BASE_HI_MASK GENMASK(11, 4)
#define DT_SHIFT   28

static inline phys_addr_t rk_dte_addr_phys_v2(u32 addr)
{
	return (phys_addr_t)(addr & RK_DTE_PT_ADDRESS_MASK) |
	       ((addr & DT_HI_MASK) << DT_SHIFT);
	u64 addr64 = addr;
	return (phys_addr_t)(addr64 & RK_DTE_PT_ADDRESS_MASK) |
	       ((addr64 & DTE_BASE_HI_MASK) << DT_SHIFT);
}

static inline u32 rk_dma_addr_dte_v2(dma_addr_t dt_dma)