Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / ide / ide-floppy.c
index c949e98..a53e3ce 100644 (file)
@@ -98,6 +98,7 @@
 #include <linux/cdrom.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -317,7 +318,7 @@ typedef struct ide_floppy_obj {
        unsigned long flags;
 } idefloppy_floppy_t;
 
-#define IDEFLOPPY_TICKS_DELAY  3       /* default delay for ZIP 100 */
+#define IDEFLOPPY_TICKS_DELAY  HZ/20   /* default delay for ZIP 100 (50ms) */
 
 /*
  *     Floppy flag bits values.
@@ -517,7 +518,7 @@ typedef struct {
        u8              reserved[4];
 } idefloppy_mode_parameter_header_t;
 
-static DECLARE_MUTEX(idefloppy_ref_sem);
+static DEFINE_MUTEX(idefloppy_ref_mutex);
 
 #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
 
@@ -528,11 +529,11 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
 {
        struct ide_floppy_obj *floppy = NULL;
 
-       down(&idefloppy_ref_sem);
+       mutex_lock(&idefloppy_ref_mutex);
        floppy = ide_floppy_g(disk);
        if (floppy)
                kref_get(&floppy->kref);
-       up(&idefloppy_ref_sem);
+       mutex_unlock(&idefloppy_ref_mutex);
        return floppy;
 }
 
@@ -540,9 +541,9 @@ static void ide_floppy_release(struct kref *);
 
 static void ide_floppy_put(struct ide_floppy_obj *floppy)
 {
-       down(&idefloppy_ref_sem);
+       mutex_lock(&idefloppy_ref_mutex);
        kref_put(&floppy->kref, ide_floppy_release);
-       up(&idefloppy_ref_sem);
+       mutex_unlock(&idefloppy_ref_mutex);
 }
 
 /*
@@ -661,10 +662,12 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
 
        idefloppy_do_end_request(drive, 1, done >> 9);
 
+#if IDEFLOPPY_DEBUG_BUGS
        if (bcount) {
                printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
                idefloppy_write_zeros(drive, bcount);
        }
+#endif
 }
 
 static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
@@ -1048,6 +1051,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
        atapi_bcount_t bcount;
        ide_handler_t *pkt_xfer_routine;
 
+#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
+         and have lived on another thread's stack; that stack may have become
+         unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
 #if IDEFLOPPY_DEBUG_BUGS
        if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
            pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
@@ -1055,6 +1061,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
                        "Two request sense in serial were issued\n");
        }
 #endif /* IDEFLOPPY_DEBUG_BUGS */
+#endif
 
        if (floppy->failed_pc == NULL &&
            pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
@@ -1865,9 +1872,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
        idefloppy_add_settings(drive);
 }
 
-static int ide_floppy_remove(struct device *dev)
+static void ide_floppy_remove(ide_drive_t *drive)
 {
-       ide_drive_t *drive = to_ide_device(dev);
        idefloppy_floppy_t *floppy = drive->driver_data;
        struct gendisk *g = floppy->disk;
 
@@ -1876,8 +1882,6 @@ static int ide_floppy_remove(struct device *dev)
        del_gendisk(g);
 
        ide_floppy_put(floppy);
-
-       return 0;
 }
 
 static void ide_floppy_release(struct kref *kref)
@@ -1916,16 +1920,16 @@ static ide_proc_entry_t idefloppy_proc[] = {
 
 #endif /* CONFIG_PROC_FS */
 
-static int ide_floppy_probe(struct device *);
+static int ide_floppy_probe(ide_drive_t *);
 
 static ide_driver_t idefloppy_driver = {
-       .owner                  = THIS_MODULE,
        .gen_driver = {
+               .owner          = THIS_MODULE,
                .name           = "ide-floppy",
                .bus            = &ide_bus_type,
-               .probe          = ide_floppy_probe,
-               .remove         = ide_floppy_remove,
        },
+       .probe                  = ide_floppy_probe,
+       .remove                 = ide_floppy_remove,
        .version                = IDEFLOPPY_VERSION,
        .media                  = ide_floppy,
        .supports_dsc_overlap   = 0,
@@ -2025,6 +2029,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
+static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+       ide_drive_t *drive = floppy->drive;
+
+       geo->heads = drive->bios_head;
+       geo->sectors = drive->bios_sect;
+       geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+       return 0;
+}
+
 static int idefloppy_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
@@ -2032,11 +2047,9 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
        struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
        ide_drive_t *drive = floppy->drive;
        void __user *argp = (void __user *)arg;
-       int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+       int err;
        int prevent = (arg) ? 1 : 0;
        idefloppy_pc_t pc;
-       if (err != -EINVAL)
-               return err;
 
        switch (cmd) {
        case CDROMEJECT:
@@ -2088,7 +2101,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
        case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
                return idefloppy_get_format_progress(drive, argp);
        }
-       return -EINVAL;
+       return generic_ide_ioctl(drive, file, bdev, cmd, arg);
 }
 
 static int idefloppy_media_changed(struct gendisk *disk)
@@ -2116,13 +2129,13 @@ static struct block_device_operations idefloppy_ops = {
        .open           = idefloppy_open,
        .release        = idefloppy_release,
        .ioctl          = idefloppy_ioctl,
+       .getgeo         = idefloppy_getgeo,
        .media_changed  = idefloppy_media_changed,
        .revalidate_disk= idefloppy_revalidate_disk
 };
 
-static int ide_floppy_probe(struct device *dev)
+static int ide_floppy_probe(ide_drive_t *drive)
 {
-       ide_drive_t *drive = to_ide_device(dev);
        idefloppy_floppy_t *floppy;
        struct gendisk *g;
 
@@ -2140,7 +2153,7 @@ static int ide_floppy_probe(struct device *dev)
                printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
                goto failed;
        }
-       if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+       if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
                printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
                goto failed;
        }
@@ -2153,8 +2166,6 @@ static int ide_floppy_probe(struct device *dev)
 
        ide_register_subdriver(drive, &idefloppy_driver);
 
-       memset(floppy, 0, sizeof(*floppy));
-
        kref_init(&floppy->kref);
 
        floppy->drive = drive;
@@ -2189,15 +2200,13 @@ static void __exit idefloppy_exit (void)
        driver_unregister(&idefloppy_driver.gen_driver);
 }
 
-/*
- *     idefloppy_init will register the driver for each floppy.
- */
-static int idefloppy_init (void)
+static int __init idefloppy_init(void)
 {
        printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
        return driver_register(&idefloppy_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-floppy*");
 module_init(idefloppy_init);
 module_exit(idefloppy_exit);
 MODULE_LICENSE("GPL");