[PATCH 3/3] IB: expand ib_umem_get() prototype

2008-02-05 Thread akepner

Add a new parameter, dmasync, to the ib_umem_get() prototype. Use 
dmasync = 1 when mapping user-allocated CQs with ib_umem_get().

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 drivers/infiniband/core/umem.c   |   17 +
 drivers/infiniband/hw/amso1100/c2_provider.c |2 -
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 -
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 -
 drivers/infiniband/hw/ipath/ipath_mr.c   |3 +-
 drivers/infiniband/hw/mlx4/cq.c  |2 -
 drivers/infiniband/hw/mlx4/doorbell.c|2 -
 drivers/infiniband/hw/mlx4/mr.c  |3 +-
 drivers/infiniband/hw/mlx4/qp.c  |2 -
 drivers/infiniband/hw/mlx4/srq.c |2 -
 drivers/infiniband/hw/mthca/mthca_provider.c |8 +-
 drivers/infiniband/hw/mthca/mthca_user.h |   10 +++-
 include/rdma/ib_umem.h   |4 +--
 include/rdma/ib_verbs.h  |   33 +++
 14 files changed, 74 insertions(+), 18 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 4e3128f..f0e0d10 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "uverbs.h"
 
@@ -72,9 +73,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmasync: flush in-flight DMA when the memory region is written 
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmasync)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -87,6 +89,10 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   DECLARE_DMA_ATTRS(attrs);
+
+   if (dmasync)
+   dma_set_attr(, DMA_ATTR_SYNC_ON_WRITE);
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -174,10 +180,11 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
sg_set_page(>page_list[i], page_list[i + 
off], PAGE_SIZE, 0);
}
 
-   chunk->nmap = ib_dma_map_sg(context->device,
-   >page_list[0],
-   chunk->nents,
-   DMA_BIDIRECTIONAL);
+   chunk->nmap = ib_dma_map_sg_attrs(context->device,
+ >page_list[0],
+ chunk->nents,
+ DMA_BIDIRECTIONAL, 
+ );
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(sg_page(>page_list[i]));
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 7a6cece..f571dff 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr->pd = c2pd;
 
-   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(c2mr->umem)) {
err = PTR_ERR(c2mr->umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index b5436ca..66d9d65 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(mhp->umem)) {
err = PTR_ERR(mhp->umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index e239bbf..62a382c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -325,7 +325,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
- 

[PATCH 2/3] dma/ia64: update ia64 machvecs

2008-02-05 Thread akepner

Change all ia64 machvecs to use the new dma_{un}map_*_attrs()
interfaces. Implement the old dma_{un}map_*() interfaces in
terms of the corresponding new interfaces. For ia64/sn, make
use of one dma attribute, DMA_ATTR_SYNC_ON_WRITE.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 arch/ia64/hp/common/hwsw_iommu.c |   60 
 arch/ia64/hp/common/sba_iommu.c  |   62 ++--
 arch/ia64/sn/pci/pci_dma.c   |   77 ---
 include/asm-ia64/dma-mapping.h   |   28 +--
 include/asm-ia64/machvec.h   |   52 
 include/asm-ia64/machvec_hpzx1.h |   16 +++---
 include/asm-ia64/machvec_hpzx1_swiotlb.h |   16 +++---
 include/asm-ia64/machvec_sn2.h   |   16 +++---
 include/linux/dma-attrs.h|   49 +++
 lib/swiotlb.c|   50 
 10 files changed, 290 insertions(+), 136 deletions(-)

diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 94e5710..8cedd6c 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -20,10 +20,10 @@
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent  swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent   swiotlb_free_coherent;
-extern ia64_mv_dma_map_single  swiotlb_map_single;
-extern ia64_mv_dma_unmap_singleswiotlb_unmap_single;
-extern ia64_mv_dma_map_sg  swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sgswiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrsswiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrsswiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported   swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error   swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error
swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent  sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent   sba_free_coherent;
-extern ia64_mv_dma_map_single  sba_map_single;
-extern ia64_mv_dma_unmap_singlesba_unmap_single;
-extern ia64_mv_dma_map_sg  sba_map_sg;
-extern ia64_mv_dma_unmap_sgsba_unmap_sg;
+extern ia64_mv_dma_map_single_attrssba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrssba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported   sba_dma_supported;
 extern ia64_mv_dma_mapping_error   sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent sba_alloc_coherent
 #define hwiommu_free_coherent  sba_free_coherent
-#define hwiommu_map_single sba_map_single
-#define hwiommu_unmap_single   sba_unmap_single
-#define hwiommu_map_sg sba_map_sg
-#define hwiommu_unmap_sg   sba_unmap_sg
+#define hwiommu_map_single_attrs   sba_map_single_attrs
+#define hwiommu_unmap_single_attrs sba_unmap_single_attrs
+#define hwiommu_map_sg_attrs   sba_map_sg_attrs
+#define hwiommu_unmap_sg_attrs sba_unmap_sg_attrs
 #define hwiommu_dma_supported  sba_dma_supported
 #define hwiommu_dma_mapping_error  sba_dma_mapping_error
 #define hwiommu_sync_single_for_cpumachvec_dma_sync_single
@@ -98,40 +98,44 @@ hwsw_free_coherent (struct device *dev, size_t size, void 
*vaddr, dma_addr_t dma
 }
 
 dma_addr_t
-hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
+hwsw_map_single_attrs (struct device *dev, void *addr, size_t size, int dir, 
+  struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_map_single(dev, addr, size, dir);
+   return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
else
-   return hwiommu_map_single(dev, addr, size, dir);
+   return hwiommu_map_single_attrs(dev, addr, size, dir, attrs);
 }
 
 void
-hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
+hwsw_unmap_single_attrs (struct device *dev, dma_addr_t iova, size_t size, 
+int dir, struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_unmap_single(dev, iova, size, dir);
+   return swiotlb_unmap_single_attrs(dev, iova, size, dir, attrs);
else
-   return hwiommu_unmap_single(dev, iova, size, dir);
+   return hwiommu_unmap_single_attrs(dev, iova, size, dir, attrs);
 }
 
 
 int
-hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int 
dir)
+hwsw_map_sg_attrs (struct device *dev, struct scatterlist 

[PATCH 1/3 v2] dma/doc: document dma_{un}map_{single|sg}_attrs() interface

2008-02-05 Thread akepner

Document the new dma_{un}map_{single|sg}_attrs() functions.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 DMA-API.txt|   65 +
 DMA-attributes.txt |   29 +++
 2 files changed, 94 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b939ebb..4c471fc 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -395,6 +395,71 @@ Notes:  You must do this:
 
 See also dma_map_single().
 
+dma_addr_t 
+dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size, 
+enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+
+void 
+dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs* attrs)
+
+int 
+dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+int nents, enum dma_data_direction dir, 
+struct dma_attrs *attrs)
+
+void 
+dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, 
+  int nents, enum dma_data_direction dir,
+  struct dma_attrs *attrs)
+
+The four functions above are just like the counterpart functions 
+without the _attrs suffixes, except that they pass an optional 
+struct dma_attrs*. 
+
+struct dma_attrs encapsulates a set of "dma attributes". For the 
+definition of struct dma_attrs see linux/dma-attrs.h. 
+
+The interpretation of dma attributes is architecture-specific, and 
+each attribute should be documented in Documentation/DMA-attributes.txt. 
+
+If struct dma_attrs* is NULL, the semantics of each of these 
+functions is identical to those of the corresponding function 
+without the _attrs suffix. As a result dma_map_single_attrs() 
+can generally replace dma_map_single(), etc.
+
+As an example of the use of the *_attrs functions, here's how 
+you could pass an attribute DMA_ATTR_FOO when mapping memory 
+for DMA:
+
+#include 
+/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h and 
+ * documented in Documentation/DMA-attributes.txt */
+...
+
+   DECLARE_DMA_ATTRS(attrs);
+   dma_set_attr(, DMA_ATTR_FOO);
+   
+   n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, );
+   
+
+Architectures that care about DMA_ATTR_FOO would check for its 
+presence in their implementations of the mapping and unmapping 
+routines, e.g.:
+
+void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr, 
+size_t size, enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+{
+   
+   int foo =  dma_get_attr(attrs, DMA_ATTR_FOO);
+   
+   if (foo) 
+   /* twizzle the frobnozzle */
+   
+
 
 Part II - Advanced dma_ usage
 -
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index e69de29..36baea5 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -0,0 +1,29 @@
+   DMA attributes
+   ==
+
+This document describes the semantics of the DMA attributes that are 
+defined in linux/dma-attrs.h. 
+
+
+DMA_ATTR_SYNC_ON_WRITE
+--
+
+DMA_ATTR_SYNC_ON_WRITE is used on the IA64_SGI_SN2 architecture.
+It provides a mechanism for devices to explicitly order their DMA 
+writes.
+
+On IA64_SGI_SN2 machines, DMA may be reordered within the NUMA 
+interconnect. Allowing reordering improves performance, but in some 
+situations it may be necessary to ensure that one DMA write is 
+complete before another is visible. For example, if the device does 
+a DMA write to indicate that data is available in memory, DMA of the 
+"completion indication" can race with DMA of data.
+
+When a memory region is mapped with the DMA_ATTR_SYNC_ON_WRITE attribute, 
+a write to that region causes all in-flight DMA to be flushed to memory. 
+Any pending DMA will complete and be visible in memory before the write 
+to the region with the DMA_ATTR_SYNC_ON_WRITE attribute becomes visible. 
+
+(For more information, see the document titled "SGI Altix Architecture 
+Considerations for Linux Device Drivers" at http://techpubs.sgi.com/.)
+
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3 v2] dma: dma_{un}map_{single|sg}_attrs() interface

2008-02-05 Thread akepner

Introduce a new interface for passing architecture-specific
attributes when memory is mapped and unmapped for DMA. Give
the interface a default implementation which ignores
attributes.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 dma-mapping.h |   35 +++
 1 files changed, 35 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 101a2d4..4a49abe 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -116,4 +116,39 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_USES_DMA_ATTRS
+struct dma_attrs;
+
+static inline dma_addr_t dma_map_single_attrs(struct device *dev, 
+ void *cpu_addr, size_t size, 
+ enum dma_data_direction dir, 
+ struct dma_attrs* attrs)
+{
+   return dma_map_single(dev, cpu_addr, size, dir);
+}
+
+static inline void dma_unmap_single_attrs(struct device *dev, 
+ dma_addr_t dma_addr, size_t size, 
+ enum dma_data_direction dir, 
+ struct dma_attrs* attrs)
+{
+   return dma_unmap_single(dev, dma_addr, size, dir);
+}
+
+static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+  int nents, enum dma_data_direction dir, 
+  struct dma_attrs *attrs)
+{
+   return dma_map_sg(dev, sgl, nents, dir);
+}
+
+static inline void dma_unmap_sg_attrs(struct device *dev, 
+ struct scatterlist *sgl, int nents, 
+ enum dma_data_direction dir, 
+ struct dma_attrs *attrs)
+{
+   return dma_unmap_sg(dev, sgl, nents, dir);
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3 v2] dma: dma_{un}map_{single|sg}_attrs() interface

2008-02-05 Thread akepner

Introduce a new interface for passing architecture-specific
attributes when memory is mapped and unmapped for DMA. Give
the interface a default implementation which ignores
attributes.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 dma-mapping.h |   35 +++
 1 files changed, 35 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 101a2d4..4a49abe 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -116,4 +116,39 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_USES_DMA_ATTRS
+struct dma_attrs;
+
+static inline dma_addr_t dma_map_single_attrs(struct device *dev, 
+ void *cpu_addr, size_t size, 
+ enum dma_data_direction dir, 
+ struct dma_attrs* attrs)
+{
+   return dma_map_single(dev, cpu_addr, size, dir);
+}
+
+static inline void dma_unmap_single_attrs(struct device *dev, 
+ dma_addr_t dma_addr, size_t size, 
+ enum dma_data_direction dir, 
+ struct dma_attrs* attrs)
+{
+   return dma_unmap_single(dev, dma_addr, size, dir);
+}
+
+static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+  int nents, enum dma_data_direction dir, 
+  struct dma_attrs *attrs)
+{
+   return dma_map_sg(dev, sgl, nents, dir);
+}
+
+static inline void dma_unmap_sg_attrs(struct device *dev, 
+ struct scatterlist *sgl, int nents, 
+ enum dma_data_direction dir, 
+ struct dma_attrs *attrs)
+{
+   return dma_unmap_sg(dev, sgl, nents, dir);
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3 v2] dma/doc: document dma_{un}map_{single|sg}_attrs() interface

2008-02-05 Thread akepner

Document the new dma_{un}map_{single|sg}_attrs() functions.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 DMA-API.txt|   65 +
 DMA-attributes.txt |   29 +++
 2 files changed, 94 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b939ebb..4c471fc 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -395,6 +395,71 @@ Notes:  You must do this:
 
 See also dma_map_single().
 
+dma_addr_t 
+dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size, 
+enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+
+void 
+dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs* attrs)
+
+int 
+dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+int nents, enum dma_data_direction dir, 
+struct dma_attrs *attrs)
+
+void 
+dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, 
+  int nents, enum dma_data_direction dir,
+  struct dma_attrs *attrs)
+
+The four functions above are just like the counterpart functions 
+without the _attrs suffixes, except that they pass an optional 
+struct dma_attrs*. 
+
+struct dma_attrs encapsulates a set of dma attributes. For the 
+definition of struct dma_attrs see linux/dma-attrs.h. 
+
+The interpretation of dma attributes is architecture-specific, and 
+each attribute should be documented in Documentation/DMA-attributes.txt. 
+
+If struct dma_attrs* is NULL, the semantics of each of these 
+functions is identical to those of the corresponding function 
+without the _attrs suffix. As a result dma_map_single_attrs() 
+can generally replace dma_map_single(), etc.
+
+As an example of the use of the *_attrs functions, here's how 
+you could pass an attribute DMA_ATTR_FOO when mapping memory 
+for DMA:
+
+#include linux/dma-attrs.h
+/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h and 
+ * documented in Documentation/DMA-attributes.txt */
+...
+
+   DECLARE_DMA_ATTRS(attrs);
+   dma_set_attr(attrs, DMA_ATTR_FOO);
+   
+   n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, attr);
+   
+
+Architectures that care about DMA_ATTR_FOO would check for its 
+presence in their implementations of the mapping and unmapping 
+routines, e.g.:
+
+void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr, 
+size_t size, enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+{
+   
+   int foo =  dma_get_attr(attrs, DMA_ATTR_FOO);
+   
+   if (foo) 
+   /* twizzle the frobnozzle */
+   
+
 
 Part II - Advanced dma_ usage
 -
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index e69de29..36baea5 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -0,0 +1,29 @@
+   DMA attributes
+   ==
+
+This document describes the semantics of the DMA attributes that are 
+defined in linux/dma-attrs.h. 
+
+
+DMA_ATTR_SYNC_ON_WRITE
+--
+
+DMA_ATTR_SYNC_ON_WRITE is used on the IA64_SGI_SN2 architecture.
+It provides a mechanism for devices to explicitly order their DMA 
+writes.
+
+On IA64_SGI_SN2 machines, DMA may be reordered within the NUMA 
+interconnect. Allowing reordering improves performance, but in some 
+situations it may be necessary to ensure that one DMA write is 
+complete before another is visible. For example, if the device does 
+a DMA write to indicate that data is available in memory, DMA of the 
+completion indication can race with DMA of data.
+
+When a memory region is mapped with the DMA_ATTR_SYNC_ON_WRITE attribute, 
+a write to that region causes all in-flight DMA to be flushed to memory. 
+Any pending DMA will complete and be visible in memory before the write 
+to the region with the DMA_ATTR_SYNC_ON_WRITE attribute becomes visible. 
+
+(For more information, see the document titled SGI Altix Architecture 
+Considerations for Linux Device Drivers at http://techpubs.sgi.com/.)
+
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/4] dma: document dma_{un}map_{single|sg}_attrs() interface

2008-01-31 Thread akepner
On Thu, Jan 31, 2008 at 03:38:48PM -0700, Grant Grundler wrote:

Thanks for looking through this.

I'll send an updated patchset that addresses your comments 
as soon as I can - probably around Monday.

> ...
> > +struct dma_attrs encapsulates a set of "dma attributes". For the 
> > +definition of struct dma_attrs see linux/dma-attrs.h. 
> 
> Because all architectures will share the set of attrs definitions,
> would it be reasonable to document the intent of each attr?
> 
> Two reasons for doing this:
> 1) people reading the driver code should understand WHY the dma attr was 
> added.
> 2) other arch maintainers need to know in order to implement the same attr
>for their shiny new toys.
> 
> 
> > +The interpretation of dma attributes is architecture-specific. 
> 
> This statement is really importantbut:
> Could we add a reference to arch documentation for each attr?
> 
> ie something public (doesn't have to be in linux source tree)
> which explains the subtlies of how that DMA attr actually works.
> 
> Having worked on HP chipsets for 10+ years, I know releasing
> original HW docs is often not possible. I'm not asking for the
> impossible. Please don't flame me for that. But if the company
> is willing to publish the existance of a feature, a paragraph or
> two would be good marketing too. Maybe just include comments in
> the arch/ code that implements the feature and reference those
> comments in DMA-API.txt.
> 

OK, I can certainly add an explanation of the attribute that
I'm worried about. 

I think there's a reference to this behavior in our driver 
porting guide - I can add a pointer to that, too. 

This might also address your point above about documenting 
each attribute - let me know once the next patch is out.

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/4] IB: introducing MTHCA_MR_DMABARRIER

2008-01-31 Thread akepner
On Wed, Jan 30, 2008 at 07:00:11PM -0800, Roland Dreier wrote:
>  > @@ -72,6 +73,8 @@ static void __ib_umem_release(struct ib_device *dev, 
> struct ib_umem *umem, int d
>  >   * @addr: userspace virtual address to start at
>  >   * @size: length of region to pin
>  >   * @access: IB_ACCESS_xxx flags for memory being pinned
>  > + * @dmabarrier: set a "dma barrier" so that in-flight DMA is 
>  > + *  flushed when the memory region is written to
>  >   */
> 
> I see... it seems some of the previous patch snuck in here...

I'll break the next patchset up differently, and also include 
mlx4.

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/4] IB: introducing MTHCA_MR_DMABARRIER

2008-01-31 Thread akepner
On Wed, Jan 30, 2008 at 07:00:11PM -0800, Roland Dreier wrote:
   @@ -72,6 +73,8 @@ static void __ib_umem_release(struct ib_device *dev, 
 struct ib_umem *umem, int d
 * @addr: userspace virtual address to start at
 * @size: length of region to pin
 * @access: IB_ACCESS_xxx flags for memory being pinned
   + * @dmabarrier: set a dma barrier so that in-flight DMA is 
   + *  flushed when the memory region is written to
 */
 
 I see... it seems some of the previous patch snuck in here...

I'll break the next patchset up differently, and also include 
mlx4.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/4] dma: document dma_{un}map_{single|sg}_attrs() interface

2008-01-31 Thread akepner
On Thu, Jan 31, 2008 at 03:38:48PM -0700, Grant Grundler wrote:

Thanks for looking through this.

I'll send an updated patchset that addresses your comments 
as soon as I can - probably around Monday.

 ...
  +struct dma_attrs encapsulates a set of dma attributes. For the 
  +definition of struct dma_attrs see linux/dma-attrs.h. 
 
 Because all architectures will share the set of attrs definitions,
 would it be reasonable to document the intent of each attr?
 
 Two reasons for doing this:
 1) people reading the driver code should understand WHY the dma attr was 
 added.
 2) other arch maintainers need to know in order to implement the same attr
for their shiny new toys.
 
 
  +The interpretation of dma attributes is architecture-specific. 
 
 This statement is really importantbut:
 Could we add a reference to arch documentation for each attr?
 
 ie something public (doesn't have to be in linux source tree)
 which explains the subtlies of how that DMA attr actually works.
 
 Having worked on HP chipsets for 10+ years, I know releasing
 original HW docs is often not possible. I'm not asking for the
 impossible. Please don't flame me for that. But if the company
 is willing to publish the existance of a feature, a paragraph or
 two would be good marketing too. Maybe just include comments in
 the arch/ code that implements the feature and reference those
 comments in DMA-API.txt.
 

OK, I can certainly add an explanation of the attribute that
I'm worried about. 

I think there's a reference to this behavior in our driver 
porting guide - I can add a pointer to that, too. 

This might also address your point above about documenting 
each attribute - let me know once the next patch is out.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/4] dma/ia64: update ia64 machvecs

2008-01-30 Thread akepner
On Wed, Jan 30, 2008 at 11:25:58AM -0600, James Bottomley wrote:
> In general, the patches look reasonable to me.  Just an observation:
> 
> On Tue, 2008-01-29 at 21:52 -0800, [EMAIL PROTECTED] wrote:
> > diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
> > index e69de29..31af292 100644
> > --- a/include/linux/dma-attrs.h
> > +++ b/include/linux/dma-attrs.h
> > @@ -0,0 +1,48 @@
> > +#ifndef _DMA_ATTR_H
> > +#define _DMA_ATTR_H
> > +#ifdef ARCH_USES_DMA_ATTRS
> > +
> > +enum dma_attr {
> > +   DMA_ATTR_BARRIER,
> > +   DMA_ATTR_FOO,
> > +   DMA_ATTR_GOO,
> > +   DMA_ATTR_MAX,
> > +};
> > +
> 
> 
> The attribute names (DMA_ATTR_...) are going to have to live somewhere
> outside of the #ifdef ARCH_USES_DMA_ATTRS otherwise we'll get compile
> failures of drivers using attributes on architectures that don't support
> them.

Right. Thanks for catching that.

> 
> Secondly, DMA_ATTR_BARRIER doesn't quite sound right.  What you're
> actually doing is trying to prescribe strict ordering, so shouldn't this
> be something like DMA_ATTR_STRICT_ORDERING (and perhaps with a
> corresponding DMA_ATTR_RELAXED_ORDERING for the PCIe case).  

OK, I'll reconsider the names here.

> ... also,
> strike the DMA_ATTR_FOO and DMA_ATTR_GOO since they have no plausible
> meaning.
> 

Yeah, I realized only after sending that I'd forgotten to 
remove these. 

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] IB: introducing MTHCA_MR_DMABARRIER

2008-01-29 Thread akepner

Add MTHCA_MR_DMABARRIER to mthca's API, increment ABI version, 
and make use of MTHCA_MR_DMABARRIER when mapping a user-allocated 
memory region with ib_umem_get().


Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 drivers/infiniband/core/umem.c   |   15 +---
 drivers/infiniband/hw/mthca/mthca_provider.c |7 -
 drivers/infiniband/hw/mthca/mthca_user.h |   10 +++-
 include/rdma/ib_verbs.h  |   33 +++
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 5b00408..57b5ce9 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "uverbs.h"
 
@@ -72,6 +73,8 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set a "dma barrier" so that in-flight DMA is 
+ *  flushed when the memory region is written to
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
size_t size, int access, int dmabarrier)
@@ -87,6 +90,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   struct dma_attrs attrs;
+
+   dma_set_attr(, dmabarrier ? DMA_ATTR_BARRIER : 0);
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -174,10 +180,11 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
sg_set_page(>page_list[i], page_list[i + 
off], PAGE_SIZE, 0);
}
 
-   chunk->nmap = ib_dma_map_sg(context->device,
-   >page_list[0],
-   chunk->nents,
-   DMA_BIDIRECTIONAL);
+   chunk->nmap = ib_dma_map_sg_attrs(context->device,
+ >page_list[0],
+ chunk->nents,
+ DMA_BIDIRECTIONAL, 
+ );
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(sg_page(>page_list[i]));
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c 
b/drivers/infiniband/hw/mthca/mthca_provider.c
index 704d8ef..e837cc9 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1017,17 +1017,22 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd 
*pd, u64 start, u64 length,
struct mthca_dev *dev = to_mdev(pd->device);
struct ib_umem_chunk *chunk;
struct mthca_mr *mr;
+   struct mthca_reg_mr ucmd;
u64 *pages;
int shift, n, len;
int i, j, k;
int err = 0;
int write_mtt_size;
 
+   if (ib_copy_from_udata(, udata, sizeof ucmd))
+   return ERR_PTR(-EFAULT);
+
mr = kmalloc(sizeof *mr, GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
 
-   mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
+   mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 
+  ucmd.mr_attrs & MTHCA_MR_DMABARRIER);
 
if (IS_ERR(mr->umem)) {
err = PTR_ERR(mr->umem);
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h 
b/drivers/infiniband/hw/mthca/mthca_user.h
index 02cc0a7..701a430 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -41,7 +41,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MTHCA_UVERBS_ABI_VERSION   1
+#define MTHCA_UVERBS_ABI_VERSION   2
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -61,6 +61,14 @@ struct mthca_alloc_pd_resp {
__u32 reserved;
 };
 
+struct mthca_reg_mr {
+   __u32 mr_attrs;
+#define MTHCA_MR_DMABARRIER 0x1  /* set a dma barrier in order to flush 
+ * in-flight DMA on a write to memory 
+ * region */
+   __u32 reserved;
+};
+
 struct mthca_create_cq {
__u32 lkey;
__u32 pdn;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 11f3960..ac869e2 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1507,6 +1507,24 @@ static inline void ib_dma_unmap_single(struct ib_device 
*dev,
dma_unmap_single(dev->dma_device, addr, size, 

[PATCH 3/4] IB: add dmabarrier to ib_umem_get() prototype

2008-01-29 Thread akepner

Add a new parameter, dmabarrier, to the ib_umem_get() 
prototype.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

-- 

 drivers/infiniband/core/umem.c   |2 +-
 drivers/infiniband/hw/amso1100/c2_provider.c |2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 +-
 drivers/infiniband/hw/ipath/ipath_mr.c   |3 ++-
 drivers/infiniband/hw/mlx4/cq.c  |2 +-
 drivers/infiniband/hw/mlx4/doorbell.c|2 +-
 drivers/infiniband/hw/mlx4/mr.c  |3 ++-
 drivers/infiniband/hw/mlx4/qp.c  |2 +-
 drivers/infiniband/hw/mlx4/srq.c |2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c |3 ++-
 include/rdma/ib_umem.h   |4 ++--
 12 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 4e3128f..5b00408 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -74,7 +74,7 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @access: IB_ACCESS_xxx flags for memory being pinned
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 7a6cece..f571dff 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr->pd = c2pd;
 
-   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(c2mr->umem)) {
err = PTR_ERR(c2mr->umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index b5436ca..66d9d65 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(mhp->umem)) {
err = PTR_ERR(mhp->umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index e239bbf..62a382c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -325,7 +325,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
-mr_access_flags);
+mr_access_flags, 0);
if (IS_ERR(e_mr->umem)) {
ib_mr = (void *)e_mr->umem;
goto reg_user_mr_exit1;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c 
b/drivers/infiniband/hw/ipath/ipath_mr.c
index db4ba92..7ffb392 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -195,7 +195,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
goto bail;
}
 
-   umem = ib_umem_get(pd->uobject->context, start, length, 
mr_access_flags);
+   umem = ib_umem_get(pd->uobject->context, start, length, 
+  mr_access_flags, 0);
if (IS_ERR(umem))
return (void *) umem;
 
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 9d32c49..3adad6f 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -122,7 +122,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, 
int entries, int vector
}
 
cq->umem = ib_umem_get(context, ucmd.buf_addr, buf_size,
-  IB_ACCESS_LOCAL_WRITE);
+  IB_ACCESS_LOCAL_WRITE, 0);
if (IS_ERR(cq->umem)) {
err = PTR_ERR(cq->umem);
goto err_cq;
diff --git a/drivers/infiniband/hw/mlx4/doorbell.c 
b/drivers/infiniband/hw/mlx4/doorbell.c
index 1c36087..0afde2d 100644
--- a/drivers/infiniband/hw/mlx4/doorbell.c
+++ b/drivers/infiniband/hw/mlx4/doorbell.c
@@ -181,7 +181,7 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, 
unsigned long virt,
page->user_virt = (virt & PAGE_MASK);

[PATCH 2/4] dma/ia64: update ia64 machvecs

2008-01-29 Thread akepner

Change all ia64 machvecs to use the new dma_{un}map_*_attrs()
interfaces. Implement the old dma_{un}map_*() interfaces in 
terms of the corresponding new interfaces. For ia64/sn, make 
use of one dma attribute, DMA_ATTR_BARRIER.


Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 arch/ia64/hp/common/hwsw_iommu.c |   60 
 arch/ia64/hp/common/sba_iommu.c  |   62 ++--
 arch/ia64/sn/pci/pci_dma.c   |   77 ---
 include/asm-ia64/dma-mapping.h   |   28 +--
 include/asm-ia64/machvec.h   |   52 
 include/asm-ia64/machvec_hpzx1.h |   16 +++---
 include/asm-ia64/machvec_hpzx1_swiotlb.h |   16 +++---
 include/asm-ia64/machvec_sn2.h   |   16 +++---
 include/linux/dma-attrs.h|   48 +++
 lib/swiotlb.c|   50 
 10 files changed, 289 insertions(+), 136 deletions(-)

diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 94e5710..8cedd6c 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -20,10 +20,10 @@
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent  swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent   swiotlb_free_coherent;
-extern ia64_mv_dma_map_single  swiotlb_map_single;
-extern ia64_mv_dma_unmap_singleswiotlb_unmap_single;
-extern ia64_mv_dma_map_sg  swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sgswiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrsswiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrsswiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported   swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error   swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error
swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent  sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent   sba_free_coherent;
-extern ia64_mv_dma_map_single  sba_map_single;
-extern ia64_mv_dma_unmap_singlesba_unmap_single;
-extern ia64_mv_dma_map_sg  sba_map_sg;
-extern ia64_mv_dma_unmap_sgsba_unmap_sg;
+extern ia64_mv_dma_map_single_attrssba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrssba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported   sba_dma_supported;
 extern ia64_mv_dma_mapping_error   sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent sba_alloc_coherent
 #define hwiommu_free_coherent  sba_free_coherent
-#define hwiommu_map_single sba_map_single
-#define hwiommu_unmap_single   sba_unmap_single
-#define hwiommu_map_sg sba_map_sg
-#define hwiommu_unmap_sg   sba_unmap_sg
+#define hwiommu_map_single_attrs   sba_map_single_attrs
+#define hwiommu_unmap_single_attrs sba_unmap_single_attrs
+#define hwiommu_map_sg_attrs   sba_map_sg_attrs
+#define hwiommu_unmap_sg_attrs sba_unmap_sg_attrs
 #define hwiommu_dma_supported  sba_dma_supported
 #define hwiommu_dma_mapping_error  sba_dma_mapping_error
 #define hwiommu_sync_single_for_cpumachvec_dma_sync_single
@@ -98,40 +98,44 @@ hwsw_free_coherent (struct device *dev, size_t size, void 
*vaddr, dma_addr_t dma
 }
 
 dma_addr_t
-hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
+hwsw_map_single_attrs (struct device *dev, void *addr, size_t size, int dir, 
+  struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_map_single(dev, addr, size, dir);
+   return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
else
-   return hwiommu_map_single(dev, addr, size, dir);
+   return hwiommu_map_single_attrs(dev, addr, size, dir, attrs);
 }
 
 void
-hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
+hwsw_unmap_single_attrs (struct device *dev, dma_addr_t iova, size_t size, 
+int dir, struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_unmap_single(dev, iova, size, dir);
+   return swiotlb_unmap_single_attrs(dev, iova, size, dir, attrs);
else
-   return hwiommu_unmap_single(dev, iova, size, dir);
+   return hwiommu_unmap_single_attrs(dev, iova, size, dir, attrs);
 }
 
 
 int
-hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int 
dir)
+hwsw_map_sg_attrs (struct device *dev, struct scatterlist *sglist, 

[PATCH 0/4] dma: dma_{un}map_{single|sg}_attrs() interface

2008-01-29 Thread akepner

Introduce a new interface for passing architecture-specific 
attributes when memory is mapped and unmapped for DMA. Give 
the interface a default implementation which ignores 
attributes.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 dma-mapping.h |   33 +
 1 files changed, 33 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 101a2d4..bc313e3 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -116,4 +116,37 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_USES_DMA_ATTRS
+struct dma_attrs;
+
+static inline dma_addr_t dma_map_single_attrs(struct device *dev, 
+ void *cpu_addr, size_t size, 
+ int dir, struct dma_attrs* attrs)
+{
+   return dma_map_single(dev, cpu_addr, size, dir);
+}
+
+static inline void dma_unmap_single_attrs(struct device *dev, 
+ dma_addr_t dma_addr,
+ size_t size, int dir, 
+ struct dma_attrs* attrs)
+{
+   return dma_unmap_single(dev, dma_addr, size, dir);
+}
+
+static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+  int nents, int dir, struct dma_attrs *attrs)
+{
+   return dma_map_sg(dev, sgl, nents, dir);
+}
+
+static inline void dma_unmap_sg_attrs(struct device *dev, 
+ struct scatterlist *sgl,
+ int nents, int dir, 
+ struct dma_attrs *attrs)
+{
+   return dma_unmap_sg(dev, sgl, nents, dir);
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] dma: document dma_{un}map_{single|sg}_attrs() interface

2008-01-29 Thread akepner

Document the new dma_{un}map_{single|sg}_attrs() functions. 

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 DMA-API.txt |   63 
 1 files changed, 63 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b939ebb..fad05e0 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -395,6 +395,69 @@ Notes:  You must do this:
 
 See also dma_map_single().
 
+dma_addr_t 
+dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size, 
+enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+
+void 
+dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs* attrs)
+
+int 
+dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+int nents, enum dma_data_direction dir, 
+struct dma_attrs *attrs)
+
+void 
+dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, 
+  int nents, enum dma_data_direction dir,
+  struct dma_attrs *attrs)
+
+The four functions above are just like the counterpart functions 
+without the _attrs suffixes, except that they pass an optional 
+struct dma_attrs*. 
+
+struct dma_attrs encapsulates a set of "dma attributes". For the 
+definition of struct dma_attrs see linux/dma-attrs.h. 
+
+The interpretation of dma attributes is architecture-specific. 
+
+If struct dma_attrs* is NULL, the semantics of each of these 
+functions is identical to those of the corresponding function 
+without the _attrs suffix. As a result dma_map_single_attrs() 
+can generally replace dma_map_single(), etc.
+
+As an example of the use of the *_attrs functions, here's how 
+you could pass an attribute DMA_ATTR_FOO when mapping memory 
+for DMA:
+
+#include 
+/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h */
+...
+
+   DECLARE_DMA_ATTRS(attrs);
+   dma_set_attr(, DMA_ATTR_FOO);
+   
+   n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, );
+   
+
+Architectures that care about DMA_ATTR_FOO would check for its 
+presence in their implementations of the mapping and unmapping 
+routines, e.g.:
+
+void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr, 
+size_t size, enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+{
+   
+   int foo =  dma_get_attr(attrs, DMA_ATTR_FOO);
+   
+   if (foo) 
+   /* twizzle the frobnozzle */
+   
+
 
 Part II - Advanced dma_ usage
 -
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] dma: document dma_{un}map_{single|sg}_attrs() interface

2008-01-29 Thread akepner

Document the new dma_{un}map_{single|sg}_attrs() functions. 

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--

 DMA-API.txt |   63 
 1 files changed, 63 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b939ebb..fad05e0 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -395,6 +395,69 @@ Notes:  You must do this:
 
 See also dma_map_single().
 
+dma_addr_t 
+dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size, 
+enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+
+void 
+dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs* attrs)
+
+int 
+dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+int nents, enum dma_data_direction dir, 
+struct dma_attrs *attrs)
+
+void 
+dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, 
+  int nents, enum dma_data_direction dir,
+  struct dma_attrs *attrs)
+
+The four functions above are just like the counterpart functions 
+without the _attrs suffixes, except that they pass an optional 
+struct dma_attrs*. 
+
+struct dma_attrs encapsulates a set of dma attributes. For the 
+definition of struct dma_attrs see linux/dma-attrs.h. 
+
+The interpretation of dma attributes is architecture-specific. 
+
+If struct dma_attrs* is NULL, the semantics of each of these 
+functions is identical to those of the corresponding function 
+without the _attrs suffix. As a result dma_map_single_attrs() 
+can generally replace dma_map_single(), etc.
+
+As an example of the use of the *_attrs functions, here's how 
+you could pass an attribute DMA_ATTR_FOO when mapping memory 
+for DMA:
+
+#include linux/dma-attrs.h
+/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h */
+...
+
+   DECLARE_DMA_ATTRS(attrs);
+   dma_set_attr(attrs, DMA_ATTR_FOO);
+   
+   n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, attr);
+   
+
+Architectures that care about DMA_ATTR_FOO would check for its 
+presence in their implementations of the mapping and unmapping 
+routines, e.g.:
+
+void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr, 
+size_t size, enum dma_data_direction dir, 
+struct dma_attrs* attrs)
+{
+   
+   int foo =  dma_get_attr(attrs, DMA_ATTR_FOO);
+   
+   if (foo) 
+   /* twizzle the frobnozzle */
+   
+
 
 Part II - Advanced dma_ usage
 -
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PATCH] dma: dma_{un}map_{single|sg}_attrs() interface

2008-01-24 Thread akepner

Thanks for the review. 

An updated version of the patch follows.

On Tue, Jan 22, 2008 at 08:59:50PM -0800, Roland Dreier wrote:
>  > ...
>  > +static inline int dma_set_attr(struct dma_attrs *attrs, unsigned attr) {
> 
> maybe this would be cleaner if you named the DMA_ATTR enum and used
> that instead of unsigned here (and below)?

Changed that.

> 
>  > +  BUG_ON(attrs == NULL);
> 
> does this BUG_ON() buy us much?  It seems the only thing we would fail
> to oops on is if someone did dma_set_attr(NULL, INVALID) and I'm not
> sure it's worth it to BUG here.

Removed it.

> 
>  > +  if (attr > DMA_ATTR_INVALID && attr < DMA_ATTR_MAX) {
>  > +  attrs->flags = (1 << attr);
>  > +  return 0;
>  > +  }
>  > +  return 1;
> 
> returning -EINVAL here instead of 1 would probably be more "kernelish".

Kernelized it.

> 
>  > +}
>  > +
>  > +static inline int dma_get_attr(struct dma_attrs *attrs, unsigned attr) {
>  > +  if (attrs) 
>  > +   return attrs->flags & (1 << attr);
> 
> so it's OK to pass attrs == NULL into dma_get_attr() but not into
> dma_set_attr()?  seems kind of odd.
> 
>  > +  return 0;
>  > +}

Yeah, I fixed that. Passing a NULL struct dma_attrs * is now 
explicitly allowed.

> 
> It seems you're missing a way to initialize a struct dma_attrs.  How
> do I clear the flags field to start with?
> 
> A macro like DEFINE_DMA_ATTRS() that initializes things for you (like
> LIST_HEAD or DEFINE_SPIN_LOCK) would probably be a good thing to have
> as well.
> 

Yep. (Mainly I was concerned with getting the "plumbing" right for 
introducing dma attributes, so I implemented as little as possible 
of the dma attributes interface itself. It's a bit more fleshed out 
now.)

> Also I guess you could test ARCH_USES_DMA_ATTRS in this file and stub
> everything out and define an empty structure if it's not defined.
> save a few bytes of stack etc.
> 

Good idea. In fact, the forward declaration of struct dma_attrs 
is sufficient when ARCH_USES_DMA_ATTRS isn't defined, since the 
structure isn't used in that case anyway.

Updated patch below.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 arch/ia64/hp/common/hwsw_iommu.c |   60 
 arch/ia64/hp/common/sba_iommu.c  |   62 ++--
 arch/ia64/sn/pci/pci_dma.c   |   77 ---
 include/asm-ia64/dma-mapping.h   |   28 +--
 include/asm-ia64/machvec.h   |   52 
 include/asm-ia64/machvec_hpzx1.h |   16 +++---
 include/asm-ia64/machvec_hpzx1_swiotlb.h |   16 +++---
 include/asm-ia64/machvec_sn2.h   |   16 +++---
 include/linux/dma-attrs.h|   48 +++
 include/linux/dma-mapping.h  |   33 +
 lib/swiotlb.c|   50 
 11 files changed, 322 insertions(+), 136 deletions(-)


diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 94e5710..8cedd6c 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -20,10 +20,10 @@
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent  swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent   swiotlb_free_coherent;
-extern ia64_mv_dma_map_single  swiotlb_map_single;
-extern ia64_mv_dma_unmap_singleswiotlb_unmap_single;
-extern ia64_mv_dma_map_sg  swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sgswiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrsswiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrsswiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported   swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error   swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error
swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent  sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent   sba_free_coherent;
-extern ia64_mv_dma_map_single  sba_map_single;
-extern ia64_mv_dma_unmap_singlesba_unmap_single;
-extern ia64_mv_dma_map_sg  sba_map_sg;
-extern ia64_mv_dma_unmap_sgsba_unmap_sg;
+extern ia64_mv_dma_map_single_attrssba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrssba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported   sba_dma_supported;
 extern ia64_mv_dma_mapping_error   sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent sba_alloc_coherent
 #define hwiommu_free_coherent  sba_free_coherent
-#define hwiommu_map_single sba_map_single
-#define hwiommu_unmap_single   

Re: [RFC/PATCH] dma: dma_{un}map_{single|sg}_attrs() interface

2008-01-24 Thread akepner

Thanks for the review. 

An updated version of the patch follows.

On Tue, Jan 22, 2008 at 08:59:50PM -0800, Roland Dreier wrote:
   ...
   +static inline int dma_set_attr(struct dma_attrs *attrs, unsigned attr) {
 
 maybe this would be cleaner if you named the DMA_ATTR enum and used
 that instead of unsigned here (and below)?

Changed that.

 
   +  BUG_ON(attrs == NULL);
 
 does this BUG_ON() buy us much?  It seems the only thing we would fail
 to oops on is if someone did dma_set_attr(NULL, INVALID) and I'm not
 sure it's worth it to BUG here.

Removed it.

 
   +  if (attr  DMA_ATTR_INVALID  attr  DMA_ATTR_MAX) {
   +  attrs-flags = (1  attr);
   +  return 0;
   +  }
   +  return 1;
 
 returning -EINVAL here instead of 1 would probably be more kernelish.

Kernelized it.

 
   +}
   +
   +static inline int dma_get_attr(struct dma_attrs *attrs, unsigned attr) {
   +  if (attrs) 
   +   return attrs-flags  (1  attr);
 
 so it's OK to pass attrs == NULL into dma_get_attr() but not into
 dma_set_attr()?  seems kind of odd.
 
   +  return 0;
   +}

Yeah, I fixed that. Passing a NULL struct dma_attrs * is now 
explicitly allowed.

 
 It seems you're missing a way to initialize a struct dma_attrs.  How
 do I clear the flags field to start with?
 
 A macro like DEFINE_DMA_ATTRS() that initializes things for you (like
 LIST_HEAD or DEFINE_SPIN_LOCK) would probably be a good thing to have
 as well.
 

Yep. (Mainly I was concerned with getting the plumbing right for 
introducing dma attributes, so I implemented as little as possible 
of the dma attributes interface itself. It's a bit more fleshed out 
now.)

 Also I guess you could test ARCH_USES_DMA_ATTRS in this file and stub
 everything out and define an empty structure if it's not defined.
 save a few bytes of stack etc.
 

Good idea. In fact, the forward declaration of struct dma_attrs 
is sufficient when ARCH_USES_DMA_ATTRS isn't defined, since the 
structure isn't used in that case anyway.

Updated patch below.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--

 arch/ia64/hp/common/hwsw_iommu.c |   60 
 arch/ia64/hp/common/sba_iommu.c  |   62 ++--
 arch/ia64/sn/pci/pci_dma.c   |   77 ---
 include/asm-ia64/dma-mapping.h   |   28 +--
 include/asm-ia64/machvec.h   |   52 
 include/asm-ia64/machvec_hpzx1.h |   16 +++---
 include/asm-ia64/machvec_hpzx1_swiotlb.h |   16 +++---
 include/asm-ia64/machvec_sn2.h   |   16 +++---
 include/linux/dma-attrs.h|   48 +++
 include/linux/dma-mapping.h  |   33 +
 lib/swiotlb.c|   50 
 11 files changed, 322 insertions(+), 136 deletions(-)


diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 94e5710..8cedd6c 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -20,10 +20,10 @@
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent  swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent   swiotlb_free_coherent;
-extern ia64_mv_dma_map_single  swiotlb_map_single;
-extern ia64_mv_dma_unmap_singleswiotlb_unmap_single;
-extern ia64_mv_dma_map_sg  swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sgswiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrsswiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrsswiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported   swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error   swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error
swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent  sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent   sba_free_coherent;
-extern ia64_mv_dma_map_single  sba_map_single;
-extern ia64_mv_dma_unmap_singlesba_unmap_single;
-extern ia64_mv_dma_map_sg  sba_map_sg;
-extern ia64_mv_dma_unmap_sgsba_unmap_sg;
+extern ia64_mv_dma_map_single_attrssba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrssba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported   sba_dma_supported;
 extern ia64_mv_dma_mapping_error   sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent sba_alloc_coherent
 #define hwiommu_free_coherent  sba_free_coherent
-#define hwiommu_map_single sba_map_single
-#define hwiommu_unmap_single   sba_unmap_single
-#define hwiommu_map_sg sba_map_sg

[RFC/PATCH] dma: dma_{un}map_{single|sg}_attrs() interface

2008-01-21 Thread akepner

Here's a new interface for passing attributes to the dma mapping 
and unmapping routines. (I have patches that make use of the 
interface as well, but let's discuss this piece first.)

For ia64, new machvec entries replace the dma map/unmap interface, 
and the old interface is implemented in terms of the new. (All 
implementations other than ia64/sn2 ignore the new attributes.) 

For architectures other than ia64, the new interface is implemented 
in terms of the old (attributes are always ignored).

Tested on hpzx1 and ia64/sn2 (IA64_GENERIC kernels) and on x86_64. 

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

-- 

 arch/ia64/hp/common/hwsw_iommu.c |   60 +-
 arch/ia64/hp/common/sba_iommu.c  |   62 +++
 arch/ia64/sn/pci/pci_dma.c   |   71 +++
 include/asm-ia64/dma-mapping.h   |   28 ++--
 include/asm-ia64/machvec.h   |   52 +-
 include/asm-ia64/machvec_hpzx1.h |   16 +++---
 include/asm-ia64/machvec_hpzx1_swiotlb.h |   16 +++---
 include/asm-ia64/machvec_sn2.h   |   16 +++---
 include/linux/dma-attrs.h|   33 ++
 include/linux/dma-mapping.h  |   33 ++
 lib/swiotlb.c|   50 ++---
 11 files changed, 301 insertions(+), 136 deletions(-)

diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 94e5710..8cedd6c 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -20,10 +20,10 @@
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent  swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent   swiotlb_free_coherent;
-extern ia64_mv_dma_map_single  swiotlb_map_single;
-extern ia64_mv_dma_unmap_singleswiotlb_unmap_single;
-extern ia64_mv_dma_map_sg  swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sgswiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrsswiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrsswiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported   swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error   swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error
swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent  sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent   sba_free_coherent;
-extern ia64_mv_dma_map_single  sba_map_single;
-extern ia64_mv_dma_unmap_singlesba_unmap_single;
-extern ia64_mv_dma_map_sg  sba_map_sg;
-extern ia64_mv_dma_unmap_sgsba_unmap_sg;
+extern ia64_mv_dma_map_single_attrssba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrssba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported   sba_dma_supported;
 extern ia64_mv_dma_mapping_error   sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent sba_alloc_coherent
 #define hwiommu_free_coherent  sba_free_coherent
-#define hwiommu_map_single sba_map_single
-#define hwiommu_unmap_single   sba_unmap_single
-#define hwiommu_map_sg sba_map_sg
-#define hwiommu_unmap_sg   sba_unmap_sg
+#define hwiommu_map_single_attrs   sba_map_single_attrs
+#define hwiommu_unmap_single_attrs sba_unmap_single_attrs
+#define hwiommu_map_sg_attrs   sba_map_sg_attrs
+#define hwiommu_unmap_sg_attrs sba_unmap_sg_attrs
 #define hwiommu_dma_supported  sba_dma_supported
 #define hwiommu_dma_mapping_error  sba_dma_mapping_error
 #define hwiommu_sync_single_for_cpumachvec_dma_sync_single
@@ -98,40 +98,44 @@ hwsw_free_coherent (struct device *dev, size_t size, void 
*vaddr, dma_addr_t dma
 }
 
 dma_addr_t
-hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
+hwsw_map_single_attrs (struct device *dev, void *addr, size_t size, int dir, 
+  struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_map_single(dev, addr, size, dir);
+   return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
else
-   return hwiommu_map_single(dev, addr, size, dir);
+   return hwiommu_map_single_attrs(dev, addr, size, dir, attrs);
 }
 
 void
-hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
+hwsw_unmap_single_attrs (struct device *dev, dma_addr_t iova, size_t size, 
+int dir, struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_unmap_single(dev, iova, 

[RFC/PATCH] dma: dma_{un}map_{single|sg}_attrs() interface

2008-01-21 Thread akepner

Here's a new interface for passing attributes to the dma mapping 
and unmapping routines. (I have patches that make use of the 
interface as well, but let's discuss this piece first.)

For ia64, new machvec entries replace the dma map/unmap interface, 
and the old interface is implemented in terms of the new. (All 
implementations other than ia64/sn2 ignore the new attributes.) 

For architectures other than ia64, the new interface is implemented 
in terms of the old (attributes are always ignored).

Tested on hpzx1 and ia64/sn2 (IA64_GENERIC kernels) and on x86_64. 

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

-- 

 arch/ia64/hp/common/hwsw_iommu.c |   60 +-
 arch/ia64/hp/common/sba_iommu.c  |   62 +++
 arch/ia64/sn/pci/pci_dma.c   |   71 +++
 include/asm-ia64/dma-mapping.h   |   28 ++--
 include/asm-ia64/machvec.h   |   52 +-
 include/asm-ia64/machvec_hpzx1.h |   16 +++---
 include/asm-ia64/machvec_hpzx1_swiotlb.h |   16 +++---
 include/asm-ia64/machvec_sn2.h   |   16 +++---
 include/linux/dma-attrs.h|   33 ++
 include/linux/dma-mapping.h  |   33 ++
 lib/swiotlb.c|   50 ++---
 11 files changed, 301 insertions(+), 136 deletions(-)

diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 94e5710..8cedd6c 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -20,10 +20,10 @@
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent  swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent   swiotlb_free_coherent;
-extern ia64_mv_dma_map_single  swiotlb_map_single;
-extern ia64_mv_dma_unmap_singleswiotlb_unmap_single;
-extern ia64_mv_dma_map_sg  swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sgswiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrsswiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrsswiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported   swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error   swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error
swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent  sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent   sba_free_coherent;
-extern ia64_mv_dma_map_single  sba_map_single;
-extern ia64_mv_dma_unmap_singlesba_unmap_single;
-extern ia64_mv_dma_map_sg  sba_map_sg;
-extern ia64_mv_dma_unmap_sgsba_unmap_sg;
+extern ia64_mv_dma_map_single_attrssba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrssba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs  sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported   sba_dma_supported;
 extern ia64_mv_dma_mapping_error   sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent sba_alloc_coherent
 #define hwiommu_free_coherent  sba_free_coherent
-#define hwiommu_map_single sba_map_single
-#define hwiommu_unmap_single   sba_unmap_single
-#define hwiommu_map_sg sba_map_sg
-#define hwiommu_unmap_sg   sba_unmap_sg
+#define hwiommu_map_single_attrs   sba_map_single_attrs
+#define hwiommu_unmap_single_attrs sba_unmap_single_attrs
+#define hwiommu_map_sg_attrs   sba_map_sg_attrs
+#define hwiommu_unmap_sg_attrs sba_unmap_sg_attrs
 #define hwiommu_dma_supported  sba_dma_supported
 #define hwiommu_dma_mapping_error  sba_dma_mapping_error
 #define hwiommu_sync_single_for_cpumachvec_dma_sync_single
@@ -98,40 +98,44 @@ hwsw_free_coherent (struct device *dev, size_t size, void 
*vaddr, dma_addr_t dma
 }
 
 dma_addr_t
-hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
+hwsw_map_single_attrs (struct device *dev, void *addr, size_t size, int dir, 
+  struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_map_single(dev, addr, size, dir);
+   return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
else
-   return hwiommu_map_single(dev, addr, size, dir);
+   return hwiommu_map_single_attrs(dev, addr, size, dir, attrs);
 }
 
 void
-hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
+hwsw_unmap_single_attrs (struct device *dev, dma_addr_t iova, size_t size, 
+int dir, struct dma_attrs *attrs)
 {
if (use_swiotlb(dev))
-   return swiotlb_unmap_single(dev, iova, size, 

Re: [RFC/PARTIAL PATCH 0/3] dma: passing "attributes" to dma_map_* routines

2008-01-09 Thread akepner
On Wed, Jan 09, 2008 at 01:00:38PM -0800, Roland Dreier wrote:
> .
> The reason this hasn't been an issue until now is that almost all
> drivers work correctly if the Altix code just sets the "flush" bit for
> memory allocated via the consistent/coherent allocators.  However, if
> we want the device to write to userspace memory, this doesn't work
> (and mapping coherent memory allocated in the kernel into userspace is
> a mess on other platforms, because it unnecessarily consumes lowmem
> and/or kernel address space).
> 

And the only way that user level CQs work on Altix now is 
that we apply our own patches to allocate them in the 
kernel (with dma_alloc_coherent()) them mmap() them back 
to user space. A bug in one of these patches recently led  
to considerable drama with several customers - I'd love 
to get a fix in mainline so we can drop our patches and 
avoid the possibility such theatrics in the future ;-)

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 0/3] dma: passing attributes to dma_map_* routines

2008-01-09 Thread akepner
On Wed, Jan 09, 2008 at 01:00:38PM -0800, Roland Dreier wrote:
 .
 The reason this hasn't been an issue until now is that almost all
 drivers work correctly if the Altix code just sets the flush bit for
 memory allocated via the consistent/coherent allocators.  However, if
 we want the device to write to userspace memory, this doesn't work
 (and mapping coherent memory allocated in the kernel into userspace is
 a mess on other platforms, because it unnecessarily consumes lowmem
 and/or kernel address space).
 

And the only way that user level CQs work on Altix now is 
that we apply our own patches to allocate them in the 
kernel (with dma_alloc_coherent()) them mmap() them back 
to user space. A bug in one of these patches recently led  
to considerable drama with several customers - I'd love 
to get a fix in mainline so we can drop our patches and 
avoid the possibility such theatrics in the future ;-)

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 0/3] dma: passing "attributes" to dma_map_* routines

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 12:21:44PM -0600, James Bottomley wrote:
> ...
> But the point is that the Altix does something non-standard but which
> was later standardised (in a different way) largely so others could also
> benefit from the relaxed ordering speedup.
>

When you say that Altix does "something ... which was later 
standardized", what is "something"? 

The thing that I'm trying to address here is the reordering 
that may occur within the NUMA fabric. As far as I'm aware 
there's no standard for that.

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 0/3] dma: passing "attributes" to dma_map_* routines

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 05:50:54PM +, Christoph Hellwig wrote:
> ...
> Onething I've missed with these patches is drivers actually using
> it.  What driver actually needs it and why don't you send patches
> for them?

Some IB drivers need this. Here's an example with the ib_mthca 
driver.

-- 

 drivers/infiniband/core/umem.c   |   10 +
 drivers/infiniband/hw/mthca/mthca_provider.c |   16 +-
 drivers/infiniband/hw/mthca/mthca_user.h |9 +++-
 include/rdma/ib_umem.h   |4 +--
 include/rdma/ib_verbs.h  |   30 ---
 5 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 4e3128f..709345f 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -35,7 +35,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 
@@ -72,9 +72,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set "dmabarrier" attribute on this memory
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -87,6 +88,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   u32 flags = dma_flags_set_dir_attr(DMA_BIDIRECTIONAL, 
+  dmabarrier ? DMA_ATTR_BARRIER : 0);
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -176,8 +179,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
 
chunk->nmap = ib_dma_map_sg(context->device,
>page_list[0],
-   chunk->nents,
-   DMA_BIDIRECTIONAL);
+   chunk->nents, flags);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(sg_page(>page_list[i]));
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c 
b/drivers/infiniband/hw/mthca/mthca_provider.c
index 6bcde1c..7907671 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1017,17 +1017,31 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd 
*pd, u64 start, u64 length,
struct mthca_dev *dev = to_mdev(pd->device);
struct ib_umem_chunk *chunk;
struct mthca_mr *mr;
+   struct mthca_reg_mr ucmd;
u64 *pages;
int shift, n, len;
int i, j, k;
int err = 0;
int write_mtt_size;
 
