X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-ppc%2Fdma-mapping.h;h=9be4f7297400cc3cb5ac7ee42f16f4cc0d53ec1c;hb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;hp=80b5e0b9a68b224802400df604ed465d0707aa85;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h index 80b5e0b9a..9be4f7297 100644 --- a/include/asm-ppc/dma-mapping.h +++ b/include/asm-ppc/dma-mapping.h @@ -6,15 +6,48 @@ #define __ASM_PPC_DMA_MAPPING_H #include -/* we implement the API below in terms of the existing PCI one, - * so include it */ -#include /* need struct page definitions */ #include #include #include #include +#ifdef CONFIG_NOT_COHERENT_CACHE +/* + * DMA-consistent mapping functions for PowerPCs that don't support + * cache snooping. These allocate/free a region of uncached mapped + * memory space for use with DMA devices. Alternatively, you could + * allocate the space "normally" and use the cache management functions + * to ensure it is consistent. + */ +extern void *__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp); +extern void __dma_free_coherent(size_t size, void *vaddr); +extern void __dma_sync(void *vaddr, size_t size, int direction); +extern void __dma_sync_page(struct page *page, unsigned long offset, + size_t size, int direction); +#define dma_cache_inv(_start,_size) \ + invalidate_dcache_range(_start, (_start + _size)) +#define dma_cache_wback(_start,_size) \ + clean_dcache_range(_start, (_start + _size)) +#define dma_cache_wback_inv(_start,_size) \ + flush_dcache_range(_start, (_start + _size)) + +#else /* ! CONFIG_NOT_COHERENT_CACHE */ +/* + * Cache coherent cores. + */ + +#define dma_cache_inv(_start,_size) do { } while (0) +#define dma_cache_wback(_start,_size) do { } while (0) +#define dma_cache_wback_inv(_start,_size) do { } while (0) + +#define __dma_alloc_coherent(gfp, size, handle) NULL +#define __dma_free_coherent(size, addr) do { } while (0) +#define __dma_sync(addr, size, rw) do { } while (0) +#define __dma_sync_page(pg, off, sz, rw) do { } while (0) + +#endif /* ! CONFIG_NOT_COHERENT_CACHE */ + #define dma_supported(dev, mask) (1) static inline int dma_set_mask(struct device *dev, u64 dma_mask) @@ -28,28 +61,38 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask) } static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t * dma_handle, int flag) + dma_addr_t * dma_handle, int gfp) { -#ifdef CONFIG_PCI - if (dev && dev->bus == &pci_bus_type) - return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); -#endif +#ifdef CONFIG_NOT_COHERENT_CACHE + return __dma_alloc_coherent(size, dma_handle, gfp); +#else + void *ret; + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + + if (dev == NULL || dev->coherent_dma_mask < 0xffffffff) + gfp |= GFP_DMA; + + ret = (void *)__get_free_pages(gfp, get_order(size)); - return consistent_alloc(flag, size, dma_handle); + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + + return ret; +#endif } static inline void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { -#ifdef CONFIG_PCI - if (dev && dev->bus == &pci_bus_type) { - pci_free_consistent(to_pci_dev(dev), size, vaddr, dma_handle); - return; - } +#ifdef CONFIG_NOT_COHERENT_CACHE + __dma_free_coherent(size, vaddr); +#else + free_pages((unsigned long)vaddr, get_order(size)); #endif - - consistent_free(vaddr); } static inline dma_addr_t @@ -58,7 +101,7 @@ dma_map_single(struct device *dev, void *ptr, size_t size, { BUG_ON(direction == DMA_NONE); - consistent_sync(ptr, size, direction); + __dma_sync(ptr, size, direction); return virt_to_bus(ptr); } @@ -72,12 +115,14 @@ dma_map_page(struct device *dev, struct page *page, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); - consistent_sync_page(page, offset, size, direction); + + __dma_sync_page(page, offset, size, direction); + return (page - mem_map) * PAGE_SIZE + PCI_DRAM_OFFSET + offset; } /* We do nothing. */ -#define dma_unmap_page(dev, addr, size, dir) do { } while (0) +#define dma_unmap_page(dev, handle, size, dir) do { } while (0) static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, @@ -89,8 +134,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, for (i = 0; i < nents; i++, sg++) { BUG_ON(!sg->page); - consistent_sync_page(sg->page, sg->offset, - sg->length, direction); + __dma_sync_page(sg->page, sg->offset, sg->length, direction); sg->dma_address = page_to_bus(sg->page) + sg->offset; } @@ -107,50 +151,50 @@ dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, { BUG_ON(direction == DMA_NONE); - consistent_sync(bus_to_virt(dma_handle), size, direction); + __dma_sync(bus_to_virt(dma_handle), size, direction); } static inline void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, - size_t size, - enum dma_data_direction direction) + size_t size, + enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); - consistent_sync(bus_to_virt(dma_handle), size, direction); + __dma_sync(bus_to_virt(dma_handle), size, direction); } static inline void -dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction direction) +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) { int i; BUG_ON(direction == DMA_NONE); - for (i = 0; i < nelems; i++, sg++) - consistent_sync_page(sg->page, sg->offset, - sg->length, direction); + for (i = 0; i < nents; i++, sg++) + __dma_sync_page(sg->page, sg->offset, sg->length, direction); } static inline void -dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction direction) +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) { int i; BUG_ON(direction == DMA_NONE); - for (i = 0; i < nelems; i++, sg++) - consistent_sync_page(sg->page, sg->offset, - sg->length, direction); + for (i = 0; i < nents; i++, sg++) + __dma_sync_page(sg->page, sg->offset, sg->length, direction); } -/* Now for the API extensions over the pci_ one */ - #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) +#ifdef CONFIG_NOT_COHERENT_CACHE +#define dma_is_consistent(d) (0) +#else #define dma_is_consistent(d) (1) +#endif static inline int dma_get_cache_alignment(void) { @@ -163,26 +207,26 @@ static inline int dma_get_cache_alignment(void) static inline void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) + unsigned long offset, size_t size, + enum dma_data_direction direction) { - /* just sync everything, that's all the pci API can do */ + /* just sync everything for now */ dma_sync_single_for_cpu(dev, dma_handle, offset + size, direction); } static inline void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, + unsigned long offset, size_t size, enum dma_data_direction direction) { - /* just sync everything, that's all the pci API can do */ + /* just sync everything for now */ dma_sync_single_for_device(dev, dma_handle, offset + size, direction); } static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) { - consistent_sync(vaddr, size, (int)direction); + __dma_sync(vaddr, size, (int)direction); } static inline int dma_mapping_error(dma_addr_t dma_addr)