summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King - ARM Linux2011-01-03 23:45:17 +0100
committerDan Williams2011-01-05 04:16:14 +0100
commit8087aacda040bdbf84940712d132ce80c30b9d5d (patch)
tree3a59272bc4555eae854a012940a36f80a8f4c1a5
parentARM: PL08x: put txd's on the pending list in pl08x_tx_submit() (diff)
downloadkernel-qcow2-linux-8087aacda040bdbf84940712d132ce80c30b9d5d.tar.gz
kernel-qcow2-linux-8087aacda040bdbf84940712d132ce80c30b9d5d.tar.xz
kernel-qcow2-linux-8087aacda040bdbf84940712d132ce80c30b9d5d.zip
ARM: PL08x: introduce 'phychan_hold' to hold on to physical channels
Introduce 'phychan_hold' to hold on to physical DMA channels while we're preparing a new descriptor for it. This will be incremented when we allocate a physical channel and set the MUX registers during the preparation of the TXD, and will only be decremented when the TXD is submitted. This prevents the physical channel being given up before the new TXD is placed on the queue. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/dma/amba-pl08x.c11
-rw-r--r--include/linux/amba/pl08x.h3
2 files changed, 14 insertions, 0 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 650e2bbc7aad..bf6f7d02c9f6 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -959,6 +959,7 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
ch->signal,
plchan->name);
+ plchan->phychan_hold++;
plchan->phychan = ch;
return 0;
@@ -998,6 +999,8 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
/* Do this memcpy whenever there is a channel ready */
plchan->state = PL08X_CHAN_WAITING;
plchan->waiting = txd;
+ } else {
+ plchan->phychan_hold--;
}
/* This unlock follows the lock in the prep() function */
@@ -1585,6 +1588,7 @@ static void pl08x_tasklet(unsigned long data)
*/
plchan->lc = txd->tx.cookie;
}
+
/*
* If a new descriptor is queued, set it up
* plchan->at is NULL here
@@ -1598,6 +1602,12 @@ static void pl08x_tasklet(unsigned long data)
list_del(&next->node);
pl08x_start_txd(plchan, next);
+ } else if (plchan->phychan_hold) {
+ /*
+ * This channel is still in use - we have a new txd being
+ * prepared and will soon be queued. Don't give up the
+ * physical channel.
+ */
} else {
struct pl08x_dma_chan *waiting = NULL;
@@ -1625,6 +1635,7 @@ static void pl08x_tasklet(unsigned long data)
ret = prep_phy_channel(waiting,
waiting->waiting);
BUG_ON(ret);
+ waiting->phychan_hold--;
waiting->state = PL08X_CHAN_RUNNING;
waiting->waiting = NULL;
pl08x_issue_pending(&waiting->chan);
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index 08a9024e2d2f..95b76ea1829f 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -151,6 +151,8 @@ enum pl08x_dma_chan_state {
* struct pl08x_dma_chan - this structure wraps a DMA ENGINE channel
* @chan: wrappped abstract channel
* @phychan: the physical channel utilized by this channel, if there is one
+ * @phychan_hold: if non-zero, hold on to the physical channel even if we
+ * have no pending entries
* @tasklet: tasklet scheduled by the IRQ to handle actual work etc
* @name: name of channel
* @cd: channel platform data
@@ -173,6 +175,7 @@ enum pl08x_dma_chan_state {
struct pl08x_dma_chan {
struct dma_chan chan;
struct pl08x_phy_chan *phychan;
+ int phychan_hold;
struct tasklet_struct tasklet;
char *name;
struct pl08x_channel_data *cd;