+   if (ib_copy_from_udata(, udata, sizeof ucmd))
+   return ERR_PTR(-EFAULT);
+
mr = kmalloc(sizeof *mr, GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
 
-   mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+#define _DEBUG_IT_
+#ifdef  _DEBUG_IT_
+   {
+   printk(KERN_CRIT "%s: ucmd.mr_attrs & MTHCA_MR_DMAFLUSH = %d\n",
+   __FUNCTION__, ucmd.mr_attrs & MTHCA_MR_DMAFLUSH);
+   }
+#endif /* _DEBUG_IT_ */
+
+   mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 
+  ucmd.mr_attrs & MTHCA_MR_DMAFLUSH);
+
if (IS_ERR(mr->umem)) {
err = PTR_ERR(mr->umem);
goto err;
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h 
b/drivers/infiniband/hw/mthca/mthca_user.h
index 02cc0a7..76effe3 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -41,7 +41,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MTHCA_UVERBS_ABI_VERSION   1
+#define MTHCA_UVERBS_ABI_VERSION   2
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -61,6 +61,13 @@ struct mthca_alloc_pd_resp {
__u32 reserved;
 };
 
+struct mthca_reg_mr {
+   __u32 mr_attrs;
+#define MTHCA_MR_DMAFLUSH 0x1  /* flush in-flight DMA on a write to
+* memory region */
+   __u32 reserved;
+};
+
 struct mthca_create_cq {
__u32 lkey;
__u32 pdn;
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 2229842..ac3542e 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -62,7 +62,7 @@ struct ib_umem_chunk {
 #ifdef CONFIG_INFINIBAND_USER_MEM
 
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, 

Re: [RFC/PARTIAL PATCH 0/3] dma: passing "attributes" to dma_map_* routines

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 10:27:08AM -0600, James Bottomley wrote:

>  All of the attributes I can see adding are
> bus specific (even to the extent that PCIe ones wouldn't apply to PCI
> for instance)
>

The attribute I want to pass isn't bus-specific, but architecture-
specific.

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 1/3] dma: create linux/dma-direction.h

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 09:58:31AM +0100, Ingo Molnar wrote:
> 
> * [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
> 
> > +enum dma_data_attr {
> > +   DMA_ATTR_BARRIER = (1 << 0),
> > +   DMA_ATTR_FOO = (1 << 1),
> > +   DMA_ATTR_GOO = (1 << 2),
> > +   DMA_ATTR_MAX = (1 << 3),
> > +};
> 
> FOO/GOO we dont need i guess ...

Right. That's example GOO ;-)

> 
> > +#define DMA_FLAGS_ATTR_SHIFT   8
> > +#define DMA_FLAGS_DIR_MASK ((1 << DMA_FLAGS_ATTR_SHIFT) - 1)
> > +#define DMA_FLAGS_ATTR_MASK~DMA_FLAGS_DIR_MASK
> > +
> > +static inline enum dma_data_direction dma_flags_get_dir(u32 fin)
> > +{
> > +   return (fin & DMA_FLAGS_DIR_MASK);
> > +}
> 
> the u32 looks a bit weird. Why not unsigned int ?
> 

unsigned int would be fine with me.

> also, are the new dma_map_*() API compatible with the old one? I.e. does 
> dma_map_*(...,0) and dma_map_*(...,1) map to the right thing? If yes 
> then perhaps dont change 'int direction' to 'u32 flags' at all but just 
> rename 'direction' to 'flags' and be done with it.
>

Yes, the callers don't necessarily need to be modified. Callers 
of dma_map_* would only need to be changed if they want to pass 
some additional attribute(s).
 
> also, this conversion:
> 
> +   enum dma_data_direction direction = dma_flags_get_dir(flags);
> 
> would be unnecessary if callers passed in the bitmap already, instead of 
> 'flags'. 0 and 1 would still map to the right thing i think.
> 

Right, but if the caller *had* passed some optional attribute, we 
probably want to strip it off (and either use it or ignore it, as 
appropriate.)

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 1/3] dma: create linux/dma-direction.h

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 09:58:31AM +0100, Ingo Molnar wrote:
 
 * [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:
 
  +enum dma_data_attr {
  +   DMA_ATTR_BARRIER = (1  0),
  +   DMA_ATTR_FOO = (1  1),
  +   DMA_ATTR_GOO = (1  2),
  +   DMA_ATTR_MAX = (1  3),
  +};
 
 FOO/GOO we dont need i guess ...

Right. That's example GOO ;-)

 
  +#define DMA_FLAGS_ATTR_SHIFT   8
  +#define DMA_FLAGS_DIR_MASK ((1  DMA_FLAGS_ATTR_SHIFT) - 1)
  +#define DMA_FLAGS_ATTR_MASK~DMA_FLAGS_DIR_MASK
  +
  +static inline enum dma_data_direction dma_flags_get_dir(u32 fin)
  +{
  +   return (fin  DMA_FLAGS_DIR_MASK);
  +}
 
 the u32 looks a bit weird. Why not unsigned int ?
 

unsigned int would be fine with me.

 also, are the new dma_map_*() API compatible with the old one? I.e. does 
 dma_map_*(...,0) and dma_map_*(...,1) map to the right thing? If yes 
 then perhaps dont change 'int direction' to 'u32 flags' at all but just 
 rename 'direction' to 'flags' and be done with it.


Yes, the callers don't necessarily need to be modified. Callers 
of dma_map_* would only need to be changed if they want to pass 
some additional attribute(s).
 
 also, this conversion:
 
 +   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
 would be unnecessary if callers passed in the bitmap already, instead of 
 'flags'. 0 and 1 would still map to the right thing i think.
 

Right, but if the caller *had* passed some optional attribute, we 
probably want to strip it off (and either use it or ignore it, as 
appropriate.)

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 0/3] dma: passing attributes to dma_map_* routines

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 10:27:08AM -0600, James Bottomley wrote:

  All of the attributes I can see adding are
 bus specific (even to the extent that PCIe ones wouldn't apply to PCI
 for instance)


The attribute I want to pass isn't bus-specific, but architecture-
specific.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PARTIAL PATCH 0/3] dma: passing attributes to dma_map_* routines

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 05:50:54PM +, Christoph Hellwig wrote:
 ...
 Onething I've missed with these patches is drivers actually using
 it.  What driver actually needs it and why don't you send patches
 for them?

Some IB drivers need this. Here's an example with the ib_mthca 
driver.

-- 

 drivers/infiniband/core/umem.c   |   10 +
 drivers/infiniband/hw/mthca/mthca_provider.c |   16 +-
 drivers/infiniband/hw/mthca/mthca_user.h |9 +++-
 include/rdma/ib_umem.h   |4 +--
 include/rdma/ib_verbs.h  |   30 ---
 5 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 4e3128f..709345f 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -35,7 +35,7 @@
  */
 
 #include linux/mm.h
-#include linux/dma-mapping.h
+#include linux/dma-direction.h
 #include linux/sched.h
 #include linux/hugetlb.h
 
@@ -72,9 +72,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set dmabarrier attribute on this memory
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -87,6 +88,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   u32 flags = dma_flags_set_dir_attr(DMA_BIDIRECTIONAL, 
+  dmabarrier ? DMA_ATTR_BARRIER : 0);
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -176,8 +179,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
 
chunk-nmap = ib_dma_map_sg(context-device,
chunk-page_list[0],
-   chunk-nents,
-   DMA_BIDIRECTIONAL);
+   chunk-nents, flags);
if (chunk-nmap = 0) {
for (i = 0; i  chunk-nents; ++i)
put_page(sg_page(chunk-page_list[i]));
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c 
b/drivers/infiniband/hw/mthca/mthca_provider.c
index 6bcde1c..7907671 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1017,17 +1017,31 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd 
*pd, u64 start, u64 length,
struct mthca_dev *dev = to_mdev(pd-device);
struct ib_umem_chunk *chunk;
struct mthca_mr *mr;
+   struct mthca_reg_mr ucmd;
u64 *pages;
int shift, n, len;
int i, j, k;
int err = 0;
int write_mtt_size;
 
+   if (ib_copy_from_udata(ucmd, udata, sizeof ucmd))
+   return ERR_PTR(-EFAULT);
+
mr = kmalloc(sizeof *mr, GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
 
-   mr-umem = ib_umem_get(pd-uobject-context, start, length, acc);
+#define _DEBUG_IT_
+#ifdef  _DEBUG_IT_
+   {
+   printk(KERN_CRIT %s: ucmd.mr_attrs  MTHCA_MR_DMAFLUSH = %d\n,
+   __FUNCTION__, ucmd.mr_attrs  MTHCA_MR_DMAFLUSH);
+   }
+#endif /* _DEBUG_IT_ */
+
+   mr-umem = ib_umem_get(pd-uobject-context, start, length, acc, 
+  ucmd.mr_attrs  MTHCA_MR_DMAFLUSH);
+
if (IS_ERR(mr-umem)) {
err = PTR_ERR(mr-umem);
goto err;
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h 
b/drivers/infiniband/hw/mthca/mthca_user.h
index 02cc0a7..76effe3 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -41,7 +41,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MTHCA_UVERBS_ABI_VERSION   1
+#define MTHCA_UVERBS_ABI_VERSION   2
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -61,6 +61,13 @@ struct mthca_alloc_pd_resp {
__u32 reserved;
 };
 
+struct mthca_reg_mr {
+   __u32 mr_attrs;
+#define MTHCA_MR_DMAFLUSH 0x1  /* flush in-flight DMA on a write to
+* memory region */
+   __u32 reserved;
+};
+
 struct mthca_create_cq {
__u32 lkey;
__u32 pdn;
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 2229842..ac3542e 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -62,7 +62,7 @@ struct ib_umem_chunk {
 #ifdef 

Re: [RFC/PARTIAL PATCH 0/3] dma: passing attributes to dma_map_* routines

2008-01-08 Thread akepner
On Tue, Jan 08, 2008 at 12:21:44PM -0600, James Bottomley wrote:
 ...
 But the point is that the Altix does something non-standard but which
 was later standardised (in a different way) largely so others could also
 benefit from the relaxed ordering speedup.


When you say that Altix does something ... which was later 
standardized, what is something? 

The thing that I'm trying to address here is the reordering 
that may occur within the NUMA fabric. As far as I'm aware 
there's no standard for that.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC/PARTIAL PATCH 3/3] dma: x86_64 allow "attributes" to be used by dma_map_*

2008-01-07 Thread akepner

Allow dma "attributes" to be passed to dma_map_*/dma_unmap_*
implementations on x86_64.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 arch/x86/kernel/pci-calgary_64.c |   13 -
 arch/x86/kernel/pci-gart_64.c|   27 +--
 arch/x86/kernel/pci-nommu_64.c   |8 
 drivers/pci/intel-iommu.c|   10 ++
 include/asm-x86/dma-mapping_64.h |   27 ---
 include/asm-x86/swiotlb.h|8 
 6 files changed, 55 insertions(+), 38 deletions(-)

diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 6bf1f71..f742384 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -382,7 +383,7 @@ static inline struct iommu_table *find_iommu_table(struct 
device *dev)
 }
 
 static void calgary_unmap_sg(struct device *dev,
-   struct scatterlist *sglist, int nelems, int direction)
+   struct scatterlist *sglist, int nelems, u32 flags)
 {
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
@@ -421,7 +422,7 @@ static int calgary_nontranslate_map_sg(struct device* dev,
 }
 
 static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
-   int nelems, int direction)
+   int nelems, u32 flags)
 {
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
@@ -429,6 +430,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
unsigned int npages;
unsigned long entry;
int i;
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
if (!translation_enabled(tbl))
return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
@@ -457,7 +459,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
 
return nelems;
 error:
-   calgary_unmap_sg(dev, sg, nelems, direction);
+   calgary_unmap_sg(dev, sg, nelems, flags);
for_each_sg(sg, s, nelems, i) {
sg->dma_address = bad_dma_address;
sg->dma_length = 0;
@@ -466,12 +468,13 @@ error:
 }
 
 static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
-   size_t size, int direction)
+   size_t size, u32 flags)
 {
dma_addr_t dma_handle = bad_dma_address;
unsigned long uaddr;
unsigned int npages;
struct iommu_table *tbl = find_iommu_table(dev);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
uaddr = (unsigned long)vaddr;
npages = num_dma_pages(uaddr, size);
@@ -485,7 +488,7 @@ static dma_addr_t calgary_map_single(struct device *dev, 
void *vaddr,
 }
 
 static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
-   size_t size, int direction)
+   size_t size, u32 flags)
 {
struct iommu_table *tbl = find_iommu_table(dev);
unsigned int npages;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 06bcba5..da7336a 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -230,15 +231,17 @@ static dma_addr_t dma_map_area(struct device *dev, 
dma_addr_t phys_mem,
 }
 
 static dma_addr_t gart_map_simple(struct device *dev, char *buf,
-size_t size, int dir)
+size_t size, u32 flags)
 {
+   enum dma_data_direction dir = dma_flags_get_dir(flags);
dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
flush_gart();
return map;
 }
 
 /* Map a single area into the IOMMU */
-static dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, 
int dir)
+static dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, 
+ u32 flags)
 {
unsigned long phys_mem, bus;
 
@@ -249,7 +252,7 @@ static dma_addr_t gart_map_single(struct device *dev, void 
*addr, size_t size, i
if (!need_iommu(dev, phys_mem, size))
return phys_mem; 
 
-   bus = gart_map_simple(dev, addr, size, dir);
+   bus = gart_map_simple(dev, addr, size, flags);
return bus; 
 }
 
@@ -257,7 +260,7 @@ static dma_addr_t gart_map_single(struct device *dev, void 
*addr, size_t size, i
  * Free a DMA mapping.
  */
 static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
- size_t size, int direction)
+ size_t size, u32 flags)
 {
unsigned long iommu_page;
int npages;
@@ -278,10 +281,12 @@ static void gart_unmap_single(struct device *dev, 
dma_addr_t dma_addr,
 /*
  * Wrapper for pci_unmap_single working with scatterlists.
  */
-static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int 
nents, int dir)

[RFC/PARTIAL PATCH 2/3] dma: ia64/sn2 allow "attributes" to be used by dma_map_*

2008-01-07 Thread akepner

Allow dma "attributes" to be used by dma_map_*/dma_unmap_* 
implementations on the ia64/sn2 architecture. (This one also 
includes some changes to lib/swiotlb.c which aren't specific 
to ia64/sn2.)

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--

 arch/ia64/sn/pci/pci_dma.c |   45 -
 include/asm-ia64/machvec.h |8 
 lib/swiotlb.c  |   12 
 3 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 511db2f..57ddbcb 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -10,6 +10,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -153,7 +154,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 attributes
  *
  * Map the region pointed to by @cpu_addr for DMA and return the
  * DMA address.
@@ -167,17 +168,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)
+u32 flags)
 {
dma_addr_t dma_addr;
unsigned long phys_addr;
struct pci_dev *pdev = to_pci_dev(dev);
+   u32 attr = dma_flags_get_attr(flags);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
BUG_ON(dev->bus != _bus_type);
 
phys_addr = __pa(cpu_addr);
-   dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
+   if (attr & DMA_ATTR_BARRIER)
+   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;
@@ -191,17 +198,18 @@ EXPORT_SYMBOL(sn_dma_map_single);
  * @dev: device to sync
  * @dma_addr: DMA address to sync
  * @size: size of region
- * @direction: DMA direction
+ * @flags: DMA direction and attributes
  *
  * This routine is supposed to sync the DMA region specified
  * by @dma_handle into the coherence domain.  On SN, we're always cache
  * coherent, so we just need to free any ATEs associated with this mapping.
  */
 void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-int direction)
+u32 flags)
 {
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
BUG_ON(dev->bus != _bus_type);
 
@@ -214,16 +222,17 @@ EXPORT_SYMBOL(sn_dma_unmap_single);
  * @dev: device to unmap
  * @sg: scatterlist to unmap
  * @nhwentries: number of scatterlist entries
- * @direction: DMA direction
+ * @flags: DMA direction and attributes
  *
  * Unmap a set of streaming mode DMA translations.
  */
 void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
-int nhwentries, int direction)
+int nhwentries, u32 flags)
 {
int i;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
struct scatterlist *sg;
 
BUG_ON(dev->bus != _bus_type);
@@ -241,17 +250,19 @@ 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 DMA attributes
  *
  * Maps each entry of @sg for DMA.
  */
 int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
- int direction)
+ u32 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);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
+   u32 attr = dma_flags_get_attr(flags);
int i;
 
BUG_ON(dev->bus != _bus_type);
@@ -260,12 +271,20 @@ 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,
- 

[RFC/PARTIAL PATCH 1/3] dma: create linux/dma-direction.h

2008-01-07 Thread akepner

Place the definition of enum dma_data_direction in its own 
include file, and add the definition of enum dma_data_attr 
and some simple routines for manipulating the direction and 
attributes.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

-- 

 dma-direction.h |   53 +
 dma-mapping.h   |   17 +
 2 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h
index e69de29..4c67446 100644
--- a/include/linux/dma-direction.h
+++ b/include/linux/dma-direction.h
@@ -0,0 +1,53 @@
+#ifndef _LINUX_DMA_DIRECTION_H
+#define _LINUX_DMA_DIRECTION_H
+
+/* These definitions mirror those in pci.h, so they can be used
+ * interchangeably with their PCI_ counterparts */
+enum dma_data_direction {
+   DMA_BIDIRECTIONAL = 0,
+   DMA_TO_DEVICE = 1,
+   DMA_FROM_DEVICE = 2,
+   DMA_NONE = 3,
+};
+
+enum dma_data_attr {
+   DMA_ATTR_BARRIER = (1 << 0),
+   DMA_ATTR_FOO = (1 << 1),
+   DMA_ATTR_GOO = (1 << 2),
+   DMA_ATTR_MAX = (1 << 3),
+};
+
+#define DMA_FLAGS_ATTR_SHIFT   8
+#define DMA_FLAGS_DIR_MASK ((1 << DMA_FLAGS_ATTR_SHIFT) - 1)
+#define DMA_FLAGS_ATTR_MASK~DMA_FLAGS_DIR_MASK
+
+static inline enum dma_data_direction dma_flags_get_dir(u32 fin)
+{
+   return (fin & DMA_FLAGS_DIR_MASK);
+}
+
+/* return a u32 (not a enum dma_data_attr) since more than one 
+ * attribute may be set */
+static inline u32 dma_flags_get_attr(u32 fin)
+{
+   return ((fin & DMA_FLAGS_ATTR_MASK) >> DMA_FLAGS_ATTR_SHIFT);
+}
+
+static inline u32 dma_flags_set_dir_attr(enum dma_data_direction dir, u32 attr)
+{
+   return (attr << DMA_FLAGS_ATTR_SHIFT) | (dir & DMA_FLAGS_DIR_MASK);
+}
+
+static inline int valid_dma_direction(enum dma_data_direction dir)
+{
+   return ((dir == DMA_BIDIRECTIONAL) ||
+   (dir == DMA_TO_DEVICE) ||
+   (dir == DMA_FROM_DEVICE));
+}
+
+static inline int valid_dma_attr(u32 attr)
+{
+   return(attr < DMA_ATTR_MAX);
+}
+
+#endif  /*_LINUX_DMA_DIRECTION_H */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 101a2d4..be5825e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -3,15 +3,7 @@
 
 #include 
 #include 
-
-/* These definitions mirror those in pci.h, so they can be used
- * interchangeably with their PCI_ counterparts */
-enum dma_data_direction {
-   DMA_BIDIRECTIONAL = 0,
-   DMA_TO_DEVICE = 1,
-   DMA_FROM_DEVICE = 2,
-   DMA_NONE = 3,
-};
+#include 
 
 #define DMA_BIT_MASK(n)(((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
 
