Commit f3523a22 authored by Linus Torvalds's avatar Linus Torvalds

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
...@@ -933,6 +933,7 @@ F: drivers/video/fbdev/geode/ ...@@ -933,6 +933,7 @@ F: drivers/video/fbdev/geode/
AMD IOMMU (AMD-VI) AMD IOMMU (AMD-VI)
M: Joerg Roedel <joro@8bytes.org> M: Joerg Roedel <joro@8bytes.org>
R: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
L: iommu@lists.linux-foundation.org L: iommu@lists.linux-foundation.org
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
......
...@@ -849,12 +849,10 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) ...@@ -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); ret = iommu_device_register(&qcom_iommu->iommu, &qcom_iommu_ops, dev);
if (ret) { if (ret) {
dev_err(dev, "Failed to register iommu\n"); dev_err(dev, "Failed to register iommu\n");
goto err_sysfs_remove; return ret;
} }
ret = bus_set_iommu(&platform_bus_type, &qcom_iommu_ops); bus_set_iommu(&platform_bus_type, &qcom_iommu_ops);
if (ret)
goto err_unregister_device;
if (qcom_iommu->local_base) { if (qcom_iommu->local_base) {
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
...@@ -863,13 +861,6 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) ...@@ -863,13 +861,6 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
} }
return 0; 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) static int qcom_iommu_device_remove(struct platform_device *pdev)
......
...@@ -2429,10 +2429,11 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, ...@@ -2429,10 +2429,11 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
return 0; 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; struct context_entry *context;
unsigned long flags;
u16 did_old; u16 did_old;
if (!iommu) if (!iommu)
...@@ -2444,7 +2445,16 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn ...@@ -2444,7 +2445,16 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn
spin_unlock_irqrestore(&iommu->lock, flags); spin_unlock_irqrestore(&iommu->lock, flags);
return; return;
} }
did_old = context_domain_id(context);
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); context_clear_entry(context);
__iommu_flush_cache(iommu, context, sizeof(*context)); __iommu_flush_cache(iommu, context, sizeof(*context));
spin_unlock_irqrestore(&iommu->lock, flags); spin_unlock_irqrestore(&iommu->lock, flags);
...@@ -2462,6 +2472,8 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn ...@@ -2462,6 +2472,8 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn
0, 0,
0, 0,
DMA_TLB_DSI_FLUSH); 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) static inline void unlink_domain_info(struct device_domain_info *info)
...@@ -4425,9 +4437,9 @@ int __init intel_iommu_init(void) ...@@ -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) 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; return 0;
} }
...@@ -4437,12 +4449,13 @@ static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *op ...@@ -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 * devices, unbinding the driver from any one of them will possibly leave
* the others unable to operate. * 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; 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) 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) ...@@ -4459,14 +4472,13 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
iommu = info->iommu; iommu = info->iommu;
domain = info->domain; 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)) if (dev_is_pci(info->dev) && sm_supported(iommu))
intel_pasid_tear_down_entry(iommu, info->dev, intel_pasid_tear_down_entry(iommu, info->dev,
PASID_RID2PASID, false); PASID_RID2PASID, false);
iommu_disable_dev_iotlb(info); iommu_disable_dev_iotlb(info);
if (!dev_is_real_dma_subdevice(info->dev)) domain_context_clear(info);
domain_context_clear(iommu, info->dev);
intel_pasid_free_table(info->dev); intel_pasid_free_table(info->dev);
} }
......
...@@ -544,12 +544,14 @@ static inline u32 rk_dma_addr_dte(dma_addr_t dt_dma) ...@@ -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 DT_HI_MASK GENMASK_ULL(39, 32)
#define DTE_BASE_HI_MASK GENMASK(11, 4)
#define DT_SHIFT 28 #define DT_SHIFT 28
static inline phys_addr_t rk_dte_addr_phys_v2(u32 addr) static inline phys_addr_t rk_dte_addr_phys_v2(u32 addr)
{ {
return (phys_addr_t)(addr & RK_DTE_PT_ADDRESS_MASK) | u64 addr64 = addr;
((addr & DT_HI_MASK) << DT_SHIFT); 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) static inline u32 rk_dma_addr_dte_v2(dma_addr_t dt_dma)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment