diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-05-25 07:32:00 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-07-01 09:15:54 -0400 |
commit | eab82533c972bf932434b69bbb71c6724d863ef7 (patch) | |
tree | ca19df44fddcf780f37e5079795fa70ba33f2b36 /drivers | |
parent | 7847f6b55e6a5fe0bbcdaf20db291c9b1db890e8 (diff) |
dmaengine: PL08x: re-jig the starting of txds
Rather than code the de-queue of the txd several times, move that into
the start_txd function. Rename this to better illustrate what it's
now doing, and call this function when starting a delayed memcpy().
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/amba-pl08x.c | 37 |
1 files changed, 17 insertions, 20 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 88661fa4542c..c278d23adee7 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c | |||
@@ -354,20 +354,25 @@ static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch) | |||
354 | * been set when the LLIs were constructed. Poke them into the hardware | 354 | * been set when the LLIs were constructed. Poke them into the hardware |
355 | * and start the transfer. | 355 | * and start the transfer. |
356 | */ | 356 | */ |
357 | static void pl08x_start_txd(struct pl08x_dma_chan *plchan, | 357 | static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan) |
358 | struct pl08x_txd *txd) | ||
359 | { | 358 | { |
360 | struct pl08x_driver_data *pl08x = plchan->host; | 359 | struct pl08x_driver_data *pl08x = plchan->host; |
361 | struct pl08x_phy_chan *phychan = plchan->phychan; | 360 | struct pl08x_phy_chan *phychan = plchan->phychan; |
362 | struct pl08x_lli *lli = &txd->llis_va[0]; | 361 | struct pl08x_lli *lli; |
362 | struct pl08x_txd *txd; | ||
363 | u32 val; | 363 | u32 val; |
364 | 364 | ||
365 | txd = list_first_entry(&plchan->pend_list, struct pl08x_txd, node); | ||
366 | list_del(&txd->node); | ||
367 | |||
365 | plchan->at = txd; | 368 | plchan->at = txd; |
366 | 369 | ||
367 | /* Wait for channel inactive */ | 370 | /* Wait for channel inactive */ |
368 | while (pl08x_phy_channel_busy(phychan)) | 371 | while (pl08x_phy_channel_busy(phychan)) |
369 | cpu_relax(); | 372 | cpu_relax(); |
370 | 373 | ||
374 | lli = &txd->llis_va[0]; | ||
375 | |||
371 | dev_vdbg(&pl08x->adev->dev, | 376 | dev_vdbg(&pl08x->adev->dev, |
372 | "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, " | 377 | "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, " |
373 | "clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n", | 378 | "clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n", |
@@ -1272,15 +1277,8 @@ static void pl08x_issue_pending(struct dma_chan *chan) | |||
1272 | 1277 | ||
1273 | /* Take the first element in the queue and execute it */ | 1278 | /* Take the first element in the queue and execute it */ |
1274 | if (!list_empty(&plchan->pend_list)) { | 1279 | if (!list_empty(&plchan->pend_list)) { |
1275 | struct pl08x_txd *next; | ||
1276 | |||
1277 | next = list_first_entry(&plchan->pend_list, | ||
1278 | struct pl08x_txd, | ||
1279 | node); | ||
1280 | list_del(&next->node); | ||
1281 | plchan->state = PL08X_CHAN_RUNNING; | 1280 | plchan->state = PL08X_CHAN_RUNNING; |
1282 | 1281 | pl08x_start_next_txd(plchan); | |
1283 | pl08x_start_txd(plchan, next); | ||
1284 | } | 1282 | } |
1285 | 1283 | ||
1286 | spin_unlock_irqrestore(&plchan->lock, flags); | 1284 | spin_unlock_irqrestore(&plchan->lock, flags); |
@@ -1661,14 +1659,7 @@ static void pl08x_tasklet(unsigned long data) | |||
1661 | 1659 | ||
1662 | /* If a new descriptor is queued, set it up plchan->at is NULL here */ | 1660 | /* If a new descriptor is queued, set it up plchan->at is NULL here */ |
1663 | if (!list_empty(&plchan->pend_list)) { | 1661 | if (!list_empty(&plchan->pend_list)) { |
1664 | struct pl08x_txd *next; | 1662 | pl08x_start_next_txd(plchan); |
1665 | |||
1666 | next = list_first_entry(&plchan->pend_list, | ||
1667 | struct pl08x_txd, | ||
1668 | node); | ||
1669 | list_del(&next->node); | ||
1670 | |||
1671 | pl08x_start_txd(plchan, next); | ||
1672 | } else if (plchan->phychan_hold) { | 1663 | } else if (plchan->phychan_hold) { |
1673 | /* | 1664 | /* |
1674 | * This channel is still in use - we have a new txd being | 1665 | * This channel is still in use - we have a new txd being |
@@ -1700,7 +1691,13 @@ static void pl08x_tasklet(unsigned long data) | |||
1700 | BUG_ON(ret); | 1691 | BUG_ON(ret); |
1701 | waiting->phychan_hold--; | 1692 | waiting->phychan_hold--; |
1702 | waiting->state = PL08X_CHAN_RUNNING; | 1693 | waiting->state = PL08X_CHAN_RUNNING; |
1703 | pl08x_issue_pending(&waiting->chan); | 1694 | /* |
1695 | * Eww. We know this isn't going to deadlock | ||
1696 | * but lockdep probably doens't. | ||
1697 | */ | ||
1698 | spin_lock(&waiting->lock); | ||
1699 | pl08x_start_next_txd(waiting); | ||
1700 | spin_unlock(&waiting->lock); | ||
1704 | break; | 1701 | break; |
1705 | } | 1702 | } |
1706 | } | 1703 | } |