@@ -36,13 +28,6 @@ enum dma_data_direction {
 
 #define DMA_MASK_NONE  0x0ULL
 
-static inline int valid_dma_direction(int dma_direction)
-{
-   return ((dma_direction == DMA_BIDIRECTIONAL) ||
-   (dma_direction == DMA_TO_DEVICE) ||
-   (dma_direction == DMA_FROM_DEVICE));
-}
-
 static inline int is_device_dma_capable(struct device *dev)
 {
return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;



-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC/PARTIAL PATCH 0/3] dma: passing "attributes" to dma_map_* routines

2008-01-07 Thread akepner

The following patchset allows additional "attributes" to be 
passed to dma_map_*/dma_unmap_* implementations. (The reason 
why this is useful/necessary has been mentioned several times, 
most recently here:
http://marc.info/?l=linux-kernel=119258541412724=2.)

This is incomplete in that only ia64 and x86_64 are supported - 
the purpose is mainly to give us something specific to discuss. 

The approach here is to change the dma_map_* interface so 
that the last argument is an u32 which encodes the direction 
of the dma and, optionally, other attributes. Changing the 
interface is a bit intrusive, but callers of dma_map_* don't 
need to be modified.

There are 3 patches:

[1/3] dma: create linux/dma-direction.h 
[2/3] dma: ia64/sn2 allow "attributes" to be used by dma_map_*
[2/3] dma: x86_64 allow "attributes" to be used by dma_map_*

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC/PARTIAL PATCH 0/3] dma: passing attributes to dma_map_* routines

2008-01-07 Thread akepner

The following patchset allows additional attributes to be 
passed to dma_map_*/dma_unmap_* implementations. (The reason 
why this is useful/necessary has been mentioned several times, 
most recently here:
http://marc.info/?l=linux-kernelm=119258541412724w=2.)

This is incomplete in that only ia64 and x86_64 are supported - 
the purpose is mainly to give us something specific to discuss. 

The approach here is to change the dma_map_* interface so 
that the last argument is an u32 which encodes the direction 
of the dma and, optionally, other attributes. Changing the 
interface is a bit intrusive, but callers of dma_map_* don't 
need to be modified.

There are 3 patches:

[1/3] dma: create linux/dma-direction.h 
[2/3] dma: ia64/sn2 allow attributes to be used by dma_map_*
[2/3] dma: x86_64 allow attributes to be used by dma_map_*

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC/PARTIAL PATCH 1/3] dma: create linux/dma-direction.h

2008-01-07 Thread akepner

Place the definition of enum dma_data_direction in its own 
include file, and add the definition of enum dma_data_attr 
and some simple routines for manipulating the direction and 
attributes.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

-- 

 dma-direction.h |   53 +
 dma-mapping.h   |   17 +
 2 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h
index e69de29..4c67446 100644
--- a/include/linux/dma-direction.h
+++ b/include/linux/dma-direction.h
@@ -0,0 +1,53 @@
+#ifndef _LINUX_DMA_DIRECTION_H
+#define _LINUX_DMA_DIRECTION_H
+
+/* These definitions mirror those in pci.h, so they can be used
+ * interchangeably with their PCI_ counterparts */
+enum dma_data_direction {
+   DMA_BIDIRECTIONAL = 0,
+   DMA_TO_DEVICE = 1,
+   DMA_FROM_DEVICE = 2,
+   DMA_NONE = 3,
+};
+
+enum dma_data_attr {
+   DMA_ATTR_BARRIER = (1  0),
+   DMA_ATTR_FOO = (1  1),
+   DMA_ATTR_GOO = (1  2),
+   DMA_ATTR_MAX = (1  3),
+};
+
+#define DMA_FLAGS_ATTR_SHIFT   8
+#define DMA_FLAGS_DIR_MASK ((1  DMA_FLAGS_ATTR_SHIFT) - 1)
+#define DMA_FLAGS_ATTR_MASK~DMA_FLAGS_DIR_MASK
+
+static inline enum dma_data_direction dma_flags_get_dir(u32 fin)
+{
+   return (fin  DMA_FLAGS_DIR_MASK);
+}
+
+/* return a u32 (not a enum dma_data_attr) since more than one 
+ * attribute may be set */
+static inline u32 dma_flags_get_attr(u32 fin)
+{
+   return ((fin  DMA_FLAGS_ATTR_MASK)  DMA_FLAGS_ATTR_SHIFT);
+}
+
+static inline u32 dma_flags_set_dir_attr(enum dma_data_direction dir, u32 attr)
+{
+   return (attr  DMA_FLAGS_ATTR_SHIFT) | (dir  DMA_FLAGS_DIR_MASK);
+}
+
+static inline int valid_dma_direction(enum dma_data_direction dir)
+{
+   return ((dir == DMA_BIDIRECTIONAL) ||
+   (dir == DMA_TO_DEVICE) ||
+   (dir == DMA_FROM_DEVICE));
+}
+
+static inline int valid_dma_attr(u32 attr)
+{
+   return(attr  DMA_ATTR_MAX);
+}
+
+#endif  /*_LINUX_DMA_DIRECTION_H */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 101a2d4..be5825e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -3,15 +3,7 @@
 
 #include linux/device.h
 #include linux/err.h
-
-/* These definitions mirror those in pci.h, so they can be used
- * interchangeably with their PCI_ counterparts */
-enum dma_data_direction {
-   DMA_BIDIRECTIONAL = 0,
-   DMA_TO_DEVICE = 1,
-   DMA_FROM_DEVICE = 2,
-   DMA_NONE = 3,
-};
+#include linux/dma-direction.h
 
 #define DMA_BIT_MASK(n)(((n) == 64) ? ~0ULL : ((1ULL(n))-1))
 
@@ -36,13 +28,6 @@ enum dma_data_direction {
 
 #define DMA_MASK_NONE  0x0ULL
 
-static inline int valid_dma_direction(int dma_direction)
-{
-   return ((dma_direction == DMA_BIDIRECTIONAL) ||
-   (dma_direction == DMA_TO_DEVICE) ||
-   (dma_direction == DMA_FROM_DEVICE));
-}
-
 static inline int is_device_dma_capable(struct device *dev)
 {
return dev-dma_mask != NULL  *dev-dma_mask != DMA_MASK_NONE;



-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC/PARTIAL PATCH 2/3] dma: ia64/sn2 allow attributes to be used by dma_map_*

2008-01-07 Thread akepner

Allow dma attributes to be used by dma_map_*/dma_unmap_* 
implementations on the ia64/sn2 architecture. (This one also 
includes some changes to lib/swiotlb.c which aren't specific 
to ia64/sn2.)

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--

 arch/ia64/sn/pci/pci_dma.c |   45 -
 include/asm-ia64/machvec.h |8 
 lib/swiotlb.c  |   12 
 3 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 511db2f..57ddbcb 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -10,6 +10,7 @@
  */
 
 #include linux/module.h
+#include linux/dma-direction.h
 #include asm/dma.h
 #include asm/sn/intr.h
 #include asm/sn/pcibus_provider_defs.h
@@ -153,7 +154,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 attributes
  *
  * Map the region pointed to by @cpu_addr for DMA and return the
  * DMA address.
@@ -167,17 +168,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)
+u32 flags)
 {
dma_addr_t dma_addr;
unsigned long phys_addr;
struct pci_dev *pdev = to_pci_dev(dev);
+   u32 attr = dma_flags_get_attr(flags);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
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 (attr  DMA_ATTR_BARRIER)
+   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;
@@ -191,17 +198,18 @@ EXPORT_SYMBOL(sn_dma_map_single);
  * @dev: device to sync
  * @dma_addr: DMA address to sync
  * @size: size of region
- * @direction: DMA direction
+ * @flags: DMA direction and attributes
  *
  * This routine is supposed to sync the DMA region specified
  * by @dma_handle into the coherence domain.  On SN, we're always cache
  * coherent, so we just need to free any ATEs associated with this mapping.
  */
 void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-int direction)
+u32 flags)
 {
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
BUG_ON(dev-bus != pci_bus_type);
 
@@ -214,16 +222,17 @@ EXPORT_SYMBOL(sn_dma_unmap_single);
  * @dev: device to unmap
  * @sg: scatterlist to unmap
  * @nhwentries: number of scatterlist entries
- * @direction: DMA direction
+ * @flags: DMA direction and attributes
  *
  * Unmap a set of streaming mode DMA translations.
  */
 void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
-int nhwentries, int direction)
+int nhwentries, u32 flags)
 {
int i;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
struct scatterlist *sg;
 
BUG_ON(dev-bus != pci_bus_type);
@@ -241,17 +250,19 @@ 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 DMA attributes
  *
  * Maps each entry of @sg for DMA.
  */
 int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
- int direction)
+ u32 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);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
+   u32 attr = dma_flags_get_attr(flags);
int i;
 
BUG_ON(dev-bus != pci_bus_type);
@@ -260,12 +271,20 @@ 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);

[RFC/PARTIAL PATCH 3/3] dma: x86_64 allow attributes to be used by dma_map_*

2008-01-07 Thread akepner

Allow dma attributes to be passed to dma_map_*/dma_unmap_*
implementations on x86_64.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--

 arch/x86/kernel/pci-calgary_64.c |   13 -
 arch/x86/kernel/pci-gart_64.c|   27 +--
 arch/x86/kernel/pci-nommu_64.c   |8 
 drivers/pci/intel-iommu.c|   10 ++
 include/asm-x86/dma-mapping_64.h |   27 ---
 include/asm-x86/swiotlb.h|8 
 6 files changed, 55 insertions(+), 38 deletions(-)

diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 6bf1f71..f742384 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -36,6 +36,7 @@
 #include linux/pci.h
 #include linux/delay.h
 #include linux/scatterlist.h
+#include linux/dma-direction.h
 #include asm/gart.h
 #include asm/calgary.h
 #include asm/tce.h
@@ -382,7 +383,7 @@ static inline struct iommu_table *find_iommu_table(struct 
device *dev)
 }
 
 static void calgary_unmap_sg(struct device *dev,
-   struct scatterlist *sglist, int nelems, int direction)
+   struct scatterlist *sglist, int nelems, u32 flags)
 {
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
@@ -421,7 +422,7 @@ static int calgary_nontranslate_map_sg(struct device* dev,
 }
 
 static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
-   int nelems, int direction)
+   int nelems, u32 flags)
 {
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
@@ -429,6 +430,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
unsigned int npages;
unsigned long entry;
int i;
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
if (!translation_enabled(tbl))
return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
@@ -457,7 +459,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
 
return nelems;
 error:
-   calgary_unmap_sg(dev, sg, nelems, direction);
+   calgary_unmap_sg(dev, sg, nelems, flags);
for_each_sg(sg, s, nelems, i) {
sg-dma_address = bad_dma_address;
sg-dma_length = 0;
@@ -466,12 +468,13 @@ error:
 }
 
 static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
-   size_t size, int direction)
+   size_t size, u32 flags)
 {
dma_addr_t dma_handle = bad_dma_address;
unsigned long uaddr;
unsigned int npages;
struct iommu_table *tbl = find_iommu_table(dev);
+   enum dma_data_direction direction = dma_flags_get_dir(flags);
 
uaddr = (unsigned long)vaddr;
npages = num_dma_pages(uaddr, size);
@@ -485,7 +488,7 @@ static dma_addr_t calgary_map_single(struct device *dev, 
void *vaddr,
 }
 
 static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
-   size_t size, int direction)
+   size_t size, u32 flags)
 {
struct iommu_table *tbl = find_iommu_table(dev);
unsigned int npages;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 06bcba5..da7336a 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -25,6 +25,7 @@
 #include linux/bitops.h
 #include linux/kdebug.h
 #include linux/scatterlist.h
+#include linux/dma-direction.h
 #include asm/atomic.h
 #include asm/io.h
 #include asm/mtrr.h
@@ -230,15 +231,17 @@ static dma_addr_t dma_map_area(struct device *dev, 
dma_addr_t phys_mem,
 }
 
 static dma_addr_t gart_map_simple(struct device *dev, char *buf,
-size_t size, int dir)
+size_t size, u32 flags)
 {
+   enum dma_data_direction dir = dma_flags_get_dir(flags);
dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
flush_gart();
return map;
 }
 
 /* Map a single area into the IOMMU */
-static dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, 
int dir)
+static dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, 
+ u32 flags)
 {
unsigned long phys_mem, bus;
 
@@ -249,7 +252,7 @@ static dma_addr_t gart_map_single(struct device *dev, void 
*addr, size_t size, i
if (!need_iommu(dev, phys_mem, size))
return phys_mem; 
 
-   bus = gart_map_simple(dev, addr, size, dir);
+   bus = gart_map_simple(dev, addr, size, flags);
return bus; 
 }
 
@@ -257,7 +260,7 @@ static dma_addr_t gart_map_single(struct device *dev, void 
*addr, size_t size, i
  * Free a DMA mapping.
  */
 static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
- size_t size, int direction)
+ size_t size, u32 flags)
 {
unsigned long iommu_page;
int npages;
@@ -278,10 +281,12 @@ static void gart_unmap_single(struct device 

Re: [RFC] dma: passing "attributes" to dma_map_* routines

2007-12-21 Thread akepner
On Fri, Dec 21, 2007 at 07:56:25AM +1100, Benjamin Herrenschmidt wrote:
> ...
> Can't you just have a primitive to sync things up that you call
> explicitely from your driver after fetching a new status entry ?
> 

Well, the only mechanisms I know to get things synced are the ones 
I mentioned before: 1) generate an interrupt, 2) write to memory 
which has the "barrier" attribute. Obviously 1 is out - giving  
the memory used for status indications the barrier attribute is 
the most primitive means I'm aware of.

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing attributes to dma_map_* routines

2007-12-21 Thread akepner
On Fri, Dec 21, 2007 at 07:56:25AM +1100, Benjamin Herrenschmidt wrote:
 ...
 Can't you just have a primitive to sync things up that you call
 explicitely from your driver after fetching a new status entry ?
 

Well, the only mechanisms I know to get things synced are the ones 
I mentioned before: 1) generate an interrupt, 2) write to memory 
which has the barrier attribute. Obviously 1 is out - giving  
the memory used for status indications the barrier attribute is 
the most primitive means I'm aware of.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing "attributes" to dma_map_* routines

2007-12-20 Thread akepner
On Tue, Dec 18, 2007 at 09:59:24PM +0100, Stefan Richter wrote:
> 
> From its purpose it sounds like you need this only for few special
> memory regions which would typically be mapped by dma_map_single() 

We need the _sg versions too, as Roland already mentioned.

>  and
> furthermore that drivers who need this behavior will be changed to
> explicitly demand it.  If so, a nonintrusive API extension could simply
> be to add an
> 
> dma_addr_t dma_map_single_write_last(struct device *dev, void *ptr,
> size_t size, enum dma_data_direction direction);
> ...

This is the easiest thing to do, and therefore it'd be my 
preference. But I'm concerned that the keepers of the dma 
interface will object to this. So far they've been silent 
in this thread - maybe they need to see a patch before 
they'll get engaged

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing "attributes" to dma_map_* routines

2007-12-20 Thread akepner
On Tue, Dec 18, 2007 at 09:59:24PM +0100, Stefan Richter wrote:

> 
> So that would be option 3) of yours, though without your attrs
> parameter.  Do you expect the need for even more flags for other kinds
> of special behavior?

I was hoping to keep the option of adding additional 
flags, but for now there's no obvious need for other
flags that I'm aware of.

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing attributes to dma_map_* routines

2007-12-20 Thread akepner
On Tue, Dec 18, 2007 at 09:59:24PM +0100, Stefan Richter wrote:

 
 So that would be option 3) of yours, though without your attrs
 parameter.  Do you expect the need for even more flags for other kinds
 of special behavior?

I was hoping to keep the option of adding additional 
flags, but for now there's no obvious need for other
flags that I'm aware of.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing attributes to dma_map_* routines

2007-12-20 Thread akepner
On Tue, Dec 18, 2007 at 09:59:24PM +0100, Stefan Richter wrote:
 
 From its purpose it sounds like you need this only for few special
 memory regions which would typically be mapped by dma_map_single() 

We need the _sg versions too, as Roland already mentioned.

  and
 furthermore that drivers who need this behavior will be changed to
 explicitly demand it.  If so, a nonintrusive API extension could simply
 be to add an
 
 dma_addr_t dma_map_single_write_last(struct device *dev, void *ptr,
 size_t size, enum dma_data_direction direction);
 ...

This is the easiest thing to do, and therefore it'd be my 
preference. But I'm concerned that the keepers of the dma 
interface will object to this. So far they've been silent 
in this thread - maybe they need to see a patch before 
they'll get engaged

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing "attributes" to dma_map_* routines

2007-12-18 Thread akepner
On Tue, Dec 18, 2007 at 05:50:42PM +0100, Stefan Richter wrote:

> Do I understand correctly?:  A device and the CPUs communicate via two
> separate memory areas:  A data buffer and a status FIFO.  The NUMA
> interconnect may reorder accesses of the device to the areas.  (Write
> accesses?  Read accesses?  Both?)

Yes, I think you understand. Reorderings are possible on reads and
writes. Things get synced up by either an interrupt or a write to
a memory region with a "barrier attribute". Memory allocated with
dma_alloc_coherent() gets the barrier attribute. The idea here is
to allow memory allocated with plain old malloc() or whatever to
get the same attribute.

> 
> To ensure synchronization between device and CPUs, you want to mark a
> memory area which is to be dma-mapped with a flag which says:  "Writes
> to the memory region will cause in-flight DMA to be flushed".  Whose
> writes?  A write access from the device or a write access from a CPU?

A write from the device, e.g., when the device writes to indicate
"data DMA is complete".

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] dma: passing attributes to dma_map_* routines

2007-12-18 Thread akepner
On Tue, Dec 18, 2007 at 05:50:42PM +0100, Stefan Richter wrote:

 Do I understand correctly?:  A device and the CPUs communicate via two
 separate memory areas:  A data buffer and a status FIFO.  The NUMA
 interconnect may reorder accesses of the device to the areas.  (Write
 accesses?  Read accesses?  Both?)

Yes, I think you understand. Reorderings are possible on reads and
writes. Things get synced up by either an interrupt or a write to
a memory region with a barrier attribute. Memory allocated with
dma_alloc_coherent() gets the barrier attribute. The idea here is
to allow memory allocated with plain old malloc() or whatever to
get the same attribute.

 
 To ensure synchronization between device and CPUs, you want to mark a
 memory area which is to be dma-mapped with a flag which says:  Writes
 to the memory region will cause in-flight DMA to be flushed.  Whose
 writes?  A write access from the device or a write access from a CPU?

A write from the device, e.g., when the device writes to indicate
data DMA is complete.

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC] dma: passing "attributes" to dma_map_* routines

2007-12-17 Thread akepner

Waaay back in October I sent some patches for passing additional 
attributes to the dma_map_* routines:

http://marc.info/?l=linux-kernel=119137949604365=2

This is somthing needed for ia64 Altix NUMA machines (as described 
in that thread).

Several folks objected to the approach I used - it was a bit of a 
hack - and so these patches were dropped. 

This time I'd like to get something resembling concensus before 
spending much time on this. 

Can you please comment on the options listed here, or suggest 
alternatives?

We could:

1) add an additional parameter to the dma_map_* routines, somthing 
   like:

 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction, u32 flags)
 

2) change the "direction" argument to be a field of bits:

 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
u32 flags)
 

 where flags encodes the direction and optionally other attributes.

3) add new functions to the dma interface, e.g.:

 dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
  enum dma_data_direction direction, u32 attrs)
 .

1) and 2) are going to require many minor changes, and 3) is going 
to pollute the dma interface a bit. 

Other ideas?

-- 
Arthur

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC] dma: passing attributes to dma_map_* routines

2007-12-17 Thread akepner

Waaay back in October I sent some patches for passing additional 
attributes to the dma_map_* routines:

http://marc.info/?l=linux-kernelm=119137949604365w=2

This is somthing needed for ia64 Altix NUMA machines (as described 
in that thread).

Several folks objected to the approach I used - it was a bit of a 
hack - and so these patches were dropped. 

This time I'd like to get something resembling concensus before 
spending much time on this. 

Can you please comment on the options listed here, or suggest 
alternatives?

We could:

1) add an additional parameter to the dma_map_* routines, somthing 
   like:

 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction, u32 flags)
 

2) change the direction argument to be a field of bits:

 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
u32 flags)
 

 where flags encodes the direction and optionally other attributes.

3) add new functions to the dma interface, e.g.:

 dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
  enum dma_data_direction direction, u32 attrs)
 .

1) and 2) are going to require many minor changes, and 3) is going 
to pollute the dma interface a bit. 

Other ideas?

-- 
Arthur

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] dma: add dma_flags_set/get_*() interfaces

2007-10-17 Thread akepner

[reply to the series of three mails below]

On Tue, Oct 16, 2007 at 08:27:28PM -0700, Andrew Morton wrote:
> On Tue, 16 Oct 2007 18:41:28 -0700 [EMAIL PROTECTED] wrote:
> 
> > +#define DMA_BARRIER_ATTR   0x1
> > +#ifndef ARCH_USES_DMA_ATTRS
> > +static inline int dma_flags_set_attr(u32 attr, enum dma_data_direction 
> > dir) 
> > +{
> > +   return dir;
> > +}
> 
> This function takes an `enum dma_data_direction' as its second arg, but your
> ia64 implementation takes an 'int'.
> 

This is because the dma_data_direction enum type isn't available 
at the point the ia64 implementation is defined. 


> > .
> >  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?

Changing the type of the last argument to dma_map_* functions 
to be a bitmask? Or adding an additional argument? (Both of 
which you mention below.)

> > .

> > +DMA_BARRIER_ATTR would be set when the memory region is mapped for DMA,
> > +e.g.:
> > +
> > + int count;
> > + int flags = dma_flags_set_attr(DMA_BARRIER_ATTR, DMA_BIDIRECTIONAL);
> > + 
> > + count = dma_map_sg(dev, sglist, nents, flags);
> > +
> 
> Isn't this rather a kludge?

I prefer the term "hack".

> 
> What would be the cost of doing this cleanly and either redefining
> dma_data_direction to be a field-of-bits or just leave dma_data_direction
> alone (it is quite unrelated to this work, isn't it?) and adding new
> fields/arguments to manage this new functionality?

It'd be significantly more work to do change or add arguments 
to the dma_map_* functions. But if that's what I need to do to 
get this accepted, I'll back up and have another go at it.

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] dma: add dma_flags_set/get_*() interfaces

2007-10-17 Thread akepner

[reply to the series of three mails below]

On Tue, Oct 16, 2007 at 08:27:28PM -0700, Andrew Morton wrote:
 On Tue, 16 Oct 2007 18:41:28 -0700 [EMAIL PROTECTED] wrote:
 
  +#define DMA_BARRIER_ATTR   0x1
  +#ifndef ARCH_USES_DMA_ATTRS
  +static inline int dma_flags_set_attr(u32 attr, enum dma_data_direction 
  dir) 
  +{
  +   return dir;
  +}
 
 This function takes an `enum dma_data_direction' as its second arg, but your
 ia64 implementation takes an 'int'.
 

This is because the dma_data_direction enum type isn't available 
at the point the ia64 implementation is defined. 


  .
   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?

Changing the type of the last argument to dma_map_* functions 
to be a bitmask? Or adding an additional argument? (Both of 
which you mention below.)

  .

  +DMA_BARRIER_ATTR would be set when the memory region is mapped for DMA,
  +e.g.:
  +
  + int count;
  + int flags = dma_flags_set_attr(DMA_BARRIER_ATTR, DMA_BIDIRECTIONAL);
  + 
  + count = dma_map_sg(dev, sglist, nents, flags);
  +
 
 Isn't this rather a kludge?

I prefer the term hack.

 
 What would be the cost of doing this cleanly and either redefining
 dma_data_direction to be a field-of-bits or just leave dma_data_direction
 alone (it is quite unrelated to this work, isn't it?) and adding new
 fields/arguments to manage this new functionality?

It'd be significantly more work to do change or add arguments 
to the dma_map_* functions. But if that's what I need to do to 
get this accepted, I'll back up and have another go at it.

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] document dma_flags_set/get_*()

