Re: [PATCH v2] fsldma: Add DMA_SLAVE support

2009-06-19 Thread Ira Snyder
On Thu, Jun 18, 2009 at 03:53:45PM -0700, Ira Snyder wrote:
 Use the DMA_SLAVE capability of the DMAEngine API to copy/from a
 scatterlist into an arbitrary list of hardware address/length pairs.
 
 This allows a single DMA transaction to copy data from several different
 devices into a scatterlist at the same time.
 
 This also adds support to enable some controller-specific features such as
 external start and external pause for a DMA transaction.
 
 Signed-off-by: Ira W. Snyder i...@ovro.caltech.edu
 ---
 
 After discussion with Dan Williams, this is the second version of the
 DMA_SLAVE API for the Freescale DMA controller. I've tested it heavily
 with both drivers I have written against this API, an FPGA programmer
 and an FPGA data grabber.
 
 Kumar, Dan asked me to add you to the CC list, so you can have a look at
 this patch before he adds it to his tree.
 
 The other two small patches I posted earlier are very helpful in testing
 this functionality. They make the fsldma driver leave the BWC (bandwidth
 control) bits alone on the 83xx controller, as well as making the
 external start feature available on 83xx.
 
 In order for the external start/pause features to be useful, the
 bandwidth control bits (in the mode register) need to be set before
 attempting to use the controller. I could spin a v3 of this patch that
 adds a field to struct fsl_dma_slave to set the bits appropriately. Or I
 could send another patch for that. Thoughts?
 
 Many thanks to all that have participated in the discussion about this
 patch.
 
 v1 - v2:
 * move fsldma.h from include/linux to arch/powerpc/include/asm
 * add kerneldoc documentation
 

[snip]

 +
 + /* Enable extra controller features */
 + if (fsl_chan-set_src_loop_size)
 + fsl_chan-set_src_loop_size(fsl_chan, slave-src_loop_size);
 +
 + if (fsl_chan-set_dest_loop_size)
 + fsl_chan-set_dest_loop_size(fsl_chan, slave-dst_loop_size);
 +
 + if (fsl_chan-toggle_ext_start)
 + fsl_chan-toggle_ext_start(fsl_chan, slave-external_start);
 +
 + if (fsl_chan-toggle_ext_pause)
 + fsl_chan-toggle_ext_pause(fsl_chan, slave-external_pause);

I just noticed that I got this wrong for external pause. It takes a
size, not a boolean enable/disable. I'll split the size out from the
external pause feature, and send another patch.

 +
 + return first-async_tx;
 +
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2] fsldma: Add DMA_SLAVE support

2009-06-18 Thread Ira Snyder
Use the DMA_SLAVE capability of the DMAEngine API to copy/from a
scatterlist into an arbitrary list of hardware address/length pairs.

This allows a single DMA transaction to copy data from several different
devices into a scatterlist at the same time.

This also adds support to enable some controller-specific features such as
external start and external pause for a DMA transaction.

Signed-off-by: Ira W. Snyder i...@ovro.caltech.edu
---

After discussion with Dan Williams, this is the second version of the
DMA_SLAVE API for the Freescale DMA controller. I've tested it heavily
with both drivers I have written against this API, an FPGA programmer
and an FPGA data grabber.

Kumar, Dan asked me to add you to the CC list, so you can have a look at
this patch before he adds it to his tree.

The other two small patches I posted earlier are very helpful in testing
this functionality. They make the fsldma driver leave the BWC (bandwidth
control) bits alone on the 83xx controller, as well as making the
external start feature available on 83xx.

In order for the external start/pause features to be useful, the
bandwidth control bits (in the mode register) need to be set before
attempting to use the controller. I could spin a v3 of this patch that
adds a field to struct fsl_dma_slave to set the bits appropriately. Or I
could send another patch for that. Thoughts?

Many thanks to all that have participated in the discussion about this
patch.

v1 - v2:
* move fsldma.h from include/linux to arch/powerpc/include/asm
* add kerneldoc documentation

 arch/powerpc/include/asm/fsldma.h |  134 ++
 drivers/dma/fsldma.c  |  224 +
 2 files changed, 358 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/include/asm/fsldma.h

diff --git a/arch/powerpc/include/asm/fsldma.h 
b/arch/powerpc/include/asm/fsldma.h
new file mode 100644
index 000..1bc71fb
--- /dev/null
+++ b/arch/powerpc/include/asm/fsldma.h
@@ -0,0 +1,134 @@
+/*
+ * Freescale MPC83XX / MPC85XX DMA Controller
+ *
+ * Copyright (c) 2009 Ira W. Snyder i...@ovro.caltech.edu
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed as is without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
+#define __ARCH_POWERPC_ASM_FSLDMA_H__
+
+#include linux/dmaengine.h
+
+/*
+ * Definitions for the Freescale DMA controller's DMA_SLAVE implemention
+ *
+ * The Freescale DMA_SLAVE implementation was designed to handle many-to-many
+ * transfers. An example usage would be an accelerated copy between two
+ * scatterlists. Another example use would be an accelerated copy from
+ * multiple non-contiguous device buffers into a single scatterlist.
+ *
+ * A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This
+ * structure contains a list of hardware addresses that should be copied
+ * to/from the scatterlist passed into device_prep_slave_sg(). The structure
+ * also has some fields to enable hardware-specific features.
+ */
+
+/**
+ * struct fsl_dma_hw_addr
+ * @entry: linked list entry
+ * @address: the hardware address
+ * @length: length to transfer
+ *
+ * Holds a single physical hardware address / length pair for use
+ * with the DMAEngine DMA_SLAVE API.
+ */
+struct fsl_dma_hw_addr {
+   struct list_head entry;
+
+   dma_addr_t address;
+   size_t length;
+};
+
+/**
+ * struct fsl_dma_slave
+ * @addresses: a linked list of struct fsl_dma_hw_addr structures
+ * @src_loop_size: setup and enable constant source-address DMA transfers
+ * @dst_loop_size: setup and enable constant destination address DMA transfers
+ * @external_start: enable externally started DMA transfers
+ * @external_pause: enable externally paused DMA transfers
+ *
+ * Holds a list of address / length pairs for use with the DMAEngine
+ * DMA_SLAVE API implementation for the Freescale DMA controller.
+ */
+struct fsl_dma_slave {
+
+   /* List of hardware address/length pairs */
+   struct list_head addresses;
+
+   /* Support for extra controller features */
+   unsigned int src_loop_size;
+   unsigned int dst_loop_size;
+   bool external_start;
+   bool external_pause;
+};
+
+/**
+ * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave
+ * @slave: the struct fsl_dma_slave to add to
+ * @address: the hardware address to add
+ * @length: the length of bytes to transfer from @address
+ *
+ * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on
+ * success, -ERRNO otherwise.
+ */
+static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave,
+  dma_addr_t address, size_t length)
+{
+   struct fsl_dma_hw_addr *addr;
+
+   addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
+   if (!addr)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(addr-entry);
+   addr-address = address;