Rework of pnv_pci_ioda_dma_set_mask() effectively reverted commit
253fd51e2f53 ("powerpc/powernv/pci: Return failure for some uses of
dma_set_mask()").

Reintroduce the desired behavior that an unfulfilled request for a DMA
mask between 32 and 64 bits will return error instead of silently
falling back to 32 bits.

Fixes: 2d6ad41b2c21 ("powerpc/powernv: use the generic iommu bypass code")
Signed-off-by: Reza Arbab <ar...@linux.ibm.com>
Cc: Christoph Hellwig <h...@lst.de>
---
 arch/powerpc/kernel/dma-iommu.c           | 19 +++++++++++++++----
 arch/powerpc/platforms/powernv/pci-ioda.c |  8 ++++++--
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index e486d1d78de2..e1693760654b 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -122,10 +122,21 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask)
 {
        struct iommu_table *tbl = get_iommu_table_base(dev);
 
-       if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
-               dev->archdata.iommu_bypass = true;
-               dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
-               return 1;
+       if (dev_is_pci(dev)) {
+               if (dma_iommu_bypass_supported(dev, mask)) {
+                       dev->archdata.iommu_bypass = true;
+                       dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
+                       return 1;
+               }
+
+               if (mask >> 32) {
+                       dev_err(dev, "Warning: IOMMU dma bypass not supported: 
mask 0x%016llx\n",
+                               mask);
+
+                       /* A 64-bit request falls back to default ops */
+                       if (mask != DMA_BIT_MASK(64))
+                               return 0;
+               }
        }
 
        if (!tbl) {
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 70e834635971..b78b5e81f941 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1863,8 +1863,12 @@ static bool pnv_pci_ioda_iommu_bypass_supported(struct 
pci_dev *pdev,
                bypass = true;
        }
 
-       /* Update peer npu devices */
-       pnv_npu_try_dma_set_bypass(pdev, dma_mask);
+       /*
+        * Update peer npu devices. We also do this for the special case where
+        * a 64-bit dma mask can't be fulfilled and falls back to default.
+        */
+       if (bypass || !(dma_mask >> 32) || dma_mask == DMA_BIT_MASK(64))
+               pnv_npu_try_dma_set_bypass(pdev, dma_mask);
 
        return bypass;
 }
-- 
1.8.3.1

Reply via email to