[PATCH 2/3] dma: redefine dma_flags_set/get_*() for sn-ia64
From: akepner
Date: Tue Oct 16 2007 - 21:44:42 EST
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().
Signed-off-by: Arthur Kepner <akepner@xxxxxxx>
---
arch/ia64/sn/pci/pci_dma.c | 37 +++++++++++++++++++++++++++----------
include/asm-ia64/sn/io.h | 27 +++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index ecd8a52..73d3897 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -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;
}
diff --git a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
index 41c73a7..52a6fdb 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -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 */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/