Skip to content

Commit

Permalink
Merge tag 'iommu-fixes-v5.17-rc6' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
torvalds committed Mar 4, 2022
2 parents a4ffdb6 + 9826e39 commit 3f509f5
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 10 deletions.
1 change: 1 addition & 0 deletions drivers/iommu/amd/amd_iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/amd/amd_iommu_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions drivers/iommu/amd/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 6 additions & 6 deletions drivers/iommu/amd/io_pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
10 changes: 8 additions & 2 deletions drivers/iommu/amd/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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);

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/intel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
4 changes: 3 additions & 1 deletion drivers/iommu/tegra-smmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit 3f509f5

Please sign in to comment.