summary refs log tree commit diff
path: root/drivers/block/floppy.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-03-26 01:36:54 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 08:56:53 -0800
commit6dc659d813fdd1789e605d69d0b8762d284e8c60 (patch)
tree3eda05a63e1ed271d8382ca4de3315d1e1c19a24 /drivers/block/floppy.c
parent36ddf5bbdea7ba4582abc62f106f0f0e9f0b6b91 (diff)
downloadlinux-6dc659d813fdd1789e605d69d0b8762d284e8c60.tar.gz
[PATCH] drivers/block/floppy.c: dont free_irq() from irq context
free_irq() should not be executed from softirq context.

Found by the lock validator.  The fix is to push fd_free_irq() into
keventd.  The code validates fine with this patch applied.

(akpm: this is revolting, but so is floppy.c)

[akpm@osdl.org: added flush_scheduled_work()]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r--drivers/block/floppy.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 840919bba76c..d3ad9081697e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -250,6 +250,18 @@ static int irqdma_allocated;
 #include <linux/cdrom.h>	/* for the compatibility eject ioctl */
 #include <linux/completion.h>
 
+/*
+ * Interrupt freeing also means /proc VFS work - dont do it
+ * from interrupt context. We push this work into keventd:
+ */
+static void fd_free_irq_fn(void *data)
+{
+	fd_free_irq();
+}
+
+static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL);
+
+
 static struct request *current_req;
 static struct request_queue *floppy_queue;
 static void do_fd_request(request_queue_t * q);
@@ -4433,6 +4445,13 @@ static int floppy_grab_irq_and_dma(void)
 		return 0;
 	}
 	spin_unlock_irqrestore(&floppy_usage_lock, flags);
+
+	/*
+	 * We might have scheduled a free_irq(), wait it to
+	 * drain first:
+	 */
+	flush_scheduled_work();
+
 	if (fd_request_irq()) {
 		DPRINT("Unable to grab IRQ%d for the floppy driver\n",
 		       FLOPPY_IRQ);
@@ -4522,7 +4541,7 @@ static void floppy_release_irq_and_dma(void)
 	if (irqdma_allocated) {
 		fd_disable_dma();
 		fd_free_dma();
-		fd_free_irq();
+		schedule_work(&fd_free_irq_work);
 		irqdma_allocated = 0;
 	}
 	set_dor(0, ~0, 8);
@@ -4633,6 +4652,8 @@ void cleanup_module(void)
 	/* eject disk, if any */
 	fd_eject(0);
 
+	flush_scheduled_work();		/* fd_free_irq() might be pending */
+
 	wait_for_completion(&device_release);
 }