]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/kernel/dma_64.c
Merge branch 'server-cluster-locking-api' of git://linux-nfs.org/~bfields/linux
[linux-2.6-omap-h63xx.git] / arch / powerpc / kernel / dma_64.c
index 4e65511997827228ee7af41846506566e2fc0b2c..7b0e754383cf53e47affcf4a46acab9b5264761c 100644 (file)
@@ -111,19 +111,27 @@ EXPORT_SYMBOL(dma_iommu_ops);
 
 /*
  * Generic direct DMA implementation
+ *
+ * This implementation supports a global offset that can be applied if
+ * the address at which memory is visible to devices is not 0.
  */
+unsigned long dma_direct_offset;
 
 static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
                                       dma_addr_t *dma_handle, gfp_t flag)
 {
+       struct page *page;
        void *ret;
+       int node = dev->archdata.numa_node;
 
        /* TODO: Maybe use the numa node here too ? */
-       ret = (void *)__get_free_pages(flag, get_order(size));
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_abs(ret);
-       }
+       page = alloc_pages_node(node, flag, get_order(size));
+       if (page == NULL)
+               return NULL;
+       ret = page_address(page);
+       memset(ret, 0, size);
+       *dma_handle = virt_to_abs(ret) | dma_direct_offset;
+
        return ret;
 }
 
@@ -137,7 +145,7 @@ static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
                                        size_t size,
                                        enum dma_data_direction direction)
 {
-       return virt_to_abs(ptr);
+       return virt_to_abs(ptr) | dma_direct_offset;
 }
 
 static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
@@ -152,7 +160,8 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg,
        int i;
 
        for (i = 0; i < nents; i++, sg++) {
-               sg->dma_address = page_to_phys(sg->page) + sg->offset;
+               sg->dma_address = (page_to_phys(sg->page) + sg->offset) |
+                       dma_direct_offset;
                sg->dma_length = sg->length;
        }