summaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/consistent.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/consistent.c')
-rw-r--r--arch/arm/mm/consistent.c29
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;
}