diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-13 17:13:56 +0100 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-13 17:13:56 +0100 |
commit | e758936e02700ff88a0b08b722a3847b95283ef2 (patch) | |
tree | 50c919bef1b459a778b85159d5929de95b6c4a01 /arch/arm/include/asm | |
parent | 239cfbde1f5843c4a24199f117d5f67f637d72d5 (diff) | |
parent | 4480f15b3306f43bbb0310d461142b4e897ca45b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
include/asm-x86/statfs.h
Diffstat (limited to 'arch/arm/include/asm')
27 files changed, 545 insertions, 603 deletions
diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h index 7b62351f097..4d88425a416 100644 --- a/arch/arm/include/asm/bug.h +++ b/arch/arm/include/asm/bug.h @@ -12,7 +12,7 @@ extern void __bug(const char *file, int line) __attribute__((noreturn)); #else /* this just causes an oops */ -#define BUG() (*(int *)0 = 0) +#define BUG() do { *(int *)0 = 0; } while (1) #endif diff --git a/arch/arm/include/asm/byteorder.h b/arch/arm/include/asm/byteorder.h index d04a7a2bc2e..4fbfb22f65a 100644 --- a/arch/arm/include/asm/byteorder.h +++ b/arch/arm/include/asm/byteorder.h @@ -18,15 +18,7 @@ #include <linux/compiler.h> #include <asm/types.h> -#ifdef __ARMEB__ -# define __BIG_ENDIAN -#else -# define __LITTLE_ENDIAN -#endif - -#define __SWAB_64_THRU_32__ - -static inline __attribute_const__ __u32 __arch_swab32(__u32 x) +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __u32 t; @@ -48,8 +40,19 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x) return x; } -#define __arch_swab32 __arch_swab32 -#include <linux/byteorder.h> +#define __arch__swab32(x) ___arch__swab32(x) + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __BYTEORDER_HAS_U64__ +# define __SWAB_64_THRU_32__ +#endif + +#ifdef __ARMEB__ +#include <linux/byteorder/big_endian.h> +#else +#include <linux/byteorder/little_endian.h> +#endif #endif + diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 9073d9c6567..de6c59f814a 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -444,94 +444,4 @@ static inline void flush_ioremap_region(unsigned long phys, void __iomem *virt, dmac_inv_range(start, start + size); } -#define __cacheid_present(val) (val != read_cpuid(CPUID_ID)) -#define __cacheid_type_v7(val) ((val & (7 << 29)) == (4 << 29)) - -#define __cacheid_vivt_prev7(val) ((val & (15 << 25)) != (14 << 25)) -#define __cacheid_vipt_prev7(val) ((val & (15 << 25)) == (14 << 25)) -#define __cacheid_vipt_nonaliasing_prev7(val) ((val & (15 << 25 | 1 << 23)) == (14 << 25)) -#define __cacheid_vipt_aliasing_prev7(val) ((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23)) - -#define __cacheid_vivt(val) (__cacheid_type_v7(val) ? 0 : __cacheid_vivt_prev7(val)) -#define __cacheid_vipt(val) (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_prev7(val)) -#define __cacheid_vipt_nonaliasing(val) (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_nonaliasing_prev7(val)) -#define __cacheid_vipt_aliasing(val) (__cacheid_type_v7(val) ? 0 : __cacheid_vipt_aliasing_prev7(val)) -#define __cacheid_vivt_asid_tagged_instr(val) (__cacheid_type_v7(val) ? ((val & (3 << 14)) == (1 << 14)) : 0) - -#if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT) -/* - * VIVT caches only - */ -#define cache_is_vivt() 1 -#define cache_is_vipt() 0 -#define cache_is_vipt_nonaliasing() 0 -#define cache_is_vipt_aliasing() 0 -#define icache_is_vivt_asid_tagged() 0 - -#elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT) -/* - * VIPT caches only - */ -#define cache_is_vivt() 0 -#define cache_is_vipt() 1 -#define cache_is_vipt_nonaliasing() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_vipt_nonaliasing(__val); \ - }) - -#define cache_is_vipt_aliasing() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_vipt_aliasing(__val); \ - }) - -#define icache_is_vivt_asid_tagged() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_vivt_asid_tagged_instr(__val); \ - }) - -#else -/* - * VIVT or VIPT caches. Note that this is unreliable since ARM926 - * and V6 CPUs satisfy the "(val & (15 << 25)) == (14 << 25)" test. - * There's no way to tell from the CacheType register what type (!) - * the cache is. - */ -#define cache_is_vivt() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - (!__cacheid_present(__val)) || __cacheid_vivt(__val); \ - }) - -#define cache_is_vipt() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_present(__val) && __cacheid_vipt(__val); \ - }) - -#define cache_is_vipt_nonaliasing() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_present(__val) && \ - __cacheid_vipt_nonaliasing(__val); \ - }) - -#define cache_is_vipt_aliasing() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_present(__val) && \ - __cacheid_vipt_aliasing(__val); \ - }) - -#define icache_is_vivt_asid_tagged() \ - ({ \ - unsigned int __val = read_cpuid(CPUID_CACHETYPE); \ - __cacheid_present(__val) && \ - __cacheid_vivt_asid_tagged_instr(__val); \ - }) - -#endif - #endif diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h new file mode 100644 index 00000000000..d3a4c2cb9f2 --- /dev/null +++ b/arch/arm/include/asm/cachetype.h @@ -0,0 +1,52 @@ +#ifndef __ASM_ARM_CACHETYPE_H +#define __ASM_ARM_CACHETYPE_H + +#define CACHEID_VIVT (1 << 0) +#define CACHEID_VIPT_NONALIASING (1 << 1) +#define CACHEID_VIPT_ALIASING (1 << 2) +#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING) +#define CACHEID_ASID_TAGGED (1 << 3) + +extern unsigned int cacheid; + +#define cache_is_vivt() cacheid_is(CACHEID_VIVT) +#define cache_is_vipt() cacheid_is(CACHEID_VIPT) +#define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING) +#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) +#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) + +/* + * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture + * Mask out support which will never be present on newer CPUs. + * - v6+ is never VIVT + * - v7+ VIPT never aliases + */ +#if __LINUX_ARM_ARCH__ >= 7 +#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED) +#elif __LINUX_ARM_ARCH__ >= 6 +#define __CACHEID_ARCH_MIN (~CACHEID_VIVT) +#else +#define __CACHEID_ARCH_MIN (~0) +#endif + +/* + * Mask out support which isn't configured + */ +#if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT) +#define __CACHEID_ALWAYS (CACHEID_VIVT) +#define __CACHEID_NEVER (~CACHEID_VIVT) +#elif !defined(CONFIG_CPU_CACHE_VIVT) && defined(CONFIG_CPU_CACHE_VIPT) +#define __CACHEID_ALWAYS (0) +#define __CACHEID_NEVER (CACHEID_VIVT) +#else +#define __CACHEID_ALWAYS (0) +#define __CACHEID_NEVER (0) +#endif + +static inline unsigned int __attribute__((pure)) cacheid_is(unsigned int mask) +{ + return (__CACHEID_ALWAYS & mask) | + (~__CACHEID_NEVER & __CACHEID_ARCH_MIN & mask & cacheid); +} + +#endif diff --git a/arch/arm/include/asm/cnt32_to_63.h b/arch/arm/include/asm/cnt32_to_63.h deleted file mode 100644 index 480c873fa74..00000000000 --- a/arch/arm/include/asm/cnt32_to_63.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * include/asm/cnt32_to_63.h -- extend a 32-bit counter to 63 bits - * - * Author: Nicolas Pitre - * Created: December 3, 2006 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef __INCLUDE_CNT32_TO_63_H__ -#define __INCLUDE_CNT32_TO_63_H__ - -#include <linux/compiler.h> -#include <asm/types.h> -#include <asm/byteorder.h> - -/* - * Prototype: u64 cnt32_to_63(u32 cnt) - * Many hardware clock counters are only 32 bits wide and therefore have - * a relatively short period making wrap-arounds rather frequent. This - * is a problem when implementing sched_clock() for example, where a 64-bit - * non-wrapping monotonic value is expected to be returned. - * - * To overcome that limitation, let's extend a 32-bit counter to 63 bits - * in a completely lock free fashion. Bits 0 to 31 of the clock are provided - * by the hardware while bits 32 to 62 are stored in memory. The top bit in - * memory is used to synchronize with the hardware clock half-period. When - * the top bit of both counters (hardware and in memory) differ then the - * memory is updated with a new value, incrementing it when the hardware - * counter wraps around. - * - * Because a word store in memory is atomic then the incremented value will - * always be in synch with the top bit indicating to any potential concurrent - * reader if the value in memory is up to date or not with regards to the - * needed increment. And any race in updating the value in memory is harmless - * as the same value would simply be stored more than once. - * - * The only restriction for the algorithm to work properly is that this - * code must be executed at least once per each half period of the 32-bit - * counter to properly update the state bit in memory. This is usually not a - * problem in practice, but if it is then a kernel timer could be scheduled - * to manage for this code to be executed often enough. - * - * Note that the top bit (bit 63) in the returned value should be considered - * as garbage. It is not cleared here because callers are likely to use a - * multiplier on the returned value which can get rid of the top bit - * implicitly by making the multiplier even, therefore saving on a runtime - * clear-bit instruction. Otherwise caller must remember to clear the top - * bit explicitly. - */ - -/* this is used only to give gcc a clue about good code generation */ -typedef union { - struct { -#if defined(__LITTLE_ENDIAN) - u32 lo, hi; -#elif defined(__BIG_ENDIAN) - u32 hi, lo; -#endif - }; - u64 val; -} cnt32_to_63_t; - -#define cnt32_to_63(cnt_lo) \ -({ \ - static volatile u32 __m_cnt_hi = 0; \ - cnt32_to_63_t __x; \ - __x.hi = __m_cnt_hi; \ - __x.lo = (cnt_lo); \ - if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ - __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ - __x.val; \ -}) - -#endif diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h new file mode 100644 index 00000000000..7b9d27e749b --- /dev/null +++ b/arch/arm/include/asm/cputype.h @@ -0,0 +1,64 @@ +#ifndef __ASM_ARM_CPUTYPE_H +#define __ASM_ARM_CPUTYPE_H + +#include <linux/stringify.h> + +#define CPUID_ID 0 +#define CPUID_CACHETYPE 1 +#define CPUID_TCM 2 +#define CPUID_TLBTYPE 3 + +#ifdef CONFIG_CPU_CP15 +#define read_cpuid(reg) \ + ({ \ + unsigned int __val; \ + asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \ + : "=r" (__val) \ + : \ + : "cc"); \ + __val; \ + }) +#else +extern unsigned int processor_id; +#define read_cpuid(reg) (processor_id) +#endif + +/* + * The CPU ID never changes at run time, so we might as well tell the + * compiler that it's constant. Use this function to read the CPU ID + * rather than directly reading processor_id or read_cpuid() directly. + */ +static inline unsigned int __attribute_const__ read_cpuid_id(void) +{ + return read_cpuid(CPUID_ID); +} + +static inline unsigned int __attribute_const__ read_cpuid_cachetype(void) +{ + return read_cpuid(CPUID_CACHETYPE); +} + +/* + * Intel's XScale3 core supports some v6 features (supersections, L2) + * but advertises itself as v5 as it does not support the v6 ISA. For + * this reason, we need a way to explicitly test for this type of CPU. + */ +#ifndef CONFIG_CPU_XSC3 +#define cpu_is_xsc3() 0 +#else +static inline int cpu_is_xsc3(void) +{ + if ((read_cpuid_id() & 0xffffe000) == 0x69056000) + return 1; + + return 0; +} +#endif + +#if !defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_CPU_XSC3) +#define cpu_is_xscale() 0 +#else +#define cpu_is_xscale() 1 +#endif + +#endif diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 7b95d205839..1cb8602dd9d 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -104,15 +104,14 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) * Dummy noncoherent implementation. We don't provide a dma_cache_sync * function so drivers using this API are highlighted with build warnings. */ -static inline void * -dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) +static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, + dma_addr_t *handle, gfp_t gfp) { return NULL; } -static inline void -dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr, - dma_addr_t handle) +static inline void dma_free_noncoherent(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t handle) { } @@ -127,8 +126,7 @@ dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr, * return the CPU-viewed address, and sets @handle to be the * device-viewed address. */ -extern void * -dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp); +extern void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t); /** * dma_free_coherent - free memory allocated by dma_alloc_coherent @@ -143,9 +141,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gf * References to memory and mappings associated with cpu_addr/handle * during and after this call executing are illegal. */ -extern void -dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, - dma_addr_t handle); +extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t); /** * dma_mmap_coherent - map a coherent DMA allocation into user space @@ -159,8 +155,8 @@ dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, * into user space. The coherent DMA buffer must not be freed by the * driver until the user space mapping has been released. */ -int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t handle, size_t size); +int dma_mmap_coherent(struct device *, struct vm_area_struct *, + void *, dma_addr_t, size_t); /** @@ -174,14 +170,94 @@ int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, * return the CPU-viewed address, and sets @handle to be the * device-viewed address. */ -extern void * -dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp); +extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *, + gfp_t); #define dma_free_writecombine(dev,size,cpu_addr,handle) \ dma_free_coherent(dev,size,cpu_addr,handle) -int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t handle, size_t size); +int dma_mmap_writecombine(struct device *, struct vm_area_struct *, + void *, dma_addr_t, size_t); + + +#ifdef CONFIG_DMABOUNCE +/* + * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic" + * and utilize bounce buffers as needed to work around limited DMA windows. + * + * On the SA-1111, a bug limits DMA to only certain regions of RAM. + * On the IXP425, the PCI inbound window is 64MB (256MB total RAM) + * On some ADI engineering systems, PCI inbound window is 32MB (12MB total RAM) + * + * The following are helper functions used by the dmabounce subystem + * + */ + +/** + * dmabounce_register_dev + * + * @dev: valid struct device pointer + * @small_buf_size: size of buffers to use with small buffer pool + * @large_buf_size: size of buffers to use with large buffer pool (can be 0) + * + * This function should be called by low-level platform code to register + * a device as requireing DMA buffer bouncing. The function will allocate + * appropriate DMA pools for the device. + * + */ +extern int dmabounce_register_dev(struct device *, unsigned long, + unsigned long); + +/** + * dmabounce_unregister_dev + * + * @dev: valid struct device pointer + * + * This function should be called by low-level platform code when device + * that was previously registered with dmabounce_register_dev is removed + * from the system. + * + */ +extern void dmabounce_unregister_dev(struct device *); + +/** + * dma_needs_bounce + * + * @dev: valid struct device pointer + * @dma_handle: dma_handle of unbounced buffer + * @size: size of region being mapped + * + * Platforms that utilize the dmabounce mechanism must implement + * this function. + * + * The dmabounce routines call this function whenever a dma-mapping + * is requested to determine whether a given buffer needs to be bounced + * or not. The function must return 0 if the buffer is OK for + * DMA access and 1 if the buffer needs to be bounced. + * + */ +extern int dma_needs_bounce(struct device*, dma_addr_t, size_t); + +/* + * The DMA API, implemented by dmabounce.c. See below for descriptions. + */ +extern dma_addr_t dma_map_single(struct device *, void *, size_t, + enum dma_data_direction); +extern dma_addr_t dma_map_page(struct device *, struct page *, + unsigned long, size_t, enum dma_data_direction); +extern void dma_unmap_single(struct device *, dma_addr_t, size_t, + enum dma_data_direction); + +/* + * Private functions + */ +int dmabounce_sync_for_cpu(struct device *, dma_addr_t, unsigned long, + size_t, enum dma_data_direction); +int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long, + size_t, enum dma_data_direction); +#else +#define dmabounce_sync_for_cpu(dev,dma,off,sz,dir) (1) +#define dmabounce_sync_for_device(dev,dma,off,sz,dir) (1) /** @@ -198,19 +274,16 @@ int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma, * can regain ownership by calling dma_unmap_single() or * dma_sync_single_for_cpu(). */ -#ifndef CONFIG_DMABOUNCE -static inline dma_addr_t -dma_map_single(struct device *dev, void *cpu_addr, size_t size, - enum dma_data_direction dir) +static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, + size_t size, enum dma_data_direction dir) { + BUG_ON(!valid_dma_direction(dir)); + if (!arch_is_coherent()) dma_cache_maint(cpu_addr, size, dir); return virt_to_dma(dev, cpu_addr); } -#else -extern dma_addr_t dma_map_single(struct device *,void *, size_t, enum dma_data_direction); -#endif /** * dma_map_page - map a portion of a page for streaming DMA @@ -224,23 +297,25 @@ extern dma_addr_t dma_map_single(struct device *,void *, size_t, enum dma_data_d * or written back. * * The device owns this memory once this call has completed. The CPU - * can regain ownership by calling dma_unmap_page() or - * dma_sync_single_for_cpu(). + * can regain ownership by calling dma_unmap_page(). */ -static inline dma_addr_t -dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir) +static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction dir) { - return dma_map_single(dev, page_address(page) + offset, size, dir); + BUG_ON(!valid_dma_direction(dir)); + + if (!arch_is_coherent()) + dma_cache_maint(page_address(page) + offset, size, dir); + + return page_to_dma(dev, page) + offset; } /** * dma_unmap_single - unmap a single buffer previously mapped * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices * @handle: DMA address of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction + * @size: size of buffer (same as passed to dma_map_single) + * @dir: DMA transfer direction (same as passed to dma_map_single) * * Unmap a single streaming mode DMA translation. The handle and size * must match what was provided in the previous dma_map_single() call. @@ -249,108 +324,34 @@ dma_map_page(struct device *dev, struct page *page, * After this call, reads by the CPU to the buffer are guaranteed to see * whatever the device wrote there. */ -#ifndef CONFIG_DMABOUNCE -static inline void -dma_unmap_single(struct device *dev, dma_addr_t handle, size_t size, - enum dma_data_direction dir) +static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, + size_t size, enum dma_data_direction dir) { /* nothing to do */ } -#else -extern void dma_unmap_single(struct device *, dma_addr_t, size_t, enum dma_data_direction); -#endif +#endif /* CONFIG_DMABOUNCE */ /** * dma_unmap_page - unmap a buffer previously mapped through dma_map_page() * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices * @handle: DMA address of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction + * @size: size of buffer (same as passed to dma_map_page) + * @dir: DMA transfer direction (same as passed to dma_map_page) * - * Unmap a single streaming mode DMA translation. The handle and size - * must match what was provided in the previous dma_map_single() call. + * Unmap a page streaming mode DMA translation. The handle and size + * must match what was provided in the previous dma_map_page() call. * All other usages are undefined. * * After this call, reads by the CPU to the buffer are guaranteed to see * whatever the device wrote there. */ -static inline void -dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size, - enum dma_data_direction dir) +static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, + size_t size, enum dma_data_direction dir) { dma_unmap_single(dev, handle, size, dir); } /** - * dma_map_sg - map a set of SG buffers for streaming mode DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @sg: list of buffers - * @nents: number of buffers to map - * @dir: DMA transfer direction - * - * Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scatter-gather version of the - * above dma_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for dma_map_single are - * the same here. - */ -#ifndef CONFIG_DMABOUNCE -static inline int -dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; i++, sg++) { - char *virt; - - sg->dma_address = page_to_dma(dev, sg_page(sg)) + sg->offset; - virt = sg_virt(sg); - - if (!arch_is_coherent()) - dma_cache_maint(virt, sg->length, dir); - } - - return nents; -} -#else -extern int dma_map_sg(struct device *, struct scatterlist *, int, enum dma_data_direction); -#endif - -/** - * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @sg: list of buffers - * @nents: number of buffers to map - * @dir: DMA transfer direction - * - * Unmap a set of streaming mode DMA translations. - * Again, CPU read rules concerning calls here are the same as for - * dma_unmap_single() above. - */ -#ifndef CONFIG_DMABOUNCE -static inline void -dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir) -{ - - /* nothing to do */ -} -#else -extern void dma_unmap_sg(struct device *, struct scatterlist *, int, enum dma_data_direction); -#endif - - -/** * dma_sync_single_range_for_cpu * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices * @handle: DMA address of buffer @@ -368,145 +369,52 @@ extern void dma_unmap_sg(struct device *, struct scatterlist *, int, enum dma_da * must first the perform a dma_sync_for_device, and then the * device again owns the buffer. */ -#ifndef CONFIG_DMABOUNCE -static inline void -dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t handle, - unsigned long offset, size_t size, - enum dma_data_direction dir) +static inline void dma_sync_single_range_for_cpu(struct device *dev, + dma_addr_t handle, unsigned long offset, size_t size, + enum dma_data_direction dir) { - if (!arch_is_coherent()) - dma_cache_maint(dma_to_virt(dev, handle) + offset, size, dir); + BUG_ON(!valid_dma_direction(dir)); + + dmabounce_sync_for_cpu(dev, handle, offset, size, dir); } -static inline void -dma_sync_single_range_for_device(struct device *dev, dma_addr_t handle, - unsigned long offset, size_t size, - enum dma_data_direction dir) +static inline void dma_sync_single_range_for_device(struct device *dev, + dma_addr_t handle, unsigned long offset, size_t size, + enum dma_data_direction dir) { + BUG_ON(!valid_dma_direction(dir)); + + if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) + return; + if (!arch_is_coherent()) dma_cache_maint(dma_to_virt(dev, handle) + offset, size, dir); } -#else -extern void dma_sync_single_range_for_cpu(struct device *, dma_addr_t, unsigned long, size_t, enum dma_data_direction); -extern void dma_sync_single_range_for_device(struct device *, dma_addr_t, unsigned long, size_t, enum dma_data_direction); -#endif -static inline void -dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size, - enum dma_data_direction dir) +static inline void dma_sync_single_for_cpu(struct device *dev, + dma_addr_t handle, size_t size, enum dma_data_direction dir) { dma_sync_single_range_for_cpu(dev, handle, 0, size, dir); } -static inline void -dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, - enum dma_data_direction dir) +static inline void dma_sync_single_for_device(struct device *dev, + dma_addr_t handle, size_t size, enum dma_data_direction dir) { dma_sync_single_range_for_device(dev, handle, 0, size, dir); } - -/** - * dma_sync_sg_for_cpu - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @sg: list of buffers - * @nents: number of buffers to map - * @dir: DMA transfer direction - * - * Make physical memory consistent for a set of streaming - * mode DMA translations after a transfer. - * - * The same as dma_sync_single_for_* but for a scatter-gather list, - * same rules and usage. - */ -#ifndef CONFIG_DMABOUNCE -static inline void -dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; i++, sg++) { - char *virt = sg_virt(sg); - if (!arch_is_coherent()) - dma_cache_maint(virt, sg->length, dir); - } -} - -static inline void -dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; i++, sg++) { - char *virt = sg_virt(sg); - if (!arch_is_coherent()) - dma_cache_maint(virt, sg->length, dir); - } -} -#else -extern void dma_sync_sg_for_cpu(struct device*, struct scatterlist*, int, enum dma_data_direction); -extern void dma_sync_sg_for_device(struct device*, struct scatterlist*, int, enum dma_data_direction); -#endif - -#ifdef CONFIG_DMABOUNCE /* - * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic" - * and utilize bounce buffers as needed to work around limited DMA windows. - * - * On the SA-1111, a bug limits DMA to only certain regions of RAM. - * On the IXP425, the PCI inbound window is 64MB (256MB total RAM) - * On some ADI engineering systems, PCI inbound window is 32MB (12MB total RAM) - * - * The following are helper functions used by the dmabounce subystem - * - */ - -/** - * dmabounce_register_dev - * - * @dev: valid struct device pointer |