]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/block/floppy.c
block: autoconvert trivial BKL users to private mutex
[net-next-2.6.git] / drivers / block / floppy.c
index 90c4038702da3606e796bc3dea012ee37eb7bcc4..3b57459bb745d962402e27d1c8107b26eb0154a2 100644 (file)
@@ -198,6 +198,7 @@ static int print_unex = 1;
  * It's been recommended that take about 1/4 of the default speed
  * in some more extreme cases.
  */
+static DEFINE_MUTEX(floppy_mutex);
 static int slow_floppy;
 
 #include <asm/dma.h>
@@ -514,8 +515,6 @@ static unsigned long fdc_busy;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-#define NO_SIGNAL (!interruptible || !signal_pending(current))
-
 /* Errors during formatting are counted here. */
 static int format_errors;
 
@@ -539,7 +538,7 @@ static int max_buffer_sectors;
 
 static int *errors;
 typedef void (*done_f)(int);
-static struct cont_t {
+static const struct cont_t {
        void (*interrupt)(void);
                                /* this is called after the interrupt of the
                                 * main command */
@@ -578,7 +577,7 @@ static void reset_fdc(void);
 #define NEED_1_RECAL   -2
 #define NEED_2_RECAL   -3
 
-static int usage_count;
+static atomic_t usage_count = ATOMIC_INIT(0);
 
 /* buffer related variables */
 static int buffer_track = -1;
@@ -858,36 +857,15 @@ static void set_fdc(int drive)
 }
 
 /* locks the driver */
-static int _lock_fdc(int drive, bool interruptible, int line)
+static int lock_fdc(int drive, bool interruptible)
 {
-       if (!usage_count) {
-               pr_err("Trying to lock fdc while usage count=0 at line %d\n",
-                      line);
+       if (WARN(atomic_read(&usage_count) == 0,
+                "Trying to lock fdc while usage count=0\n"))
                return -1;
-       }
-
-       if (test_and_set_bit(0, &fdc_busy)) {
-               DECLARE_WAITQUEUE(wait, current);
-               add_wait_queue(&fdc_wait, &wait);
-
-               for (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       if (!test_and_set_bit(0, &fdc_busy))
-                               break;
 
-                       schedule();
-
-                       if (!NO_SIGNAL) {
-                               remove_wait_queue(&fdc_wait, &wait);
-                               return -EINTR;
-                       }
-               }
+       if (wait_event_interruptible(fdc_wait, !test_and_set_bit(0, &fdc_busy)))
+               return -EINTR;
 
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&fdc_wait, &wait);
-               flush_scheduled_work();
-       }
        command_status = FD_COMMAND_NONE;
 
        __reschedule_timeout(drive, "lock fdc");
@@ -895,11 +873,8 @@ static int _lock_fdc(int drive, bool interruptible, int line)
        return 0;
 }
 
-#define lock_fdc(drive, interruptible)                 \
-       _lock_fdc(drive, interruptible, __LINE__)
-
 /* unlocks the driver */
