Skip to content

Commit 3f509f5

Browse files
committed
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
2 parents a4ffdb6 + 9826e39 commit 3f509f5

File tree

7 files changed

+30
-10
lines changed

7 files changed

+30
-10
lines changed

drivers/iommu/amd/amd_iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
1515
extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
1616
extern void amd_iommu_apply_erratum_63(u16 devid);
17+
extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu);
1718
extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
1819
extern int amd_iommu_init_devices(void);
1920
extern void amd_iommu_uninit_devices(void);

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
#define PASID_MASK 0x0000ffff
111111

112112
/* MMIO status bits */
113+
#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK (1 << 0)
113114
#define MMIO_STATUS_EVT_INT_MASK (1 << 1)
114115
#define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2)
115116
#define MMIO_STATUS_PPR_INT_MASK (1 << 6)

drivers/iommu/amd/init.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,16 @@ static int __init alloc_command_buffer(struct amd_iommu *iommu)
657657
return iommu->cmd_buf ? 0 : -ENOMEM;
658658
}
659659

660+
/*
661+
* This function restarts event logging in case the IOMMU experienced
662+
* an event log buffer overflow.
663+
*/
664+
void amd_iommu_restart_event_logging(struct amd_iommu *iommu)
665+
{
666+
iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
667+
iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
668+
}
669+
660670
/*
661671
* This function resets the command buffer if the IOMMU stopped fetching
662672
* commands from it.

drivers/iommu/amd/io_pgtable.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -492,18 +492,18 @@ static void v1_free_pgtable(struct io_pgtable *iop)
492492

493493
dom = container_of(pgtable, struct protection_domain, iop);
494494

495-
/* Update data structure */
496-
amd_iommu_domain_clr_pt_root(dom);
497-
498-
/* Make changes visible to IOMMUs */
499-
amd_iommu_domain_update(dom);
500-
501495
/* Page-table is not visible to IOMMU anymore, so free it */
502496
BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
503497
pgtable->mode > PAGE_MODE_6_LEVEL);
504498

505499
free_sub_pt(pgtable->root, pgtable->mode, &freelist);
506500

501+
/* Update data structure */
502+
amd_iommu_domain_clr_pt_root(dom);
503+
504+
/* Make changes visible to IOMMUs */
505+
amd_iommu_domain_update(dom);
506+
507507
put_pages_list(&freelist);
508508
}
509509

drivers/iommu/amd/iommu.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,8 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { }
764764
#endif /* !CONFIG_IRQ_REMAP */
765765

766766
#define AMD_IOMMU_INT_MASK \
767-
(MMIO_STATUS_EVT_INT_MASK | \
767+
(MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \
768+
MMIO_STATUS_EVT_INT_MASK | \
768769
MMIO_STATUS_PPR_INT_MASK | \
769770
MMIO_STATUS_GALOG_INT_MASK)
770771

@@ -774,7 +775,7 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
774775
u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
775776

776777
while (status & AMD_IOMMU_INT_MASK) {
777-
/* Enable EVT and PPR and GA interrupts again */
778+
/* Enable interrupt sources again */
778779
writel(AMD_IOMMU_INT_MASK,
779780
iommu->mmio_base + MMIO_STATUS_OFFSET);
780781

@@ -795,6 +796,11 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
795796
}
796797
#endif
797798

799+
if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) {
800+
pr_info_ratelimited("IOMMU event log overflow\n");
801+
amd_iommu_restart_event_logging(iommu);
802+
}
803+
798804
/*
799805
* Hardware bug: ERBT1312
800806
* When re-enabling interrupt (by writing 1

drivers/iommu/intel/iommu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2738,7 +2738,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
27382738
spin_unlock_irqrestore(&device_domain_lock, flags);
27392739

27402740
/* PASID table is mandatory for a PCI device in scalable mode. */
2741-
if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
2741+
if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
27422742
ret = intel_pasid_alloc_table(dev);
27432743
if (ret) {
27442744
dev_err(dev, "PASID table allocation failed\n");

drivers/iommu/tegra-smmu.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,8 +808,10 @@ static struct tegra_smmu *tegra_smmu_find(struct device_node *np)
808808
return NULL;
809809

810810
mc = platform_get_drvdata(pdev);
811-
if (!mc)
811+
if (!mc) {
812+
put_device(&pdev->dev);
812813
return NULL;
814+
}
813815

814816
return mc->smmu;
815817
}

0 commit comments

Comments
 (0)