Commit c014906a authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Paul Mundt

dmaengine: shdma: extend .device_terminate_all() to record partial transfer

This patch extends the .device_terminate_all() method of the shdma driver
to return number of bytes transfered in the current descriptor.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent c8e3149b
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#ifndef ASM_DMAENGINE_H #ifndef ASM_DMAENGINE_H
#define ASM_DMAENGINE_H #define ASM_DMAENGINE_H
#include <linux/dmaengine.h>
#include <linux/list.h>
#include <asm/dma-register.h> #include <asm/dma-register.h>
#define SH_DMAC_MAX_CHANNELS 6 #define SH_DMAC_MAX_CHANNELS 6
...@@ -70,4 +73,21 @@ struct sh_dmae_slave { ...@@ -70,4 +73,21 @@ struct sh_dmae_slave {
struct sh_dmae_slave_config *config; /* Set by the driver */ struct sh_dmae_slave_config *config; /* Set by the driver */
}; };
struct sh_dmae_regs {
u32 sar; /* SAR / source address */
u32 dar; /* DAR / destination address */
u32 tcr; /* TCR / transfer count */
};
struct sh_desc {
struct sh_dmae_regs hw;
struct list_head node;
struct dma_async_tx_descriptor async_tx;
enum dma_data_direction direction;
dma_cookie_t cookie;
size_t partial;
int chunks;
int mark;
};
#endif #endif
...@@ -587,6 +587,19 @@ static void sh_dmae_terminate_all(struct dma_chan *chan) ...@@ -587,6 +587,19 @@ static void sh_dmae_terminate_all(struct dma_chan *chan)
if (!chan) if (!chan)
return; return;
dmae_halt(sh_chan);
spin_lock_bh(&sh_chan->desc_lock);
if (!list_empty(&sh_chan->ld_queue)) {
/* Record partial transfer */
struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
struct sh_desc, node);
desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
sh_chan->xmit_shift;
}
spin_unlock_bh(&sh_chan->desc_lock);
sh_dmae_chan_ld_cleanup(sh_chan, true); sh_dmae_chan_ld_cleanup(sh_chan, true);
} }
...@@ -701,6 +714,9 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan) ...@@ -701,6 +714,9 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
/* Find the first not transferred desciptor */ /* Find the first not transferred desciptor */
list_for_each_entry(desc, &sh_chan->ld_queue, node) list_for_each_entry(desc, &sh_chan->ld_queue, node)
if (desc->mark == DESC_SUBMITTED) { if (desc->mark == DESC_SUBMITTED) {
dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
desc->async_tx.cookie, sh_chan->id,
desc->hw.tcr, desc->hw.sar, desc->hw.dar);
/* Get the ld start address from ld_queue */ /* Get the ld start address from ld_queue */
dmae_set_reg(sh_chan, &desc->hw); dmae_set_reg(sh_chan, &desc->hw);
dmae_start(sh_chan); dmae_start(sh_chan);
......
...@@ -21,22 +21,6 @@ ...@@ -21,22 +21,6 @@
#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */
struct sh_dmae_regs {
u32 sar; /* SAR / source address */
u32 dar; /* DAR / destination address */
u32 tcr; /* TCR / transfer count */
};
struct sh_desc {
struct sh_dmae_regs hw;
struct list_head node;
struct dma_async_tx_descriptor async_tx;
enum dma_data_direction direction;
dma_cookie_t cookie;
int chunks;
int mark;
};
struct device; struct device;
struct sh_dmae_chan { struct sh_dmae_chan {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment