diff options
-rw-r--r-- | drivers/block/floppy.c | 23 |
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 | */ | ||
257 | static void fd_free_irq_fn(void *data) | ||
258 | { | ||
259 | fd_free_irq(); | ||
260 | } | ||
261 | |||
262 | static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL); | ||
263 | |||
264 | |||
253 | static struct request *current_req; | 265 | static struct request *current_req; |
254 | static struct request_queue *floppy_queue; | 266 | static struct request_queue *floppy_queue; |
255 | static void do_fd_request(request_queue_t * q); | 267 | static 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 | ||