[POWERPC] Add an optional offset to direct DMA on 64 bits
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Sat, 11 Nov 2006 06:25:14 +0000 (17:25 +1100)
committerPaul Mackerras <paulus@samba.org>
Mon, 4 Dec 2006 09:38:57 +0000 (20:38 +1100)
This patch adds an optional global offset that can be added to DMA addresses
when using the direct DMA operations.

That brings it a step closer to the 32 bits direct DMA operations, and makes
it useable on Cell when the MMU is disabled and we are using a spider
southbridge.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/dma_64.c
include/asm-powerpc/dma-mapping.h

index 4e65511997827228ee7af41846506566e2fc0b2c..1d1dc76606acbb5b229e05fd79805cc65e93dd5f 100644 (file)
@@ -111,7 +111,11 @@ 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)
@@ -122,7 +126,7 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
        ret = (void *)__get_free_pages(flag, get_order(size));
        if (ret != NULL) {
                memset(ret, 0, size);
-               *dma_handle = virt_to_abs(ret);
+               *dma_handle = virt_to_abs(ret) | dma_direct_offset;
        }
        return ret;
 }
@@ -137,7 +141,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 +156,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;
        }
 
index 8367810c994ce9873a3f37228072aa69395e2fde..7e38b5fddada918a8b7decdafa9c87139e5d4aff 100644 (file)
@@ -187,6 +187,8 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 extern struct dma_mapping_ops dma_iommu_ops;
 extern struct dma_mapping_ops dma_direct_ops;
 
+extern unsigned long dma_direct_offset;
+
 #else /* CONFIG_PPC64 */
 
 #define dma_supported(dev, mask)       (1)