diff options
author | Sebastian Siewior <bigeasy@linutronix.de> | 2013-04-23 03:31:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-25 04:11:49 -0400 |
commit | 817f6d1a13754b043e1a6c1cb713763022860689 (patch) | |
tree | 80488896dae65d080e4463f2bf79efb8a0f9c617 | |
parent | 2bac7cb316d1327c457a715bac5fd56bbc42bc63 (diff) |
net/davinci_cpdma: don't check for jiffies with interrupts
__cpdma_chan_process() holds the lock with interrupts off (and its
caller as well), same goes for cpdma_ctlr_start(). With interrupts off,
jiffies will not make any progress and if the wait condition never gets
true we wait for ever.
Tgis patch adds a a simple udelay and counting down attempt.
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/ti/davinci_cpdma.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index ee13dc78430c..3e34187997de 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/delay.h> | ||
23 | 24 | ||
24 | #include "davinci_cpdma.h" | 25 | #include "davinci_cpdma.h" |
25 | 26 | ||
@@ -312,14 +313,16 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) | |||
312 | } | 313 | } |
313 | 314 | ||
314 | if (ctlr->params.has_soft_reset) { | 315 | if (ctlr->params.has_soft_reset) { |
315 | unsigned long timeout = jiffies + HZ/10; | 316 | unsigned timeout = 10 * 100; |
316 | 317 | ||
317 | dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); | 318 | dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); |
318 | while (time_before(jiffies, timeout)) { | 319 | while (timeout) { |
319 | if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) | 320 | if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) |
320 | break; | 321 | break; |
322 | udelay(10); | ||
323 | timeout--; | ||
321 | } | 324 | } |
322 | WARN_ON(!time_before(jiffies, timeout)); | 325 | WARN_ON(!timeout); |
323 | } | 326 | } |
324 | 327 | ||
325 | for (i = 0; i < ctlr->num_chan; i++) { | 328 | for (i = 0; i < ctlr->num_chan; i++) { |
@@ -868,7 +871,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) | |||
868 | struct cpdma_desc_pool *pool = ctlr->pool; | 871 | struct cpdma_desc_pool *pool = ctlr->pool; |
869 | unsigned long flags; | 872 | unsigned long flags; |
870 | int ret; | 873 | int ret; |
871 | unsigned long timeout; | 874 | unsigned timeout; |
872 | 875 | ||
873 | spin_lock_irqsave(&chan->lock, flags); | 876 | spin_lock_irqsave(&chan->lock, flags); |
874 | if (chan->state != CPDMA_STATE_ACTIVE) { | 877 | if (chan->state != CPDMA_STATE_ACTIVE) { |
@@ -883,14 +886,15 @@ int cpdma_chan_stop(struct cpdma_chan *chan) | |||
883 | dma_reg_write(ctlr, chan->td, chan_linear(chan)); | 886 | dma_reg_write(ctlr, chan->td, chan_linear(chan)); |
884 | 887 | ||
885 | /* wait for teardown complete */ | 888 | /* wait for teardown complete */ |
886 | timeout = jiffies + HZ/10; /* 100 msec */ | 889 | timeout = 100 * 100; /* 100 ms */ |
887 | while (time_before(jiffies, timeout)) { | 890 | while (timeout) { |
888 | u32 cp = chan_read(chan, cp); | 891 | u32 cp = chan_read(chan, cp); |
889 | if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) | 892 | if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) |
890 | break; | 893 | break; |
891 | cpu_relax(); | 894 | udelay(10); |
895 | timeout--; | ||
892 | } | 896 | } |
893 | WARN_ON(!time_before(jiffies, timeout)); | 897 | WARN_ON(!timeout); |
894 | chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); | 898 | chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); |
895 | 899 | ||
896 | /* handle completed packets */ | 900 | /* handle completed packets */ |