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

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")
Cc: stable@vger.kernel.org # v5.15+
Signed-off-by: Gaurav Batra <gbatra@linux.vnet.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230505184701.91613-1-gbatra@linux.vnet.ibm.com

authored by Gaurav Batra and committed by Michael Ellerman 1f7aacc5 096339ab

Changed files
+12 -5
arch
powerpc
kernel
platforms
pseries
+3 -1
arch/powerpc/kernel/dma-iommu.c
··· 144 144 /* We support DMA to/from any memory page via the iommu */ 145 145 int dma_iommu_dma_supported(struct device *dev, u64 mask) 146 146 { 147 - struct iommu_table *tbl = get_iommu_table_base(dev); 147 + struct iommu_table *tbl; 148 148 149 149 if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) { 150 150 /* ··· 161 161 dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n"); 162 162 return 1; 163 163 } 164 + 165 + tbl = get_iommu_table_base(dev); 164 166 165 167 if (!tbl) { 166 168 dev_err(dev, "Warning: IOMMU dma not supported: mask 0x%08llx, table unavailable\n", mask);
+9 -4
arch/powerpc/platforms/pseries/iommu.c
··· 91 91 static void iommu_pseries_free_group(struct iommu_table_group *table_group, 92 92 const char *node_name) 93 93 { 94 - struct iommu_table *tbl; 95 - 96 94 if (!table_group) 97 95 return; 98 96 99 - tbl = table_group->tables[0]; 100 97 #ifdef CONFIG_IOMMU_API 101 98 if (table_group->group) { 102 99 iommu_group_put(table_group->group); 103 100 BUG_ON(table_group->group); 104 101 } 105 102 #endif 106 - iommu_tce_table_put(tbl); 103 + 104 + /* Default DMA window table is at index 0, while DDW at 1. SR-IOV 105 + * adapters only have table on index 1. 106 + */ 107 + if (table_group->tables[0]) 108 + iommu_tce_table_put(table_group->tables[0]); 109 + 110 + if (table_group->tables[1]) 111 + iommu_tce_table_put(table_group->tables[1]); 107 112 108 113 kfree(table_group); 109 114 }