[PATCH 05/11] powerpc/powernv: Return failure for some uses of dma_set_mask()

Reza Arbab arbab at linux.ibm.com
Thu Oct 31 03:59:54 AEDT 2019


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 <arbab at linux.ibm.com>
Cc: Christoph Hellwig <hch at 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



More information about the Linuxppc-dev mailing list