core, dma-direct: add a flag 32-bit dma limits
authorChristoph Hellwig <hch@lst.de>
Fri, 27 Apr 2018 07:02:55 +0000 (09:02 +0200)
committerChristoph Hellwig <hch@lst.de>
Mon, 28 May 2018 10:46:54 +0000 (12:46 +0200)
Various PCI bridges (VIA PCI, Xilinx PCIe) limit DMA to only 32-bits
even if the device itself supports more.  Add a single bit flag to
struct device (to be moved into the dma extension once we get to it)
to flag such devices and reject larger DMA to them.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/device.h
lib/dma-direct.c

index 563077d..00b6c3b 100644 (file)
@@ -904,6 +904,8 @@ struct dev_links_info {
  * @offline:   Set after successful invocation of bus type's .offline().
  * @of_node_reused: Set if the device-tree node is shared with an ancestor
  *              device.
+ * @dma_32bit_limit: bridge limited to 32bit DMA even if the device itself
+ *             indicates support for a higher limit in the dma_mask field.
  *
  * At the lowest level, every device in a Linux system is represented by an
  * instance of struct device. The device structure contains the information
@@ -992,6 +994,7 @@ struct device {
        bool                    offline_disabled:1;
        bool                    offline:1;
        bool                    of_node_reused:1;
+       bool                    dma_32bit_limit:1;
 };
 
 static inline struct device *kobj_to_dev(struct kobject *kobj)
index b824eb2..a48f94e 100644 (file)
@@ -172,6 +172,12 @@ int dma_direct_supported(struct device *dev, u64 mask)
        if (mask < DMA_BIT_MASK(32))
                return 0;
 #endif
+       /*
+        * Various PCI/PCIe bridges have broken support for > 32bit DMA even
+        * if the device itself might support it.
+        */
+       if (dev->dma_32bit_limit && mask > DMA_BIT_MASK(32))
+               return 0;
        return 1;
 }