dma-mapping: add flags to dma_map_ops to indicate PCI P2PDMA support
authorLogan Gunthorpe <logang@deltatee.com>
Fri, 8 Jul 2022 16:50:57 +0000 (10:50 -0600)
committerChristoph Hellwig <hch@lst.de>
Tue, 26 Jul 2022 11:27:48 +0000 (07:27 -0400)
Add a flags member to the dma_map_ops structure with one flag to
indicate support for PCI P2PDMA.

Also, add a helper to check if a device supports PCI P2PDMA.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
include/linux/dma-map-ops.h
include/linux/dma-mapping.h
kernel/dma/mapping.c

index 99cec59..010df04 100644 (file)
 
 struct cma;
 
+/*
+ * Values for struct dma_map_ops.flags:
+ *
+ * DMA_F_PCI_P2PDMA_SUPPORTED: Indicates the dma_map_ops implementation can
+ * handle PCI P2PDMA pages in the map_sg/unmap_sg operation.
+ */
+#define DMA_F_PCI_P2PDMA_SUPPORTED     (1 << 0)
+
 struct dma_map_ops {
+       unsigned int flags;
+
        void *(*alloc)(struct device *dev, size_t size,
                        dma_addr_t *dma_handle, gfp_t gfp,
                        unsigned long attrs);
index fe38494..25a3090 100644 (file)
@@ -140,6 +140,7 @@ int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
                unsigned long attrs);
 bool dma_can_mmap(struct device *dev);
 int dma_supported(struct device *dev, u64 mask);
+bool dma_pci_p2pdma_supported(struct device *dev);
 int dma_set_mask(struct device *dev, u64 mask);
 int dma_set_coherent_mask(struct device *dev, u64 mask);
 u64 dma_get_required_mask(struct device *dev);
@@ -251,6 +252,10 @@ static inline int dma_supported(struct device *dev, u64 mask)
 {
        return 0;
 }
+static inline bool dma_pci_p2pdma_supported(struct device *dev)
+{
+       return false;
+}
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
        return -EIO;
index 746d468..a9ce5d7 100644 (file)
@@ -723,6 +723,24 @@ int dma_supported(struct device *dev, u64 mask)
 }
 EXPORT_SYMBOL(dma_supported);
 
+bool dma_pci_p2pdma_supported(struct device *dev)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev);
+
+       /* if ops is not set, dma direct will be used which supports P2PDMA */
+       if (!ops)
+               return true;
+
+       /*
+        * Note: dma_ops_bypass is not checked here because P2PDMA should
+        * not be used with dma mapping ops that do not have support even
+        * if the specific device is bypassing them.
+        */
+
+       return ops->flags & DMA_F_PCI_P2PDMA_SUPPORTED;
+}
+EXPORT_SYMBOL_GPL(dma_pci_p2pdma_supported);
+
 #ifdef CONFIG_ARCH_HAS_DMA_SET_MASK
 void arch_dma_set_mask(struct device *dev, u64 mask);
 #else