mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
IOMMU Fixes for Linux v6.15-rc1
Including:
- Fix two crashes, one in core code and a NULL-ptr dereference in the
Mediatek IOMMU driver.
- Dma_ops cleanup fix for core code.
- Two fixes for Intel VT-d driver:
- Fix posted MSI issue when users change cpu affinity.
- Remove invalid set_dma_ops() call in the iommu driver.
- Warning fix for Tegra IOMMU driver.
- Suspend/Resume fix for Exynos IOMMU driver.
- Probe failure fix for Renesas IOMMU driver
- Cosmetic fix
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEr9jSbILcajRFYWYyK/BELZcBGuMFAmf5JycACgkQK/BELZcB
GuNWZA//VoMJW59ZkgaratBofLAm1k8EWsULC0F/EcHe3XzEVO9SBN7DUxv1Zy++
fkPKkZYaj1Uy9L9g0VWAvAChI+EuCmKHsatCQWZZQoOXmVJxZkWfRt5Kp0yppnS7
HTVDBpkezqqWrCtHPfXRMI/56SwvRFIjS7+baGMFYO1AnFXxBQFhy8NlBZuTZ2jA
4fXWMyuMcVPD6xkP3CEusWSvp9fdEbVbo4uv63V+AtffZlYhFfgI4qVodNj29FKh
nvFufGv0KWfJF0tC7dC1k7Oqa5QfXIOxQdFmnfelrvfMV8qF0UrlgEMYiWzkNIEA
z24kZbP/T4MhqN+w4WncQyixY992aEkeY8q0D9f2PBrf7oU606PPS2JgHqL+mJYy
ZQ+494nexX7T2fnkxomDumRrNndDzqhukv347sFGkO2o1VW36s4LSihHkVJoSS4e
eNvNXnwsLpjNClUyZZAwcQnh5wgXYihrXsC58K7OORLEK1T/25Lx25cOz/oDEzSs
cWBdVM+NRI7N489wRRcHf/BhICOpJho11CejgrqxOFayGYWG7O0Z3nqGXcQsabP2
Qbr2C/jXY0reLmseWcQBkaN+RneI6LyuGH99LSrisoEQ2Fth4sZPr2zU7NN1QRUX
KapBT76/1bgZc3s/c7agCAxCxXe9W4kFa/jwqzmyrF2VX7ltQYY=
=oz0M
-----END PGP SIGNATURE-----
Merge tag 'iommu-fixes-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux
Pull iommu fixes from Joerg Roedel:
- Fix two crashes, one in core code and a NULL-ptr dereference in the
Mediatek IOMMU driver
- Dma_ops cleanup fix for core code
- Two fixes for Intel VT-d driver:
- Fix posted MSI issue when users change cpu affinity
- Remove invalid set_dma_ops() call in the iommu driver
- Warning fix for Tegra IOMMU driver
- Suspend/Resume fix for Exynos IOMMU driver
- Probe failure fix for Renesas IOMMU driver
- Cosmetic fix
* tag 'iommu-fixes-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux:
iommu/tegra241-cmdqv: Fix warnings due to dmam_free_coherent()
iommu: remove unneeded semicolon
iommu/mediatek: Fix NULL pointer deference in mtk_iommu_device_group
iommu/exynos: Fix suspend/resume with IDENTITY domain
iommu/ipmmu-vmsa: Register in a sensible order
iommu: Clear iommu-dma ops on cleanup
iommu/vt-d: Remove an unnecessary call set_dma_ops()
iommu/vt-d: Wire up irq_ack() to irq_move_irq() for posted MSIs
iommu: Fix crash in report_iommu_fault()
This commit is contained in:
commit
023e62ce85
|
|
@ -487,17 +487,6 @@ static int tegra241_cmdqv_hw_reset(struct arm_smmu_device *smmu)
|
|||
|
||||
/* VCMDQ Resource Helpers */
|
||||
|
||||
static void tegra241_vcmdq_free_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
|
||||
{
|
||||
struct arm_smmu_queue *q = &vcmdq->cmdq.q;
|
||||
size_t nents = 1 << q->llq.max_n_shift;
|
||||
size_t qsz = nents << CMDQ_ENT_SZ_SHIFT;
|
||||
|
||||
if (!q->base)
|
||||
return;
|
||||
dmam_free_coherent(vcmdq->cmdqv->smmu.dev, qsz, q->base, q->base_dma);
|
||||
}
|
||||
|
||||
static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
|
||||
{
|
||||
struct arm_smmu_device *smmu = &vcmdq->cmdqv->smmu;
|
||||
|
|
@ -560,7 +549,8 @@ static void tegra241_vintf_free_lvcmdq(struct tegra241_vintf *vintf, u16 lidx)
|
|||
struct tegra241_vcmdq *vcmdq = vintf->lvcmdqs[lidx];
|
||||
char header[64];
|
||||
|
||||
tegra241_vcmdq_free_smmu_cmdq(vcmdq);
|
||||
/* Note that the lvcmdq queue memory space is managed by devres */
|
||||
|
||||
tegra241_vintf_deinit_lvcmdq(vintf, lidx);
|
||||
|
||||
dev_dbg(vintf->cmdqv->dev,
|
||||
|
|
@ -768,13 +758,13 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)
|
|||
|
||||
vintf = kzalloc(sizeof(*vintf), GFP_KERNEL);
|
||||
if (!vintf)
|
||||
goto out_fallback;
|
||||
return -ENOMEM;
|
||||
|
||||
/* Init VINTF0 for in-kernel use */
|
||||
ret = tegra241_cmdqv_init_vintf(cmdqv, 0, vintf);
|
||||
if (ret) {
|
||||
dev_err(cmdqv->dev, "failed to init vintf0: %d\n", ret);
|
||||
goto free_vintf;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Preallocate logical VCMDQs to VINTF0 */
|
||||
|
|
@ -783,24 +773,12 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)
|
|||
|
||||
vcmdq = tegra241_vintf_alloc_lvcmdq(vintf, lidx);
|
||||
if (IS_ERR(vcmdq))
|
||||
goto free_lvcmdq;
|
||||
return PTR_ERR(vcmdq);
|
||||
}
|
||||
|
||||
/* Now, we are ready to run all the impl ops */
|
||||
smmu->impl_ops = &tegra241_cmdqv_impl_ops;
|
||||
return 0;
|
||||
|
||||
free_lvcmdq:
|
||||
for (lidx--; lidx >= 0; lidx--)
|
||||
tegra241_vintf_free_lvcmdq(vintf, lidx);
|
||||
tegra241_cmdqv_deinit_vintf(cmdqv, vintf->idx);
|
||||
free_vintf:
|
||||
kfree(vintf);
|
||||
out_fallback:
|
||||
dev_info(smmu->impl_dev, "Falling back to standard SMMU CMDQ\n");
|
||||
smmu->options &= ~ARM_SMMU_OPT_TEGRA241_CMDQV;
|
||||
tegra241_cmdqv_remove(smmu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOMMU_DEBUGFS
|
||||
|
|
|
|||
|
|
@ -1754,7 +1754,7 @@ static size_t cookie_msi_granule(const struct iommu_domain *domain)
|
|||
return PAGE_SIZE;
|
||||
default:
|
||||
BUG();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static struct list_head *cookie_msi_pages(const struct iommu_domain *domain)
|
||||
|
|
@ -1766,7 +1766,7 @@ static struct list_head *cookie_msi_pages(const struct iommu_domain *domain)
|
|||
return &domain->msi_cookie->msi_page_list;
|
||||
default:
|
||||
BUG();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
|
||||
|
|
|
|||
|
|
@ -832,7 +832,7 @@ static int __maybe_unused exynos_sysmmu_suspend(struct device *dev)
|
|||
struct exynos_iommu_owner *owner = dev_iommu_priv_get(master);
|
||||
|
||||
mutex_lock(&owner->rpm_lock);
|
||||
if (&data->domain->domain != &exynos_identity_domain) {
|
||||
if (data->domain) {
|
||||
dev_dbg(data->sysmmu, "saving state\n");
|
||||
__sysmmu_disable(data);
|
||||
}
|
||||
|
|
@ -850,7 +850,7 @@ static int __maybe_unused exynos_sysmmu_resume(struct device *dev)
|
|||
struct exynos_iommu_owner *owner = dev_iommu_priv_get(master);
|
||||
|
||||
mutex_lock(&owner->rpm_lock);
|
||||
if (&data->domain->domain != &exynos_identity_domain) {
|
||||
if (data->domain) {
|
||||
dev_dbg(data->sysmmu, "restoring state\n");
|
||||
__sysmmu_enable(data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3835,7 +3835,6 @@ static void intel_iommu_release_device(struct device *dev)
|
|||
intel_pasid_free_table(dev);
|
||||
intel_iommu_debugfs_remove_dev(info);
|
||||
kfree(info);
|
||||
set_dma_ops(dev, NULL);
|
||||
}
|
||||
|
||||
static void intel_iommu_get_resv_regions(struct device *device,
|
||||
|
|
|
|||
|
|
@ -1287,43 +1287,44 @@ static struct irq_chip intel_ir_chip = {
|
|||
};
|
||||
|
||||
/*
|
||||
* With posted MSIs, all vectors are multiplexed into a single notification
|
||||
* vector. Devices MSIs are then dispatched in a demux loop where
|
||||
* EOIs can be coalesced as well.
|
||||
* With posted MSIs, the MSI vectors are multiplexed into a single notification
|
||||
* vector, and only the notification vector is sent to the APIC IRR. Device
|
||||
* MSIs are then dispatched in a demux loop that harvests the MSIs from the
|
||||
* CPU's Posted Interrupt Request bitmap. I.e. Posted MSIs never get sent to
|
||||
* the APIC IRR, and thus do not need an EOI. The notification handler instead
|
||||
* performs a single EOI after processing the PIR.
|
||||
*
|
||||
* "INTEL-IR-POST" IRQ chip does not do EOI on ACK, thus the dummy irq_ack()
|
||||
* function. Instead EOI is performed by the posted interrupt notification
|
||||
* handler.
|
||||
* Note! Pending SMP/CPU affinity changes, which are per MSI, must still be
|
||||
* honored, only the APIC EOI is omitted.
|
||||
*
|
||||
* For the example below, 3 MSIs are coalesced into one CPU notification. Only
|
||||
* one apic_eoi() is needed.
|
||||
* one apic_eoi() is needed, but each MSI needs to process pending changes to
|
||||
* its CPU affinity.
|
||||
*
|
||||
* __sysvec_posted_msi_notification()
|
||||
* irq_enter();
|
||||
* handle_edge_irq()
|
||||
* irq_chip_ack_parent()
|
||||
* dummy(); // No EOI
|
||||
* irq_move_irq(); // No EOI
|
||||
* handle_irq_event()
|
||||
* driver_handler()
|
||||
* handle_edge_irq()
|
||||
* irq_chip_ack_parent()
|
||||
* dummy(); // No EOI
|
||||
* irq_move_irq(); // No EOI
|
||||
* handle_irq_event()
|
||||
* driver_handler()
|
||||
* handle_edge_irq()
|
||||
* irq_chip_ack_parent()
|
||||
* dummy(); // No EOI
|
||||
* irq_move_irq(); // No EOI
|
||||
* handle_irq_event()
|
||||
* driver_handler()
|
||||
* apic_eoi()
|
||||
* irq_exit()
|
||||
*
|
||||
*/
|
||||
|
||||
static void dummy_ack(struct irq_data *d) { }
|
||||
|
||||
static struct irq_chip intel_ir_chip_post_msi = {
|
||||
.name = "INTEL-IR-POST",
|
||||
.irq_ack = dummy_ack,
|
||||
.irq_ack = irq_move_irq,
|
||||
.irq_set_affinity = intel_ir_set_affinity,
|
||||
.irq_compose_msi_msg = intel_ir_compose_msi_msg,
|
||||
.irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
|
||||
|
|
|
|||
|
|
@ -538,6 +538,9 @@ static void iommu_deinit_device(struct device *dev)
|
|||
dev->iommu_group = NULL;
|
||||
module_put(ops->owner);
|
||||
dev_iommu_free(dev);
|
||||
#ifdef CONFIG_IOMMU_DMA
|
||||
dev->dma_iommu = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct iommu_domain *pasid_array_entry_to_domain(void *entry)
|
||||
|
|
@ -2717,7 +2720,8 @@ int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
|
|||
* if upper layers showed interest and installed a fault handler,
|
||||
* invoke it.
|
||||
*/
|
||||
if (domain->handler)
|
||||
if (domain->cookie_type == IOMMU_COOKIE_FAULT_HANDLER &&
|
||||
domain->handler)
|
||||
ret = domain->handler(domain, dev, iova, flags,
|
||||
domain->handler_token);
|
||||
|
||||
|
|
|
|||
|
|
@ -1081,31 +1081,24 @@ static int ipmmu_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mmu);
|
||||
/*
|
||||
* Register the IPMMU to the IOMMU subsystem in the following cases:
|
||||
* - R-Car Gen2 IPMMU (all devices registered)
|
||||
* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
|
||||
*/
|
||||
if (!mmu->features->has_cache_leaf_nodes || !ipmmu_is_root(mmu)) {
|
||||
ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
|
||||
dev_name(&pdev->dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (mmu->features->has_cache_leaf_nodes && ipmmu_is_root(mmu))
|
||||
return 0;
|
||||
|
||||
ret = iommu_device_register(&mmu->iommu, &ipmmu_ops, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL, dev_name(&pdev->dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We can't create the ARM mapping here as it requires the bus to have
|
||||
* an IOMMU, which only happens when bus_set_iommu() is called in
|
||||
* ipmmu_init() after the probe function returns.
|
||||
*/
|
||||
ret = iommu_device_register(&mmu->iommu, &ipmmu_ops, &pdev->dev);
|
||||
if (ret)
|
||||
iommu_device_sysfs_remove(&mmu->iommu);
|
||||
|
||||
platform_set_drvdata(pdev, mmu);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ipmmu_remove(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -1372,15 +1372,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, data);
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
|
||||
"mtk-iommu.%pa", &ioaddr);
|
||||
if (ret)
|
||||
goto out_link_remove;
|
||||
|
||||
ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev);
|
||||
if (ret)
|
||||
goto out_sysfs_remove;
|
||||
|
||||
if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) {
|
||||
list_add_tail(&data->list, data->plat_data->hw_list);
|
||||
data->hw_list = data->plat_data->hw_list;
|
||||
|
|
@ -1390,19 +1381,28 @@ static int mtk_iommu_probe(struct platform_device *pdev)
|
|||
data->hw_list = &data->hw_list_head;
|
||||
}
|
||||
|
||||
ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
|
||||
"mtk-iommu.%pa", &ioaddr);
|
||||
if (ret)
|
||||
goto out_list_del;
|
||||
|
||||
ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev);
|
||||
if (ret)
|
||||
goto out_sysfs_remove;
|
||||
|
||||
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
|
||||
ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
|
||||
if (ret)
|
||||
goto out_list_del;
|
||||
goto out_device_unregister;
|
||||
}
|
||||
return ret;
|
||||
|
||||
out_list_del:
|
||||
list_del(&data->list);
|
||||
out_device_unregister:
|
||||
iommu_device_unregister(&data->iommu);
|
||||
out_sysfs_remove:
|
||||
iommu_device_sysfs_remove(&data->iommu);
|
||||
out_link_remove:
|
||||
out_list_del:
|
||||
list_del(&data->list);
|
||||
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
|
||||
device_link_remove(data->smicomm_dev, dev);
|
||||
out_runtime_disable:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user