Commit 3f509f59 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents a4ffdb61 9826e393
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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)
+10 −0
Original line number Diff line number Diff line
@@ -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.
+6 −6
Original line number Diff line number Diff line
@@ -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);
}

+8 −2
Original line number Diff line number Diff line
@@ -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
Loading