The code was assuming that in such cases we can just use cpu addresses as physical ones. This is incorrect on MIPS, the only platform that has its own virt_to_phys/phys_to_virt functions defined. This fixes issues with DMA mappings on MIPS, with e1000 PCI ethernet card now working on Malta in QEMU. Signed-off-by: Denis Orlov <denorl2009@xxxxxxxxx> --- drivers/dma/map.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/dma/map.c b/drivers/dma/map.c index a00abf6421..13dbf2840f 100644 --- a/drivers/dma/map.c +++ b/drivers/dma/map.c @@ -3,25 +3,20 @@ #include <dma.h> -static inline dma_addr_t cpu_to_dma(struct device *dev, - unsigned long cpu_addr) +static inline dma_addr_t cpu_to_dma(struct device *dev, void *cpu_addr) { - dma_addr_t dma_addr = cpu_addr; + if (dev && dev->dma_offset) + return (unsigned long)cpu_addr - dev->dma_offset; - if (dev) - dma_addr -= dev->dma_offset; - - return dma_addr; + return virt_to_phys(cpu_addr); } -static inline unsigned long dma_to_cpu(struct device *dev, dma_addr_t addr) +static inline void *dma_to_cpu(struct device *dev, dma_addr_t addr) { - unsigned long cpu_addr = addr; - - if (dev) - cpu_addr += dev->dma_offset; + if (dev && dev->dma_offset) + return (void *)(addr + dev->dma_offset); - return cpu_addr; + return phys_to_virt(addr); } dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, @@ -31,13 +26,13 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, dma_sync_single_for_device(addr, size, dir); - return cpu_to_dma(dev, addr); + return cpu_to_dma(dev, ptr); } void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long addr = dma_to_cpu(dev, dma_addr); + unsigned long addr = (unsigned long)dma_to_cpu(dev, dma_addr); dma_sync_single_for_cpu(addr, size, dir); } -- 2.30.2