[PATCH v11 07/11] device-mapping: Introduce DMA range map, supplanting dma_pfn_offset
Christoph Hellwig
hch at lst.de
Tue Sep 8 07:29:35 UTC 2020
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:
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index c21893f683b585..072fc42349874d 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -35,21 +35,16 @@ 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);
+ return translate_phys_to_dma(dev, 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);
+ return PFN_DOWN(translate_dma_to_phys(dev, 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;
}
More information about the devel
mailing list