Thread (34 messages) 34 messages, 5 authors, 2012-02-01

[PATCH v2 2/2] msm: DMAEngine: Add DMAEngine driver based on old MSM DMA APIs

From: Daniel Walker <hidden>
Date: 2012-01-08 00:14:09
Also in: linux-arch, linux-arm-msm, lkml

On Sat, 2012-01-07 at 19:21 +0000, Russell King - ARM Linux wrote:
On Sat, Jan 07, 2012 at 10:54:43AM -0800, David Brown wrote:
quoted
On Fri, Jan 06, 2012 at 05:59:29PM -0800, Daniel Walker wrote:
quoted
quoted
diff --git a/drivers/dma/msm-dma.c b/drivers/dma/msm-dma.c
new file mode 100644
index 0000000..51d9a2b
--- /dev/null
+++ b/drivers/dma/msm-dma.c
...
+static void msm_chan_desc_cleanup(struct msm_dma_chan *chan)
+{
+	struct msm_dma_desc_sw *desc, *_desc;
+	unsigned long flags;
+
+	dev_dbg(chan->dev, "Cleaning completed descriptor of channel %d\n",
+							chan->chan_id);
+	spin_lock_irqsave(&chan->lock, flags);
+
+	list_for_each_entry_safe(desc, _desc, &chan->active_list, node) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		if (msm_dma_desc_status(chan, desc) == DMA_IN_PROGRESS)
+			break;
+
+		/* Remove from the list of running transactions */
+		list_del(&desc->node);
+
+		/* Run the link descriptor callback function */
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock_irqrestore(&chan->lock, flags);
+			callback(callback_param);
Are you sure unlocking here is safe? at_hdmac.c holds the lock the
entire time, and fsldma.c deletes the entire list, then runs the
operations.
Good catch.

According to a comment in at_hdmac.c, it is safe to hold the lock
while calling the callbacks, so that's probably the easiest solution.
I suspect that you've got something in another driver expecting the
lock to be released, and that might have to be changed.
It is _not_ safe to hold the lock while calling callbacks.

Please refer to the DMA engine documentation, found here:

Documentation/dmaengine.txt

section 3:

   Note:
        Although the async_tx API specifies that completion callback
        routines cannot submit any new operations, this is not the
        case for slave/cyclic DMA.

        For slave DMA, the subsequent transaction may not be available
        for submission prior to callback function being invoked, so
        slave DMA callbacks are permitted to prepare and submit a new
        transaction.

        For cyclic DMA, a callback function may wish to terminate the
        DMA via dmaengine_terminate_all().

*       Therefore, it is important that DMA engine drivers drop any
*       locks before calling the callback function which may cause a
*       deadlock.
Here's the comment from at_hdmac.c .

                /*
                 * The API requires that no submissions are done from a
                 * callback, so we don't need to drop the lock here
                 */
                if (callback)
                        callback(param);

I don't know much about the DMA engine, but maybe there is some special
case here that makes this ok.. (CC'ed Nicolas Ferre)

Daniel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help