diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/block/floppy.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r-- | drivers/block/floppy.c | 301 |
1 files changed, 153 insertions, 148 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 2ddd64a9ffd..9955a53733b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -188,10 +188,10 @@ static int print_unex = 1; | |||
188 | #include <linux/init.h> | 188 | #include <linux/init.h> |
189 | #include <linux/platform_device.h> | 189 | #include <linux/platform_device.h> |
190 | #include <linux/mod_devicetable.h> | 190 | #include <linux/mod_devicetable.h> |
191 | #include <linux/buffer_head.h> /* for invalidate_buffers() */ | ||
191 | #include <linux/mutex.h> | 192 | #include <linux/mutex.h> |
192 | #include <linux/io.h> | 193 | #include <linux/io.h> |
193 | #include <linux/uaccess.h> | 194 | #include <linux/uaccess.h> |
194 | #include <linux/async.h> | ||
195 | 195 | ||
196 | /* | 196 | /* |
197 | * PS/2 floppies have much slower step rates than regular floppies. | 197 | * PS/2 floppies have much slower step rates than regular floppies. |
@@ -203,6 +203,7 @@ static int slow_floppy; | |||
203 | 203 | ||
204 | #include <asm/dma.h> | 204 | #include <asm/dma.h> |
205 | #include <asm/irq.h> | 205 | #include <asm/irq.h> |
206 | #include <asm/system.h> | ||
206 | 207 | ||
207 | static int FLOPPY_IRQ = 6; | 208 | static int FLOPPY_IRQ = 6; |
208 | static int FLOPPY_DMA = 2; | 209 | static int FLOPPY_DMA = 2; |
@@ -552,7 +553,7 @@ static void floppy_ready(void); | |||
552 | static void floppy_start(void); | 553 | static void floppy_start(void); |
553 | static void process_fd_request(void); | 554 | static void process_fd_request(void); |
554 | static void recalibrate_floppy(void); | 555 | static void recalibrate_floppy(void); |
555 | static void floppy_shutdown(struct work_struct *); | 556 | static void floppy_shutdown(unsigned long); |
556 | 557 | ||
557 | static int floppy_request_regions(int); | 558 | static int floppy_request_regions(int); |
558 | static void floppy_release_regions(int); | 559 | static void floppy_release_regions(int); |
@@ -589,8 +590,6 @@ static int buffer_max = -1; | |||
589 | static struct floppy_fdc_state fdc_state[N_FDC]; | 590 | static struct floppy_fdc_state fdc_state[N_FDC]; |
590 | static int fdc; /* current fdc */ | 591 | static int fdc; /* current fdc */ |
591 | 592 | ||
592 | static struct workqueue_struct *floppy_wq; | ||
593 | |||
594 | static struct floppy_struct *_floppy = floppy_type; | 593 | static struct floppy_struct *_floppy = floppy_type; |
595 | static unsigned char current_drive; | 594 | static unsigned char current_drive; |
596 | static long current_count_sectors; | 595 | static long current_count_sectors; |
@@ -632,15 +631,16 @@ static inline void set_debugt(void) { } | |||
632 | static inline void debugt(const char *func, const char *msg) { } | 631 | static inline void debugt(const char *func, const char *msg) { } |
633 | #endif /* DEBUGT */ | 632 | #endif /* DEBUGT */ |
634 | 633 | ||
634 | typedef void (*timeout_fn)(unsigned long); | ||
635 | static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0); | ||
635 | 636 | ||
636 | static DECLARE_DELAYED_WORK(fd_timeout, floppy_shutdown); | ||
637 | static const char *timeout_message; | 637 | static const char *timeout_message; |
638 | 638 | ||
639 | static void is_alive(const char *func, const char *message) | 639 | static void is_alive(const char *func, const char *message) |
640 | { | 640 | { |
641 | /* this routine checks whether the floppy driver is "alive" */ | 641 | /* this routine checks whether the floppy driver is "alive" */ |
642 | if (test_bit(0, &fdc_busy) && command_status < 2 && | 642 | if (test_bit(0, &fdc_busy) && command_status < 2 && |
643 | !delayed_work_pending(&fd_timeout)) { | 643 | !timer_pending(&fd_timeout)) { |
644 | DPRINT("%s: timeout handler died. %s\n", func, message); | 644 | DPRINT("%s: timeout handler died. %s\n", func, message); |
645 | } | 645 | } |
646 | } | 646 | } |
@@ -668,18 +668,15 @@ static int output_log_pos; | |||
668 | 668 | ||
669 | static void __reschedule_timeout(int drive, const char *message) | 669 | static void __reschedule_timeout(int drive, const char *message) |
670 | { | 670 | { |
671 | unsigned long delay; | ||
672 | |||
673 | if (drive == current_reqD) | 671 | if (drive == current_reqD) |
674 | drive = current_drive; | 672 | drive = current_drive; |
675 | 673 | del_timer(&fd_timeout); | |
676 | if (drive < 0 || drive >= N_DRIVE) { | 674 | if (drive < 0 || drive >= N_DRIVE) { |
677 | delay = 20UL * HZ; | 675 | fd_timeout.expires = jiffies + 20UL * HZ; |
678 | drive = 0; | 676 | drive = 0; |
679 | } else | 677 | } else |
680 | delay = UDP->timeout; | 678 | fd_timeout.expires = jiffies + UDP->timeout; |
681 | 679 | add_timer(&fd_timeout); | |
682 | mod_delayed_work(floppy_wq, &fd_timeout, delay); | ||
683 | if (UDP->flags & FD_DEBUG) | 680 | if (UDP->flags & FD_DEBUG) |
684 | DPRINT("reschedule timeout %s\n", message); | 681 | DPRINT("reschedule timeout %s\n", message); |
685 | timeout_message = message; | 682 | timeout_message = message; |
@@ -877,7 +874,7 @@ static int lock_fdc(int drive, bool interruptible) | |||
877 | 874 | ||
878 | command_status = FD_COMMAND_NONE; | 875 | command_status = FD_COMMAND_NONE; |
879 | 876 | ||
880 | reschedule_timeout(drive, "lock fdc"); | 877 | __reschedule_timeout(drive, "lock fdc"); |
881 | set_fdc(drive); | 878 | set_fdc(drive); |
882 | return 0; | 879 | return 0; |
883 | } | 880 | } |
@@ -885,15 +882,23 @@ static int lock_fdc(int drive, bool interruptible) | |||
885 | /* unlocks the driver */ | 882 | /* unlocks the driver */ |
886 | static void unlock_fdc(void) | 883 | static void unlock_fdc(void) |
887 | { | 884 | { |
885 | unsigned long flags; | ||
886 | |||
887 | raw_cmd = NULL; | ||
888 | if (!test_bit(0, &fdc_busy)) | 888 | if (!test_bit(0, &fdc_busy)) |
889 | DPRINT("FDC access conflict!\n"); | 889 | DPRINT("FDC access conflict!\n"); |
890 | 890 | ||
891 | raw_cmd = NULL; | 891 | if (do_floppy) |
892 | DPRINT("device interrupt still active at FDC release: %pf!\n", | ||
893 | do_floppy); | ||
892 | command_status = FD_COMMAND_NONE; | 894 | command_status = FD_COMMAND_NONE; |
893 | cancel_delayed_work(&fd_timeout); | 895 | spin_lock_irqsave(&floppy_lock, flags); |
894 | do_floppy = NULL; | 896 | del_timer(&fd_timeout); |
895 | cont = NULL; | 897 | cont = NULL; |
896 | clear_bit(0, &fdc_busy); | 898 | clear_bit(0, &fdc_busy); |
899 | if (current_req || set_next_request()) | ||
900 | do_fd_request(current_req->q); | ||
901 | spin_unlock_irqrestore(&floppy_lock, flags); | ||
897 | wake_up(&fdc_wait); | 902 | wake_up(&fdc_wait); |
898 | } | 903 | } |
899 | 904 | ||
@@ -965,24 +970,26 @@ static DECLARE_WORK(floppy_work, NULL); | |||
965 | 970 | ||
966 | static void schedule_bh(void (*handler)(void)) | 971 | static void schedule_bh(void (*handler)(void)) |
967 | { | 972 | { |
968 | WARN_ON(work_pending(&floppy_work)); | ||
969 | |||
970 | PREPARE_WORK(&floppy_work, (work_func_t)handler); | 973 | PREPARE_WORK(&floppy_work, (work_func_t)handler); |
971 | queue_work(floppy_wq, &floppy_work); | 974 | schedule_work(&floppy_work); |
972 | } | 975 | } |
973 | 976 | ||
974 | static DECLARE_DELAYED_WORK(fd_timer, NULL); | 977 | static DEFINE_TIMER(fd_timer, NULL, 0, 0); |
975 | 978 | ||
976 | static void cancel_activity(void) | 979 | static void cancel_activity(void) |
977 | { | 980 | { |
981 | unsigned long flags; | ||
982 | |||
983 | spin_lock_irqsave(&floppy_lock, flags); | ||
978 | do_floppy = NULL; | 984 | do_floppy = NULL; |
979 | cancel_delayed_work_sync(&fd_timer); | 985 | PREPARE_WORK(&floppy_work, (work_func_t)empty); |
980 | cancel_work_sync(&floppy_work); | 986 | del_timer(&fd_timer); |
987 | spin_unlock_irqrestore(&floppy_lock, flags); | ||
981 | } | 988 | } |
982 | 989 | ||
983 | /* this function makes sure that the disk stays in the drive during the | 990 | /* this function makes sure that the disk stays in the drive during the |
984 | * transfer */ | 991 | * transfer */ |
985 | static void fd_watchdog(struct work_struct *arg) | 992 | static void fd_watchdog(void) |
986 | { | 993 | { |
987 | debug_dcl(DP->flags, "calling disk change from watchdog\n"); | 994 | debug_dcl(DP->flags, "calling disk change from watchdog\n"); |
988 | 995 | ||
@@ -992,20 +999,21 @@ static void fd_watchdog(struct work_struct *arg) | |||
992 | cont->done(0); | 999 | cont->done(0); |
993 | reset_fdc(); | 1000 | reset_fdc(); |
994 | } else { | 1001 | } else { |
995 | cancel_delayed_work(&fd_timer); | 1002 | del_timer(&fd_timer); |
996 | PREPARE_DELAYED_WORK(&fd_timer, fd_watchdog); | 1003 | fd_timer.function = (timeout_fn)fd_watchdog; |
997 | queue_delayed_work(floppy_wq, &fd_timer, HZ / 10); | 1004 | fd_timer.expires = jiffies + HZ / 10; |
1005 | add_timer(&fd_timer); | ||
998 | } | 1006 | } |
999 | } | 1007 | } |
1000 | 1008 | ||
1001 | static void main_command_interrupt(void) | 1009 | static void main_command_interrupt(void) |
1002 | { | 1010 | { |
1003 | cancel_delayed_work(&fd_timer); | 1011 | del_timer(&fd_timer); |
1004 | cont->interrupt(); | 1012 | cont->interrupt(); |
1005 | } | 1013 | } |
1006 | 1014 | ||
1007 | /* waits for a delay (spinup or select) to pass */ | 1015 | /* waits for a delay (spinup or select) to pass */ |
1008 | static int fd_wait_for_completion(unsigned long expires, work_func_t function) | 1016 | static int fd_wait_for_completion(unsigned long delay, timeout_fn function) |
1009 | { | 1017 | { |
1010 | if (FDCS->reset) { | 1018 | if (FDCS->reset) { |
1011 | reset_fdc(); /* do the reset during sleep to win time | 1019 | reset_fdc(); /* do the reset during sleep to win time |
@@ -1014,15 +1022,47 @@ static int fd_wait_for_completion(unsigned long expires, work_func_t function) | |||
1014 | return 1; | 1022 | return 1; |
1015 | } | 1023 | } |
1016 | 1024 | ||
1017 | if (time_before(jiffies, expires)) { | 1025 | if (time_before(jiffies, delay)) { |
1018 | cancel_delayed_work(&fd_timer); | 1026 | del_timer(&fd_timer); |
1019 | PREPARE_DELAYED_WORK(&fd_timer, function); | 1027 | fd_timer.function = function; |
1020 | queue_delayed_work(floppy_wq, &fd_timer, expires - jiffies); | 1028 | fd_timer.expires = delay; |
1029 | add_timer(&fd_timer); | ||
1021 | return 1; | 1030 | return 1; |
1022 | } | 1031 | } |
1023 | return 0; | 1032 | return 0; |
1024 | } | 1033 | } |
1025 | 1034 | ||
1035 | static DEFINE_SPINLOCK(floppy_hlt_lock); | ||
1036 | static int hlt_disabled; | ||
1037 | static void floppy_disable_hlt(void) | ||
1038 | { | ||
1039 | unsigned long flags; | ||
1040 | |||
1041 | WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012"); | ||
1042 | spin_lock_irqsave(&floppy_hlt_lock, flags); | ||
1043 | if (!hlt_disabled) { | ||
1044 | hlt_disabled = 1; | ||
1045 | #ifdef HAVE_DISABLE_HLT | ||
1046 | disable_hlt(); | ||
1047 | #endif | ||
1048 | } | ||
1049 | spin_unlock_irqrestore(&floppy_hlt_lock, flags); | ||
1050 | } | ||
1051 | |||
1052 | static void floppy_enable_hlt(void) | ||
1053 | { | ||
1054 | unsigned long flags; | ||
1055 | |||
1056 | spin_lock_irqsave(&floppy_hlt_lock, flags); | ||
1057 | if (hlt_disabled) { | ||
1058 | hlt_disabled = 0; | ||
1059 | #ifdef HAVE_DISABLE_HLT | ||
1060 | enable_hlt(); | ||
1061 | #endif | ||
1062 | } | ||
1063 | spin_unlock_irqrestore(&floppy_hlt_lock, flags); | ||
1064 | } | ||
1065 | |||
1026 | static void setup_DMA(void) | 1066 | static void setup_DMA(void) |
1027 | { | 1067 | { |
1028 | unsigned long f; | 1068 | unsigned long f; |
@@ -1067,6 +1107,7 @@ static void setup_DMA(void) | |||
1067 | fd_enable_dma(); | 1107 | fd_enable_dma(); |
1068 | release_dma_lock(f); | 1108 | release_dma_lock(f); |
1069 | #endif | 1109 | #endif |
1110 | floppy_disable_hlt(); | ||
1070 | } | 1111 | } |
1071 | 1112 | ||
1072 | static void show_floppy(void); | 1113 | static void show_floppy(void); |
@@ -1335,7 +1376,7 @@ static int fdc_dtr(void) | |||
1335 | */ | 1376 | */ |
1336 | FDCS->dtr = raw_cmd->rate & 3; | 1377 | FDCS->dtr = raw_cmd->rate & 3; |
1337 | return fd_wait_for_completion(jiffies + 2UL * HZ / 100, | 1378 | return fd_wait_for_completion(jiffies + 2UL * HZ / 100, |
1338 | (work_func_t)floppy_ready); | 1379 | (timeout_fn)floppy_ready); |
1339 | } /* fdc_dtr */ | 1380 | } /* fdc_dtr */ |
1340 | 1381 | ||
1341 | static void tell_sector(void) | 1382 | static void tell_sector(void) |
@@ -1440,7 +1481,7 @@ static void setup_rw_floppy(void) | |||
1440 | int flags; | 1481 | int flags; |
1441 | int dflags; | 1482 | int dflags; |
1442 | unsigned long ready_date; | 1483 | unsigned long ready_date; |
1443 | work_func_t function; | 1484 | timeout_fn function; |
1444 | 1485 | ||
1445 | flags = raw_cmd->flags; | 1486 | flags = raw_cmd->flags; |
1446 | if (flags & (FD_RAW_READ | FD_RAW_WRITE)) | 1487 | if (flags & (FD_RAW_READ | FD_RAW_WRITE)) |
@@ -1454,9 +1495,9 @@ static void setup_rw_floppy(void) | |||
1454 | */ | 1495 | */ |
1455 | if (time_after(ready_date, jiffies + DP->select_delay)) { | 1496 | if (time_after(ready_date, jiffies + DP->select_delay)) { |
1456 | ready_date -= DP->select_delay; | 1497 | ready_date -= DP->select_delay; |
1457 | function = (work_func_t)floppy_start; | 1498 | function = (timeout_fn)floppy_start; |
1458 | } else | 1499 | } else |
1459 | function = (work_func_t)setup_rw_floppy; | 1500 | function = (timeout_fn)setup_rw_floppy; |
1460 | 1501 | ||
1461 | /* wait until the floppy is spinning fast enough */ | 1502 | /* wait until the floppy is spinning fast enough */ |
1462 | if (fd_wait_for_completion(ready_date, function)) | 1503 | if (fd_wait_for_completion(ready_date, function)) |
@@ -1486,7 +1527,7 @@ static void setup_rw_floppy(void) | |||
1486 | inr = result(); | 1527 | inr = result(); |
1487 | cont->interrupt(); | 1528 | cont->interrupt(); |
1488 | } else if (flags & FD_RAW_NEED_DISK) | 1529 | } else if (flags & FD_RAW_NEED_DISK) |
1489 | fd_watchdog(NULL); | 1530 | fd_watchdog(); |
1490 | } | 1531 | } |
1491 | 1532 | ||
1492 | static int blind_seek; | 1533 | static int blind_seek; |
@@ -1668,6 +1709,7 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) | |||
1668 | fd_disable_dma(); | 1709 | fd_disable_dma(); |
1669 | release_dma_lock(f); | 1710 | release_dma_lock(f); |
1670 | 1711 | ||
1712 | floppy_enable_hlt(); | ||
1671 | do_floppy = NULL; | 1713 | do_floppy = NULL; |
1672 | if (fdc >= N_FDC || FDCS->address == -1) { | 1714 | if (fdc >= N_FDC || FDCS->address == -1) { |
1673 | /* we don't even know which FDC is the culprit */ | 1715 | /* we don't even know which FDC is the culprit */ |
@@ -1795,22 +1837,20 @@ static void show_floppy(void) | |||
1795 | pr_info("do_floppy=%pf\n", do_floppy); | 1837 | pr_info("do_floppy=%pf\n", do_floppy); |
1796 | if (work_pending(&floppy_work)) | 1838 | if (work_pending(&floppy_work)) |
1797 | pr_info("floppy_work.func=%pf\n", floppy_work.func); | 1839 | pr_info("floppy_work.func=%pf\n", floppy_work.func); |
1798 | if (delayed_work_pending(&fd_timer)) | 1840 | if (timer_pending(&fd_timer)) |
1799 | pr_info("delayed work.function=%p expires=%ld\n", | 1841 | pr_info("fd_timer.function=%pf\n", fd_timer.function); |
1800 | fd_timer.work.func, | 1842 | if (timer_pending(&fd_timeout)) { |
1801 | fd_timer.timer.expires - jiffies); | 1843 | pr_info("timer_function=%pf\n", fd_timeout.function); |
1802 | if (delayed_work_pending(&fd_timeout)) | 1844 | pr_info("expires=%lu\n", fd_timeout.expires - jiffies); |
1803 | pr_info("timer_function=%p expires=%ld\n", | 1845 | pr_info("now=%lu\n", jiffies); |
1804 | fd_timeout.work.func, | 1846 | } |
1805 | fd_timeout.timer.expires - jiffies); | ||
1806 | |||
1807 | pr_info("cont=%p\n", cont); | 1847 | pr_info("cont=%p\n", cont); |
1808 | pr_info("current_req=%p\n", current_req); | 1848 | pr_info("current_req=%p\n", current_req); |
1809 | pr_info("command_status=%d\n", command_status); | 1849 | pr_info("command_status=%d\n", command_status); |
1810 | pr_info("\n"); | 1850 | pr_info("\n"); |
1811 | } | 1851 | } |
1812 | 1852 | ||
1813 | static void floppy_shutdown(struct work_struct *arg) | 1853 | static void floppy_shutdown(unsigned long data) |
1814 | { | 1854 | { |
1815 | unsigned long flags; | 1855 | unsigned long flags; |
1816 | 1856 | ||
@@ -1818,6 +1858,8 @@ static void floppy_shutdown(struct work_struct *arg) | |||
1818 | show_floppy(); | 1858 | show_floppy(); |
1819 | cancel_activity(); | 1859 | cancel_activity(); |
1820 | 1860 | ||
1861 | floppy_enable_hlt(); | ||
1862 | |||
1821 | flags = claim_dma_lock(); | 1863 | flags = claim_dma_lock(); |
1822 | fd_disable_dma(); | 1864 | fd_disable_dma(); |
1823 | release_dma_lock(flags); | 1865 | release_dma_lock(flags); |
@@ -1863,7 +1905,7 @@ static int start_motor(void (*function)(void)) | |||
1863 | 1905 | ||
1864 | /* wait_for_completion also schedules reset if needed. */ | 1906 | /* wait_for_completion also schedules reset if needed. */ |
1865 | return fd_wait_for_completion(DRS->select_date + DP->select_delay, | 1907 | return fd_wait_for_completion(DRS->select_date + DP->select_delay, |
1866 | (work_func_t)function); | 1908 | (timeout_fn)function); |
1867 | } | 1909 | } |
1868 | 1910 | ||
1869 | static void floppy_ready(void) | 1911 | static void floppy_ready(void) |
@@ -2516,7 +2558,8 @@ static int make_raw_rw_request(void) | |||
2516 | set_fdc((long)current_req->rq_disk->private_data); | 2558 | set_fdc((long)current_req->rq_disk->private_data); |
2517 | 2559 | ||
2518 | raw_cmd = &default_raw_cmd; | 2560 | raw_cmd = &default_raw_cmd; |
2519 | raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; | 2561 | raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK | |
2562 | FD_RAW_NEED_SEEK; | ||
2520 | raw_cmd->cmd_count = NR_RW; | 2563 | raw_cmd->cmd_count = NR_RW; |
2521 | if (rq_data_dir(current_req) == READ) { | 2564 | if (rq_data_dir(current_req) == READ) { |
2522 | raw_cmd->flags |= FD_RAW_READ; | 2565 | raw_cmd->flags |= FD_RAW_READ; |
@@ -2815,6 +2858,7 @@ do_request: | |||
2815 | spin_lock_irq(&floppy_lock); | 2858 | spin_lock_irq(&floppy_lock); |
2816 | pending = set_next_request(); | 2859 | pending = set_next_request(); |
2817 | spin_unlock_irq(&floppy_lock); | 2860 | spin_unlock_irq(&floppy_lock); |
2861 | |||
2818 | if (!pending) { | 2862 | if (!pending) { |
2819 | do_floppy = NULL; | 2863 | do_floppy = NULL; |
2820 | unlock_fdc(); | 2864 | unlock_fdc(); |
@@ -2891,15 +2935,13 @@ static void do_fd_request(struct request_queue *q) | |||
2891 | current_req->cmd_flags)) | 2935 | current_req->cmd_flags)) |
2892 | return; | 2936 | return; |
2893 | 2937 | ||
2894 | if (test_and_set_bit(0, &fdc_busy)) { | 2938 | if (test_bit(0, &fdc_busy)) { |
2895 | /* fdc busy, this new request will be treated when the | 2939 | /* fdc busy, this new request will be treated when the |
2896 | current one is done */ | 2940 | current one is done */ |
2897 | is_alive(__func__, "old request running"); | 2941 | is_alive(__func__, "old request running"); |
2898 | return; | 2942 | return; |
2899 | } | 2943 | } |
2900 | command_status = FD_COMMAND_NONE; | 2944 | lock_fdc(MAXTIMEOUT, false); |
2901 | __reschedule_timeout(MAXTIMEOUT, "fd_request"); | ||
2902 | set_fdc(0); | ||
2903 | process_fd_request(); | 2945 | process_fd_request(); |
2904 | is_alive(__func__, ""); | 2946 | is_alive(__func__, ""); |
2905 | } | 2947 | } |
@@ -3607,7 +3649,9 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) | |||
3607 | 3649 | ||
3608 | mutex_lock(&floppy_mutex); | 3650 | mutex_lock(&floppy_mutex); |
3609 | mutex_lock(&open_lock); | 3651 | mutex_lock(&open_lock); |
3610 | if (!UDRS->fd_ref--) { | 3652 | if (UDRS->fd_ref < 0) |
3653 | UDRS->fd_ref = 0; | ||
3654 | else if (!UDRS->fd_ref--) { | ||
3611 | DPRINT("floppy_release with fd_ref == 0"); | 3655 | DPRINT("floppy_release with fd_ref == 0"); |
3612 | UDRS->fd_ref = 0; | 3656 | UDRS->fd_ref = 0; |
3613 | } | 3657 | } |
@@ -3643,7 +3687,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3643 | set_bit(FD_VERIFY_BIT, &UDRS->flags); | 3687 | set_bit(FD_VERIFY_BIT, &UDRS->flags); |
3644 | } | 3688 | } |
3645 | 3689 | ||
3646 | UDRS->fd_ref++; | 3690 | if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL))) |
3691 | goto out2; | ||
3692 | |||
3693 | if (mode & FMODE_EXCL) | ||
3694 | UDRS->fd_ref = -1; | ||
3695 | else | ||
3696 | UDRS->fd_ref++; | ||
3647 | 3697 | ||
3648 | opened_bdev[drive] = bdev; | 3698 | opened_bdev[drive] = bdev; |
3649 | 3699 | ||
@@ -3706,8 +3756,10 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3706 | mutex_unlock(&floppy_mutex); | 3756 | mutex_unlock(&floppy_mutex); |
3707 | return 0; | 3757 | return 0; |
3708 | out: | 3758 | out: |
3709 | UDRS->fd_ref--; | 3759 | if (UDRS->fd_ref < 0) |
3710 | 3760 | UDRS->fd_ref = 0; | |
3761 | else | ||
3762 | UDRS->fd_ref--; | ||
3711 | if (!UDRS->fd_ref) | 3763 | if (!UDRS->fd_ref) |
3712 | opened_bdev[drive] = NULL; | 3764 | opened_bdev[drive] = NULL; |
3713 | out2: | 3765 | out2: |
@@ -3781,7 +3833,7 @@ static int __floppy_read_block_0(struct block_device *bdev) | |||
3781 | bio.bi_size = size; | 3833 | bio.bi_size = size; |
3782 | bio.bi_bdev = bdev; | 3834 | bio.bi_bdev = bdev; |
3783 | bio.bi_sector = 0; | 3835 | bio.bi_sector = 0; |
3784 | bio.bi_flags = (1 << BIO_QUIET); | 3836 | bio.bi_flags = BIO_QUIET; |
3785 | init_completion(&complete); | 3837 | init_completion(&complete); |
3786 | bio.bi_private = &complete; | 3838 | bio.bi_private = &complete; |
3787 | bio.bi_end_io = floppy_rb0_complete; | 3839 | bio.bi_end_io = floppy_rb0_complete; |
@@ -4109,19 +4161,12 @@ static struct platform_driver floppy_driver = { | |||
4109 | 4161 | ||
4110 | static struct platform_device floppy_device[N_DRIVE]; | 4162 | static struct platform_device floppy_device[N_DRIVE]; |
4111 | 4163 | ||
4112 | static bool floppy_available(int drive) | ||
4113 | { | ||
4114 | if (!(allowed_drive_mask & (1 << drive))) | ||
4115 | return false; | ||
4116 | if (fdc_state[FDC(drive)].version == FDC_NONE) | ||
4117 | return false; | ||
4118 | return true; | ||
4119 | } | ||
4120 | |||
4121 | static struct kobject *floppy_find(dev_t dev, int *part, void *data) | 4164 | static struct kobject *floppy_find(dev_t dev, int *part, void *data) |
4122 | { | 4165 | { |
4123 | int drive = (*part & 3) | ((*part & 0x80) >> 5); | 4166 | int drive = (*part & 3) | ((*part & 0x80) >> 5); |
4124 | if (drive >= N_DRIVE || !floppy_available(drive)) | 4167 | if (drive >= N_DRIVE || |
4168 | !(allowed_drive_mask & (1 << drive)) || | ||
4169 | fdc_state[FDC(drive)].version == FDC_NONE) | ||
4125 | return NULL; | 4170 | return NULL; |
4126 | if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) | 4171 | if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) |
4127 | return NULL; | 4172 | return NULL; |
@@ -4129,9 +4174,10 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) | |||
4129 | return get_disk(disks[drive]); | 4174 | return get_disk(disks[drive]); |
4130 | } | 4175 | } |
4131 | 4176 | ||
4132 | static int __init do_floppy_init(void) | 4177 | static int __init floppy_init(void) |
4133 | { | 4178 | { |
4134 | int i, unit, drive, err; | 4179 | int i, unit, drive; |
4180 | int err, dr; | ||
4135 | 4181 | ||
4136 | set_debugt(); | 4182 | set_debugt(); |
4137 | interruptjiffies = resultjiffies = jiffies; | 4183 | interruptjiffies = resultjiffies = jiffies; |
@@ -4143,32 +4189,28 @@ static int __init do_floppy_init(void) | |||
4143 | 4189 | ||
4144 | raw_cmd = NULL; | 4190 | raw_cmd = NULL; |
4145 | 4191 | ||
4146 | floppy_wq = alloc_ordered_workqueue("floppy", 0); | 4192 | for (dr = 0; dr < N_DRIVE; dr++) { |
4147 | if (!floppy_wq) | 4193 | disks[dr] = alloc_disk(1); |
4148 | return -ENOMEM; | 4194 | if (!disks[dr]) { |
4149 | |||
4150 | for (drive = 0; drive < N_DRIVE; drive++) { | ||
4151 | disks[drive] = alloc_disk(1); | ||
4152 | if (!disks[drive]) { | ||
4153 | err = -ENOMEM; | 4195 | err = -ENOMEM; |
4154 | goto out_put_disk; | 4196 | goto out_put_disk; |
4155 | } | 4197 | } |
4156 | 4198 | ||
4157 | disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); | 4199 | disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); |
4158 | if (!disks[drive]->queue) { | 4200 | if (!disks[dr]->queue) { |
4159 | err = -ENOMEM; | 4201 | err = -ENOMEM; |
4160 | goto out_put_disk; | 4202 | goto out_put_disk; |
4161 | } | 4203 | } |
4162 | 4204 | ||
4163 | blk_queue_max_hw_sectors(disks[drive]->queue, 64); | 4205 | blk_queue_max_hw_sectors(disks[dr]->queue, 64); |
4164 | disks[drive]->major = FLOPPY_MAJOR; | 4206 | disks[dr]->major = FLOPPY_MAJOR; |
4165 | disks[drive]->first_minor = TOMINOR(drive); | 4207 | disks[dr]->first_minor = TOMINOR(dr); |
4166 | disks[drive]->fops = &floppy_fops; | 4208 | disks[dr]->fops = &floppy_fops; |
4167 | sprintf(disks[drive]->disk_name, "fd%d", drive); | 4209 | sprintf(disks[dr]->disk_name, "fd%d", dr); |
4168 | 4210 | ||
4169 | init_timer(&motor_off_timer[drive]); | 4211 | init_timer(&motor_off_timer[dr]); |
4170 | motor_off_timer[drive].data = drive; | 4212 | motor_off_timer[dr].data = dr; |
4171 | motor_off_timer[drive].function = motor_off_callback; | 4213 | motor_off_timer[dr].function = motor_off_callback; |
4172 | } | 4214 | } |
4173 | 4215 | ||
4174 | err = register_blkdev(FLOPPY_MAJOR, "fd"); | 4216 | err = register_blkdev(FLOPPY_MAJOR, "fd"); |
@@ -4208,7 +4250,7 @@ static int __init do_floppy_init(void) | |||
4208 | use_virtual_dma = can_use_virtual_dma & 1; | 4250 | use_virtual_dma = can_use_virtual_dma & 1; |
4209 | fdc_state[0].address = FDC1; | 4251 | fdc_state[0].address = FDC1; |
4210 | if (fdc_state[0].address == -1) { | 4252 | if (fdc_state[0].address == -1) { |
4211 | cancel_delayed_work(&fd_timeout); | 4253 | del_timer_sync(&fd_timeout); |
4212 | err = -ENODEV; | 4254 | err = -ENODEV; |
4213 | goto out_unreg_region; | 4255 | goto out_unreg_region; |
4214 | } | 4256 | } |
@@ -4219,7 +4261,7 @@ static int __init do_floppy_init(void) | |||
4219 | fdc = 0; /* reset fdc in case of unexpected interrupt */ | 4261 | fdc = 0; /* reset fdc in case of unexpected interrupt */ |
4220 | err = floppy_grab_irq_and_dma(); | 4262 | err = floppy_grab_irq_and_dma(); |
4221 | if (err) { | 4263 | if (err) { |
4222 | cancel_delayed_work(&fd_timeout); | 4264 | del_timer_sync(&fd_timeout); |
4223 | err = -EBUSY; | 4265 | err = -EBUSY; |
4224 | goto out_unreg_region; | 4266 | goto out_unreg_region; |
4225 | } | 4267 | } |
@@ -4276,17 +4318,19 @@ static int __init do_floppy_init(void) | |||
4276 | user_reset_fdc(-1, FD_RESET_ALWAYS, false); | 4318 | user_reset_fdc(-1, FD_RESET_ALWAYS, false); |
4277 | } | 4319 | } |
4278 | fdc = 0; | 4320 | fdc = 0; |
4279 | cancel_delayed_work(&fd_timeout); | 4321 | del_timer_sync(&fd_timeout); |
4280 | current_drive = 0; | 4322 | current_drive = 0; |
4281 | initialized = true; | 4323 | initialized = true; |
4282 | if (have_no_fdc) { | 4324 | if (have_no_fdc) { |
4283 | DPRINT("no floppy controllers found\n"); | 4325 | DPRINT("no floppy controllers found\n"); |
4284 | err = have_no_fdc; | 4326 | err = have_no_fdc; |
4285 | goto out_release_dma; | 4327 | goto out_flush_work; |
4286 | } | 4328 | } |
4287 | 4329 | ||
4288 | for (drive = 0; drive < N_DRIVE; drive++) { | 4330 | for (drive = 0; drive < N_DRIVE; drive++) { |
4289 | if (!floppy_available(drive)) | 4331 | if (!(allowed_drive_mask & (1 << drive))) |
4332 | continue; | ||
4333 | if (fdc_state[FDC(drive)].version == FDC_NONE) | ||
4290 | continue; | 4334 | continue; |
4291 | 4335 | ||
4292 | floppy_device[drive].name = floppy_device_name; | 4336 | floppy_device[drive].name = floppy_device_name; |
@@ -4295,7 +4339,7 @@ static int __init do_floppy_init(void) | |||
4295 | 4339 | ||
4296 | err = platform_device_register(&floppy_device[drive]); | 4340 | err = platform_device_register(&floppy_device[drive]); |
4297 | if (err) | 4341 | if (err) |
4298 | goto out_remove_drives; | 4342 | goto out_flush_work; |
4299 | 4343 | ||
4300 | err = device_create_file(&floppy_device[drive].dev, | 4344 | err = device_create_file(&floppy_device[drive].dev, |
4301 | &dev_attr_cmos); | 4345 | &dev_attr_cmos); |
@@ -4313,15 +4357,8 @@ static int __init do_floppy_init(void) | |||
4313 | 4357 | ||
4314 | out_unreg_platform_dev: | 4358 | out_unreg_platform_dev: |
4315 | platform_device_unregister(&floppy_device[drive]); | 4359 | platform_device_unregister(&floppy_device[drive]); |
4316 | out_remove_drives: | 4360 | out_flush_work: |
4317 | while (drive--) { | 4361 | flush_work_sync(&floppy_work); |
4318 | if (floppy_available(drive)) { | ||
4319 | del_gendisk(disks[drive]); | ||
4320 | device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); | ||
4321 | platform_device_unregister(&floppy_device[drive]); | ||
4322 | } | ||
4323 | } | ||
4324 | out_release_dma: | ||
4325 | if (atomic_read(&usage_count)) | 4362 | if (atomic_read(&usage_count)) |
4326 | floppy_release_irq_and_dma(); | 4363 | floppy_release_irq_and_dma(); |
4327 | out_unreg_region: | 4364 | out_unreg_region: |
@@ -4330,38 +4367,15 @@ out_unreg_region: | |||
4330 | out_unreg_blkdev: | 4367 | out_unreg_blkdev: |
4331 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 4368 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
4332 | out_put_disk: | 4369 | out_put_disk: |
4333 | destroy_workqueue(floppy_wq); | 4370 | while (dr--) { |
4334 | for (drive = 0; drive < N_DRIVE; drive++) { | 4371 | del_timer_sync(&motor_off_timer[dr]); |
4335 | if (!disks[drive]) | 4372 | if (disks[dr]->queue) |
4336 | break; | 4373 | blk_cleanup_queue(disks[dr]->queue); |
4337 | if (disks[drive]->queue) { | 4374 | put_disk(disks[dr]); |
4338 | del_timer_sync(&motor_off_timer[drive]); | ||
4339 | blk_cleanup_queue(disks[drive]->queue); | ||
4340 | disks[drive]->queue = NULL; | ||
4341 | } | ||
4342 | put_disk(disks[drive]); | ||
4343 | } | 4375 | } |
4344 | return err; | 4376 | return err; |
4345 | } | 4377 | } |
4346 | 4378 | ||
4347 | #ifndef MODULE | ||
4348 | static __init void floppy_async_init(void *data, async_cookie_t cookie) | ||
4349 | { | ||
4350 | do_floppy_init(); | ||
4351 | } | ||
4352 | #endif | ||
4353 | |||
4354 | static int __init floppy_init(void) | ||
4355 | { | ||
4356 | #ifdef MODULE | ||
4357 | return do_floppy_init(); | ||
4358 | #else | ||
4359 | /* Don't hold up the bootup by the floppy initialization */ | ||
4360 | async_schedule(floppy_async_init, NULL); | ||
4361 | return 0; | ||
4362 | #endif | ||
4363 | } | ||
4364 | |||
4365 | static const struct io_region { | 4379 | static const struct io_region { |
4366 | int offset; | 4380 | int offset; |
4367 | int size; | 4381 | int size; |
@@ -4414,7 +4428,7 @@ static int floppy_grab_irq_and_dma(void) | |||
4414 | * We might have scheduled a free_irq(), wait it to | 4428 | * We might have scheduled a free_irq(), wait it to |
4415 | * drain first: | 4429 | * drain first: |
4416 | */ | 4430 | */ |
4417 | flush_workqueue(floppy_wq); | 4431 | flush_work_sync(&floppy_work); |
4418 | 4432 | ||
4419 | if (fd_request_irq()) { | 4433 | if (fd_request_irq()) { |
4420 | DPRINT("Unable to grab IRQ%d for the floppy driver\n", | 4434 | DPRINT("Unable to grab IRQ%d for the floppy driver\n", |
@@ -4490,6 +4504,7 @@ static void floppy_release_irq_and_dma(void) | |||
4490 | #if N_FDC > 1 | 4504 | #if N_FDC > 1 |
4491 | set_dor(1, ~8, 0); | 4505 | set_dor(1, ~8, 0); |
4492 | #endif | 4506 | #endif |
4507 | floppy_enable_hlt(); | ||
4493 | 4508 | ||
4494 | if (floppy_track_buffer && max_buffer_sectors) { | 4509 | if (floppy_track_buffer && max_buffer_sectors) { |
4495 | tmpsize = max_buffer_sectors * 1024; | 4510 | tmpsize = max_buffer_sectors * 1024; |
@@ -4505,9 +4520,9 @@ static void floppy_release_irq_and_dma(void) | |||
4505 | pr_info("motor off timer %d still active\n", drive); | 4520 | pr_info("motor off timer %d still active\n", drive); |
4506 | #endif | 4521 | #endif |
4507 | 4522 | ||
4508 | if (delayed_work_pending(&fd_timeout)) | 4523 | if (timer_pending(&fd_timeout)) |
4509 | pr_info("floppy timer still active:%s\n", timeout_message); | 4524 | pr_info("floppy timer still active:%s\n", timeout_message); |
4510 | if (delayed_work_pending(&fd_timer)) | 4525 | if (timer_pending(&fd_timer)) |
4511 | pr_info("auxiliary floppy timer still active\n"); | 4526 | pr_info("auxiliary floppy timer still active\n"); |
4512 | if (work_pending(&floppy_work)) | 4527 | if (work_pending(&floppy_work)) |
4513 | pr_info("work still pending\n"); | 4528 | pr_info("work still pending\n"); |
@@ -4555,31 +4570,21 @@ static void __exit floppy_module_exit(void) | |||
4555 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 4570 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
4556 | platform_driver_unregister(&floppy_driver); | 4571 | platform_driver_unregister(&floppy_driver); |
4557 | 4572 | ||
4558 | destroy_workqueue(floppy_wq); | ||
4559 | |||
4560 | for (drive = 0; drive < N_DRIVE; drive++) { | 4573 | for (drive = 0; drive < N_DRIVE; drive++) { |
4561 | del_timer_sync(&motor_off_timer[drive]); | 4574 | del_timer_sync(&motor_off_timer[drive]); |
4562 | 4575 | ||
4563 | if (floppy_available(drive)) { | 4576 | if ((allowed_drive_mask & (1 << drive)) && |
4577 | fdc_state[FDC(drive)].version != FDC_NONE) { | ||
4564 | del_gendisk(disks[drive]); | 4578 | del_gendisk(disks[drive]); |
4565 | device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); | 4579 | device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); |
4566 | platform_device_unregister(&floppy_device[drive]); | 4580 | platform_device_unregister(&floppy_device[drive]); |
4567 | } | 4581 | } |
4568 | blk_cleanup_queue(disks[drive]->queue); | 4582 | blk_cleanup_queue(disks[drive]->queue); |
4569 | |||
4570 | /* | ||
4571 | * These disks have not called add_disk(). Don't put down | ||
4572 | * queue reference in put_disk(). | ||
4573 | */ | ||
4574 | if (!(allowed_drive_mask & (1 << drive)) || | ||
4575 | fdc_state[FDC(drive)].version == FDC_NONE) | ||
4576 | disks[drive]->queue = NULL; | ||
4577 | |||
4578 | put_disk(disks[drive]); | 4583 | put_disk(disks[drive]); |
4579 | } | 4584 | } |
4580 | 4585 | ||
4581 | cancel_delayed_work_sync(&fd_timeout); | 4586 | del_timer_sync(&fd_timeout); |
4582 | cancel_delayed_work_sync(&fd_timer); | 4587 | del_timer_sync(&fd_timer); |
4583 | 4588 | ||
4584 | if (atomic_read(&usage_count)) | 4589 | if (atomic_read(&usage_count)) |
4585 | floppy_release_irq_and_dma(); | 4590 | floppy_release_irq_and_dma(); |