The ioctl VFIO_IOMMU_SPAPR_TCE_GET_INFO is not reporting the
actuals on the platform as not all the details are correctly
collected during the platform probe/scan into the iommu_table_group.

Collect the information during the device setup time as the DMA
window property is already looked up on parent nodes anyway.

Signed-off-by: Shivaprasad G Bhat <sb...@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/iommu.c |   81 ++++++++++++++++++++++++++------
 1 file changed, 67 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index bbe7eaacd829..97b9a4e6bf8a 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -865,13 +865,6 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus 
*bus)
                                be32_to_cpu(prop.tce_shift), NULL,
                                &iommu_table_lpar_multi_ops);
 
-               /* Only for normal boot with default window. Doesn't matter even
-                * if we set these with DDW which is 64bit during kdump, since
-                * these will not be used during kdump.
-                */
-               ppci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
-               ppci->table_group->tce32_size = 1 << 
be32_to_cpu(prop.window_shift);
-
                if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
                        panic("Failed to initialize iommu table");
 
@@ -1623,6 +1616,71 @@ static bool enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
        return direct_mapping;
 }
 
+static __u64 query_page_size_to_mask(u32 query_page_size)
+{
+       const long shift[] = {
+               (SZ_4K),   (SZ_64K), (SZ_16M),
+               (SZ_32M),  (SZ_64M), (SZ_128M),
+               (SZ_256M), (SZ_16G), (SZ_2M)
+       };
+       int i, ret = 0;
+
+       for (i = 0; i < ARRAY_SIZE(shift); i++) {
+               if (query_page_size & (1 << i))
+                       ret |= shift[i];
+       }
+
+       return ret;
+}
+
+static void spapr_tce_init_table_group(struct pci_dev *pdev,
+                                      struct device_node *pdn,
+                                      struct dynamic_dma_window_prop prop)
+{
+       struct iommu_table_group  *table_group = PCI_DN(pdn)->table_group;
+       u32 ddw_avail[DDW_APPLICABLE_SIZE];
+
+       struct ddw_query_response query;
+       int ret;
+
+       /* Only for normal boot with default window. Doesn't matter during
+        * kdump, since these will not be used during kdump.
+        */
+       if (is_kdump_kernel())
+               return;
+
+       if (table_group->max_dynamic_windows_supported != 0)
+               return; /* already initialized */
+
+       table_group->tce32_start = be64_to_cpu(prop.dma_base);
+       table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);
+
+       if (!of_find_property(pdn, "ibm,dma-window", NULL))
+               dev_err(&pdev->dev, "default dma window missing!\n");
+
+       ret = of_property_read_u32_array(pdn, "ibm,ddw-applicable",
+                       &ddw_avail[0], DDW_APPLICABLE_SIZE);
+       if (ret) {
+               table_group->max_dynamic_windows_supported = -1;
+               return;
+       }
+
+       ret = query_ddw(pdev, ddw_avail, &query, pdn);
+       if (ret) {
+               dev_err(&pdev->dev, "%s: query_ddw failed\n", __func__);
+               table_group->max_dynamic_windows_supported = -1;
+               return;
+       }
+
+       if (query.windows_available == 0)
+               table_group->max_dynamic_windows_supported = 1;
+       else
+               table_group->max_dynamic_windows_supported = 
IOMMU_TABLE_GROUP_MAX_TABLES;
+
+       table_group->max_levels = 1;
+       table_group->pgsizes |= query_page_size_to_mask(query.page_size);
+}
+
 static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 {
        struct device_node *pdn, *dn;
@@ -1662,13 +1720,6 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev 
*dev)
                                be32_to_cpu(prop.tce_shift), NULL,
                                &iommu_table_lpar_multi_ops);
 
-               /* Only for normal boot with default window. Doesn't matter even
-                * if we set these with DDW which is 64bit during kdump, since
-                * these will not be used during kdump.
-                */
-               pci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
-               pci->table_group->tce32_size = 1 << 
be32_to_cpu(prop.window_shift);
-
                iommu_init_table(tbl, pci->phb->node, 0, 0);
                iommu_register_group(pci->table_group,
                                pci_domain_nr(pci->phb->bus), 0);
@@ -1677,6 +1728,8 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev 
*dev)
                pr_debug("  found DMA window, table: %p\n", pci->table_group);
        }
 
+       spapr_tce_init_table_group(dev, pdn, prop);
+
        set_iommu_table_base(&dev->dev, pci->table_group->tables[0]);
        iommu_add_device(pci->table_group, &dev->dev);
 }


Reply via email to