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/
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
......
......@@ -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)
......
......@@ -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;
}
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);
__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);
}
......
......@@ -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)
......
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