dma: redefine dma_flags_set/get_*() for sn-ia64
PATCH 2/3 dma: redefine dma_flags_set/get_*() for sn-ia64
Redefine dma_flags_set/get_*() for sn-ia64.
dma_flags_set_attr() "borrows" bits from the dma_map_* routines' direction arguments (renamed "flags"). It uses the borrowed bits to pass additional attributes.
dma_flags_get_dir() and dma_flags_get_attr() return the direction and attributes that were set with dma_flags_set_attr().
---
arch/ia64/sn/pci/pci_dma.c | 37 +++++++++++++++++++++++++++---------- include/asm-ia64/sn/io.h | 27 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 10 deletions(-)
arch/ia64/sn/pci/pci_dma.c +27 -10
@@ -153,7 +153,7 @@ EXPORT_SYMBOL(sn_dma_free_coherent);* @dev: device to map for * @cpu_addr: kernel virtual address of the region to map * @size: size of the region -* @direction: DMA direction +* @flags: DMA direction, and arch-specific attributes * * Map the region pointed to by @cpu_addr for DMA and return the * DMA address.
@@ -167,17 +167,23 @@ EXPORT_SYMBOL(sn_dma_free_coherent);* figure out how to save dmamap handle so can use two step. */ dma_addr_t sn_dma_map_single (struct device *dev,void *cpu_addr,size_t size, -int direction) +int flags) {dma_addr_t dma_addr;unsigned long phys_addr;struct pci_dev *pdev =to_pci_dev (dev);struct sn_pcibus_provider *provider =SN_PCIDEV_BUSPROVIDER (pdev); +int dmabarrier =dma_flags_get_attr (flags) &DMA_BARRIER_ATTR ;BUG_ON (dev->bus != &pci_bus_type); phys_addr =__pa (cpu_addr); - dma_addr = provider->dma_map (pdev, phys_addr, size,SN_DMA_ADDR_PHYS ); +if (dmabarrier) + dma_addr = provider->dma_map_consistent (pdev, phys_addr, size, +SN_DMA_ADDR_PHYS ); +else + dma_addr = provider->dma_map (pdev, phys_addr, size, +SN_DMA_ADDR_PHYS );if (!dma_addr) {printk (KERN_ERR "%s: out of ATEs\n" , __FUNCTION__);return 0 ;
@@ -241,18 +247,20 @@ EXPORT_SYMBOL(sn_dma_unmap_sg);* @dev: device to map for * @sg: scatterlist to map * @nhwentries: number of entries -* @direction: direction of the DMA transaction +* @flags: direction of the DMA transaction, and arch-specific attributes * * Maps each entry of @sg for DMA. */ int sn_dma_map_sg (struct device *dev,struct scatterlist *sgl,int nhwentries, -int direction) +int flags) {unsigned long phys_addr;struct scatterlist *saved_sg = sgl, *sg;struct pci_dev *pdev =to_pci_dev (dev);struct sn_pcibus_provider *provider =SN_PCIDEV_BUSPROVIDER (pdev);int i; +int dmabarrier =dma_flags_get_attr (flags) &DMA_BARRIER_ATTR ; +int dir =dma_flags_get_dir (flags);BUG_ON (dev->bus != &pci_bus_type);
@@ -260,19 +268,28 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,* Setup a DMA address for each entry in the scatterlist. */ for_each_sg (sgl, sg, nhwentries, i) { +dma_addr_t dma_addr; phys_addr =SG_ENT_PHYS_ADDRESS (sg); - sg->dma_address = provider->dma_map (pdev, - phys_addr, sg->length, -SN_DMA_ADDR_PHYS ); -if (!sg->dma_address) { +if (dmabarrier) { + dma_addr = provider->dma_map_consistent (pdev, + phys_addr, + sg->length, +SN_DMA_ADDR_PHYS ); + }else { + dma_addr = provider->dma_map (pdev, + phys_addr, sg->length, +SN_DMA_ADDR_PHYS ); + } + +if (!(sg->dma_address = dma_addr)) {printk (KERN_ERR "%s: out of ATEs\n" , __FUNCTION__);/* * Free any successfully allocated entries. */ if (i >0 ) -sn_dma_unmap_sg (dev, saved_sg, i, direction); +sn_dma_unmap_sg (dev, saved_sg, i, dir);return 0 ; }
include/asm-ia64/sn/io.h +27 -0
@@ -271,4 +271,31 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long *addr, int vchan) return 0; } +#ifdef CONFIG_IA64_SGI_SN2 +/* we have to check for CONFIG_IA64_SGI_SN2 since at least one +* driver directly includes this file for both IA64_GENERIC +* and IA64_SGI_SN2 */ +#define ARCH_USES_DMA_ATTRS +/* we pass additional dma attributes in the direction argument to the +* dma_map_* routines */ +#define SN_DMA_ATTR_SHIFT 8 +/* bottom 8 bits for direction, remaining bits for dma attributes */ +#define SN_DMA_DIR_MASK ((1 << SN_DMA_ATTR_SHIFT) - 1) +#define SN_DMA_ATTR_MASK ~SN_DMA_DIR_MASK + +static inline int dma_flags_set_attr (int attr,int dir) +{ +return (dir | (attr <<SN_DMA_ATTR_SHIFT )); +} + +static inline int dma_flags_get_dir (int flags) +{ +return (flags &SN_DMA_DIR_MASK ); +} + +static inline int dma_flags_get_attr (int flags) +{ +return ((flags &SN_DMA_ATTR_MASK ) >>SN_DMA_ATTR_SHIFT ); +} +#endif /* CONFIG_IA64_SGI_SN2 */ #endif /* _ASM_SN_IO_H */
Quoted 11 lines · On Tue, 16 Oct 2007 18:43:16 -0700 [email protected] wrote:
arch/ia64/sn/pci/pci_dma.c +1
-1@@ -153,7 +153,7 @@ EXPORT_SYMBOL(sn_dma_free_coherent);* @dev: device to map for * @cpu_addr: kernel virtual address of the region to map * @size: size of the region -* @direction: DMA direction +* @flags: DMA direction, and arch-specific attributes * * Map the region pointed to by @cpu_addr for DMA and return the * DMA address. @@ -167,17 +167,23 @@ EXPORT_SYMBOL(sn_dma_free_coherent);* figure out how to save dmamap handle so can use two step.
arch/ia64/sn/pci/pci_dma.c EXPORT_SYMBOL(sn_dma_free_coherent); · line 176
Quoted 10 lines
arch/ia64/sn/pci/pci_dma.c +2
-1*/ dma_addr_t sn_dma_map_single (struct device *dev,void *cpu_addr,size_t size, -int direction) +int flags) {dma_addr_t dma_addr;unsigned long phys_addr;struct pci_dev *pdev =to_pci_dev (dev);struct sn_pcibus_provider *provider =SN_PCIDEV_BUSPROVIDER (pdev); +int dmabarrier =dma_flags_get_attr (flags) &DMA_BARRIER_ATTR ;
So we take an `enum data_direction' and then wedge it into a word alongside some extra flags?
Can we do something nicer than that?
From: Andrew Morton <[email protected]>
Date: Tue, 16 Oct 2007 20:29:04 -0700
Quoted 4 lines
So we take an `enum
data_direction' and then wedge it into a word alongside some extra flags?Can we do something nicer than that?
Yes, I discussed this last time around, this type abuse stinks and it's confusing.