2007-10-16 Thread akepner

Document the dma_flags_set/get_*() interfaces.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--- 

 DMA-API.txt |   38 ++
 1 files changed, 38 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b939ebb..00919b0 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -547,3 +547,41 @@ size is the size (and should be a page-sized multiple).
 The return value will be either a pointer to the processor virtual
 address of the memory, or an error (via PTR_ERR()) if any part of the
 region is occupied.
+
+int 
+dma_flags_set_attr(u32 attr, enum dma_data_direction dir)
+
+Amend dir with a platform-specific "dma attribute".
+
+The only attribute currently defined is DMA_BARRIER_ATTR, which causes 
+in-flight DMA to be flushed when the associated memory region is written 
+to (see example below).  Setting DMA_BARRIER_ATTR provides a mechanism 
+to enforce ordering of DMA on platforms that permit DMA to be reordered 
+between device and host memory (within a NUMA interconnect).  On other 
+platforms this is a nop.
+
+DMA_BARRIER_ATTR would be set when the memory region is mapped for DMA, 
+e.g.:
+
+   int count;
+   int flags = dma_flags_set_attr(DMA_BARRIER_ATTR, DMA_BIDIRECTIONAL);
+   
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+As an example of a situation where this would be useful, suppose that 
+the device does a DMA write to indicate that data is ready and 
+available in memory.  The DMA of the "completion indication" could 
+race with data DMA.  Using DMA_BARRIER_ATTR on the memory used for 
+completion indications would prevent the race.
+
+int
+dma_flags_get_dir(int flags)
+
+Retrieve the original DMA direction, where flags was returned from 
+dma_flags_set_attr().
+
+int
+dma_flags_get_attr(int flags)
+
+Retrieve the "dma attributes", where flags was returned from 
+dma_flags_set_attr().
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] dma: redefine dma_flags_set/get_*() for sn-ia64

2007-10-16 Thread akepner

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 <[EMAIL PROTECTED]>

--- 

 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 != _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 != _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 

[PATCH 1/3] dma: add dma_flags_set/get_*() interfaces

2007-10-16 Thread akepner

Introduce the dma_flags_set/get_*() interfaces and give them 
default implementations. 

Architectures which allow DMA to be reordered between a device and 
host memory (within a NUMA interconnect) can redefine these to allow 
a driver to explicitly synchronize DMA from the device when necessary.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--- 

Andrew, this is the first in a series of three patches:

  [1/3] dma: add dma_flags_set/get_*() interfaces
  [2/3] dma: redefine dma_flags_set/get_*() for sn-ia64
  [3/3] dma: document dma_flags_set/get_*()

Variants of these patches have been discussed on several 
occasions, most recently in a thread beginning:

http://marc.info/?l=linux-kernel=119137949604365=2

Please consider this for 2.6.24.

Jes, Tony, please note that I added an explicit test for 
CONFIG_IA64_SGI_SN2 in asm-ia64/sn/io.h (Yuck). This is 
needed for IA64_GENERIC to build, since there's at least one 
driver (qla1280) that includes asm-ia64/sn/io.h for 
CONFIG_IA64_GENERIC. 

 dma-mapping.h |   18 ++
 1 files changed, 18 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0ebfafb..132b559 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -106,4 +106,22 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#define DMA_BARRIER_ATTR   0x1
+#ifndef ARCH_USES_DMA_ATTRS
+static inline int dma_flags_set_attr(u32 attr, enum dma_data_direction dir) 
+{
+   return dir;
+}
+
+static inline int dma_flags_get_dir(int flags)
+{
+   return flags;
+}
+
+static inline int dma_flags_get_attr(int flags)
+{
+   return 0;
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] dma: add dma_flags_set/get_*() interfaces

2007-10-16 Thread akepner

Introduce the dma_flags_set/get_*() interfaces and give them 
default implementations. 

Architectures which allow DMA to be reordered between a device and 
host memory (within a NUMA interconnect) can redefine these to allow 
a driver to explicitly synchronize DMA from the device when necessary.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--- 

Andrew, this is the first in a series of three patches:

  [1/3] dma: add dma_flags_set/get_*() interfaces
  [2/3] dma: redefine dma_flags_set/get_*() for sn-ia64
  [3/3] dma: document dma_flags_set/get_*()

Variants of these patches have been discussed on several 
occasions, most recently in a thread beginning:

http://marc.info/?l=linux-kernelm=119137949604365w=2

Please consider this for 2.6.24.

Jes, Tony, please note that I added an explicit test for 
CONFIG_IA64_SGI_SN2 in asm-ia64/sn/io.h (Yuck). This is 
needed for IA64_GENERIC to build, since there's at least one 
driver (qla1280) that includes asm-ia64/sn/io.h for 
CONFIG_IA64_GENERIC. 

 dma-mapping.h |   18 ++
 1 files changed, 18 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0ebfafb..132b559 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -106,4 +106,22 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#define DMA_BARRIER_ATTR   0x1
+#ifndef ARCH_USES_DMA_ATTRS
+static inline int dma_flags_set_attr(u32 attr, enum dma_data_direction dir) 
+{
+   return dir;
+}
+
+static inline int dma_flags_get_dir(int flags)
+{
+   return flags;
+}
+
+static inline int dma_flags_get_attr(int flags)
+{
+   return 0;
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] dma: redefine dma_flags_set/get_*() for sn-ia64

2007-10-16 Thread akepner

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 [EMAIL PROTECTED]

--- 

 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 

[PATCH 3/3] document dma_flags_set/get_*()

2007-10-16 Thread akepner

Document the dma_flags_set/get_*() interfaces.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--- 

 DMA-API.txt |   38 ++
 1 files changed, 38 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b939ebb..00919b0 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -547,3 +547,41 @@ size is the size (and should be a page-sized multiple).
 The return value will be either a pointer to the processor virtual
 address of the memory, or an error (via PTR_ERR()) if any part of the
 region is occupied.
+
+int 
+dma_flags_set_attr(u32 attr, enum dma_data_direction dir)
+
+Amend dir with a platform-specific dma attribute.
+
+The only attribute currently defined is DMA_BARRIER_ATTR, which causes 
+in-flight DMA to be flushed when the associated memory region is written 
+to (see example below).  Setting DMA_BARRIER_ATTR provides a mechanism 
+to enforce ordering of DMA on platforms that permit DMA to be reordered 
+between device and host memory (within a NUMA interconnect).  On other 
+platforms this is a nop.
+
+DMA_BARRIER_ATTR would be set when the memory region is mapped for DMA, 
+e.g.:
+
+   int count;
+   int flags = dma_flags_set_attr(DMA_BARRIER_ATTR, DMA_BIDIRECTIONAL);
+   
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+As an example of a situation where this would be useful, suppose that 
+the device does a DMA write to indicate that data is ready and 
+available in memory.  The DMA of the completion indication could 
+race with data DMA.  Using DMA_BARRIER_ATTR on the memory used for 
+completion indications would prevent the race.
+
+int
+dma_flags_get_dir(int flags)
+
+Retrieve the original DMA direction, where flags was returned from 
+dma_flags_set_attr().
+
+int
+dma_flags_get_attr(int flags)
+
+Retrieve the dma attributes, where flags was returned from 
+dma_flags_set_attr().
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/5] infiniband: add "dmabarrier" argument to ib_umem_get()

2007-10-03 Thread akepner
On Tue, Oct 02, 2007 at 08:10:23PM -0700, David Miller wrote:
> From: [EMAIL PROTECTED]
> Date: Tue, 2 Oct 2007 19:49:06 -0700
> 
> > 
> > Pass a "dmabarrier" argument to ib_umem_get() and use the new 
> > argument to control setting the DMA_BARRIER_ATTR attribute on 
> > the memory that ib_umem_get() maps for DMA.
> > 
> > Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>
> 
> Acked-by: David S. Miller <[EMAIL PROTECTED]>
> 
> However I'm a little unhappy with how IA64 achieves this.
> 
> The last argument for dma_map_foo() is an enum not an int,
> every platform other than IA64 properly defines the last
> argument as "enum dma_data_direction".  It can take one
> of several distinct values, it is not a mask.
> 
> This hijacking of the DMA direction argument is hokey at
> best, and at worst is type bypassing which is going to
> explode subtly for someone in the future and result in
> a long painful debugging session.
> 

I don't dispute your point about abusing the enum here, it 
just seemed the least objectionable, and most expedient way 
to go.  But I'll add that ia64 isn't alone, x86_64 also uses 
an int for the final argument to its dma_map_* implementations.

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 5/5] mthca: allow setting "dmabarrier" on user-allocated memory

2007-10-03 Thread akepner
On Wed, Oct 03, 2007 at 05:56:45AM +0300, Heikki Orsila wrote:
> On Tue, Oct 02, 2007 at 07:50:07PM -0700, [EMAIL PROTECTED] wrote:
> > +struct mthca_reg_mr {
> > +   __u32 mr_attrs;
> > +#define MTHCA_MR_DMAFLUSH 0x1  /* flush in-flight DMA on a write to 
> > +* memory region */
> > +   __u32 reserved;
> > +};
> 
> Seems like a very odd place to #define something new..
> 

Lots of drivers do that - #define flags or whatever near the 
variable to which they apply. Didn't see any examples in the 
mthca driver though, so maybe it's setting a precedent there. 
If the maintainer objects, I'll move it.

--  
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/5] infiniband: add dmabarrier argument to ib_umem_get()

2007-10-03 Thread akepner
On Tue, Oct 02, 2007 at 08:10:23PM -0700, David Miller wrote:
 From: [EMAIL PROTECTED]
 Date: Tue, 2 Oct 2007 19:49:06 -0700
 
  
  Pass a dmabarrier argument to ib_umem_get() and use the new 
  argument to control setting the DMA_BARRIER_ATTR attribute on 
  the memory that ib_umem_get() maps for DMA.
  
  Signed-off-by: Arthur Kepner [EMAIL PROTECTED]
 
 Acked-by: David S. Miller [EMAIL PROTECTED]
 
 However I'm a little unhappy with how IA64 achieves this.
 
 The last argument for dma_map_foo() is an enum not an int,
 every platform other than IA64 properly defines the last
 argument as enum dma_data_direction.  It can take one
 of several distinct values, it is not a mask.
 
 This hijacking of the DMA direction argument is hokey at
 best, and at worst is type bypassing which is going to
 explode subtly for someone in the future and result in
 a long painful debugging session.
 

I don't dispute your point about abusing the enum here, it 
just seemed the least objectionable, and most expedient way 
to go.  But I'll add that ia64 isn't alone, x86_64 also uses 
an int for the final argument to its dma_map_* implementations.

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 5/5] mthca: allow setting dmabarrier on user-allocated memory

2007-10-03 Thread akepner
On Wed, Oct 03, 2007 at 05:56:45AM +0300, Heikki Orsila wrote:
 On Tue, Oct 02, 2007 at 07:50:07PM -0700, [EMAIL PROTECTED] wrote:
  +struct mthca_reg_mr {
  +   __u32 mr_attrs;
  +#define MTHCA_MR_DMAFLUSH 0x1  /* flush in-flight DMA on a write to 
  +* memory region */
  +   __u32 reserved;
  +};
 
 Seems like a very odd place to #define something new..
 

Lots of drivers do that - #define flags or whatever near the 
variable to which they apply. Didn't see any examples in the 
mthca driver though, so maybe it's setting a precedent there. 
If the maintainer objects, I'll move it.

--  
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 5/5] mthca: allow setting "dmabarrier" on user-allocated memory

2007-10-02 Thread akepner

Allow setting a "dmabarrier" when the mthca driver registers user-
allocated memory.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 mthca_provider.c |7 ++-
 mthca_user.h |   10 +-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c 
b/drivers/infiniband/hw/mthca/mthca_provider.c
index 17486a4..c818708 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1017,17 +1017,22 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd 
*pd, u64 start, u64 length,
struct mthca_dev *dev = to_mdev(pd->device);
struct ib_umem_chunk *chunk;
struct mthca_mr *mr;
+   struct mthca_reg_mr ucmd;
u64 *pages;
int shift, n, len;
int i, j, k;
int err = 0;
int write_mtt_size;
 
+   if (ib_copy_from_udata(, udata, sizeof ucmd)) 
+   return ERR_PTR(-EFAULT);
+
mr = kmalloc(sizeof *mr, GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
 
-   mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
+   mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 
+  ucmd.mr_attrs & MTHCA_MR_DMAFLUSH);
if (IS_ERR(mr->umem)) {
err = PTR_ERR(mr->umem);
goto err;
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h 
b/drivers/infiniband/hw/mthca/mthca_user.h
index 02cc0a7..5662aea 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -41,7 +41,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MTHCA_UVERBS_ABI_VERSION   1
+#define MTHCA_UVERBS_ABI_VERSION   2
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -61,6 +61,14 @@ struct mthca_alloc_pd_resp {
__u32 reserved;
 };
 
+struct mthca_reg_mr {
+   __u32 mr_attrs;
+#define MTHCA_MR_DMAFLUSH 0x1  /* flush in-flight DMA on a write to 
+* memory region */
+   __u32 reserved;
+};
+
+
 struct mthca_create_cq {
__u32 lkey;
__u32 pdn;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/5] dma: document dma_flags_set_attr()

2007-10-02 Thread akepner

Document dma_flags_set_attr().

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 DMA-API.txt |   27 +++
 1 files changed, 27 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index cc7a8c3..16e15c0 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -544,3 +544,30 @@ size is the size (and should be a page-sized multiple).
 The return value will be either a pointer to the processor virtual
 address of the memory, or an error (via PTR_ERR()) if any part of the
 region is occupied.
+
+int 
+dma_flags_set_attr(u32 attr, enum dma_data_direction dir)
+
+Amend dir with a platform-specific "dma attribute".
+
+The only attribute currently defined is DMA_BARRIER_ATTR, which causes 
+in-flight DMA to be flushed when the associated memory region is written 
+to (see example below).  Setting DMA_BARRIER_ATTR provides a mechanism 
+to enforce ordering of DMA on platforms that permit DMA to be reordered 
+between device and host memory (within a NUMA interconnect).  On other 
+platforms this is a nop.
+
+DMA_BARRIER_ATTR would be set when the memory region is mapped for DMA, 
+e.g.:
+
+   int count;
+   int flags = dma_flags_set_attr(DMA_BARRIER_ATTR, DMA_BIDIRECTIONAL);
+   
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+As an example of a situation where this would be useful, suppose that 
+the device does a DMA write to indicate that data is ready and 
+available in memory.  The DMA of the "completion indication" could 
+race with data DMA.  Using DMA_BARRIER_ATTR on the memory used for 
+completion indications would prevent the race.
+
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/5] infiniband: add "dmabarrier" argument to ib_umem_get()

2007-10-02 Thread akepner

Pass a "dmabarrier" argument to ib_umem_get() and use the new 
argument to control setting the DMA_BARRIER_ATTR attribute on 
the memory that ib_umem_get() maps for DMA.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 drivers/infiniband/core/umem.c   |8 ++--
 drivers/infiniband/hw/amso1100/c2_provider.c |2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 +-
 drivers/infiniband/hw/ipath/ipath_mr.c   |2 +-
 drivers/infiniband/hw/mlx4/cq.c  |2 +-
 drivers/infiniband/hw/mlx4/doorbell.c|2 +-
 drivers/infiniband/hw/mlx4/mr.c  |3 ++-
 drivers/infiniband/hw/mlx4/qp.c  |2 +-
 drivers/infiniband/hw/mlx4/srq.c |2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c |2 +-
 include/rdma/ib_umem.h   |4 ++--
 12 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 664d2fa..093b58d 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -69,9 +69,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set "dmabarrier" attribute on this memory
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -83,6 +84,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   int flags = dmabarrier ? dma_flags_set_attr(DMA_BARRIER_ATTR, 
+   DMA_BIDIRECTIONAL) : 
+DMA_BIDIRECTIONAL;
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -160,7 +164,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
chunk->nmap = ib_dma_map_sg(context->device,
>page_list[0],
chunk->nents,
-   DMA_BIDIRECTIONAL);
+   flags);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(chunk->page_list[i].page);
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 997cf15..17243b7 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr->pd = c2pd;
 
-   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(c2mr->umem)) {
err = PTR_ERR(c2mr->umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c7775..d0a514c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(mhp->umem)) {
err = PTR_ERR(mhp->umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index d97eda3..c13c11c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -329,7 +329,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
-mr_access_flags);
+mr_access_flags, 0);
if (IS_ERR(e_mr->umem)) {
ib_mr = (void *)e_mr->umem;
goto reg_user_mr_exit1;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c 
b/drivers/infiniband/hw/ipath/ipath_mr.c
index e442470..e351222 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -195,7 +195,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,

[PATCH 2/5] dma: redefine dma_flags_set_attr() for sn-ia64

2007-10-02 Thread akepner

define dma_flags_set_attr() for sn-ia64 - it "borrows" bits from 
the direction argument (renamed "flags") to the dma_map_* routines 
to pass an additional attributes.  Also define routines to retrieve 
the original direction and attribute from "flags".

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 arch/ia64/sn/pci/pci_dma.c |   37 +++--
 include/asm-ia64/sn/io.h   |   23 +++
 2 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddac..84b6227 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 != _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;
@@ -240,18 +246,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 *sg, int nhwentries,
- int direction)
+ int flags)
 {
unsigned long phys_addr;
struct scatterlist *saved_sg = 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 != _bus_type);
 
@@ -259,19 +267,28 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
 * Setup a DMA address for each entry in the scatterlist.
 */
for (i = 0; i < nhwentries; i++, sg++) {
+   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..d2b94ce 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -271,4 +271,27 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long 
*addr, int vchan)
return 0;
 }
 
