Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Hexagon: use correct translations for DMA mappings

With physical offsets, pa<->va translations aren't just based
on PAGE_OFFSET anymore.

Signed-off-by: Richard Kuo <rkuo@codeaurora.org>

+22 -10
+5
arch/hexagon/include/asm/page.h
··· 140 140 */ 141 141 #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) 142 142 143 + #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 144 + #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) 145 + 146 + #define page_to_virt(page) __va(page_to_phys(page)) 147 + 143 148 /* 144 149 * For port to Hexagon Virtual Machine, MAYBE we check for attempts 145 150 * to reference reserved HVM space, but in any case, the VM will be
+17 -10
arch/hexagon/kernel/dma.c
··· 1 1 /* 2 2 * DMA implementation for Hexagon 3 3 * 4 - * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify 7 7 * it under the terms of the GNU General Public License version 2 and ··· 23 23 #include <linux/genalloc.h> 24 24 #include <asm/dma-mapping.h> 25 25 #include <linux/module.h> 26 + #include <asm/page.h> 26 27 27 28 struct dma_map_ops *dma_ops; 28 29 EXPORT_SYMBOL(dma_ops); 29 30 30 31 int bad_dma_address; /* globals are automatically initialized to zero */ 32 + 33 + static inline void *dma_addr_to_virt(dma_addr_t dma_addr) 34 + { 35 + return phys_to_virt((unsigned long) dma_addr); 36 + } 31 37 32 38 int dma_supported(struct device *dev, u64 mask) 33 39 { ··· 66 60 { 67 61 void *ret; 68 62 63 + /* 64 + * Our max_low_pfn should have been backed off by 16MB in 65 + * mm/init.c to create DMA coherent space. Use that as the VA 66 + * for the pool. 67 + */ 68 + 69 69 if (coherent_pool == NULL) { 70 70 coherent_pool = gen_pool_create(PAGE_SHIFT, -1); 71 71 ··· 79 67 panic("Can't create %s() memory pool!", __func__); 80 68 else 81 69 gen_pool_add(coherent_pool, 82 - (PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)), 70 + pfn_to_virt(max_low_pfn), 83 71 hexagon_coherent_pool_size, -1); 84 72 } 85 73 ··· 87 75 88 76 if (ret) { 89 77 memset(ret, 0, size); 90 - *dma_addr = (dma_addr_t) (ret - PAGE_OFFSET); 78 + *dma_addr = (dma_addr_t) virt_to_phys(ret); 91 79 } else 92 80 *dma_addr = ~0; 93 81 ··· 130 118 131 119 s->dma_length = s->length; 132 120 133 - flush_dcache_range(PAGE_OFFSET + s->dma_address, 134 - PAGE_OFFSET + s->dma_address + s->length); 121 + flush_dcache_range(dma_addr_to_virt(s->dma_address), 122 + dma_addr_to_virt(s->dma_address + s->length)); 135 123 } 136 124 137 125 return nents; ··· 159 147 default: 160 148 BUG(); 161 149 } 162 - } 163 - 164 - static inline void *dma_addr_to_virt(dma_addr_t dma_addr) 165 - { 166 - return phys_to_virt((unsigned long) dma_addr); 167 150 } 168 151 169 152 /**