diff options
Diffstat (limited to 'arch/arm/mm/consistent.c')
-rw-r--r-- | arch/arm/mm/consistent.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 76d1a5c74..310107678 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -29,20 +29,29 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) if (in_interrupt()) BUG(); + size = PAGE_ALIGN(size); order = get_order(size); page = __get_free_pages(gfp, order); if (!page) goto no_page; - memset((void *)page, 0, PAGE_SIZE << order); - clean_cache_area(page, PAGE_SIZE << order); + memset((void *)page, 0, size); + clean_cache_area(page, size); *dma_handle = virt_to_bus((void *)page); - ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0); - if (ret) + ret = __ioremap(virt_to_phys((void *)page), size, 0); + if (ret) { + /* free wasted pages */ + unsigned long end = page + (PAGE_SIZE << order); + page += size; + while (page < end) { + free_page(page); + page += PAGE_SIZE; + } return ret; + } free_pages(page, order); no_page: @@ -81,18 +90,18 @@ void consistent_free(void *vaddr) /* * make an area consistent. */ -void consistent_sync(void *vaddr, size_t size, int rw) +void consistent_sync(void *vaddr, size_t size, int direction) { - switch (rw) { - case 0: + switch (direction) { + case PCI_DMA_NONE: BUG(); - case 1: /* invalidate only */ + case PCI_DMA_FROMDEVICE: /* invalidate only */ dma_cache_inv(vaddr, size); break; - case 2: /* writeback only */ + case PCI_DMA_TODEVICE: /* writeback only */ dma_cache_wback(vaddr, size); break; - case 3: /* writeback and invalidate */ + case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */ dma_cache_wback_inv(vaddr, size); break; } |