+#define ARCH_USES_DMA_ATTRS
+/* we pass additional dma attributes in the 

[PATCH 1/5] dma: add dma_flags_set_attr() to dma interface

2007-10-02 Thread akepner

Introduce the dma_flags_set_attr() interface and give it a default 
no-op implementation.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---

 dma-mapping.h |8 
 1 files changed, 8 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 2dc21cb..4990aaf 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -99,4 +99,12 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#define DMA_BARRIER_ATTR   0x1
+#ifndef ARCH_USES_DMA_ATTRS
+static inline int dma_flags_set_attr(u32 attr, enum dma_data_direction dir) 
+{
+   return dir;
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/5] allow drivers to flush in-flight DMA v3

2007-10-02 Thread akepner

On Altix, DMA may be reordered between a device and host memory. 
This reordering can happen in the NUMA interconnect, and it usually 
results in correct operation and improved performance. In some 
situations it may be necessary to explicitly synchronize DMA from 
the device.

This patchset allows a memory region to be mapped with a "dmabarrier". 
Writes to the memory region will cause in-flight DMA to be flushed, 
providing a mechanism to order DMA from a device.

There are 5 patches in this patchset:

  [1/5] dma: add dma_flags_set_attr() to dma interface
  [2/5] dma: redefine dma_flags_set_attr() for sn-ia64
  [3/5] dma: document dma_flags_set_attr()
  [4/5] infiniband: add "dmabarrier" argument to ib_umem_get()
  [5/5] mthca: allow setting "dmabarrier" on user-allocated memory

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 0/4] allow drivers to flush in-flight DMA v2

2007-10-02 Thread akepner
On Fri, Sep 28, 2007 at 03:43:39PM -0700, David Miller wrote:
> 
> My only beef with this patch set is that it seems
> a bit much to create a totally new function name every
> time we want to set some kind of new attribute on some
> DMA object.  Why not add a "dma_set_flags()" or similar
> that can be used later on to set other kinds of aspects
> we'd like to change?
> 
> You can make the arguments "u32 flags" and "int dir".
> Actually you should probably use the dma direction
> enumaration instead of 'int'.

OK, this will be in the next version along with the 
coding style changes you mentioned.

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [4/4] mthca: allow setting "dmabarrier" on user-allocated memory

2007-10-02 Thread akepner
On Fri, Sep 28, 2007 at 12:50:00PM -0700, Roland Dreier wrote:

> Sorry for not mentioning this earlier, but this patch should really be
> two (or more) patches: one to add dmabarrier support to the core user
> memory stuff in drivers/infiniband, and a second one to add support to
> mthca (and more patches to add support to mlx4, cxgb3, etc, etc).

Makes sense. 

> 
>  > + * @dmabarrier: set "dmabarrier" attribute on this memory, if necessary 
> 
> Nit: just delete the "if necessary" since I don't think it makes
> things clearer (and actually doesn't make much sense in this context)
>

OK.
 
> Other than that this look fine to me, and I'm ready to merge it once
> the necessary core DMA stuff is settled.
> 

Great. A new version of the patchset is on the way.

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [4/4] mthca: allow setting dmabarrier on user-allocated memory

2007-10-02 Thread akepner
On Fri, Sep 28, 2007 at 12:50:00PM -0700, Roland Dreier wrote:

 Sorry for not mentioning this earlier, but this patch should really be
 two (or more) patches: one to add dmabarrier support to the core user
 memory stuff in drivers/infiniband, and a second one to add support to
 mthca (and more patches to add support to mlx4, cxgb3, etc, etc).

Makes sense. 

 
   + * @dmabarrier: set dmabarrier attribute on this memory, if necessary 
 
 Nit: just delete the if necessary since I don't think it makes
 things clearer (and actually doesn't make much sense in this context)


OK.
 
 Other than that this look fine to me, and I'm ready to merge it once
 the necessary core DMA stuff is settled.
 

Great. A new version of the patchset is on the way.

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 0/4] allow drivers to flush in-flight DMA v2

2007-10-02 Thread akepner
On Fri, Sep 28, 2007 at 03:43:39PM -0700, David Miller wrote:
 
 My only beef with this patch set is that it seems
 a bit much to create a totally new function name every
 time we want to set some kind of new attribute on some
 DMA object.  Why not add a dma_set_flags() or similar
 that can be used later on to set other kinds of aspects
 we'd like to change?
 
 You can make the arguments u32 flags and int dir.
 Actually you should probably use the dma direction
 enumaration instead of 'int'.

OK, this will be in the next version along with the 
coding style changes you mentioned.

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/5] allow drivers to flush in-flight DMA v3

2007-10-02 Thread akepner

On Altix, DMA may be reordered between a device and host memory. 
This reordering can happen in the NUMA interconnect, and it usually 
results in correct operation and improved performance. In some 
situations it may be necessary to explicitly synchronize DMA from 
the device.

This patchset allows a memory region to be mapped with a dmabarrier. 
Writes to the memory region will cause in-flight DMA to be flushed, 
providing a mechanism to order DMA from a device.

There are 5 patches in this patchset:

  [1/5] dma: add dma_flags_set_attr() to dma interface
  [2/5] dma: redefine dma_flags_set_attr() for sn-ia64
  [3/5] dma: document dma_flags_set_attr()
  [4/5] infiniband: add dmabarrier argument to ib_umem_get()
  [5/5] mthca: allow setting dmabarrier on user-allocated memory

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/5] dma: add dma_flags_set_attr() to dma interface

2007-10-02 Thread akepner

Introduce the dma_flags_set_attr() interface and give it a default 
no-op implementation.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 dma-mapping.h |8 
 1 files changed, 8 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 2dc21cb..4990aaf 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -99,4 +99,12 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#define DMA_BARRIER_ATTR   0x1
+#ifndef ARCH_USES_DMA_ATTRS
+static inline int dma_flags_set_attr(u32 attr, enum dma_data_direction dir) 
+{
+   return dir;
+}
+#endif /* ARCH_USES_DMA_ATTRS */
+
 #endif
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/5] dma: redefine dma_flags_set_attr() for sn-ia64

2007-10-02 Thread akepner

define dma_flags_set_attr() for sn-ia64 - it borrows bits from 
the direction argument (renamed flags) to the dma_map_* routines 
to pass an additional attributes.  Also define routines to retrieve 
the original direction and attribute from flags.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 arch/ia64/sn/pci/pci_dma.c |   37 +++--
 include/asm-ia64/sn/io.h   |   23 +++
 2 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddac..84b6227 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;
@@ -240,18 +246,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 *sg, int nhwentries,
- int direction)
+ int flags)
 {
unsigned long phys_addr;
struct scatterlist *saved_sg = 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);
 
@@ -259,19 +267,28 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
 * Setup a DMA address for each entry in the scatterlist.
 */
for (i = 0; i  nhwentries; i++, sg++) {
+   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..d2b94ce 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -271,4 +271,27 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long 
*addr, int vchan)
return 0;
 }
 
+#define ARCH_USES_DMA_ATTRS
+/* we pass additional dma attributes in the direction argument to the 
+ * 

[PATCH 3/5] dma: document dma_flags_set_attr()

2007-10-02 Thread akepner

Document dma_flags_set_attr().

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 DMA-API.txt |   27 +++
 1 files changed, 27 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index cc7a8c3..16e15c0 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -544,3 +544,30 @@ size is the size (and should be a page-sized multiple).
 The return value will be either a pointer to the processor virtual
 address of the memory, or an error (via PTR_ERR()) if any part of the
 region is occupied.
+
+int 
+dma_flags_set_attr(u32 attr, enum dma_data_direction dir)
+
+Amend dir with a platform-specific dma attribute.
+
+The only attribute currently defined is DMA_BARRIER_ATTR, which causes 
+in-flight DMA to be flushed when the associated memory region is written 
+to (see example below).  Setting DMA_BARRIER_ATTR provides a mechanism 
+to enforce ordering of DMA on platforms that permit DMA to be reordered 
+between device and host memory (within a NUMA interconnect).  On other 
+platforms this is a nop.
+
+DMA_BARRIER_ATTR would be set when the memory region is mapped for DMA, 
+e.g.:
+
+   int count;
+   int flags = dma_flags_set_attr(DMA_BARRIER_ATTR, DMA_BIDIRECTIONAL);
+   
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+As an example of a situation where this would be useful, suppose that 
+the device does a DMA write to indicate that data is ready and 
+available in memory.  The DMA of the completion indication could 
+race with data DMA.  Using DMA_BARRIER_ATTR on the memory used for 
+completion indications would prevent the race.
+
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/5] infiniband: add dmabarrier argument to ib_umem_get()

2007-10-02 Thread akepner

Pass a dmabarrier argument to ib_umem_get() and use the new 
argument to control setting the DMA_BARRIER_ATTR attribute on 
the memory that ib_umem_get() maps for DMA.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 drivers/infiniband/core/umem.c   |8 ++--
 drivers/infiniband/hw/amso1100/c2_provider.c |2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 +-
 drivers/infiniband/hw/ipath/ipath_mr.c   |2 +-
 drivers/infiniband/hw/mlx4/cq.c  |2 +-
 drivers/infiniband/hw/mlx4/doorbell.c|2 +-
 drivers/infiniband/hw/mlx4/mr.c  |3 ++-
 drivers/infiniband/hw/mlx4/qp.c  |2 +-
 drivers/infiniband/hw/mlx4/srq.c |2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c |2 +-
 include/rdma/ib_umem.h   |4 ++--
 12 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 664d2fa..093b58d 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -69,9 +69,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set dmabarrier attribute on this memory
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -83,6 +84,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   int flags = dmabarrier ? dma_flags_set_attr(DMA_BARRIER_ATTR, 
+   DMA_BIDIRECTIONAL) : 
+DMA_BIDIRECTIONAL;
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -160,7 +164,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
chunk-nmap = ib_dma_map_sg(context-device,
chunk-page_list[0],
chunk-nents,
-   DMA_BIDIRECTIONAL);
+   flags);
if (chunk-nmap = 0) {
for (i = 0; i  chunk-nents; ++i)
put_page(chunk-page_list[i].page);
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 997cf15..17243b7 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr-pd = c2pd;
 
-   c2mr-umem = ib_umem_get(pd-uobject-context, start, length, acc);
+   c2mr-umem = ib_umem_get(pd-uobject-context, start, length, acc, 0);
if (IS_ERR(c2mr-umem)) {
err = PTR_ERR(c2mr-umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c7775..d0a514c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp-umem = ib_umem_get(pd-uobject-context, start, length, acc);
+   mhp-umem = ib_umem_get(pd-uobject-context, start, length, acc, 0);
if (IS_ERR(mhp-umem)) {
err = PTR_ERR(mhp-umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index d97eda3..c13c11c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -329,7 +329,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr-umem = ib_umem_get(pd-uobject-context, start, length,
-mr_access_flags);
+mr_access_flags, 0);
if (IS_ERR(e_mr-umem)) {
ib_mr = (void *)e_mr-umem;
goto reg_user_mr_exit1;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c 
b/drivers/infiniband/hw/ipath/ipath_mr.c
index e442470..e351222 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -195,7 +195,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
goto bail;
}
 
-   

[PATCH 5/5] mthca: allow setting dmabarrier on user-allocated memory

2007-10-02 Thread akepner

Allow setting a dmabarrier when the mthca driver registers user-
allocated memory.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---

 mthca_provider.c |7 ++-
 mthca_user.h |   10 +-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c 
b/drivers/infiniband/hw/mthca/mthca_provider.c
index 17486a4..c818708 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1017,17 +1017,22 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd 
*pd, u64 start, u64 length,
struct mthca_dev *dev = to_mdev(pd-device);
struct ib_umem_chunk *chunk;
struct mthca_mr *mr;
+   struct mthca_reg_mr ucmd;
u64 *pages;
int shift, n, len;
int i, j, k;
int err = 0;
int write_mtt_size;
 
+   if (ib_copy_from_udata(ucmd, udata, sizeof ucmd)) 
+   return ERR_PTR(-EFAULT);
+
mr = kmalloc(sizeof *mr, GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
 
-   mr-umem = ib_umem_get(pd-uobject-context, start, length, acc, 0);
+   mr-umem = ib_umem_get(pd-uobject-context, start, length, acc, 
+  ucmd.mr_attrs  MTHCA_MR_DMAFLUSH);
if (IS_ERR(mr-umem)) {
err = PTR_ERR(mr-umem);
goto err;
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h 
b/drivers/infiniband/hw/mthca/mthca_user.h
index 02cc0a7..5662aea 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -41,7 +41,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MTHCA_UVERBS_ABI_VERSION   1
+#define MTHCA_UVERBS_ABI_VERSION   2
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -61,6 +61,14 @@ struct mthca_alloc_pd_resp {
__u32 reserved;
 };
 
+struct mthca_reg_mr {
+   __u32 mr_attrs;
+#define MTHCA_MR_DMAFLUSH 0x1  /* flush in-flight DMA on a write to 
+* memory region */
+   __u32 reserved;
+};
+
+
 struct mthca_create_cq {
__u32 lkey;
__u32 pdn;
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[4/4] mthca: allow setting "dmabarrier" on user-allocated memory

2007-09-27 Thread akepner

Use the dma_flags_set_dmabarrier() interface to allow a "dmabarrier"
attribute to be associated with user-allocated memory. (For now,
it's only implemented for mthca.)

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--- 
 drivers/infiniband/core/umem.c   |7 +--
 drivers/infiniband/hw/amso1100/c2_provider.c |2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 +-
 drivers/infiniband/hw/ipath/ipath_mr.c   |2 +-
 drivers/infiniband/hw/mlx4/cq.c  |2 +-
 drivers/infiniband/hw/mlx4/doorbell.c|2 +-
 drivers/infiniband/hw/mlx4/mr.c  |3 ++-
 drivers/infiniband/hw/mlx4/qp.c  |2 +-
 drivers/infiniband/hw/mlx4/srq.c |2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c |7 ++-
 drivers/infiniband/hw/mthca/mthca_user.h |   10 +-
 include/rdma/ib_umem.h   |4 ++--
 13 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 664d2fa..5b30b0c 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -69,9 +69,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set "dmabarrier" attribute on this memory, if necessary 
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -83,6 +84,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   int flags = dmabarrier ? dma_flags_set_dmabarrier(DMA_BIDIRECTIONAL): 
+   DMA_BIDIRECTIONAL;
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -160,7 +163,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
chunk->nmap = ib_dma_map_sg(context->device,
>page_list[0],
chunk->nents,
-   DMA_BIDIRECTIONAL);
+   flags);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(chunk->page_list[i].page);
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 997cf15..17243b7 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr->pd = c2pd;
 
-   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(c2mr->umem)) {
err = PTR_ERR(c2mr->umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c7775..d0a514c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(mhp->umem)) {
err = PTR_ERR(mhp->umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index d97eda3..c13c11c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -329,7 +329,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
-mr_access_flags);
+mr_access_flags, 0);
if (IS_ERR(e_mr->umem)) {
ib_mr = (void *)e_mr->umem;
goto reg_user_mr_exit1;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c 
b/drivers/infiniband/hw/ipath/ipath_mr.c
index e442470..e351222 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -195,7 +195,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
  

[3/4] dma: document dma_flags_set_dmabarrier()

2007-09-27 Thread akepner

Document dma_flags_set_dmabarrier().

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---
 DMA-API.txt |   26 ++
 1 files changed, 26 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index cc7a8c3..5fc0bba 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -544,3 +544,29 @@ size is the size (and should be a page-sized multiple).
 The return value will be either a pointer to the processor virtual
 address of the memory, or an error (via PTR_ERR()) if any part of the
 region is occupied.
+
+int 
+dma_flags_set_dmabarrier(int dir)
+
+Amend dir (one of the enum dma_data_direction values), with a 
+platform-specific "dmabarrier" attribute.  The dmabarrier attribute 
+forces a flush of all in-flight DMA when the associated memory 
+region is written to (see example below.)
+
+This provides a mechanism to enforce ordering of DMA on platforms that 
+permit DMA to be reordered between device and host memory (within a 
+NUMA interconnect).  On other platforms this is a nop.
+
+The dmabarrier would be set when the memory region is mapped for DMA, 
+e.g.:
+
+   int count, flags = dma_flags_set_dmabarrier(DMA_BIDIRECTIONAL);
+   
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+As an example of a situation where this would be useful, suppose that 
+the device does a DMA write to indicate that data is ready and 
+available in memory.  The DMA of the "completion indication" could 
+race with data DMA.  Using a dmabarrier on the memory used for 
+completion indications would prevent the race.
+
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[2/4] dma: redefine dma_flags_set_dmabarrier() for sn-ia64

2007-09-27 Thread akepner

define dma_flags_set_dmabarrier() for sn-ia64 - it "borrows"
bits from the direction argument (renamed "flags") to the
dma_map_* routines to pass an additional "dmabarrier" attribute.
Also define routines to retrieve the original direction and
attribute from "flags".

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

---
 arch/ia64/sn/pci/pci_dma.c |   35 ++-
 include/asm-ia64/sn/io.h   |   24 
 2 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddac..6c0a498 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_dmabarrier(flags);
 
BUG_ON(dev->bus != _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;
@@ -240,18 +246,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 *sg, int nhwentries,
- int direction)
+ int flags)
 {
unsigned long phys_addr;
struct scatterlist *saved_sg = 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_dmabarrier(flags);
+   int direction = dma_flags_get_direction(flags);
 
BUG_ON(dev->bus != _bus_type);
 
@@ -259,12 +267,21 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
 * Setup a DMA address for each entry in the scatterlist.
 */
for (i = 0; i < nhwentries; i++, sg++) {
+   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__);
 
/*
diff --git a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
index 41c73a7..301bc47 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -271,4 +271,28 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long 
*addr, int vchan)
return 0;
 }
 
+#define ARCH_CAN_REORDER_DMA
+/* here we steal some upper bits from the "direction" argument to the 
+ * dma_map_* routines */
+#define DMA_ATTR_SHIFT 8
+/* bottom 8 bits for direction, remaining bits for additional "attributes" */
+#define DMA_BARRIER_ATTR   0x1
+/* Setting DMA_BARRIER_ATTR on a DMA-mapped memory region causes all in-
+ * flight DMA to be flushed when the memory region is written to. So 
+ * 

[1/4] dma: add dma_flags_set_dmabarrier() to dma interface

2007-09-27 Thread akepner

Introduce the dma_flags_set_dmabarrier() interface and give it
a default no-op implementation.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>

--- 

 dma-mapping.h |6 ++
 1 files changed, 6 insertions(+)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h

index 2dc21cb..4d1d199 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -99,4 +99,10 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_CAN_REORDER_DMA
+static inline int dma_flags_set_dmabarrier(int dir) {
+   return dir;
+}
+#endif /* ARCH_CAN_REORDER_DMA */
+
 #endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/4] allow drivers to flush in-flight DMA v2

2007-09-27 Thread akepner

On Altix, DMA may be reordered between a device and host memory. 
This reordering can happen in the NUMA interconnect, and it usually 
results in correct operation and improved performance. In some 
situations it may be necessary to explicitly synchronize DMA from 
the device.

This patchset allows a memory region to be mapped with a "dmabarrier". 
Writes to the memory region will cause in-flight DMA to be flushed, 
providing a mechanism to order DMA from a device.

There are 4 patches in this patchset:

  [1/4] dma: add dma_flags_set_dmabarrier() to dma interface
  [2/4] dma: redefine dma_flags_set_dmabarrier() for sn-ia64
  [3/4] dma: document dma_flags_set_dmabarrier()
  [4/4] mthca: allow setting "dmabarrier" on user-allocated memory

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 0/4] allow drivers to flush in-flight DMA

2007-09-27 Thread akepner
On Wed, Sep 26, 2007 at 12:49:50AM -0600, Grant Grundler wrote:

[edited out several points that I think have been already 
addresed by others in this thread.]

> 
> Defining it terms of completion queues won't mean much to most folks.
> Better to add a description of completion queues to the DMA-API.txt if
> necessary.  dma_alloc_coherent() API is pretty well understood.

OK, next time I'll use a more generic description.

> 
> > There are four patches in this set:
> > 
> >   [1/4] dma: add dma_flags_set_dmaflush() to dma interface
> 
> Sorry - this feels like a "color of the shed" argument, but isn't
> this about DMA ordering attribute?
> "dmaflush" is an action and not an attribute to me.

Right - an attribute is a noun, not a verb. I'm going to try 
"s/dmaflush/dmabarrier/" in the next version.

> 
> This patch updates Documentation/DMA-mapping.txt. But it's a change to
> the generic (not PCI specific) API described in DMA-API.txt.
> Can you update that as well please?
>

Ja, I realized that soon after hitting the send button. I'll 
move the documentation to DMA-API.txt.

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/4] dma: add dma_flags_set_dmaflush() to dma interface

2007-09-27 Thread akepner
On Tue, Sep 25, 2007 at 10:13:33PM -0700, Randy Dunlap wrote:
> On Tue, 25 Sep 2007 17:00:57 -0700 [EMAIL PROTECTED] wrote:
> ..
> 1.  Function signature should be on one line if possible (and it is).
> Aw crud, I looked at dma-mapping.h and it uses this format sometimes.
> Well, it's undesirable, so please don't propagate it.
> 
> 2.  No parens on return: it's not a function.
> 
> static inline int dma_flags_set_dmaflush(int dir)
> {
>   return dir;
> }
> 
> 
> Similar comments for patch 2/4: sn-ia64.
> 

Both fixed in next version. Thanks, Randy.

-- 
Arthur

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 0/4] allow drivers to flush in-flight DMA

2007-09-27 Thread akepner
On Wed, Sep 26, 2007 at 12:49:50AM -0600, Grant Grundler wrote:

[edited out several points that I think have been already 
addresed by others in this thread.]

 
 Defining it terms of completion queues won't mean much to most folks.
 Better to add a description of completion queues to the DMA-API.txt if
 necessary.  dma_alloc_coherent() API is pretty well understood.

OK, next time I'll use a more generic description.

 
  There are four patches in this set:
  
[1/4] dma: add dma_flags_set_dmaflush() to dma interface
 
 Sorry - this feels like a color of the shed argument, but isn't
 this about DMA ordering attribute?
 dmaflush is an action and not an attribute to me.

Right - an attribute is a noun, not a verb. I'm going to try 
s/dmaflush/dmabarrier/ in the next version.

 
 This patch updates Documentation/DMA-mapping.txt. But it's a change to
 the generic (not PCI specific) API described in DMA-API.txt.
 Can you update that as well please?


Ja, I realized that soon after hitting the send button. I'll 
move the documentation to DMA-API.txt.

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[4/4] mthca: allow setting dmabarrier on user-allocated memory

2007-09-27 Thread akepner

