diff options
Diffstat (limited to 'arch/arm/include/asm/dma-mapping.h')
| -rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 79 | 
1 files changed, 77 insertions, 2 deletions
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 5b579b95150..c45b61a4b4a 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -11,17 +11,28 @@  #include <asm-generic/dma-coherent.h>  #include <asm/memory.h> +#include <xen/xen.h> +#include <asm/xen/hypervisor.h> +  #define DMA_ERROR_CODE	(~0)  extern struct dma_map_ops arm_dma_ops;  extern struct dma_map_ops arm_coherent_dma_ops; -static inline struct dma_map_ops *get_dma_ops(struct device *dev) +static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)  {  	if (dev && dev->archdata.dma_ops)  		return dev->archdata.dma_ops;  	return &arm_dma_ops;  } +static inline struct dma_map_ops *get_dma_ops(struct device *dev) +{ +	if (xen_initial_domain()) +		return xen_dma_ops; +	else +		return __generic_dma_ops(dev); +} +  static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)  {  	BUG_ON(!dev); @@ -47,23 +58,40 @@ static inline int dma_set_mask(struct device *dev, u64 mask)  #ifndef __arch_pfn_to_dma  static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)  { +	if (dev) +		pfn -= dev->dma_pfn_offset;  	return (dma_addr_t)__pfn_to_bus(pfn);  }  static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)  { -	return __bus_to_pfn(addr); +	unsigned long pfn = __bus_to_pfn(addr); + +	if (dev) +		pfn += dev->dma_pfn_offset; + +	return pfn;  }  static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)  { +	if (dev) { +		unsigned long pfn = dma_to_pfn(dev, addr); + +		return phys_to_virt(__pfn_to_phys(pfn)); +	} +  	return (void *)__bus_to_virt((unsigned long)addr);  }  static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)  { +	if (dev) +		return pfn_to_dma(dev, virt_to_pfn(addr)); +  	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));  } +  #else  static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)  { @@ -86,6 +114,53 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)  }  #endif +/* The ARM override for dma_max_pfn() */ +static inline unsigned long dma_max_pfn(struct device *dev) +{ +	return PHYS_PFN_OFFSET + dma_to_pfn(dev, *dev->dma_mask); +} +#define dma_max_pfn(dev) dma_max_pfn(dev) + +static inline int set_arch_dma_coherent_ops(struct device *dev) +{ +	set_dma_ops(dev, &arm_coherent_dma_ops); +	return 0; +} +#define set_arch_dma_coherent_ops(dev)	set_arch_dma_coherent_ops(dev) + +static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) +{ +	unsigned int offset = paddr & ~PAGE_MASK; +	return pfn_to_dma(dev, __phys_to_pfn(paddr)) + offset; +} + +static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr) +{ +	unsigned int offset = dev_addr & ~PAGE_MASK; +	return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset; +} + +static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) +{ +	u64 limit, mask; + +	if (!dev->dma_mask) +		return 0; + +	mask = *dev->dma_mask; + +	limit = (mask + 1) & ~mask; +	if (limit && size > limit) +		return 0; + +	if ((addr | (addr + size - 1)) & ~mask) +		return 0; + +	return 1; +} + +static inline void dma_mark_clean(void *addr, size_t size) { } +  /*   * DMA errors are defined by all-bits-set in the DMA address.   */  | 
