summary refs log tree commit diff
diff options
context:
space:
mode:
authorIra Snyder <iws@ovro.caltech.edu>2012-01-26 10:59:54 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-02-27 11:33:59 +1100
commit75ff85a81680e5779383aa6210a4f89ed76e40ec (patch)
treec327f25f2a51fc32382f0fcff4fee7c0532b6f15
parent6d45584fdc202fd30da655120412210153429104 (diff)
downloadlinux-75ff85a81680e5779383aa6210a4f89ed76e40ec.tar.gz
carma-fpga: fix lockdep warning
Lockdep occasionally complains with the message:
INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected

This is caused by calling videobuf_dma_unmap() under spin_lock_irq(). To
fix the warning, we drop the lock before unmapping and freeing the
buffer.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--drivers/misc/carma/carma-fpga.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index 14e974b2a781..4fd896deda0d 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -1079,6 +1079,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
 	struct fpga_reader *reader = filp->private_data;
 	struct fpga_device *priv = reader->priv;
 	struct list_head *used = &priv->used;
+	bool drop_buffer = false;
 	struct data_buf *dbuf;
 	size_t avail;
 	void *data;
@@ -1166,10 +1167,12 @@ have_buffer:
 	 * One of two things has happened, the device is disabled, or the
 	 * device has been reconfigured underneath us. In either case, we
 	 * should just throw away the buffer.
+	 *
+	 * Lockdep complains if this is done under the spinlock, so we
+	 * handle it during the unlock path.
 	 */
 	if (!priv->enabled || dbuf->size != priv->bufsize) {
-		videobuf_dma_unmap(priv->dev, &dbuf->vb);
-		data_free_buffer(dbuf);
+		drop_buffer = true;
 		goto out_unlock;
 	}
 
@@ -1178,6 +1181,12 @@ have_buffer:
 
 out_unlock:
 	spin_unlock_irq(&priv->lock);
+
+	if (drop_buffer) {
+		videobuf_dma_unmap(priv->dev, &dbuf->vb);
+		data_free_buffer(dbuf);
+	}
+
 	return count;
 }