Commit 6dc659d8 authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds

[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: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 36ddf5bb
...@@ -250,6 +250,18 @@ static int irqdma_allocated; ...@@ -250,6 +250,18 @@ static int irqdma_allocated;
#include <linux/cdrom.h> /* for the compatibility eject ioctl */ #include <linux/cdrom.h> /* for the compatibility eject ioctl */
#include <linux/completion.h> #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 *current_req;
static struct request_queue *floppy_queue; static struct request_queue *floppy_queue;
static void do_fd_request(request_queue_t * q); static void do_fd_request(request_queue_t * q);
...@@ -4433,6 +4445,13 @@ static int floppy_grab_irq_and_dma(void) ...@@ -4433,6 +4445,13 @@ static int floppy_grab_irq_and_dma(void)
return 0; return 0;
} }
spin_unlock_irqrestore(&floppy_usage_lock, flags); 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()) { if (fd_request_irq()) {
DPRINT("Unable to grab IRQ%d for the floppy driver\n", DPRINT("Unable to grab IRQ%d for the floppy driver\n",
FLOPPY_IRQ); FLOPPY_IRQ);
...@@ -4522,7 +4541,7 @@ static void floppy_release_irq_and_dma(void) ...@@ -4522,7 +4541,7 @@ static void floppy_release_irq_and_dma(void)
if (irqdma_allocated) { if (irqdma_allocated) {
fd_disable_dma(); fd_disable_dma();
fd_free_dma(); fd_free_dma();
fd_free_irq(); schedule_work(&fd_free_irq_work);
irqdma_allocated = 0; irqdma_allocated = 0;
} }
set_dor(0, ~0, 8); set_dor(0, ~0, 8);
...@@ -4633,6 +4652,8 @@ void cleanup_module(void) ...@@ -4633,6 +4652,8 @@ void cleanup_module(void)
/* eject disk, if any */ /* eject disk, if any */
fd_eject(0); fd_eject(0);
flush_scheduled_work(); /* fd_free_irq() might be pending */
wait_for_completion(&device_release); wait_for_completion(&device_release);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment