Pull button into test branch
[linux-drm-fsl-dcu.git] / arch / xtensa / kernel / pci-dma.c
index 1ff82268e8eacf354e5f16eae1a9ea182d3ca191..ca76f071666e895aea125f3927d07bcb385fdcd7 100644 (file)
  */
 
 void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
 {
-       void *ret;
+       unsigned long ret;
+       unsigned long uncached = 0;
 
        /* ignore region speicifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
-       if (dev == NULL || (*dev->dma_mask < 0xffffffff))
-               gfp |= GFP_DMA;
-       ret = (void *)__get_free_pages(gfp, get_order(size));
+       flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *handle = virt_to_bus(ret);
+       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+               flag |= GFP_DMA;
+       ret = (unsigned long)__get_free_pages(flag, get_order(size));
+
+       if (ret == 0)
+               return NULL;
+
+       /* We currently don't support coherent memory outside KSEG */
+
+       if (ret < XCHAL_KSEG_CACHED_VADDR
+           || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
+               BUG();
+
+
+       if (ret != 0) {
+               memset((void*) ret, 0, size);
+               uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;
+               *handle = virt_to_bus((void*)ret);
+               __flush_invalidate_dcache_range(ret, size);
        }
-       return (void*) BYPASS_ADDR((unsigned long)ret);
+
+       return (void*)uncached;
 }
 
 void dma_free_coherent(struct device *hwdev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
-       free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
+       long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+
+       if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
+               BUG();
+
+       free_pages(addr, get_order(size));
 }