diff options
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r-- | drivers/block/floppy.c | 182 |
1 files changed, 70 insertions, 112 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 90c4038702da..cf04c1b234ed 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -178,6 +178,7 @@ static int print_unex = 1; | |||
178 | #include <linux/slab.h> | 178 | #include <linux/slab.h> |
179 | #include <linux/mm.h> | 179 | #include <linux/mm.h> |
180 | #include <linux/bio.h> | 180 | #include <linux/bio.h> |
181 | #include <linux/smp_lock.h> | ||
181 | #include <linux/string.h> | 182 | #include <linux/string.h> |
182 | #include <linux/jiffies.h> | 183 | #include <linux/jiffies.h> |
183 | #include <linux/fcntl.h> | 184 | #include <linux/fcntl.h> |
@@ -514,8 +515,6 @@ static unsigned long fdc_busy; | |||
514 | static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); | 515 | static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); |
515 | static DECLARE_WAIT_QUEUE_HEAD(command_done); | 516 | static DECLARE_WAIT_QUEUE_HEAD(command_done); |
516 | 517 | ||
517 | #define NO_SIGNAL (!interruptible || !signal_pending(current)) | ||
518 | |||
519 | /* Errors during formatting are counted here. */ | 518 | /* Errors during formatting are counted here. */ |
520 | static int format_errors; | 519 | static int format_errors; |
521 | 520 | ||
@@ -539,7 +538,7 @@ static int max_buffer_sectors; | |||
539 | 538 | ||
540 | static int *errors; | 539 | static int *errors; |
541 | typedef void (*done_f)(int); | 540 | typedef void (*done_f)(int); |
542 | static struct cont_t { | 541 | static const struct cont_t { |
543 | void (*interrupt)(void); | 542 | void (*interrupt)(void); |
544 | /* this is called after the interrupt of the | 543 | /* this is called after the interrupt of the |
545 | * main command */ | 544 | * main command */ |
@@ -578,7 +577,7 @@ static void reset_fdc(void); | |||
578 | #define NEED_1_RECAL -2 | 577 | #define NEED_1_RECAL -2 |
579 | #define NEED_2_RECAL -3 | 578 | #define NEED_2_RECAL -3 |
580 | 579 | ||
581 | static int usage_count; | 580 | static atomic_t usage_count = ATOMIC_INIT(0); |
582 | 581 | ||
583 | /* buffer related variables */ | 582 | /* buffer related variables */ |
584 | static int buffer_track = -1; | 583 | static int buffer_track = -1; |
@@ -858,36 +857,15 @@ static void set_fdc(int drive) | |||
858 | } | 857 | } |
859 | 858 | ||
860 | /* locks the driver */ | 859 | /* locks the driver */ |
861 | static int _lock_fdc(int drive, bool interruptible, int line) | 860 | static int lock_fdc(int drive, bool interruptible) |
862 | { | 861 | { |
863 | if (!usage_count) { | 862 | if (WARN(atomic_read(&usage_count) == 0, |
864 | pr_err("Trying to lock fdc while usage count=0 at line %d\n", | 863 | "Trying to lock fdc while usage count=0\n")) |
865 | line); | ||
866 | return -1; | 864 | return -1; |
867 | } | ||
868 | |||
869 | if (test_and_set_bit(0, &fdc_busy)) { | ||
870 | DECLARE_WAITQUEUE(wait, current); | ||
871 | add_wait_queue(&fdc_wait, &wait); | ||
872 | |||
873 | for (;;) { | ||
874 | set_current_state(TASK_INTERRUPTIBLE); | ||
875 | |||
876 | if (!test_and_set_bit(0, &fdc_busy)) | ||
877 | break; | ||
878 | 865 | ||
879 | schedule(); | 866 | if (wait_event_interruptible(fdc_wait, !test_and_set_bit(0, &fdc_busy))) |
880 | 867 | return -EINTR; | |
881 | if (!NO_SIGNAL) { | ||
882 | remove_wait_queue(&fdc_wait, &wait); | ||
883 | return -EINTR; | ||
884 | } | ||
885 | } | ||
886 | 868 | ||
887 | set_current_state(TASK_RUNNING); | ||
888 | remove_wait_queue(&fdc_wait, &wait); | ||
889 | flush_scheduled_work(); | ||
890 | } | ||
891 | command_status = FD_COMMAND_NONE; | 869 | command_status = FD_COMMAND_NONE; |
892 | 870 | ||
893 | __reschedule_timeout(drive, "lock fdc"); | 871 | __reschedule_timeout(drive, "lock fdc"); |
@@ -895,11 +873,8 @@ static int _lock_fdc(int drive, bool interruptible, int line) | |||
895 | return 0; | 873 | return 0; |
896 | } | 874 | } |
897 | 875 | ||
898 | #define lock_fdc(drive, interruptible) \ | ||
899 | _lock_fdc(drive, interruptible, __LINE__) | ||
900 | |||
901 | /* unlocks the driver */ | 876 | /* unlocks the driver */ |
902 | static inline void unlock_fdc(void) | 877 | static void unlock_fdc(void) |
903 | { | 878 | { |
904 | unsigned long flags; | 879 | unsigned long flags; |
905 | 880 | ||
@@ -1224,7 +1199,7 @@ static int need_more_output(void) | |||
1224 | /* Set perpendicular mode as required, based on data rate, if supported. | 1199 | /* Set perpendicular mode as required, based on data rate, if supported. |
1225 | * 82077 Now tested. 1Mbps data rate only possible with 82077-1. | 1200 | * 82077 Now tested. 1Mbps data rate only possible with 82077-1. |
1226 | */ | 1201 | */ |
1227 | static inline void perpendicular_mode(void) | 1202 | static void perpendicular_mode(void) |
1228 | { | 1203 | { |
1229 | unsigned char perp_mode; | 1204 | unsigned char perp_mode; |
1230 | 1205 | ||
@@ -1995,14 +1970,14 @@ static void do_wakeup(void) | |||
1995 | wake_up(&command_done); | 1970 | wake_up(&command_done); |
1996 | } | 1971 | } |
1997 | 1972 | ||
1998 | static struct cont_t wakeup_cont = { | 1973 | static const struct cont_t wakeup_cont = { |
1999 | .interrupt = empty, | 1974 | .interrupt = empty, |
2000 | .redo = do_wakeup, | 1975 | .redo = do_wakeup, |
2001 | .error = empty, | 1976 | .error = empty, |
2002 | .done = (done_f)empty | 1977 | .done = (done_f)empty |
2003 | }; | 1978 | }; |
2004 | 1979 | ||
2005 | static struct cont_t intr_cont = { | 1980 | static const struct cont_t intr_cont = { |
2006 | .interrupt = empty, | 1981 | .interrupt = empty, |
2007 | .redo = process_fd_request, | 1982 | .redo = process_fd_request, |
2008 | .error = empty, | 1983 | .error = empty, |
@@ -2015,25 +1990,10 @@ static int wait_til_done(void (*handler)(void), bool interruptible) | |||
2015 | 1990 | ||
2016 | schedule_bh(handler); | 1991 | schedule_bh(handler); |
2017 | 1992 | ||
2018 | if (command_status < 2 && NO_SIGNAL) { | 1993 | if (interruptible) |
2019 | DECLARE_WAITQUEUE(wait, current); | 1994 | wait_event_interruptible(command_done, command_status >= 2); |
2020 | 1995 | else | |
2021 | add_wait_queue(&command_done, &wait); | 1996 | wait_event(command_done, command_status >= 2); |
2022 | for (;;) { | ||
2023 | set_current_state(interruptible ? | ||
2024 | TASK_INTERRUPTIBLE : | ||
2025 | TASK_UNINTERRUPTIBLE); | ||
2026 | |||
2027 | if (command_status >= 2 || !NO_SIGNAL) | ||
2028 | break; | ||
2029 | |||
2030 | is_alive(__func__, ""); | ||
2031 | schedule(); | ||
2032 | } | ||
2033 | |||
2034 | set_current_state(TASK_RUNNING); | ||
2035 | remove_wait_queue(&command_done, &wait); | ||
2036 | } | ||
2037 | 1997 | ||
2038 | if (command_status < 2) { | 1998 | if (command_status < 2) { |
2039 | cancel_activity(); | 1999 | cancel_activity(); |
@@ -2223,7 +2183,7 @@ static void redo_format(void) | |||
2223 | debugt(__func__, "queue format request"); | 2183 | debugt(__func__, "queue format request"); |
2224 | } | 2184 | } |
2225 | 2185 | ||
2226 | static struct cont_t format_cont = { | 2186 | static const struct cont_t format_cont = { |
2227 | .interrupt = format_interrupt, | 2187 | .interrupt = format_interrupt, |
2228 | .redo = redo_format, | 2188 | .redo = redo_format, |
2229 | .error = bad_flp_intr, | 2189 | .error = bad_flp_intr, |
@@ -2583,10 +2543,8 @@ static int make_raw_rw_request(void) | |||
2583 | int tracksize; | 2543 | int tracksize; |
2584 | int ssize; | 2544 | int ssize; |
2585 | 2545 | ||
2586 | if (max_buffer_sectors == 0) { | 2546 | if (WARN(max_buffer_sectors == 0, "VFS: Block I/O scheduled on unopened device\n")) |
2587 | pr_info("VFS: Block I/O scheduled on unopened device\n"); | ||
2588 | return 0; | 2547 | return 0; |
2589 | } | ||
2590 | 2548 | ||
2591 | set_fdc((long)current_req->rq_disk->private_data); | 2549 | set_fdc((long)current_req->rq_disk->private_data); |
2592 | 2550 | ||
@@ -2921,7 +2879,7 @@ do_request: | |||
2921 | return; | 2879 | return; |
2922 | } | 2880 | } |
2923 | 2881 | ||
2924 | static struct cont_t rw_cont = { | 2882 | static const struct cont_t rw_cont = { |
2925 | .interrupt = rw_interrupt, | 2883 | .interrupt = rw_interrupt, |
2926 | .redo = redo_fd_request, | 2884 | .redo = redo_fd_request, |
2927 | .error = bad_flp_intr, | 2885 | .error = bad_flp_intr, |
@@ -2936,19 +2894,16 @@ static void process_fd_request(void) | |||
2936 | 2894 | ||
2937 | static void do_fd_request(struct request_queue *q) | 2895 | static void do_fd_request(struct request_queue *q) |
2938 | { | 2896 | { |
2939 | if (max_buffer_sectors == 0) { | 2897 | if (WARN(max_buffer_sectors == 0, |
2940 | pr_info("VFS: %s called on non-open device\n", __func__); | 2898 | "VFS: %s called on non-open device\n", __func__)) |
2941 | return; | 2899 | return; |
2942 | } | ||
2943 | 2900 | ||
2944 | if (usage_count == 0) { | 2901 | if (WARN(atomic_read(&usage_count) == 0, |
2945 | pr_info("warning: usage count=0, current_req=%p exiting\n", | 2902 | "warning: usage count=0, current_req=%p sect=%ld type=%x flags=%x\n", |
2946 | current_req); | 2903 | current_req, (long)blk_rq_pos(current_req), current_req->cmd_type, |
2947 | pr_info("sect=%ld type=%x flags=%x\n", | 2904 | current_req->cmd_flags)) |
2948 | (long)blk_rq_pos(current_req), current_req->cmd_type, | ||
2949 | current_req->cmd_flags); | ||
2950 | return; | 2905 | return; |
2951 | } | 2906 | |
2952 | if (test_bit(0, &fdc_busy)) { | 2907 | if (test_bit(0, &fdc_busy)) { |
2953 | /* fdc busy, this new request will be treated when the | 2908 | /* fdc busy, this new request will be treated when the |
2954 | current one is done */ | 2909 | current one is done */ |
@@ -2960,7 +2915,7 @@ static void do_fd_request(struct request_queue *q) | |||
2960 | is_alive(__func__, ""); | 2915 | is_alive(__func__, ""); |
2961 | } | 2916 | } |
2962 | 2917 | ||
2963 | static struct cont_t poll_cont = { | 2918 | static const struct cont_t poll_cont = { |
2964 | .interrupt = success_and_wakeup, | 2919 | .interrupt = success_and_wakeup, |
2965 | .redo = floppy_ready, | 2920 | .redo = floppy_ready, |
2966 | .error = generic_failure, | 2921 | .error = generic_failure, |
@@ -2991,7 +2946,7 @@ static void reset_intr(void) | |||
2991 | pr_info("weird, reset interrupt called\n"); | 2946 | pr_info("weird, reset interrupt called\n"); |
2992 | } | 2947 | } |
2993 | 2948 | ||
2994 | static struct cont_t reset_cont = { | 2949 | static const struct cont_t reset_cont = { |
2995 | .interrupt = reset_intr, | 2950 | .interrupt = reset_intr, |
2996 | .redo = success_and_wakeup, | 2951 | .redo = success_and_wakeup, |
2997 | .error = generic_failure, | 2952 | .error = generic_failure, |
@@ -3033,7 +2988,7 @@ static inline int fd_copyin(void __user *param, void *address, | |||
3033 | return copy_from_user(address, param, size) ? -EFAULT : 0; | 2988 | return copy_from_user(address, param, size) ? -EFAULT : 0; |
3034 | } | 2989 | } |
3035 | 2990 | ||
3036 | static inline const char *drive_name(int type, int drive) | 2991 | static const char *drive_name(int type, int drive) |
3037 | { | 2992 | { |
3038 | struct floppy_struct *floppy; | 2993 | struct floppy_struct *floppy; |
3039 | 2994 | ||
@@ -3096,14 +3051,14 @@ static void raw_cmd_done(int flag) | |||
3096 | generic_done(flag); | 3051 | generic_done(flag); |
3097 | } | 3052 | } |
3098 | 3053 | ||
3099 | static struct cont_t raw_cmd_cont = { | 3054 | static const struct cont_t raw_cmd_cont = { |
3100 | .interrupt = success_and_wakeup, | 3055 | .interrupt = success_and_wakeup, |
3101 | .redo = floppy_start, | 3056 | .redo = floppy_start, |
3102 | .error = generic_failure, | 3057 | .error = generic_failure, |
3103 | .done = raw_cmd_done | 3058 | .done = raw_cmd_done |
3104 | }; | 3059 | }; |
3105 | 3060 | ||
3106 | static inline int raw_cmd_copyout(int cmd, void __user *param, | 3061 | static int raw_cmd_copyout(int cmd, void __user *param, |
3107 | struct floppy_raw_cmd *ptr) | 3062 | struct floppy_raw_cmd *ptr) |
3108 | { | 3063 | { |
3109 | int ret; | 3064 | int ret; |
@@ -3148,7 +3103,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr) | |||
3148 | } | 3103 | } |
3149 | } | 3104 | } |
3150 | 3105 | ||
3151 | static inline int raw_cmd_copyin(int cmd, void __user *param, | 3106 | static int raw_cmd_copyin(int cmd, void __user *param, |
3152 | struct floppy_raw_cmd **rcmd) | 3107 | struct floppy_raw_cmd **rcmd) |
3153 | { | 3108 | { |
3154 | struct floppy_raw_cmd *ptr; | 3109 | struct floppy_raw_cmd *ptr; |
@@ -3266,7 +3221,7 @@ static int invalidate_drive(struct block_device *bdev) | |||
3266 | return 0; | 3221 | return 0; |
3267 | } | 3222 | } |
3268 | 3223 | ||
3269 | static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | 3224 | static int set_geometry(unsigned int cmd, struct floppy_struct *g, |
3270 | int drive, int type, struct block_device *bdev) | 3225 | int drive, int type, struct block_device *bdev) |
3271 | { | 3226 | { |
3272 | int cnt; | 3227 | int cnt; |
@@ -3337,7 +3292,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
3337 | } | 3292 | } |
3338 | 3293 | ||
3339 | /* handle obsolete ioctl's */ | 3294 | /* handle obsolete ioctl's */ |
3340 | static int ioctl_table[] = { | 3295 | static unsigned int ioctl_table[] = { |
3341 | FDCLRPRM, | 3296 | FDCLRPRM, |
3342 | FDSETPRM, | 3297 | FDSETPRM, |
3343 | FDDEFPRM, | 3298 | FDDEFPRM, |
@@ -3365,7 +3320,7 @@ static int ioctl_table[] = { | |||
3365 | FDTWADDLE | 3320 | FDTWADDLE |
3366 | }; | 3321 | }; |
3367 | 3322 | ||
3368 | static inline int normalize_ioctl(int *cmd, int *size) | 3323 | static int normalize_ioctl(unsigned int *cmd, int *size) |
3369 | { | 3324 | { |
3370 | int i; | 3325 | int i; |
3371 | 3326 | ||
@@ -3417,7 +3372,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
3417 | return 0; | 3372 | return 0; |
3418 | } | 3373 | } |
3419 | 3374 | ||
3420 | static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | 3375 | static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, |
3421 | unsigned long param) | 3376 | unsigned long param) |
3422 | { | 3377 | { |
3423 | int drive = (long)bdev->bd_disk->private_data; | 3378 | int drive = (long)bdev->bd_disk->private_data; |
@@ -3593,6 +3548,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | |||
3593 | return 0; | 3548 | return 0; |
3594 | } | 3549 | } |
3595 | 3550 | ||
3551 | static int fd_ioctl(struct block_device *bdev, fmode_t mode, | ||
3552 | unsigned int cmd, unsigned long param) | ||
3553 | { | ||
3554 | int ret; | ||
3555 | |||
3556 | lock_kernel(); | ||
3557 | ret = fd_locked_ioctl(bdev, mode, cmd, param); | ||
3558 | unlock_kernel(); | ||
3559 | |||
3560 | return ret; | ||
3561 | } | ||
3562 | |||
3596 | static void __init config_types(void) | 3563 | static void __init config_types(void) |
3597 | { | 3564 | { |
3598 | bool has_drive = false; | 3565 | bool has_drive = false; |
@@ -3649,6 +3616,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) | |||
3649 | { | 3616 | { |
3650 | int drive = (long)disk->private_data; | 3617 | int drive = (long)disk->private_data; |
3651 | 3618 | ||
3619 | lock_kernel(); | ||
3652 | mutex_lock(&open_lock); | 3620 | mutex_lock(&open_lock); |
3653 | if (UDRS->fd_ref < 0) | 3621 | if (UDRS->fd_ref < 0) |
3654 | UDRS->fd_ref = 0; | 3622 | UDRS->fd_ref = 0; |
@@ -3659,6 +3627,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) | |||
3659 | if (!UDRS->fd_ref) | 3627 | if (!UDRS->fd_ref) |
3660 | opened_bdev[drive] = NULL; | 3628 | opened_bdev[drive] = NULL; |
3661 | mutex_unlock(&open_lock); | 3629 | mutex_unlock(&open_lock); |
3630 | unlock_kernel(); | ||
3662 | 3631 | ||
3663 | return 0; | 3632 | return 0; |
3664 | } | 3633 | } |
@@ -3676,6 +3645,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3676 | int res = -EBUSY; | 3645 | int res = -EBUSY; |
3677 | char *tmp; | 3646 | char *tmp; |
3678 | 3647 | ||
3648 | lock_kernel(); | ||
3679 | mutex_lock(&open_lock); | 3649 | mutex_lock(&open_lock); |
3680 | old_dev = UDRS->fd_device; | 3650 | old_dev = UDRS->fd_device; |
3681 | if (opened_bdev[drive] && opened_bdev[drive] != bdev) | 3651 | if (opened_bdev[drive] && opened_bdev[drive] != bdev) |
@@ -3752,6 +3722,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3752 | goto out; | 3722 | goto out; |
3753 | } | 3723 | } |
3754 | mutex_unlock(&open_lock); | 3724 | mutex_unlock(&open_lock); |
3725 | unlock_kernel(); | ||
3755 | return 0; | 3726 | return 0; |
3756 | out: | 3727 | out: |
3757 | if (UDRS->fd_ref < 0) | 3728 | if (UDRS->fd_ref < 0) |
@@ -3762,6 +3733,7 @@ out: | |||
3762 | opened_bdev[drive] = NULL; | 3733 | opened_bdev[drive] = NULL; |
3763 | out2: | 3734 | out2: |
3764 | mutex_unlock(&open_lock); | 3735 | mutex_unlock(&open_lock); |
3736 | unlock_kernel(); | ||
3765 | return res; | 3737 | return res; |
3766 | } | 3738 | } |
3767 | 3739 | ||
@@ -3829,6 +3801,7 @@ static int __floppy_read_block_0(struct block_device *bdev) | |||
3829 | bio.bi_size = size; | 3801 | bio.bi_size = size; |
3830 | bio.bi_bdev = bdev; | 3802 | bio.bi_bdev = bdev; |
3831 | bio.bi_sector = 0; | 3803 | bio.bi_sector = 0; |
3804 | bio.bi_flags = BIO_QUIET; | ||
3832 | init_completion(&complete); | 3805 | init_completion(&complete); |
3833 | bio.bi_private = &complete; | 3806 | bio.bi_private = &complete; |
3834 | bio.bi_end_io = floppy_rb0_complete; | 3807 | bio.bi_end_io = floppy_rb0_complete; |
@@ -3857,10 +3830,10 @@ static int floppy_revalidate(struct gendisk *disk) | |||
3857 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || | 3830 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || |
3858 | test_bit(FD_VERIFY_BIT, &UDRS->flags) || | 3831 | test_bit(FD_VERIFY_BIT, &UDRS->flags) || |
3859 | test_bit(drive, &fake_change) || NO_GEOM) { | 3832 | test_bit(drive, &fake_change) || NO_GEOM) { |
3860 | if (usage_count == 0) { | 3833 | if (WARN(atomic_read(&usage_count) == 0, |
3861 | pr_info("VFS: revalidate called on non-open device.\n"); | 3834 | "VFS: revalidate called on non-open device.\n")) |
3862 | return -EFAULT; | 3835 | return -EFAULT; |
3863 | } | 3836 | |
3864 | lock_fdc(drive, false); | 3837 | lock_fdc(drive, false); |
3865 | cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || | 3838 | cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || |
3866 | test_bit(FD_VERIFY_BIT, &UDRS->flags)); | 3839 | test_bit(FD_VERIFY_BIT, &UDRS->flags)); |
@@ -3893,7 +3866,7 @@ static const struct block_device_operations floppy_fops = { | |||
3893 | .owner = THIS_MODULE, | 3866 | .owner = THIS_MODULE, |
3894 | .open = floppy_open, | 3867 | .open = floppy_open, |
3895 | .release = floppy_release, | 3868 | .release = floppy_release, |
3896 | .locked_ioctl = fd_ioctl, | 3869 | .ioctl = fd_ioctl, |
3897 | .getgeo = fd_getgeo, | 3870 | .getgeo = fd_getgeo, |
3898 | .media_changed = check_floppy_change, | 3871 | .media_changed = check_floppy_change, |
3899 | .revalidate_disk = floppy_revalidate, | 3872 | .revalidate_disk = floppy_revalidate, |
@@ -4126,7 +4099,7 @@ static ssize_t floppy_cmos_show(struct device *dev, | |||
4126 | return sprintf(buf, "%X\n", UDP->cmos); | 4099 | return sprintf(buf, "%X\n", UDP->cmos); |
4127 | } | 4100 | } |
4128 | 4101 | ||
4129 | DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL); | 4102 | static DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL); |
4130 | 4103 | ||
4131 | static void floppy_device_release(struct device *dev) | 4104 | static void floppy_device_release(struct device *dev) |
4132 | { | 4105 | { |
@@ -4175,6 +4148,9 @@ static int __init floppy_init(void) | |||
4175 | int i, unit, drive; | 4148 | int i, unit, drive; |
4176 | int err, dr; | 4149 | int err, dr; |
4177 | 4150 | ||
4151 | set_debugt(); | ||
4152 | interruptjiffies = resultjiffies = jiffies; | ||
4153 | |||
4178 | #if defined(CONFIG_PPC) | 4154 | #if defined(CONFIG_PPC) |
4179 | if (check_legacy_ioport(FDC1)) | 4155 | if (check_legacy_ioport(FDC1)) |
4180 | return -ENODEV; | 4156 | return -ENODEV; |
@@ -4353,7 +4329,7 @@ out_unreg_platform_dev: | |||
4353 | platform_device_unregister(&floppy_device[drive]); | 4329 | platform_device_unregister(&floppy_device[drive]); |
4354 | out_flush_work: | 4330 | out_flush_work: |
4355 | flush_scheduled_work(); | 4331 | flush_scheduled_work(); |
4356 | if (usage_count) | 4332 | if (atomic_read(&usage_count)) |
4357 | floppy_release_irq_and_dma(); | 4333 | floppy_release_irq_and_dma(); |
4358 | out_unreg_region: | 4334 | out_unreg_region: |
4359 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); | 4335 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); |
@@ -4370,8 +4346,6 @@ out_put_disk: | |||
4370 | return err; | 4346 | return err; |
4371 | } | 4347 | } |
4372 | 4348 | ||
4373 | static DEFINE_SPINLOCK(floppy_usage_lock); | ||
4374 | |||
4375 | static const struct io_region { | 4349 | static const struct io_region { |
4376 | int offset; | 4350 | int offset; |
4377 | int size; | 4351 | int size; |
@@ -4417,14 +4391,8 @@ static void floppy_release_regions(int fdc) | |||
4417 | 4391 | ||
4418 | static int floppy_grab_irq_and_dma(void) | 4392 | static int floppy_grab_irq_and_dma(void) |
4419 | { | 4393 | { |
4420 | unsigned long flags; | 4394 | if (atomic_inc_return(&usage_count) > 1) |
4421 | |||
4422 | spin_lock_irqsave(&floppy_usage_lock, flags); | ||
4423 | if (usage_count++) { | ||
4424 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4425 | return 0; | 4395 | return 0; |
4426 | } | ||
4427 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4428 | 4396 | ||
4429 | /* | 4397 | /* |
4430 | * We might have scheduled a free_irq(), wait it to | 4398 | * We might have scheduled a free_irq(), wait it to |
@@ -4435,9 +4403,7 @@ static int floppy_grab_irq_and_dma(void) | |||
4435 | if (fd_request_irq()) { | 4403 | if (fd_request_irq()) { |
4436 | DPRINT("Unable to grab IRQ%d for the floppy driver\n", | 4404 | DPRINT("Unable to grab IRQ%d for the floppy driver\n", |
4437 | FLOPPY_IRQ); | 4405 | FLOPPY_IRQ); |
4438 | spin_lock_irqsave(&floppy_usage_lock, flags); | 4406 | atomic_dec(&usage_count); |
4439 | usage_count--; | ||
4440 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4441 | return -1; | 4407 | return -1; |
4442 | } | 4408 | } |
4443 | if (fd_request_dma()) { | 4409 | if (fd_request_dma()) { |
@@ -4447,9 +4413,7 @@ static int floppy_grab_irq_and_dma(void) | |||
4447 | use_virtual_dma = can_use_virtual_dma = 1; | 4413 | use_virtual_dma = can_use_virtual_dma = 1; |
4448 | if (!(can_use_virtual_dma & 1)) { | 4414 | if (!(can_use_virtual_dma & 1)) { |
4449 | fd_free_irq(); | 4415 | fd_free_irq(); |
4450 | spin_lock_irqsave(&floppy_usage_lock, flags); | 4416 | atomic_dec(&usage_count); |
4451 | usage_count--; | ||
4452 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4453 | return -1; | 4417 | return -1; |
4454 | } | 4418 | } |
4455 | } | 4419 | } |
@@ -4484,9 +4448,7 @@ cleanup: | |||
4484 | fd_free_dma(); | 4448 | fd_free_dma(); |
4485 | while (--fdc >= 0) | 4449 | while (--fdc >= 0) |
4486 | floppy_release_regions(fdc); | 4450 | floppy_release_regions(fdc); |
4487 | spin_lock_irqsave(&floppy_usage_lock, flags); | 4451 | atomic_dec(&usage_count); |
4488 | usage_count--; | ||
4489 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4490 | return -1; | 4452 | return -1; |
4491 | } | 4453 | } |
4492 | 4454 | ||
@@ -4498,14 +4460,10 @@ static void floppy_release_irq_and_dma(void) | |||
4498 | #endif | 4460 | #endif |
4499 | long tmpsize; | 4461 | long tmpsize; |
4500 | unsigned long tmpaddr; | 4462 | unsigned long tmpaddr; |
4501 | unsigned long flags; | ||
4502 | 4463 | ||
4503 | spin_lock_irqsave(&floppy_usage_lock, flags); | 4464 | if (!atomic_dec_and_test(&usage_count)) |
4504 | if (--usage_count) { | ||
4505 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4506 | return; | 4465 | return; |
4507 | } | 4466 | |
4508 | spin_unlock_irqrestore(&floppy_usage_lock, flags); | ||
4509 | if (irqdma_allocated) { | 4467 | if (irqdma_allocated) { |
4510 | fd_disable_dma(); | 4468 | fd_disable_dma(); |
4511 | fd_free_dma(); | 4469 | fd_free_dma(); |
@@ -4598,7 +4556,7 @@ static void __exit floppy_module_exit(void) | |||
4598 | del_timer_sync(&fd_timer); | 4556 | del_timer_sync(&fd_timer); |
4599 | blk_cleanup_queue(floppy_queue); | 4557 | blk_cleanup_queue(floppy_queue); |
4600 | 4558 | ||
4601 | if (usage_count) | 4559 | if (atomic_read(&usage_count)) |
4602 | floppy_release_irq_and_dma(); | 4560 | floppy_release_irq_and_dma(); |
4603 | 4561 | ||
4604 | /* eject disk, if any */ | 4562 | /* eject disk, if any */ |