Message ID | 1302583351-10449-1-git-send-email-srk@ti.com (mailing list archive) |
---|---|
State | Awaiting Upstream |
Headers | show |
From: Sriramakrishnan A G <srk@ti.com> Date: Tue, 12 Apr 2011 10:12:31 +0530 > The DMA cleanup function was holding the spinlock across > a busy loop where it waits for HW to indicate teardown is complete. > This generates a backtrace, when DEBUG_SPINLOCK is enabled. Make the > locking more granular. > > Signed-off-by: Sriramakrishnan A G <srk@ti.com> You can't really sleep in this function at all. For example, it gets invoked from the ->ndo_tx_timeout() method in davinci_emac.c, which runs from a timer. So even if you hack the spinlock usage, there are still major issues here. We could conditionalize the timeout handling, but I don't think so much complexity is worth it here. Just do a udelay()/mdelay() or similar, instead of the timed sleeps. Thanks.
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c index ae47f23..57fd0fc 100644 --- a/drivers/net/davinci_cpdma.c +++ b/drivers/net/davinci_cpdma.c @@ -824,6 +824,8 @@ int cpdma_chan_stop(struct cpdma_chan *chan) /* trigger teardown */ dma_reg_write(ctlr, chan->td, chan->chan_num); + spin_unlock_irqrestore(&chan->lock, flags); + /* wait for teardown complete */ timeout = jiffies + HZ/10; /* 100 msec */ while (time_before(jiffies, timeout)) { @@ -843,6 +845,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); /* remaining packets haven't been tx/rx'ed, clean them up */ + spin_lock_irqsave(&chan->lock, flags); while (chan->head) { struct cpdma_desc __iomem *desc = chan->head; dma_addr_t next_dma;
The DMA cleanup function was holding the spinlock across a busy loop where it waits for HW to indicate teardown is complete. This generates a backtrace, when DEBUG_SPINLOCK is enabled. Make the locking more granular. Signed-off-by: Sriramakrishnan A G <srk@ti.com> --- drivers/net/davinci_cpdma.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)