diff mbox series

iommu/powerpc: Incorrect DDW Table is referenced for SR-IOV device

Message ID 20230505184701.91613-1-gbatra@linux.vnet.ibm.com (mailing list archive)
State Accepted
Commit 1f7aacc5eb9ed2cc17be7a90da5cd559effb9d59
Headers show
Series iommu/powerpc: Incorrect DDW Table is referenced for SR-IOV device | expand

Checks

Context Check Description
snowpatch_ozlabs/github-powerpc_ppctests success Successfully ran 8 jobs.
snowpatch_ozlabs/github-powerpc_selftests success Successfully ran 8 jobs.
snowpatch_ozlabs/github-powerpc_sparse success Successfully ran 4 jobs.
snowpatch_ozlabs/github-powerpc_kernel_qemu success Successfully ran 24 jobs.
snowpatch_ozlabs/github-powerpc_clang success Successfully ran 6 jobs.

Commit Message

Gaurav Batra May 5, 2023, 6:47 p.m. UTC
For an SR-IOV device, while enabling DDW, a new table is created and added
at index 1 in the group. In the below 2 scenarios, the table is incorrectly
referenced at index 0 (which is where the table is for default DMA window).

1. When adding DDW

        This issue is exposed with "slub_debug". Error thrown out from
        dma_iommu_dma_supported()

        Warning: IOMMU offset too big for device mask
        mask: 0xffffffff, table offset: 0x800000000000000

2. During Dynamic removal of the PCI device.

        Error is from iommu_tce_table_put() since a NULL table pointer is
        passed in.

Fixes: 381ceda88c4c ("powerpc/pseries/iommu: Make use of DDW for indirect mapping")

Signed-off-by: Gaurav Batra <gbatra@linux.vnet.ibm.com>

Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/dma-iommu.c        |  4 +++-
 arch/powerpc/platforms/pseries/iommu.c | 13 +++++++++----
 2 files changed, 12 insertions(+), 5 deletions(-)

--

Comments

Michael Ellerman July 3, 2023, 5:21 a.m. UTC | #1
On Fri, 05 May 2023 13:47:01 -0500, Gaurav Batra wrote:
> For an SR-IOV device, while enabling DDW, a new table is created and added
> at index 1 in the group. In the below 2 scenarios, the table is incorrectly
> referenced at index 0 (which is where the table is for default DMA window).
> 
> 1. When adding DDW
> 
>         This issue is exposed with "slub_debug". Error thrown out from
>         dma_iommu_dma_supported()
> 
> [...]

Applied to powerpc/fixes.

[1/1] iommu/powerpc: Incorrect DDW Table is referenced for SR-IOV device
      https://git.kernel.org/powerpc/c/1f7aacc5eb9ed2cc17be7a90da5cd559effb9d59

cheers
diff mbox series

Patch

diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 038ce8d9061d..8920862ffd79 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -144,7 +144,7 @@  static bool dma_iommu_bypass_supported(struct device *dev, u64 mask)
 /* We support DMA to/from any memory page via the iommu */
 int dma_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	struct iommu_table *tbl = get_iommu_table_base(dev);
+	struct iommu_table *tbl;
 
 	if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
 		/*
@@ -162,6 +162,8 @@  int dma_iommu_dma_supported(struct device *dev, u64 mask)
 		return 1;
 	}
 
+	tbl = get_iommu_table_base(dev);
+
 	if (!tbl) {
 		dev_err(dev, "Warning: IOMMU dma not supported: mask 0x%08llx, table unavailable\n", mask);
 		return 0;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index c74b71d4733d..a8acd3b402d7 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -85,19 +85,24 @@  static struct iommu_table_group *iommu_pseries_alloc_group(int node)
 static void iommu_pseries_free_group(struct iommu_table_group *table_group,
 		const char *node_name)
 {
-	struct iommu_table *tbl;
-
 	if (!table_group)
 		return;
 
-	tbl = table_group->tables[0];
 #ifdef CONFIG_IOMMU_API
 	if (table_group->group) {
 		iommu_group_put(table_group->group);
 		BUG_ON(table_group->group);
 	}
 #endif
-	iommu_tce_table_put(tbl);
+
+	/* Default DMA window table is at index 0, while DDW at 1. SR-IOV
+	 * adapters only have table on index 1.
+	 */
+	if (table_group->tables[0])
+		iommu_tce_table_put(table_group->tables[0]);
+
+	if (table_group->tables[1])
+		iommu_tce_table_put(table_group->tables[1]);
 
 	kfree(table_group);
 }