16
16
*/
17
17
18
18
#include <linux/dma-contiguous.h>
19
+ #include <linux/dma-direct.h>
19
20
#include <linux/gfp.h>
20
21
#include <linux/highmem.h>
21
22
#include <linux/mm.h>
@@ -123,7 +124,7 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
123
124
unsigned long attrs )
124
125
{
125
126
unsigned long ret ;
126
- unsigned long uncached = 0 ;
127
+ unsigned long uncached ;
127
128
unsigned long count = PAGE_ALIGN (size ) >> PAGE_SHIFT ;
128
129
struct page * page = NULL ;
129
130
@@ -144,15 +145,27 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
144
145
if (!page )
145
146
return NULL ;
146
147
147
- ret = ( unsigned long ) page_address (page );
148
+ * handle = phys_to_dma ( dev , page_to_phys (page ) );
148
149
149
- /* We currently don't support coherent memory outside KSEG */
150
+ #ifdef CONFIG_MMU
151
+ if (PageHighMem (page )) {
152
+ void * p ;
150
153
154
+ p = dma_common_contiguous_remap (page , size , VM_MAP ,
155
+ pgprot_noncached (PAGE_KERNEL ),
156
+ __builtin_return_address (0 ));
157
+ if (!p ) {
158
+ if (!dma_release_from_contiguous (dev , page , count ))
159
+ __free_pages (page , get_order (size ));
160
+ }
161
+ return p ;
162
+ }
163
+ #endif
164
+ ret = (unsigned long )page_address (page );
151
165
BUG_ON (ret < XCHAL_KSEG_CACHED_VADDR ||
152
166
ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1 );
153
167
154
168
uncached = ret + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR ;
155
- * handle = virt_to_bus ((void * )ret );
156
169
__invalidate_dcache_range (ret , size );
157
170
158
171
return (void * )uncached ;
@@ -161,13 +174,20 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
161
174
static void xtensa_dma_free (struct device * dev , size_t size , void * vaddr ,
162
175
dma_addr_t dma_handle , unsigned long attrs )
163
176
{
164
- unsigned long addr = (unsigned long )vaddr +
165
- XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR ;
166
- struct page * page = virt_to_page (addr );
167
177
unsigned long count = PAGE_ALIGN (size ) >> PAGE_SHIFT ;
168
-
169
- BUG_ON (addr < XCHAL_KSEG_CACHED_VADDR ||
170
- addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1 );
178
+ unsigned long addr = (unsigned long )vaddr ;
179
+ struct page * page ;
180
+
181
+ if (addr >= XCHAL_KSEG_BYPASS_VADDR &&
182
+ addr - XCHAL_KSEG_BYPASS_VADDR < XCHAL_KSEG_SIZE ) {
183
+ addr += XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR ;
184
+ page = virt_to_page (addr );
185
+ } else {
186
+ #ifdef CONFIG_MMU
187
+ dma_common_free_remap (vaddr , size , VM_MAP );
188
+ #endif
189
+ page = pfn_to_page (PHYS_PFN (dma_to_phys (dev , dma_handle )));
190
+ }
171
191
172
192
if (!dma_release_from_contiguous (dev , page , count ))
173
193
__free_pages (page , get_order (size ));
0 commit comments