[PATCH] devfs: Remove the devfs_fs_kernel.h file from the tree
[safe/jmp/linux-2.6] / drivers / block / floppy.c
index 21f58c4..0242cbb 100644 (file)
  */
 
 /*
+ * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
+ */
+
+/*
  * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of
  * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting &
  * use of '0' for NULL.
@@ -158,10 +162,6 @@ static int print_unex = 1;
 #define FDPATCHES
 #include <linux/fdreg.h>
 
-/*
- * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
- */
-
 #include <linux/fd.h>
 #include <linux/hdreg.h>
 
@@ -170,15 +170,16 @@ static int print_unex = 1;
 #include <linux/mm.h>
 #include <linux/bio.h>
 #include <linux/string.h>
+#include <linux/jiffies.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h> /* CMOS defines */
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/buffer_head.h> /* for invalidate_buffers() */
+#include <linux/mutex.h>
 
 /*
  * PS/2 floppies have much slower step rates than regular floppies.
@@ -222,7 +223,6 @@ static struct completion device_release;
 static unsigned short virtual_dma_port = 0x3f0;
 irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int set_dor(int fdc, char mask, char data);
-static void register_devfs_entries(int drive) __init;
 
 #define K_64   0x10000         /* 64KB */
 
@@ -242,7 +242,6 @@ static int allowed_drive_mask = 0x33;
 
 static int irqdma_allocated;
 
-#define LOCAL_END_REQUEST
 #define DEVICE_NAME "floppy"
 
 #include <linux/blkdev.h>
@@ -250,6 +249,18 @@ static int irqdma_allocated;
 #include <linux/cdrom.h>       /* for the compatibility eject ioctl */
 #include <linux/completion.h>
 
+/*
+ * Interrupt freeing also means /proc VFS work - dont do it
+ * from interrupt context. We push this work into keventd:
+ */
+static void fd_free_irq_fn(void *data)
+{
+       fd_free_irq();
+}
+
+static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL);
+
+
 static struct request *current_req;
 static struct request_queue *floppy_queue;
 static void do_fd_request(request_queue_t * q);
@@ -414,7 +425,7 @@ static struct floppy_write_errors write_errors[N_DRIVE];
 static struct timer_list motor_off_timer[N_DRIVE];
 static struct gendisk *disks[N_DRIVE];
 static struct block_device *opened_bdev[N_DRIVE];
-static DECLARE_MUTEX(open_lock);
+static DEFINE_MUTEX(open_lock);
 static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
 
 /*
@@ -479,7 +490,6 @@ static struct floppy_struct floppy_type[32] = {
        { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5"    */
 };
 
-#define        NUMBER(x)       (sizeof(x) / sizeof(*(x)))
 #define SECTSIZE (_FD_SECTSIZE(*floppy))
 
 /* Auto-detection: Disk type used until the next media change occurs. */
