IOMMU Fixes for Linux v5.17-rc6
Including: - Fix a double list_add() in Intel VT-d code - Add missing put_device() in Tegra SMMU driver - Two AMD IOMMU fixes: - Memory leak in IO page-table freeing code - Add missing recovery from event-log overflow -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEr9jSbILcajRFYWYyK/BELZcBGuMFAmIiMSIACgkQK/BELZcB GuNoHxAAqgsx7bL8KvyZGhh3XwKl638wdNctCmTKTGj04GI0IsiZOyj0jcR+o8Z7 LJXkZORMbJmrtGkL/jhURkpHYJxfy5MMVSBvcP0G5/24JfM9lkQ88kxL08diqGkd /IktUD+TrmgknvsSJ807EWoCrVvHU3YAqHub70uEnxcpcPK33S9b0EUz1MYge6MD NY56cAQxCJ9JV5bTZ4X5RNbTvEFC7bOLU218khEgFq5dJ+35/8xGubUfoyX+repU RaNHWhNOiEYNQXkqsuZQaAivBj1uPuY/1wL7pB/g2OsRZ7BMZMS7zhncYdWAA0ER 1npkmOcZWwp2ymUmFzgS4y9bo6gVP6SFzYBc9I5ZUwRaYBMS34qJEevMVZm0cCKr i4gpWIeUEXT5v94F4zyzGE+cO5lYmvYFxpTm5l+NcBMWb/el7ht0Kj2CEmx2JKj2 mG+3/++JDuTNSigIaF5Dk2d5g2L/2gW2sT9/kvinRcbsga+SFOuQXstY9wAGCLFg L/YBxnn/cnEphqx23tog/tt+sje6HgNXNhcWTM8ojYFECX3hY9x7sEIR1MAuN6ym jRPJHz9zNpNtVrMkYd8e/irOs4ouWMDmd9H6bYbCapCgg2UrCBEjbvqwbz3iaVB6 hTFAd0RGRDQOldm0L4Q2xTeq2J7EsYCLfOpw72tWV9tp2dfEvRc= =j2I8 -----END PGP SIGNATURE----- Merge tag 'iommu-fixes-v5.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pull iommu fixes from Joerg Roedel: - Fix a double list_add() in Intel VT-d code - Add missing put_device() in Tegra SMMU driver - Two AMD IOMMU fixes: - Memory leak in IO page-table freeing code - Add missing recovery from event-log overflow * tag 'iommu-fixes-v5.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/tegra-smmu: Fix missing put_device() call in tegra_smmu_find iommu/vt-d: Fix double list_add when enabling VMD in scalable mode iommu/amd: Fix I/O page table memory leak iommu/amd: Recover from event log overflow
This commit is contained in:
commit
3f509f5971
@ -14,6 +14,7 @@
|
||||
extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
|
||||
extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
|
||||
extern void amd_iommu_apply_erratum_63(u16 devid);
|
||||
extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu);
|
||||
extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
|
||||
extern int amd_iommu_init_devices(void);
|
||||
extern void amd_iommu_uninit_devices(void);
|
||||
|
@ -110,6 +110,7 @@
|
||||
#define PASID_MASK 0x0000ffff
|
||||
|
||||
/* MMIO status bits */
|
||||
#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK (1 << 0)
|
||||
#define MMIO_STATUS_EVT_INT_MASK (1 << 1)
|
||||
#define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2)
|
||||
#define MMIO_STATUS_PPR_INT_MASK (1 << 6)
|
||||
|
@ -657,6 +657,16 @@ static int __init alloc_command_buffer(struct amd_iommu *iommu)
|
||||
return iommu->cmd_buf ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function restarts event logging in case the IOMMU experienced
|
||||
* an event log buffer overflow.
|
||||
*/
|
||||
void amd_iommu_restart_event_logging(struct amd_iommu *iommu)
|
||||
{
|
||||
iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
|
||||
iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function resets the command buffer if the IOMMU stopped fetching
|
||||
* commands from it.
|
||||
|
@ -492,18 +492,18 @@ static void v1_free_pgtable(struct io_pgtable *iop)
|
||||
|
||||
dom = container_of(pgtable, struct protection_domain, iop);
|
||||
|
||||
/* Update data structure */
|
||||
amd_iommu_domain_clr_pt_root(dom);
|
||||
|
||||
/* Make changes visible to IOMMUs */
|
||||
amd_iommu_domain_update(dom);
|
||||
|
||||
/* Page-table is not visible to IOMMU anymore, so free it */
|
||||
BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
|
||||
pgtable->mode > PAGE_MODE_6_LEVEL);
|
||||
|
||||
free_sub_pt(pgtable->root, pgtable->mode, &freelist);
|
||||
|
||||
/* Update data structure */
|
||||
amd_iommu_domain_clr_pt_root(dom);
|
||||
|
||||
/* Make changes visible to IOMMUs */
|
||||
amd_iommu_domain_update(dom);
|
||||
|
||||
put_pages_list(&freelist);
|
||||
}
|
||||
|
||||
|
@ -764,7 +764,8 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { }
|
||||
#endif /* !CONFIG_IRQ_REMAP */
|
||||
|
||||
#define AMD_IOMMU_INT_MASK \
|
||||
(MMIO_STATUS_EVT_INT_MASK | \
|
||||
(MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \
|
||||
MMIO_STATUS_EVT_INT_MASK | \
|
||||
MMIO_STATUS_PPR_INT_MASK | \
|
||||
MMIO_STATUS_GALOG_INT_MASK)
|
||||
|
||||
@ -774,7 +775,7 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
|
||||
u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
|
||||
|
||||
while (status & AMD_IOMMU_INT_MASK) {
|
||||
/* Enable EVT and PPR and GA interrupts again */
|
||||
/* Enable interrupt sources again */
|
||||
writel(AMD_IOMMU_INT_MASK,
|
||||
iommu->mmio_base + MMIO_STATUS_OFFSET);
|
||||
|
||||
@ -795,6 +796,11 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) {
|
||||
pr_info_ratelimited("IOMMU event log overflow\n");
|
||||
amd_iommu_restart_event_logging(iommu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardware bug: ERBT1312
|
||||
* When re-enabling interrupt (by writing 1
|
||||
|
@ -2738,7 +2738,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
|
||||
/* PASID table is mandatory for a PCI device in scalable mode. */
|
||||
if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
|
||||
if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
|
||||
ret = intel_pasid_alloc_table(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "PASID table allocation failed\n");
|
||||
|
@ -808,8 +808,10 @@ static struct tegra_smmu *tegra_smmu_find(struct device_node *np)
|
||||
return NULL;
|
||||
|
||||
mc = platform_get_drvdata(pdev);
|
||||
if (!mc)
|
||||
if (!mc) {
|
||||
put_device(&pdev->dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mc->smmu;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user