On Tue, Sep 08, 2020 at 09:29:35AM +0200, Christoph Hellwig wrote:
> FYI, this is what I'd do relative to the patch on the dma-ranges
> branch.  In fact realizing this makes me want to refactor things a bit
> so that the new code can entirely live in the dma-direct code, but please
> test this first:

And of course this isn't going to work for arm devices without any
range, so let's try this instead:

diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index c21893f683b585..e913e04d2be8b9 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -35,21 +35,20 @@ static inline const struct dma_map_ops 
*get_arch_dma_ops(struct bus_type *bus)
 #ifndef __arch_pfn_to_dma
 static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-       if (dev) {
-               phys_addr_t paddr = PFN_PHYS(pfn);
-
-               pfn -= PFN_DOWN(dma_offset_from_phys_addr(dev, paddr));
-       }
-       return (dma_addr_t)__pfn_to_bus(pfn);
+       if (!dev)
+               return (dma_addr_t)__pfn_to_bus(pfn);
+       if (dev->dma_range_map)
+               return translate_phys_to_dma(dev, PFN_PHYS(pfn));
+       return (dma_addr_t)PFN_PHYS(pfn);
 }
 
 static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-       unsigned long pfn = __bus_to_pfn(addr);
-
-       if (dev)
-               pfn += PFN_DOWN(dma_offset_from_dma_addr(dev, addr));
-       return pfn;
+       if (!dev)
+               return __bus_to_pfn(addr);
+       if (dev->dma_range_map)
+               return PFN_DOWN(translate_dma_to_phys(dev, addr));
+       return PFN_DOWN(addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 7831ca5b1b5dd6..e624171c4962ad 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -19,12 +19,16 @@ extern unsigned int zone_dma_bits;
 #else
 static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-       return (dma_addr_t)paddr - dma_offset_from_phys_addr(dev, paddr);
+       if (dev->dma_range_map)
+               return (dma_addr_t)paddr - translate_phys_to_dma(dev, paddr);
+       return (dma_addr_t)paddr;
 }
 
-static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t 
dev_addr)
+static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t 
dma_addr)
 {
-       return (phys_addr_t)dev_addr + dma_offset_from_dma_addr(dev, dev_addr);
+       if (dev->dma_range_map)
+               return translate_dma_to_phys(dev, dma_addr);
+       return (phys_addr_t)dma_addr;
 }
 #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
 
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4c4646761afee4..3b1ceebb6f2ad5 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -199,29 +199,28 @@ struct bus_dma_region {
 };
 
 #ifdef CONFIG_HAS_DMA
-static inline u64 dma_offset_from_dma_addr(struct device *dev,
-               dma_addr_t dma_addr)
+static inline dma_addr_t translate_phys_to_dma(struct device *dev,
+               phys_addr_t paddr)
 {
-       const struct bus_dma_region *m = dev->dma_range_map;
+       const struct bus_dma_region *m;
 
-       if (m)
-               for (; m->size; m++)
-                       if (dma_addr >= m->dma_start &&
-                           dma_addr - m->dma_start < m->size)
-                               return m->offset;
-       return 0;
+       for (m = dev->dma_range_map; m->size; m++)
+               if (paddr >= m->cpu_start && paddr - m->cpu_start < m->size)
+                       return (dma_addr_t)paddr - m->offset;
+
+       /* make sure dma_capable fails when no translation is available */
+       return DMA_MAPPING_ERROR; 
 }
 
-static inline u64 dma_offset_from_phys_addr(struct device *dev,
-               phys_addr_t paddr)
+static inline phys_addr_t translate_dma_to_phys(struct device *dev,
+               dma_addr_t dma_addr)
 {
-       const struct bus_dma_region *m = dev->dma_range_map;
+       const struct bus_dma_region *m;
+
+       for (m = dev->dma_range_map; m->size; m++)
+               if (dma_addr >= m->dma_start && dma_addr - m->dma_start < 
m->size)
+                       return (phys_addr_t)dma_addr + m->offset;
 
-       if (m)
-               for (; m->size; m++)
-                       if (paddr >= m->cpu_start &&
-                           paddr - m->cpu_start < m->size)
-                               return m->offset;
        return 0;
 }
 
_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to