-static inline void unlock_fdc(void)
+static void unlock_fdc(void)
 {
        unsigned long flags;
 
@@ -1224,7 +1199,7 @@ static int need_more_output(void)
 /* Set perpendicular mode as required, based on data rate, if supported.
  * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
  */
-static inline void perpendicular_mode(void)
+static void perpendicular_mode(void)
 {
        unsigned char perp_mode;
 
@@ -1995,14 +1970,14 @@ static void do_wakeup(void)
        wake_up(&command_done);
 }
 
-static struct cont_t wakeup_cont = {
+static const struct cont_t wakeup_cont = {
        .interrupt      = empty,
        .redo           = do_wakeup,
        .error          = empty,
        .done           = (done_f)empty
 };
 
-static struct cont_t intr_cont = {
+static const struct cont_t intr_cont = {
        .interrupt      = empty,
        .redo           = process_fd_request,
        .error          = empty,
@@ -2015,25 +1990,10 @@ static int wait_til_done(void (*handler)(void), bool interruptible)
 
        schedule_bh(handler);
 
-       if (command_status < 2 && NO_SIGNAL) {
-               DECLARE_WAITQUEUE(wait, current);
-
-               add_wait_queue(&command_done, &wait);
-               for (;;) {
-                       set_current_state(interruptible ?
-                                         TASK_INTERRUPTIBLE :
-                                         TASK_UNINTERRUPTIBLE);
-
-                       if (command_status >= 2 || !NO_SIGNAL)
-                               break;
-
-                       is_alive(__func__, "");
-                       schedule();
-               }
-
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&command_done, &wait);
-       }
+       if (interruptible)
+               wait_event_interruptible(command_done, command_status >= 2);
+       else
+               wait_event(command_done, command_status >= 2);
 
        if (command_status < 2) {
                cancel_activity();
@@ -2223,7 +2183,7 @@ static void redo_format(void)
        debugt(__func__, "queue format request");
 }
 
-static struct cont_t format_cont = {
+static const struct cont_t format_cont = {
        .interrupt      = format_interrupt,
        .redo           = redo_format,
        .error          = bad_flp_intr,
@@ -2583,10 +2543,8 @@ static int make_raw_rw_request(void)
        int tracksize;
        int ssize;
 
-       if (max_buffer_sectors == 0) {
-               pr_info("VFS: Block I/O scheduled on unopened device\n");
+       if (WARN(max_buffer_sectors == 0, "VFS: Block I/O scheduled on unopened device\n"))
                return 0;
-       }
 
        set_fdc((long)current_req->rq_disk->private_data);
 
@@ -2921,7 +2879,7 @@ do_request:
        return;
 }
 
-static struct cont_t rw_cont = {
+static const struct cont_t rw_cont = {
        .interrupt      = rw_interrupt,
        .redo           = redo_fd_request,
        .error          = bad_flp_intr,
@@ -2936,19 +2894,16 @@ static void process_fd_request(void)
 
 static void do_fd_request(struct request_queue *q)
 {
-       if (max_buffer_sectors == 0) {
-               pr_info("VFS: %s called on non-open device\n", __func__);
+       if (WARN(max_buffer_sectors == 0,
+                "VFS: %s called on non-open device\n", __func__))
                return;
-       }
 
-       if (usage_count == 0) {
-               pr_info("warning: usage count=0, current_req=%p exiting\n",
-                       current_req);
-               pr_info("sect=%ld type=%x flags=%x\n",
-                       (long)blk_rq_pos(current_req), current_req->cmd_type,
-                       current_req->cmd_flags);
+       if (WARN(atomic_read(&usage_count) == 0,
+                "warning: usage count=0, current_req=%p sect=%ld type=%x flags=%x\n",
+                current_req, (long)blk_rq_pos(current_req), current_req->cmd_type,
+                current_req->cmd_flags))
                return;
-       }
+
        if (test_bit(0, &fdc_busy)) {
                /* fdc busy, this new request will be treated when the
                   current one is done */
@@ -2960,7 +2915,7 @@ static void do_fd_request(struct request_queue *q)
        is_alive(__func__, "");
 }
 
-static struct cont_t poll_cont = {
+static const struct cont_t poll_cont = {
        .interrupt      = success_and_wakeup,
        .redo           = floppy_ready,
        .error          = generic_failure,
@@ -2991,7 +2946,7 @@ static void reset_intr(void)
        pr_info("weird, reset interrupt called\n");
 }
 
-static struct cont_t reset_cont = {
+static const struct cont_t reset_cont = {
        .interrupt      = reset_intr,
        .redo           = success_and_wakeup,
        .error          = generic_failure,
@@ -3033,7 +2988,7 @@ static inline int fd_copyin(void __user *param, void *address,
        return copy_from_user(address, param, size) ? -EFAULT : 0;
 }
 
-static inline const char *drive_name(int type, int drive)
+static const char *drive_name(int type, int drive)
 {
        struct floppy_struct *floppy;
 
@@ -3096,14 +3051,14 @@ static void raw_cmd_done(int flag)
        generic_done(flag);
 }
 
-static struct cont_t raw_cmd_cont = {
+static const struct cont_t raw_cmd_cont = {
        .interrupt      = success_and_wakeup,
        .redo           = floppy_start,
        .error          = generic_failure,
        .done           = raw_cmd_done
 };
 
-static inline int raw_cmd_copyout(int cmd, void __user *param,
+static int raw_cmd_copyout(int cmd, void __user *param,
                                  struct floppy_raw_cmd *ptr)
 {
        int ret;
@@ -3148,7 +3103,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr)
        }
 }
 
-static inline int raw_cmd_copyin(int cmd, void __user *param,
+static int raw_cmd_copyin(int cmd, void __user *param,
                                 struct floppy_raw_cmd **rcmd)
 {
        struct floppy_raw_cmd *ptr;
@@ -3266,7 +3221,7 @@ static int invalidate_drive(struct block_device *bdev)
        return 0;
 }
 
-static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
+static int set_geometry(unsigned int cmd, struct floppy_struct *g,
                               int drive, int type, struct block_device *bdev)
 {
        int cnt;
@@ -3337,7 +3292,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
 }
 
 /* handle obsolete ioctl's */
-static int ioctl_table[] = {
+static unsigned int ioctl_table[] = {
        FDCLRPRM,
        FDSETPRM,
        FDDEFPRM,
@@ -3365,7 +3320,7 @@ static int ioctl_table[] = {
        FDTWADDLE
 };
 
-static inline int normalize_ioctl(int *cmd, int *size)
+static int normalize_ioctl(unsigned int *cmd, int *size)
 {
        int i;
 
@@ -3417,7 +3372,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
 }
 
-static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
+static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                    unsigned long param)
 {
        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,
        return 0;
 }
 
+static int fd_ioctl(struct block_device *bdev, fmode_t mode,
+                            unsigned int cmd, unsigned long param)
+{
+       int ret;
+
+       mutex_lock(&floppy_mutex);
+       ret = fd_locked_ioctl(bdev, mode, cmd, param);
+       mutex_unlock(&floppy_mutex);
+
+       return ret;
+}
+
 static void __init config_types(void)
 {
        bool has_drive = false;
@@ -3649,6 +3616,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
        int drive = (long)disk->private_data;
 
+       mutex_lock(&floppy_mutex);
        mutex_lock(&open_lock);
        if (UDRS->fd_ref < 0)
                UDRS->fd_ref = 0;
@@ -3659,6 +3627,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
        if (!UDRS->fd_ref)
                opened_bdev[drive] = NULL;
        mutex_unlock(&open_lock);
+       mutex_unlock(&floppy_mutex);
 
        return 0;
 }
@@ -3676,6 +3645,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
        int res = -EBUSY;
        char *tmp;
 
+       mutex_lock(&floppy_mutex);
        mutex_lock(&open_lock);
        old_dev = UDRS->fd_device;
        if (opened_bdev[drive] && opened_bdev[drive] != bdev)
@@ -3752,6 +3722,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
                        goto out;
        }
        mutex_unlock(&open_lock);
+       mutex_unlock(&floppy_mutex);
        return 0;
 out:
        if (UDRS->fd_ref < 0)
@@ -3762,6 +3733,7 @@ out:
                opened_bdev[drive] = NULL;
 out2:
        mutex_unlock(&open_lock);
+       mutex_unlock(&floppy_mutex);
        return res;
 }
 
@@ -3829,6 +3801,7 @@ static int __floppy_read_block_0(struct block_device *bdev)
        bio.bi_size = size;
        bio.bi_bdev = bdev;
        bio.bi_sector = 0;
+       bio.bi_flags = BIO_QUIET;
        init_completion(&complete);
        bio.bi_private = &complete;
        bio.bi_end_io = floppy_rb0_complete;
@@ -3857,10 +3830,10 @@ static int floppy_revalidate(struct gendisk *disk)
        if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
            test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
            test_bit(drive, &fake_change) || NO_GEOM) {
-               if (usage_count == 0) {
-                       pr_info("VFS: revalidate called on non-open device.\n");
+               if (WARN(atomic_read(&usage_count) == 0,
+                        "VFS: revalidate called on non-open device.\n"))
                        return -EFAULT;
-               }
+
                lock_fdc(drive, false);
                cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
                      test_bit(FD_VERIFY_BIT, &UDRS->flags));
@@ -3893,7 +3866,7 @@ static const struct block_device_operations floppy_fops = {
        .owner                  = THIS_MODULE,
        .open                   = floppy_open,
        .release                = floppy_release,
-       .locked_ioctl           = fd_ioctl,
+       .ioctl                  = fd_ioctl,
        .getgeo                 = fd_getgeo,
        .media_changed          = check_floppy_change,
        .revalidate_disk        = floppy_revalidate,
@@ -4126,7 +4099,7 @@ static ssize_t floppy_cmos_show(struct device *dev,
        return sprintf(buf, "%X\n", UDP->cmos);
 }
 
-DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
+static DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
 
 static void floppy_device_release(struct device *dev)
 {
@@ -4175,6 +4148,9 @@ static int __init floppy_init(void)
        int i, unit, drive;
        int err, dr;
 
+       set_debugt();
+       interruptjiffies = resultjiffies = jiffies;
+
 #if defined(CONFIG_PPC)
        if (check_legacy_ioport(FDC1))
                return -ENODEV;
@@ -4353,7 +4329,7 @@ out_unreg_platform_dev:
        platform_device_unregister(&floppy_device[drive]);
 out_flush_work:
        flush_scheduled_work();
-       if (usage_count)
+       if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
 out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
@@ -4370,8 +4346,6 @@ out_put_disk:
        return err;
 }
 
-static DEFINE_SPINLOCK(floppy_usage_lock);
-
 static const struct io_region {
        int offset;
        int size;
@@ -4417,14 +4391,8 @@ static void floppy_release_regions(int fdc)
 
 static int floppy_grab_irq_and_dma(void)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&floppy_usage_lock, flags);
-       if (usage_count++) {
-               spin_unlock_irqrestore(&floppy_usage_lock, flags);
+       if (atomic_inc_return(&usage_count) > 1)
                return 0;
-       }
-       spin_unlock_irqrestore(&floppy_usage_lock, flags);
 
        /*
         * We might have scheduled a free_irq(), wait it to
@@ -4435,9 +4403,7 @@ static int floppy_grab_irq_and_dma(void)
        if (fd_request_irq()) {
                DPRINT("Unable to grab IRQ%d for the floppy driver\n",
                       FLOPPY_IRQ);
-               spin_lock_irqsave(&floppy_usage_lock, flags);
-               usage_count--;
-               spin_unlock_irqrestore(&floppy_usage_lock, flags);
+               atomic_dec(&usage_count);
                return -1;
        }
        if (fd_request_dma()) {
@@ -4447,9 +4413,7 @@ static int floppy_grab_irq_and_dma(void)
                        use_virtual_dma = can_use_virtual_dma = 1;
                if (!(can_use_virtual_dma & 1)) {
                        fd_free_irq();
-                       spin_lock_irqsave(&floppy_usage_lock, flags);
-                       usage_count--;
-                       spin_unlock_irqrestore(&floppy_usage_lock, flags);
+                       atomic_dec(&usage_count);
                        return -1;
                }
        }
@@ -4484,9 +4448,7 @@ cleanup:
        fd_free_dma();
        while (--fdc >= 0)
                floppy_release_regions(fdc);
-       spin_lock_irqsave(&floppy_usage_lock, flags);
-       usage_count--;
-       spin_unlock_irqrestore(&floppy_usage_lock, flags);
+       atomic_dec(&usage_count);
        return -1;
 }
 
@@ -4498,14 +4460,10 @@ static void floppy_release_irq_and_dma(void)
 #endif
        long tmpsize;
        unsigned long tmpaddr;
-       unsigned long flags;
 
-       spin_lock_irqsave(&floppy_usage_lock, flags);
-       if (--usage_count) {
-               spin_unlock_irqrestore(&floppy_usage_lock, flags);
+       if (!atomic_dec_and_test(&usage_count))
                return;
-       }
-       spin_unlock_irqrestore(&floppy_usage_lock, flags);
+
        if (irqdma_allocated) {
                fd_disable_dma();
                fd_free_dma();
@@ -4598,7 +4556,7 @@ static void __exit floppy_module_exit(void)
        del_timer_sync(&fd_timer);
        blk_cleanup_queue(floppy_queue);
 
-       if (usage_count)
+       if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
 
        /* eject disk, if any */