Use the dma_flags_set_dmabarrier() interface to allow a dmabarrier
attribute to be associated with user-allocated memory. (For now,
it's only implemented for mthca.)

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--- 
 drivers/infiniband/core/umem.c   |7 +--
 drivers/infiniband/hw/amso1100/c2_provider.c |2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 +-
 drivers/infiniband/hw/ipath/ipath_mr.c   |2 +-
 drivers/infiniband/hw/mlx4/cq.c  |2 +-
 drivers/infiniband/hw/mlx4/doorbell.c|2 +-
 drivers/infiniband/hw/mlx4/mr.c  |3 ++-
 drivers/infiniband/hw/mlx4/qp.c  |2 +-
 drivers/infiniband/hw/mlx4/srq.c |2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c |7 ++-
 drivers/infiniband/hw/mthca/mthca_user.h |   10 +-
 include/rdma/ib_umem.h   |4 ++--
 13 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 664d2fa..5b30b0c 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -69,9 +69,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmabarrier: set dmabarrier attribute on this memory, if necessary 
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmabarrier)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -83,6 +84,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   int flags = dmabarrier ? dma_flags_set_dmabarrier(DMA_BIDIRECTIONAL): 
+   DMA_BIDIRECTIONAL;
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -160,7 +163,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
chunk-nmap = ib_dma_map_sg(context-device,
chunk-page_list[0],
chunk-nents,
-   DMA_BIDIRECTIONAL);
+   flags);
if (chunk-nmap = 0) {
for (i = 0; i  chunk-nents; ++i)
put_page(chunk-page_list[i].page);
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 997cf15..17243b7 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr-pd = c2pd;
 
-   c2mr-umem = ib_umem_get(pd-uobject-context, start, length, acc);
+   c2mr-umem = ib_umem_get(pd-uobject-context, start, length, acc, 0);
if (IS_ERR(c2mr-umem)) {
err = PTR_ERR(c2mr-umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c7775..d0a514c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp-umem = ib_umem_get(pd-uobject-context, start, length, acc);
+   mhp-umem = ib_umem_get(pd-uobject-context, start, length, acc, 0);
if (IS_ERR(mhp-umem)) {
err = PTR_ERR(mhp-umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index d97eda3..c13c11c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -329,7 +329,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr-umem = ib_umem_get(pd-uobject-context, start, length,
-mr_access_flags);
+mr_access_flags, 0);
if (IS_ERR(e_mr-umem)) {
ib_mr = (void *)e_mr-umem;
goto reg_user_mr_exit1;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c 
b/drivers/infiniband/hw/ipath/ipath_mr.c
index e442470..e351222 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -195,7 +195,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
goto bail;
}

[3/4] dma: document dma_flags_set_dmabarrier()

2007-09-27 Thread akepner

Document dma_flags_set_dmabarrier().

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---
 DMA-API.txt |   26 ++
 1 files changed, 26 insertions(+)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index cc7a8c3..5fc0bba 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -544,3 +544,29 @@ size is the size (and should be a page-sized multiple).
 The return value will be either a pointer to the processor virtual
 address of the memory, or an error (via PTR_ERR()) if any part of the
 region is occupied.
+
+int 
+dma_flags_set_dmabarrier(int dir)
+
+Amend dir (one of the enum dma_data_direction values), with a 
+platform-specific dmabarrier attribute.  The dmabarrier attribute 
+forces a flush of all in-flight DMA when the associated memory 
+region is written to (see example below.)
+
+This provides a mechanism to enforce ordering of DMA on platforms that 
+permit DMA to be reordered between device and host memory (within a 
+NUMA interconnect).  On other platforms this is a nop.
+
+The dmabarrier would be set when the memory region is mapped for DMA, 
+e.g.:
+
+   int count, flags = dma_flags_set_dmabarrier(DMA_BIDIRECTIONAL);
+   
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+As an example of a situation where this would be useful, suppose that 
+the device does a DMA write to indicate that data is ready and 
+available in memory.  The DMA of the completion indication could 
+race with data DMA.  Using a dmabarrier on the memory used for 
+completion indications would prevent the race.
+
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[2/4] dma: redefine dma_flags_set_dmabarrier() for sn-ia64

2007-09-27 Thread akepner

define dma_flags_set_dmabarrier() for sn-ia64 - it borrows
bits from the direction argument (renamed flags) to the
dma_map_* routines to pass an additional dmabarrier attribute.
Also define routines to retrieve the original direction and
attribute from flags.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

---
 arch/ia64/sn/pci/pci_dma.c |   35 ++-
 include/asm-ia64/sn/io.h   |   24 
 2 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddac..6c0a498 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_dmabarrier(flags);
 
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;
@@ -240,18 +246,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 *sg, int nhwentries,
- int direction)
+ int flags)
 {
unsigned long phys_addr;
struct scatterlist *saved_sg = 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_dmabarrier(flags);
+   int direction = dma_flags_get_direction(flags);
 
BUG_ON(dev-bus != pci_bus_type);
 
@@ -259,12 +267,21 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
 * Setup a DMA address for each entry in the scatterlist.
 */
for (i = 0; i  nhwentries; i++, sg++) {
+   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__);
 
/*
diff --git a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
index 41c73a7..301bc47 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -271,4 +271,28 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long 
*addr, int vchan)
return 0;
 }
 
+#define ARCH_CAN_REORDER_DMA
+/* here we steal some upper bits from the direction argument to the 
+ * dma_map_* routines */
+#define DMA_ATTR_SHIFT 8
+/* bottom 8 bits for direction, remaining bits for additional attributes */
+#define DMA_BARRIER_ATTR   0x1
+/* Setting DMA_BARRIER_ATTR on a DMA-mapped memory region causes all in-
+ * flight DMA to be flushed when the memory region is written to. So 
+ * DMA_BARRIER_ATTR is a 

[1/4] dma: add dma_flags_set_dmabarrier() to dma interface

2007-09-27 Thread akepner

Introduce the dma_flags_set_dmabarrier() interface and give it
a default no-op implementation.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]

--- 

 dma-mapping.h |6 ++
 1 files changed, 6 insertions(+)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h

index 2dc21cb..4d1d199 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -99,4 +99,10 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_CAN_REORDER_DMA
+static inline int dma_flags_set_dmabarrier(int dir) {
+   return dir;
+}
+#endif /* ARCH_CAN_REORDER_DMA */
+
 #endif
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/4] allow drivers to flush in-flight DMA v2

2007-09-27 Thread akepner

On Altix, DMA may be reordered between a device and host memory. 
This reordering can happen in the NUMA interconnect, and it usually 
results in correct operation and improved performance. In some 
situations it may be necessary to explicitly synchronize DMA from 
the device.

This patchset allows a memory region to be mapped with a dmabarrier. 
Writes to the memory region will cause in-flight DMA to be flushed, 
providing a mechanism to order DMA from a device.

There are 4 patches in this patchset:

  [1/4] dma: add dma_flags_set_dmabarrier() to dma interface
  [2/4] dma: redefine dma_flags_set_dmabarrier() for sn-ia64
  [3/4] dma: document dma_flags_set_dmabarrier()
  [4/4] mthca: allow setting dmabarrier on user-allocated memory

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/4] dma: add dma_flags_set_dmaflush() to dma interface

2007-09-27 Thread akepner
On Tue, Sep 25, 2007 at 10:13:33PM -0700, Randy Dunlap wrote:
 On Tue, 25 Sep 2007 17:00:57 -0700 [EMAIL PROTECTED] wrote:
 ..
 1.  Function signature should be on one line if possible (and it is).
 Aw crud, I looked at dma-mapping.h and it uses this format sometimes.
 Well, it's undesirable, so please don't propagate it.
 
 2.  No parens on return: it's not a function.
 
 static inline int dma_flags_set_dmaflush(int dir)
 {
   return dir;
 }
 
 
 Similar comments for patch 2/4: sn-ia64.
 

Both fixed in next version. Thanks, Randy.

-- 
Arthur

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] mthca: allow setting "dmaflush" attribute on user-allocated memory

2007-09-25 Thread akepner

Use the dma_flags_set_dmaflush() interface to allow a "dmaflush" 
attribute to be associated with user-allocated memory. (For now, 
it's only implemented for mthca.)

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>
--
 drivers/infiniband/core/umem.c   |7 +--
 drivers/infiniband/hw/amso1100/c2_provider.c |2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c  |2 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |2 +-
 drivers/infiniband/hw/ipath/ipath_mr.c   |2 +-
 drivers/infiniband/hw/mlx4/cq.c  |2 +-
 drivers/infiniband/hw/mlx4/doorbell.c|2 +-
 drivers/infiniband/hw/mlx4/mr.c  |3 ++-
 drivers/infiniband/hw/mlx4/qp.c  |2 +-
 drivers/infiniband/hw/mlx4/srq.c |2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c |7 ++-
 drivers/infiniband/hw/mthca/mthca_user.h |   10 +-
 include/rdma/ib_umem.h   |4 ++--
 13 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 664d2fa..e8a3dd4 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -69,9 +69,10 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmaflush: set "dmaflush" attribute on this memory, if necessary 
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-   size_t size, int access)
+   size_t size, int access, int dmaflush)
 {
struct ib_umem *umem;
struct page **page_list;
@@ -83,6 +84,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
int ret;
int off;
int i;
+   int flags = dmaflush ? dma_flags_set_dmaflush(DMA_BIDIRECTIONAL): 
+   DMA_BIDIRECTIONAL;
 
if (!can_do_mlock())
return ERR_PTR(-EPERM);
@@ -160,7 +163,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
chunk->nmap = ib_dma_map_sg(context->device,
>page_list[0],
chunk->nents,
-   DMA_BIDIRECTIONAL);
+   flags);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(chunk->page_list[i].page);
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c 
b/drivers/infiniband/hw/amso1100/c2_provider.c
index 997cf15..17243b7 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -449,7 +449,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
return ERR_PTR(-ENOMEM);
c2mr->pd = c2pd;
 
-   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(c2mr->umem)) {
err = PTR_ERR(c2mr->umem);
kfree(c2mr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c 
b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c7775..d0a514c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -601,7 +601,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
 
-   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+   mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(mhp->umem)) {
err = PTR_ERR(mhp->umem);
kfree(mhp);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index d97eda3..c13c11c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -329,7 +329,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
}
 
e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
-mr_access_flags);
+mr_access_flags, 0);
if (IS_ERR(e_mr->umem)) {
ib_mr = (void *)e_mr->umem;
goto reg_user_mr_exit1;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c 
b/drivers/infiniband/hw/ipath/ipath_mr.c
index e442470..e351222 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -195,7 +195,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
goto 

[PATCH 2/4] dma: redefine dma_flags_set_dmaflush() for sn-ia64

2007-09-25 Thread akepner

define dma_flags_set_dmaflush() for sn-ia64 - it "borrows"
bits from the direction argument (renamed "flags") to the
dma_map_* routines to pass an additional "dmaflush" attribute.
Also define routines to retrieve the original direction and
attribute from "flags".

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>
--
 arch/ia64/sn/pci/pci_dma.c |   35 ++-
 include/asm-ia64/sn/io.h   |   26 ++
 2 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddac..754240b 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 dmaflush = dma_flags_get_dmaflush(flags);
 
BUG_ON(dev->bus != _bus_type);
 
phys_addr = __pa(cpu_addr);
-   dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
+   if (dmaflush)
+   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;
@@ -240,18 +246,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 *sg, int nhwentries,
- int direction)
+ int flags)
 {
unsigned long phys_addr;
struct scatterlist *saved_sg = sg;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
int i;
+   int dmaflush = dma_flags_get_dmaflush(flags);
+   int direction = dma_flags_get_direction(flags);
 
BUG_ON(dev->bus != _bus_type);
 
@@ -259,12 +267,21 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
 * Setup a DMA address for each entry in the scatterlist.
 */
for (i = 0; i < nhwentries; i++, sg++) {
+   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 (dmaflush) {
+   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__);
 
/*
diff --git a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
index 41c73a7..71f88ee 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -271,4 +271,30 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long 
*addr, int vchan)
return 0;
 }
 
+#define ARCH_CAN_REORDER_DMA
+/* here we steal some upper bits from the "direction" argument to the 
+ * dma_map_* routines */
+#define DMA_ATTR_SHIFT 8
+/* bottom 8 bits for direction, remaining bits for additional "attributes" */
+#define DMA_FLUSH_ATTR 0x1
+/* For now the only attribute is "flush in-flight dma when writing to 
+ * this DMA mapped memory" */
+#define DMA_DIR_MASK   ((1 << DMA_ATTR_SHIFT) - 1)
+#define 

[PATCH 3/4] dma: document dma_flags_set_dmaflush()

2007-09-25 Thread akepner

Document dma_flags_set_dmaflush().

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>
--
 DMA-mapping.txt |   25 -
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index e07f253..31e3234 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -745,7 +745,30 @@ to "Closing".
2.5., page+offset is always used, and the "address" field has been
deleted.
 
-2) More to come...
+2) Platforms that permit DMA reordering
+
+   At least one platform (SGI SN2) allows DMA to be reordered between
+   device and host memory. This reordering can happen in the NUMA
+   interconnect, and it usually results in correct operation and improved
+   performance. In some situations it may be necessary to explicitly
+   synchronize DMA from the device. For example, if the device does a DMA
+   write to indicate that data is ready, the DMA of the "completion
+   indication" can race with DMA of data. In this situation,
+   dma_flags_set_dmaflush() can be used to associate a "dmaflush"
+   attribute with a memory region. The dmaflush attribute will cause in-
+   flight DMA from the device to be flushed to host memory when the
+   associated memory region is written. (On platforms that don't permit
+   DMA reordering, this is a no-op.)
+
+   For example, you might map the memory region used for completion
+   indications as follows:
+
+   int count, flags = dma_flags_set_dmaflush(DMA_BIDIRECTIONAL);
+   .
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+
+3) More to come...
 
Handling Errors
 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/4] allow drivers to flush in-flight DMA

2007-09-25 Thread akepner


This is a followup to http://lkml.org/lkml/2007/8/24/280

Despite Grant's desire for a more elegant solution, there's 
not much new here. I moved the API change from pci.h to 
dma-mapping.h and removed the pci_ prefix from the name. 

Problem Description
---
On Altix, DMA may be reordered within the NUMA interconnect.
This can be a problem with Infiniband, where DMA to Completion Queues 
allocated in user-space can race with data DMA. This patchset allows 
a driver to associate a user-space memory region with a "dmaflush" 
attribute, so that writes to the memory region flush in-flight DMA, 
preventing the CQ/data race.

There are four patches in this set:

  [1/4] dma: add dma_flags_set_dmaflush() to dma interface
  [2/4] dma: redefine dma_flags_set_dmaflush() for sn-ia64
  [3/4] dma: document dma_flags_set_dmaflush()
  [4/4] mthca: allow setting "dmaflush" attribute on user-allocated memory

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] dma: add dma_flags_set_dmaflush() to dma interface

2007-09-25 Thread akepner

Introduce the dma_flags_set_dmaflush() interface and give it
a default no-op implementation.

Signed-off-by: Arthur Kepner <[EMAIL PROTECTED]>
-- 

 dma-mapping.h |7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 2dc21cb..a0f27b9 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -99,4 +99,11 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_CAN_REORDER_DMA
+static inline int
+dma_flags_set_dmaflush(int dir) {
+   return (dir);
+}
+#endif /* ARCH_CAN_REORDER_DMA */
+
 #endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/4] allow drivers to flush in-flight DMA

2007-09-25 Thread akepner


This is a followup to http://lkml.org/lkml/2007/8/24/280

Despite Grant's desire for a more elegant solution, there's 
not much new here. I moved the API change from pci.h to 
dma-mapping.h and removed the pci_ prefix from the name. 

Problem Description
---
On Altix, DMA may be reordered within the NUMA interconnect.
This can be a problem with Infiniband, where DMA to Completion Queues 
allocated in user-space can race with data DMA. This patchset allows 
a driver to associate a user-space memory region with a dmaflush 
attribute, so that writes to the memory region flush in-flight DMA, 
preventing the CQ/data race.

There are four patches in this set:

  [1/4] dma: add dma_flags_set_dmaflush() to dma interface
  [2/4] dma: redefine dma_flags_set_dmaflush() for sn-ia64
  [3/4] dma: document dma_flags_set_dmaflush()
  [4/4] mthca: allow setting dmaflush attribute on user-allocated memory

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] dma: add dma_flags_set_dmaflush() to dma interface

2007-09-25 Thread akepner

Introduce the dma_flags_set_dmaflush() interface and give it
a default no-op implementation.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]
-- 

 dma-mapping.h |7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 2dc21cb..a0f27b9 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -99,4 +99,11 @@ static inline void dmam_release_declared_memory(struct 
device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef ARCH_CAN_REORDER_DMA
+static inline int
+dma_flags_set_dmaflush(int dir) {
+   return (dir);
+}
+#endif /* ARCH_CAN_REORDER_DMA */
+
 #endif
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/4] dma: redefine dma_flags_set_dmaflush() for sn-ia64

2007-09-25 Thread akepner

define dma_flags_set_dmaflush() for sn-ia64 - it borrows
bits from the direction argument (renamed flags) to the
dma_map_* routines to pass an additional dmaflush attribute.
Also define routines to retrieve the original direction and
attribute from flags.

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]
--
 arch/ia64/sn/pci/pci_dma.c |   35 ++-
 include/asm-ia64/sn/io.h   |   26 ++
 2 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d79ddac..754240b 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 dmaflush = dma_flags_get_dmaflush(flags);
 
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 (dmaflush)
+   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;
@@ -240,18 +246,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 *sg, int nhwentries,
- int direction)
+ int flags)
 {
unsigned long phys_addr;
struct scatterlist *saved_sg = sg;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
int i;
+   int dmaflush = dma_flags_get_dmaflush(flags);
+   int direction = dma_flags_get_direction(flags);
 
BUG_ON(dev-bus != pci_bus_type);
 
@@ -259,12 +267,21 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
 * Setup a DMA address for each entry in the scatterlist.
 */
for (i = 0; i  nhwentries; i++, sg++) {
+   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 (dmaflush) {
+   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__);
 
/*
diff --git a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
index 41c73a7..71f88ee 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -271,4 +271,30 @@ sn_pci_set_vchan(struct pci_dev *pci_dev, unsigned long 
*addr, int vchan)
return 0;
 }
 
+#define ARCH_CAN_REORDER_DMA
+/* here we steal some upper bits from the direction argument to the 
+ * dma_map_* routines */
+#define DMA_ATTR_SHIFT 8
+/* bottom 8 bits for direction, remaining bits for additional attributes */
+#define DMA_FLUSH_ATTR 0x1
+/* For now the only attribute is flush in-flight dma when writing to 
+ * this DMA mapped memory */
+#define DMA_DIR_MASK   ((1  DMA_ATTR_SHIFT) - 1)
+#define DMA_ATTR_MASK  ~DMA_DIR_MASK
+
+static 

[PATCH 3/4] dma: document dma_flags_set_dmaflush()

2007-09-25 Thread akepner

Document dma_flags_set_dmaflush().

Signed-off-by: Arthur Kepner [EMAIL PROTECTED]
--
 DMA-mapping.txt |   25 -
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index e07f253..31e3234 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -745,7 +745,30 @@ to Closing.
2.5., page+offset is always used, and the address field has been
deleted.
 
-2) More to come...
+2) Platforms that permit DMA reordering
+
+   At least one platform (SGI SN2) allows DMA to be reordered between
+   device and host memory. This reordering can happen in the NUMA
+   interconnect, and it usually results in correct operation and improved
+   performance. In some situations it may be necessary to explicitly
+   synchronize DMA from the device. For example, if the device does a DMA
+   write to indicate that data is ready, the DMA of the completion
+   indication can race with DMA of data. In this situation,
+   dma_flags_set_dmaflush() can be used to associate a dmaflush
+   attribute with a memory region. The dmaflush attribute will cause in-
+   flight DMA from the device to be flushed to host memory when the
+   associated memory region is written. (On platforms that don't permit
+   DMA reordering, this is a no-op.)
+
+   For example, you might map the memory region used for completion
+   indications as follows:
+
+   int count, flags = dma_flags_set_dmaflush(DMA_BIDIRECTIONAL);
+   .
+   count = dma_map_sg(dev, sglist, nents, flags);
+
+
+3) More to come...
 
Handling Errors
 
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   >