@@ -628,7 +638,7 @@ static inline void debugt(const char *message) { }
 #endif /* DEBUGT */
 
 typedef void (*timeout_fn) (unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
+static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
 
 static const char *timeout_message;
 
@@ -736,7 +746,7 @@ static int disk_change(int drive)
 {
        int fdc = FDC(drive);
 #ifdef FLOPPY_SANITY_CHECK
-       if (jiffies - UDRS->select_date < UDP->select_delay)
+       if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
                DPRINT("WARNING disk change called early\n");
        if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
            (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
@@ -1012,7 +1022,7 @@ static void schedule_bh(void (*handler) (void))
        schedule_work(&floppy_work);
 }
 
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(fd_timer, NULL, 0, 0);
 
 static void cancel_activity(void)
 {
@@ -1064,7 +1074,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
                return 1;
        }
 
-       if ((signed)(jiffies - delay) < 0) {
+       if (time_before(jiffies, delay)) {
                del_timer(&fd_timer);
                fd_timer.function = function;
                fd_timer.expires = delay;
@@ -1524,7 +1534,7 @@ static void setup_rw_floppy(void)
                 * again just before spinup completion. Beware that
                 * after scandrives, we must again wait for selection.
                 */
-               if ((signed)(ready_date - jiffies) > DP->select_delay) {
+               if (time_after(ready_date, jiffies + DP->select_delay)) {
                        ready_date -= DP->select_delay;
                        function = (timeout_fn) floppy_start;
                } else
@@ -2301,7 +2311,7 @@ static void floppy_end_request(struct request *req, int uptodate)
        add_disk_randomness(req->rq_disk);
        floppy_off((long)req->rq_disk->private_data);
        blkdev_dequeue_request(req);
-       end_that_request_last(req);
+       end_that_request_last(req, uptodate);
 
        /* We're done with the request */
        current_req = NULL;
@@ -3335,7 +3345,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
        if (type) {
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               down(&open_lock);
+               mutex_lock(&open_lock);
                LOCK_FDC(drive, 1);
                floppy_type[type] = *g;
                floppy_type[type].name = "user format";
@@ -3349,7 +3359,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
                                continue;
                        __invalidate_device(bdev);
                }
-               up(&open_lock);
+               mutex_unlock(&open_lock);
        } else {
                int oldStretch;
                LOCK_FDC(drive, 1);
@@ -3445,6 +3455,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
        return 0;
 }
 
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       int drive = (long)bdev->bd_disk->private_data;
+       int type = ITYPE(drive_state[drive].fd_device);
+       struct floppy_struct *g;
+       int ret;
+
+       ret = get_floppy_geometry(drive, type, &g);
+       if (ret)
+               return ret;
+
+       geo->heads = g->head;
+       geo->sectors = g->sect;
+       geo->cylinders = g->track;
+       return 0;
+}
+
 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                    unsigned long param)
 {
@@ -3474,23 +3501,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                cmd = FDEJECT;
        }
 
-       /* generic block device ioctls */
-       switch (cmd) {
-               /* the following have been inspired by the corresponding
-                * code for other block devices. */
-               struct floppy_struct *g;
-       case HDIO_GETGEO:
-               {
-                       struct hd_geometry loc;
-                       ECALL(get_floppy_geometry(drive, type, &g));
-                       loc.heads = g->head;
-                       loc.sectors = g->sect;
-                       loc.cylinders = g->track;
-                       loc.start = 0;
-                       return _COPYOUT(loc);
-               }
-       }
-
        /* convert the old style command into a new style command */
        if ((cmd & 0xff00) == 0x0200) {
                ECALL(normalize_ioctl(&cmd, &size));
@@ -3645,7 +3655,7 @@ static void __init config_types(void)
                const char *name = NULL;
                static char temparea[32];
 
-               if (type < NUMBER(default_drive_params)) {
+               if (type < ARRAY_SIZE(default_drive_params)) {
                        params = &default_drive_params[type].params;
                        if (type) {
                                name = default_drive_params[type].name;
@@ -3664,7 +3674,6 @@ static void __init config_types(void)
                                first = 0;
                        }
                        printk("%s fd%d is %s", prepend, drive, name);
-                       register_devfs_entries(drive);
                }
                *UDP = *params;
        }
@@ -3676,7 +3685,7 @@ static int floppy_release(struct inode *inode, struct file *filp)
 {
        int drive = (long)inode->i_bdev->bd_disk->private_data;
 
-       down(&open_lock);
+       mutex_lock(&open_lock);
        if (UDRS->fd_ref < 0)
                UDRS->fd_ref = 0;
        else if (!UDRS->fd_ref--) {
@@ -3686,7 +3695,7 @@ static int floppy_release(struct inode *inode, struct file *filp)
        if (!UDRS->fd_ref)
                opened_bdev[drive] = NULL;
        floppy_release_irq_and_dma();
-       up(&open_lock);
+       mutex_unlock(&open_lock);
        return 0;
 }
 
@@ -3704,7 +3713,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
        char *tmp;
 
        filp->private_data = (void *)0;
-       down(&open_lock);
+       mutex_lock(&open_lock);
        old_dev = UDRS->fd_device;
        if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
                goto out2;
@@ -3770,8 +3779,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
        /* Allow ioctls if we have write-permissions even if read-only open.
         * Needed so that programs such as fdrawcmd still can work on write
         * protected disks */
-       if (filp->f_mode & 2
-           || permission(filp->f_dentry->d_inode, 2, NULL) == 0)
+       if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
                filp->private_data = (void *)8;
 
        if (UFDCS->rawcmd == 1)
@@ -3788,7 +3796,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
                if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
                        goto out;
        }
-       up(&open_lock);
+       mutex_unlock(&open_lock);
        return 0;
 out:
        if (UDRS->fd_ref < 0)
@@ -3799,7 +3807,7 @@ out:
                opened_bdev[drive] = NULL;
        floppy_release_irq_and_dma();
 out2:
-       up(&open_lock);
+       mutex_unlock(&open_lock);
        return res;
 }
 
@@ -3813,7 +3821,7 @@ static int check_floppy_change(struct gendisk *disk)
        if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
                return 1;
 
-       if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
+       if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
                if (floppy_grab_irq_and_dma()) {
                        return 1;
                }
@@ -3939,40 +3947,10 @@ static struct block_device_operations floppy_fops = {
        .open           = floppy_open,
        .release        = floppy_release,
        .ioctl          = fd_ioctl,
+       .getgeo         = fd_getgeo,
        .media_changed  = check_floppy_change,
        .revalidate_disk = floppy_revalidate,
 };
-static char *table[] = {
-       "", "d360", "h1200", "u360", "u720", "h360", "h720",
-       "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
-       "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
-       "h880", "u1040", "u1120", "h1600", "u1760", "u1920",
-       "u3200", "u3520", "u3840", "u1840", "u800", "u1600",
-       NULL
-};
-static int t360[] = { 1, 0 },
-       t1200[] = { 2, 5, 6, 10, 12, 14, 16, 18, 20, 23, 0 },
-       t3in[] = { 8, 9, 26, 27, 28, 7, 11, 15, 19, 24, 25, 29, 31, 3, 4, 13,
-                       17, 21, 22, 30, 0 };
-static int *table_sup[] =
-    { NULL, t360, t1200, t3in + 5 + 8, t3in + 5, t3in, t3in };
-
-static void __init register_devfs_entries(int drive)
-{
-       int base_minor = (drive < 4) ? drive : (124 + drive);
-
-       if (UDP->cmos < NUMBER(default_drive_params)) {
-               int i = 0;
-               do {
-                       int minor = base_minor + (table_sup[UDP->cmos][i] << 2);
-
-                       devfs_mk_bdev(MKDEV(FLOPPY_MAJOR, minor),
-                                     S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
-                                     S_IWGRP, "floppy/%d%s", drive,
-                                     table[table_sup[UDP->cmos][i]]);
-               } while (table_sup[UDP->cmos][i++]);
-       }
-}
 
 /*
  * Floppy Driver initialization
@@ -4193,17 +4171,16 @@ static int __init floppy_setup(char *str)
 
 static int have_no_fdc = -ENODEV;
 
-static ssize_t floppy_cmos_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t floppy_cmos_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
 {
-       struct platform_device *p = container_of(dev,struct platform_device,dev);
-       int drive = p->id;
-       ssize_t retval;
-
-       retval = sprintf(buf,"%X\n", UDP->cmos);
+       struct platform_device *p;
+       int drive;
 
-       return retval;
+       p = container_of(dev, struct platform_device,dev);
+       drive = p->id;
+       return sprintf(buf, "%X\n", UDP->cmos);
 }
-
 DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
 
 static void floppy_device_release(struct device *dev)
@@ -4220,7 +4197,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
            !(allowed_drive_mask & (1 << drive)) ||
            fdc_state[FDC(drive)].version == FDC_NONE)
                return NULL;
-       if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
+       if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
        *part = 0;
        return get_disk(disks[drive]);
@@ -4250,11 +4227,9 @@ static int __init floppy_init(void)
                motor_off_timer[dr].function = motor_off_callback;
        }
 
-       devfs_mk_dir("floppy");
-
        err = register_blkdev(FLOPPY_MAJOR, "fd");
        if (err)
-               goto out_devfs_remove;
+               goto out_put_disk;
 
        floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
        if (!floppy_queue) {
@@ -4290,7 +4265,7 @@ static int __init floppy_init(void)
        }
 
        use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC64)
+#if defined(CONFIG_PPC_MERGE)
        if (check_legacy_ioport(FDC1)) {
                del_timer(&fd_timeout);
                err = -ENODEV;
@@ -4413,8 +4388,6 @@ out_unreg_region:
        blk_cleanup_queue(floppy_queue);
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
-out_devfs_remove:
-       devfs_remove("floppy");
 out_put_disk:
        while (dr--) {
                del_timer(&motor_off_timer[dr]);
@@ -4435,6 +4408,13 @@ static int floppy_grab_irq_and_dma(void)
                return 0;
        }
        spin_unlock_irqrestore(&floppy_usage_lock, flags);
+
+       /*
+        * We might have scheduled a free_irq(), wait it to
+        * drain first:
+        */
+       flush_scheduled_work();
+
        if (fd_request_irq()) {
                DPRINT("Unable to grab IRQ%d for the floppy driver\n",
                       FLOPPY_IRQ);
@@ -4524,7 +4504,7 @@ static void floppy_release_irq_and_dma(void)
        if (irqdma_allocated) {
                fd_disable_dma();
                fd_free_dma();
-               fd_free_irq();
+               schedule_work(&fd_free_irq_work);
                irqdma_allocated = 0;
        }
        set_dor(0, ~0, 8);
@@ -4568,19 +4548,6 @@ static void floppy_release_irq_and_dma(void)
 
 static char *floppy;
 
-static void unregister_devfs_entries(int drive)
-{
-       int i;
-
-       if (UDP->cmos < NUMBER(default_drive_params)) {
-               i = 0;
-               do {
-                       devfs_remove("floppy/%d%s", drive,
-                                    table[table_sup[UDP->cmos][i]]);
-               } while (table_sup[UDP->cmos][i++]);
-       }
-}
-
 static void __init parse_floppy_cfg_string(char *cfg)
 {
        char *ptr;
@@ -4596,7 +4563,7 @@ static void __init parse_floppy_cfg_string(char *cfg)
        }
 }
 
-int init_module(void)
+int __init init_module(void)
 {
        if (floppy)
                parse_floppy_cfg_string(floppy);
@@ -4617,13 +4584,11 @@ void cleanup_module(void)
                if ((allowed_drive_mask & (1 << drive)) &&
                    fdc_state[FDC(drive)].version != FDC_NONE) {
                        del_gendisk(disks[drive]);
-                       unregister_devfs_entries(drive);
                        device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
                        platform_device_unregister(&floppy_device[drive]);
                }
                put_disk(disks[drive]);
        }
-       devfs_remove("floppy");
 
        del_timer_sync(&fd_timeout);
        del_timer_sync(&fd_timer);
@@ -4635,6 +4600,8 @@ void cleanup_module(void)
        /* eject disk, if any */
        fd_eject(0);
 
+       flush_scheduled_work();         /* fd_free_irq() might be pending */
+
        wait_for_completion(&device_release);
 }