From fdcf75080de009746d59a492dd77b944095b4936 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 26 Mar 2006 01:36:54 -0800 Subject: [PATCH] --- yaml --- r: 24023 b: refs/heads/master c: 6dc659d813fdd1789e605d69d0b8762d284e8c60 h: refs/heads/master i: 24021: a43652e965c38df5faa5acbc4ab10b03ba399cdd 24019: 0d664c016ff550ea5b925bfd6b33740fec625d28 24015: ac1c6020d61b0769d30a6f7e05f2698e60be8f9d v: v3 --- [refs] | 2 +- trunk/drivers/block/floppy.c | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 8cab7b54e0a3..ac2a6169be82 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 36ddf5bbdea7ba4582abc62f106f0f0e9f0b6b91 +refs/heads/master: 6dc659d813fdd1789e605d69d0b8762d284e8c60 diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 840919bba76c..d3ad9081697e 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -250,6 +250,18 @@ static int irqdma_allocated; #include /* for the compatibility eject ioctl */ #include +/* + * 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); }