aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-03-26 04:36:54 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 11:56:53 -0500
commit6dc659d813fdd1789e605d69d0b8762d284e8c60 (patch)
tree3eda05a63e1ed271d8382ca4de3315d1e1c19a24 /drivers
parent36ddf5bbdea7ba4582abc62f106f0f0e9f0b6b91 (diff)
[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')
-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;
250#include <linux/cdrom.h> /* for the compatibility eject ioctl */ 250#include <linux/cdrom.h> /* for the compatibility eject ioctl */
251#include <linux/completion.h> 251#include <linux/completion.h>
252 252
253/*
254 * Interrupt freeing also means /proc VFS work - dont do it
255 * from interrupt context. We push this work into keventd:
256 */
257static void fd_free_irq_fn(void *data)
258{
259 fd_free_irq();
260}
261
262static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL);
263
264
253static struct request *current_req; 265static struct request *current_req;
254static struct request_queue *floppy_queue; 266static struct request_queue *floppy_queue;
255static void do_fd_request(request_queue_t * q); 267static void do_fd_request(request_queue_t * q);
@@ -4433,6 +4445,13 @@ static int floppy_grab_irq_and_dma(void)
4433 return 0; 4445 return 0;
4434 } 4446 }
4435 spin_unlock_irqrestore(&floppy_usage_lock, flags); 4447 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4448
4449 /*
4450 * We might have scheduled a free_irq(), wait it to
4451 * drain first:
4452 */
4453 flush_scheduled_work();
4454
4436 if (fd_request_irq()) { 4455 if (fd_request_irq()) {
4437 DPRINT("Unable to grab IRQ%d for the floppy driver\n", 4456 DPRINT("Unable to grab IRQ%d for the floppy driver\n",
4438 FLOPPY_IRQ); 4457 FLOPPY_IRQ);
@@ -4522,7 +4541,7 @@ static void floppy_release_irq_and_dma(void)
4522 if (irqdma_allocated) { 4541 if (irqdma_allocated) {
4523 fd_disable_dma(); 4542 fd_disable_dma();
4524 fd_free_dma(); 4543 fd_free_dma();
4525 fd_free_irq(); 4544 schedule_work(&fd_free_irq_work);
4526 irqdma_allocated = 0; 4545 irqdma_allocated = 0;
4527 } 4546 }
4528 set_dor(0, ~0, 8); 4547 set_dor(0, ~0, 8);
@@ -4633,6 +4652,8 @@ void cleanup_module(void)
4633 /* eject disk, if any */ 4652 /* eject disk, if any */
4634 fd_eject(0); 4653 fd_eject(0);
4635 4654
4655 flush_scheduled_work(); /* fd_free_irq() might be pending */
4656
4636 wait_for_completion(&device_release); 4657 wait_for_completion(&device_release);
4637} 4658}
4638 4659