diff options
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r-- | drivers/block/floppy.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index fb2d0be7cdeb..bedb689b051f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -170,6 +170,7 @@ static int print_unex = 1; | |||
170 | #include <linux/mm.h> | 170 | #include <linux/mm.h> |
171 | #include <linux/bio.h> | 171 | #include <linux/bio.h> |
172 | #include <linux/string.h> | 172 | #include <linux/string.h> |
173 | #include <linux/jiffies.h> | ||
173 | #include <linux/fcntl.h> | 174 | #include <linux/fcntl.h> |
174 | #include <linux/delay.h> | 175 | #include <linux/delay.h> |
175 | #include <linux/mc146818rtc.h> /* CMOS defines */ | 176 | #include <linux/mc146818rtc.h> /* CMOS defines */ |
@@ -250,6 +251,18 @@ static int irqdma_allocated; | |||
250 | #include <linux/cdrom.h> /* for the compatibility eject ioctl */ | 251 | #include <linux/cdrom.h> /* for the compatibility eject ioctl */ |
251 | #include <linux/completion.h> | 252 | #include <linux/completion.h> |
252 | 253 | ||
254 | /* | ||
255 | * Interrupt freeing also means /proc VFS work - dont do it | ||
256 | * from interrupt context. We push this work into keventd: | ||
257 | */ | ||
258 | static void fd_free_irq_fn(void *data) | ||
259 | { | ||
260 | fd_free_irq(); | ||
261 | } | ||
262 | |||
263 | static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL); | ||
264 | |||
265 | |||
253 | static struct request *current_req; | 266 | static struct request *current_req; |
254 | static struct request_queue *floppy_queue; | 267 | static struct request_queue *floppy_queue; |
255 | static void do_fd_request(request_queue_t * q); | 268 | static void do_fd_request(request_queue_t * q); |
@@ -735,7 +748,7 @@ static int disk_change(int drive) | |||
735 | { | 748 | { |
736 | int fdc = FDC(drive); | 749 | int fdc = FDC(drive); |
737 | #ifdef FLOPPY_SANITY_CHECK | 750 | #ifdef FLOPPY_SANITY_CHECK |
738 | if (jiffies - UDRS->select_date < UDP->select_delay) | 751 | if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) |
739 | DPRINT("WARNING disk change called early\n"); | 752 | DPRINT("WARNING disk change called early\n"); |
740 | if (!(FDCS->dor & (0x10 << UNIT(drive))) || | 753 | if (!(FDCS->dor & (0x10 << UNIT(drive))) || |
741 | (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { | 754 | (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { |
@@ -1063,7 +1076,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function) | |||
1063 | return 1; | 1076 | return 1; |
1064 | } | 1077 | } |
1065 | 1078 | ||
1066 | if ((signed)(jiffies - delay) < 0) { | 1079 | if (time_before(jiffies, delay)) { |
1067 | del_timer(&fd_timer); | 1080 | del_timer(&fd_timer); |
1068 | fd_timer.function = function; | 1081 | fd_timer.function = function; |
1069 | fd_timer.expires = delay; | 1082 | fd_timer.expires = delay; |
@@ -1523,7 +1536,7 @@ static void setup_rw_floppy(void) | |||
1523 | * again just before spinup completion. Beware that | 1536 | * again just before spinup completion. Beware that |
1524 | * after scandrives, we must again wait for selection. | 1537 | * after scandrives, we must again wait for selection. |
1525 | */ | 1538 | */ |
1526 | if ((signed)(ready_date - jiffies) > DP->select_delay) { | 1539 | if (time_after(ready_date, jiffies + DP->select_delay)) { |
1527 | ready_date -= DP->select_delay; | 1540 | ready_date -= DP->select_delay; |
1528 | function = (timeout_fn) floppy_start; | 1541 | function = (timeout_fn) floppy_start; |
1529 | } else | 1542 | } else |
@@ -3811,7 +3824,7 @@ static int check_floppy_change(struct gendisk *disk) | |||
3811 | if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) | 3824 | if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) |
3812 | return 1; | 3825 | return 1; |
3813 | 3826 | ||
3814 | if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) { | 3827 | if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { |
3815 | if (floppy_grab_irq_and_dma()) { | 3828 | if (floppy_grab_irq_and_dma()) { |
3816 | return 1; | 3829 | return 1; |
3817 | } | 3830 | } |
@@ -4433,6 +4446,13 @@ static int floppy_grab_irq_and_dma(void) | |||
4433 | return 0; | 4446 | return 0; |
4434 | } | 4447 | } |
4435 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | 4448 | spin_unlock_irqrestore(&floppy_usage_lock, flags); |
4449 | |||
4450 | /* | ||
4451 | * We might have scheduled a free_irq(), wait it to | ||
4452 | * drain first: | ||
4453 | */ | ||
4454 | flush_scheduled_work(); | ||
4455 | |||
4436 | if (fd_request_irq()) { | 4456 | if (fd_request_irq()) { |
4437 | DPRINT("Unable to grab IRQ%d for the floppy driver\n", | 4457 | DPRINT("Unable to grab IRQ%d for the floppy driver\n", |
4438 | FLOPPY_IRQ); | 4458 | FLOPPY_IRQ); |
@@ -4522,7 +4542,7 @@ static void floppy_release_irq_and_dma(void) | |||
4522 | if (irqdma_allocated) { | 4542 | if (irqdma_allocated) { |
4523 | fd_disable_dma(); | 4543 | fd_disable_dma(); |
4524 | fd_free_dma(); | 4544 | fd_free_dma(); |
4525 | fd_free_irq(); | 4545 | schedule_work(&fd_free_irq_work); |
4526 | irqdma_allocated = 0; | 4546 | irqdma_allocated = 0; |
4527 | } | 4547 | } |
4528 | set_dor(0, ~0, 8); | 4548 | set_dor(0, ~0, 8); |
@@ -4594,7 +4614,7 @@ static void __init parse_floppy_cfg_string(char *cfg) | |||
4594 | } | 4614 | } |
4595 | } | 4615 | } |
4596 | 4616 | ||
4597 | int init_module(void) | 4617 | int __init init_module(void) |
4598 | { | 4618 | { |
4599 | if (floppy) | 4619 | if (floppy) |
4600 | parse_floppy_cfg_string(floppy); | 4620 | parse_floppy_cfg_string(floppy); |
@@ -4633,6 +4653,8 @@ void cleanup_module(void) | |||
4633 | /* eject disk, if any */ | 4653 | /* eject disk, if any */ |
4634 | fd_eject(0); | 4654 | fd_eject(0); |
4635 | 4655 | ||
4656 | flush_scheduled_work(); /* fd_free_irq() might be pending */ | ||
4657 | |||
4636 | wait_for_completion(&device_release); | 4658 | wait_for_completion(&device_release); |
4637 | } | 4659 | } |
4638 | 4660 | ||