[PATCH 12/12] DMAENGINE: define channel states for the PL08X
Linus Walleij
linus.walleij at stericsson.com
Tue Aug 31 08:12:14 EDT 2010
Instead of strange things like a bool indicating paused state for
channels, let's define a proper channel state and use that. Also
print it out in the debugfs so we get a nice overview of the
channels and states.
Signed-off-by: Linus Walleij <linus.walleij at stericsson.com>
---
drivers/dma/amba-pl08x.c | 70 ++++++++++++++++++++++++++++++++++----------
include/linux/amba/pl08x.h | 22 ++++++++++++-
2 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 49fb19d..1718b2e 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1148,9 +1148,20 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
pl08x_free_txd_list(pl08x, plchan);
spin_unlock_irqrestore(&plchan->lock, flags);
return -EBUSY;
- } else
+ } else {
+ plchan->state = PL08X_CHAN_WAITING;
plchan->waiting = txd;
- }
+ }
+ } else
+ /*
+ * Else we're all set, paused and ready to roll,
+ * status will switch to PL08X_CHAN_RUNNING when
+ * we call issue_pending(). If there is something
+ * running on the channel already we don't change
+ * its state.
+ */
+ if (plchan->state == PL08X_CHAN_IDLE)
+ plchan->state = PL08X_CHAN_PAUSED;
spin_unlock_irqrestore(&plchan->lock, flags);
return tx->cookie;
@@ -1206,9 +1217,10 @@ pl08x_dma_tx_status(struct dma_chan *chan,
dma_set_tx_state(txstate, last_complete, last_used,
bytesleft);
- if (plchan->paused)
+ if (plchan->state == PL08X_CHAN_PAUSED)
return DMA_PAUSED;
+ /* Whether waiting or running, we're in progress */
return DMA_IN_PROGRESS;
}
@@ -1366,7 +1378,7 @@ static void pl08x_issue_pending(struct dma_chan *chan)
}
/* Didn't get a physical channel so waiting for it ... */
- if (plchan->waiting)
+ if (plchan->state == PL08X_CHAN_WAITING)
return;
/* Take the first element in the queue and execute it */
@@ -1378,6 +1390,7 @@ static void pl08x_issue_pending(struct dma_chan *chan)
node);
list_del(&next->node);
plchan->at = next;
+ plchan->state = PL08X_CHAN_RUNNING;
/* Configure the physical channel for the active txd */
pl08x_config_phychan_for_txd(plchan);
@@ -1520,7 +1533,7 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
switch (cmd) {
case DMA_TERMINATE_ALL:
- plchan->paused = false;
+ plchan->state = PL08X_CHAN_IDLE;
if (plchan->phychan) {
pl08x_stop_phy_chan(plchan->phychan);
@@ -1549,11 +1562,11 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
break;
case DMA_PAUSE:
pl08x_pause_phy_chan(plchan->phychan);
- plchan->paused = true;
+ plchan->state = PL08X_CHAN_PAUSED;
break;
case DMA_RESUME:
pl08x_resume_phy_chan(plchan->phychan);
- plchan->paused = false;
+ plchan->state = PL08X_CHAN_RUNNING;
break;
default:
/* Unknown command */
@@ -1676,6 +1689,7 @@ static void pl08x_tasklet(unsigned long data)
}
pl08x_put_phy_channel(pl08x, phychan);
plchan->phychan = NULL;
+ plchan->state = PL08X_CHAN_IDLE;
/*
* And NOW before anyone else can grab that free:d
@@ -1684,13 +1698,17 @@ static void pl08x_tasklet(unsigned long data)
* being stacked up while we were choking the
* physical channels with data.
*/
- list_for_each_entry(waiting, &pl08x->memcpy.channels, chan.device_node) {
- if (waiting->waiting) {
+ list_for_each_entry(waiting, &pl08x->memcpy.channels,
+ chan.device_node) {
+ if (waiting->state == PL08X_CHAN_WAITING &&
+ waiting->waiting != NULL) {
int ret;
/* This should REALLY not fail now */
- ret = prep_phy_channel(waiting, waiting->waiting);
+ ret = prep_phy_channel(waiting,
+ waiting->waiting);
BUG_ON(ret);
+ waiting->state = PL08X_CHAN_RUNNING;
waiting->waiting = NULL;
pl08x_issue_pending(&waiting->chan);
break;
@@ -1771,6 +1789,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
}
chan->host = pl08x;
+ chan->state = PL08X_CHAN_IDLE;
if (slave) {
chan->slave = true;
@@ -1817,6 +1836,23 @@ static void pl08x_free_virtual_channels(struct dma_device *dmadev)
}
#ifdef CONFIG_DEBUG_FS
+static const char *pl08x_state_str(enum pl08x_dma_chan_state state)
+{
+ switch(state) {
+ case PL08X_CHAN_IDLE:
+ return "idle";
+ case PL08X_CHAN_RUNNING:
+ return "running";
+ case PL08X_CHAN_PAUSED:
+ return "paused";
+ case PL08X_CHAN_WAITING:
+ return "waiting";
+ default:
+ break;
+ }
+ return "UNKNOWN STATE";
+}
+
static int pl08x_debugfs_show(struct seq_file *s, void *data)
{
struct pl08x_driver_data *pl08x = s->private;
@@ -1843,17 +1879,19 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data)
}
seq_printf(s, "\nPL08x virtual memcpy channels:\n");
- seq_printf(s, "CHANNEL:\n");
- seq_printf(s, "--------\n");
+ seq_printf(s, "CHANNEL:\tSTATE:\n");
+ seq_printf(s, "--------\t------\n");
list_for_each_entry(chan, &pl08x->memcpy.channels, chan.device_node) {
- seq_printf(s, "%s\n", chan->name);
+ seq_printf(s, "%s\t\t\%s\n", chan->name,
+ pl08x_state_str(chan->state));
}
seq_printf(s, "\nPL08x virtual slave channels:\n");
- seq_printf(s, "CHANNEL:\n");
- seq_printf(s, "--------\n");
+ seq_printf(s, "CHANNEL:\tSTATE:\n");
+ seq_printf(s, "--------\t------\n");
list_for_each_entry(chan, &pl08x->slave.channels, chan.device_node) {
- seq_printf(s, "%s\n", chan->name);
+ seq_printf(s, "%s\t\t\%s\n", chan->name,
+ pl08x_state_str(chan->state));
}
return 0;
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index f461648..d54fbff 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -123,6 +123,24 @@ struct pl08x_txd {
};
/**
+ * struct pl08x_dma_chan_state - holds the PL08x specific virtual
+ * channel states
+ * @PL08X_CHAN_IDLE: the channel is idle
+ * @PL08X_CHAN_RUNNING: the channel has allocated a physical transport
+ * channel and is running a transfer on it
+ * @PL08X_CHAN_PAUSED: the channel has allocated a physical transport
+ * channel, but the transfer is currently paused
+ * @PL08X_CHAN_WAITING: the channel is waiting for a physical transport
+ * channel to become available (only pertains to memcpy channels)
+ */
+enum pl08x_dma_chan_state {
+ PL08X_CHAN_IDLE,
+ PL08X_CHAN_RUNNING,
+ PL08X_CHAN_PAUSED,
+ PL08X_CHAN_WAITING,
+};
+
+/**
* 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
@@ -137,7 +155,7 @@ struct pl08x_txd {
* @at: active transaction on this channel
* @lock: a lock for this channel data
* @host: a pointer to the host (internal use)
- * @paused: whether the channel is paused
+ * @state: whether the channel is idle, paused, running etc
* @slave: whether this channel is a device (slave) or for memcpy
* @waiting: a TX descriptor on this channel which is waiting for
* a physical channel to become available
@@ -156,7 +174,7 @@ struct pl08x_dma_chan {
struct pl08x_txd *at;
spinlock_t lock;
void *host;
- bool paused;
+ enum pl08x_dma_chan_state state;
bool slave;
struct pl08x_txd *waiting;
};
--
1.6.3.3
More information about the linux-arm-kernel
mailing list