diff options
author | Ludovic Desroches <ludovic.desroches@atmel.com> | 2013-04-18 03:52:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-18 11:54:22 -0400 |
commit | d202f05158442396033f416df376f8ece1f563df (patch) | |
tree | 1c08c8128ac638606af144eec1338c864310a3d4 | |
parent | ebe80544338a393e94b65995120c3028c80abc62 (diff) |
dmaengine: at_hdmac: fix race condition in atc_advance_work()
The BUG_ON() directive is triggered probably due to a latency
modification following inclusion of commit c10d73671ad3 ("softirq:
reduce latencies"). This condition has not been met before 3.9-rc1 and
doesn't trigger without this patch.
We now make sure that DMA channel is idle before calling
atc_complete_all() which makes the BUG_ON() "protection" useless.
Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/dma/at_hdmac.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 6e13f262139a..88cfc61329d2 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -310,8 +310,6 @@ static void atc_complete_all(struct at_dma_chan *atchan) | |||
310 | 310 | ||
311 | dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n"); | 311 | dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n"); |
312 | 312 | ||
313 | BUG_ON(atc_chan_is_enabled(atchan)); | ||
314 | |||
315 | /* | 313 | /* |
316 | * Submit queued descriptors ASAP, i.e. before we go through | 314 | * Submit queued descriptors ASAP, i.e. before we go through |
317 | * the completed ones. | 315 | * the completed ones. |
@@ -368,6 +366,9 @@ static void atc_advance_work(struct at_dma_chan *atchan) | |||
368 | { | 366 | { |
369 | dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n"); | 367 | dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n"); |
370 | 368 | ||
369 | if (atc_chan_is_enabled(atchan)) | ||
370 | return; | ||
371 | |||
371 | if (list_empty(&atchan->active_list) || | 372 | if (list_empty(&atchan->active_list) || |
372 | list_is_singular(&atchan->active_list)) { | 373 | list_is_singular(&atchan->active_list)) { |
373 | atc_complete_all(atchan); | 374 | atc_complete_all(atchan); |
@@ -1078,9 +1079,7 @@ static void atc_issue_pending(struct dma_chan *chan) | |||
1078 | return; | 1079 | return; |
1079 | 1080 | ||
1080 | spin_lock_irqsave(&atchan->lock, flags); | 1081 | spin_lock_irqsave(&atchan->lock, flags); |
1081 | if (!atc_chan_is_enabled(atchan)) { | 1082 | atc_advance_work(atchan); |
1082 | atc_advance_work(atchan); | ||
1083 | } | ||
1084 | spin_unlock_irqrestore(&atchan->lock, flags); | 1083 | spin_unlock_irqrestore(&atchan->lock, flags); |
1085 | } | 1084 | } |
1086 | 1085 | ||