]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
powerpc/powernv/pci: Return failure for some uses of dma_set_mask()
authorAlistair Popple <alistair@popple.id.au>
Wed, 26 Jul 2017 05:26:40 +0000 (15:26 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 28 Jul 2017 13:02:55 +0000 (23:02 +1000)
Commit 8e3f1b1d8255 ("powerpc/powernv/pci: Enable 64-bit devices to access
>4GB DMA space") introduced the ability for PCI device drivers to request a
DMA mask between 64 and 32 bits and actually get a mask greater than
32-bits. However currently if certain machine configuration dependent
conditions are not meet the code silently falls back to a 32-bit mask.

This makes it hard for device drivers to detect which mask they actually
got. Instead we should return an error when the request could not be
fulfilled which allows drivers to either fallback or implement other
workarounds as documented in DMA-API-HOWTO.txt.

Signed-off-by: Alistair Popple <alistair@popple.id.au>
Acked-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/platforms/powernv/pci-ioda.c

index 437613588df15ceab2a1ce5e88649b675c495de4..b900eb1d5e174c1cdafc0a7e9620caecac98bb69 100644 (file)
@@ -1852,6 +1852,14 @@ static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
                        /* 4GB offset bypasses 32-bit space */
                        set_dma_offset(&pdev->dev, (1ULL << 32));
                        set_dma_ops(&pdev->dev, &dma_direct_ops);
+               } else if (dma_mask >> 32 && dma_mask != DMA_BIT_MASK(64)) {
+                       /*
+                        * Fail the request if a DMA mask between 32 and 64 bits
+                        * was requested but couldn't be fulfilled. Ideally we
+                        * would do this for 64-bits but historically we have
+                        * always fallen back to 32-bits.
+                        */
+                       return -ENOMEM;
                } else {
                        dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n");
                        set_dma_ops(&pdev->dev, &dma_iommu_ops);