aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,
959 ch->signal, 959 ch->signal,
960 plchan->name); 960 plchan->name);
961 961
962 plchan->phychan_hold++;
962 plchan->phychan = ch; 963 plchan->phychan = ch;
963 964
964 return 0; 965 return 0;
@@ -998,6 +999,8 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
998 /* Do this memcpy whenever there is a channel ready */ 999 /* Do this memcpy whenever there is a channel ready */
999 plchan->state = PL08X_CHAN_WAITING; 1000 plchan->state = PL08X_CHAN_WAITING;
1000 plchan->waiting = txd; 1001 plchan->waiting = txd;
1002 } else {
1003 plchan->phychan_hold--;
1001 } 1004 }
1002 1005
1003 /* This unlock follows the lock in the prep() function */ 1006 /* This unlock follows the lock in the prep() function */
@@ -1585,6 +1588,7 @@ static void pl08x_tasklet(unsigned long data)
1585 */ 1588 */
1586 plchan->lc = txd->tx.cookie; 1589 plchan->lc = txd->tx.cookie;
1587 } 1590 }
1591
1588 /* 1592 /*
1589 * If a new descriptor is queued, set it up 1593 * If a new descriptor is queued, set it up
1590 * plchan->at is NULL here 1594 * plchan->at is NULL here
@@ -1598,6 +1602,12 @@ static void pl08x_tasklet(unsigned long data)
1598 list_del(&next->node); 1602 list_del(&next->node);
1599 1603
1600 pl08x_start_txd(plchan, next); 1604 pl08x_start_txd(plchan, next);
1605 } else if (plchan->phychan_hold) {
1606 /*
1607 * This channel is still in use - we have a new txd being
1608 * prepared and will soon be queued. Don't give up the
1609 * physical channel.
1610 */
1601 } else { 1611 } else {
1602 struct pl08x_dma_chan *waiting = NULL; 1612 struct pl08x_dma_chan *waiting = NULL;
1603 1613
@@ -1625,6 +1635,7 @@ static void pl08x_tasklet(unsigned long data)
1625 ret = prep_phy_channel(waiting, 1635 ret = prep_phy_channel(waiting,
1626 waiting->waiting); 1636 waiting->waiting);
1627 BUG_ON(ret); 1637 BUG_ON(ret);
1638 waiting->phychan_hold--;
1628 waiting->state = PL08X_CHAN_RUNNING; 1639 waiting->state = PL08X_CHAN_RUNNING;
1629 waiting->waiting = NULL; 1640 waiting->waiting = NULL;
1630 pl08x_issue_pending(&waiting->chan); 1641 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 {
151 * struct pl08x_dma_chan - this structure wraps a DMA ENGINE channel 151 * struct pl08x_dma_chan - this structure wraps a DMA ENGINE channel
152 * @chan: wrappped abstract channel 152 * @chan: wrappped abstract channel
153 * @phychan: the physical channel utilized by this channel, if there is one 153 * @phychan: the physical channel utilized by this channel, if there is one
154 * @phychan_hold: if non-zero, hold on to the physical channel even if we
155 * have no pending entries
154 * @tasklet: tasklet scheduled by the IRQ to handle actual work etc 156 * @tasklet: tasklet scheduled by the IRQ to handle actual work etc
155 * @name: name of channel 157 * @name: name of channel
156 * @cd: channel platform data 158 * @cd: channel platform data
@@ -173,6 +175,7 @@ enum pl08x_dma_chan_state {
173struct pl08x_dma_chan { 175struct pl08x_dma_chan {
174 struct dma_chan chan; 176 struct dma_chan chan;
175 struct pl08x_phy_chan *phychan; 177 struct pl08x_phy_chan *phychan;
178 int phychan_hold;
176 struct tasklet_struct tasklet; 179 struct tasklet_struct tasklet;
177 char *name; 180 char *name;
178 struct pl08x_channel_data *cd; 181 struct pl08x_channel_data *cd;