aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/floppy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r--drivers/block/floppy.c34
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 */
258static void fd_free_irq_fn(void *data)
259{
260 fd_free_irq();
261}
262
263static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL);
264
265
253static struct request *current_req; 266static struct request *current_req;
254static struct request_queue *floppy_queue; 267static struct request_queue *floppy_queue;
255static void do_fd_request(request_queue_t * q); 268static 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
4597int init_module(void) 4617int __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