diff options
-rw-r--r-- | drivers/dma/amba-pl08x.c | 11 | ||||
-rw-r--r-- | include/linux/amba/pl08x.h | 3 |
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 { | |||
173 | struct pl08x_dma_chan { | 175 | struct 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; |