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-tape.c
index 5a3dc46..f04791a 100644 (file)
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/jiffies.h>
 #include <linux/major.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -1011,7 +1013,9 @@ typedef struct ide_tape_obj {
          int debug_level; 
 } idetape_tape_t;
 
-static DECLARE_MUTEX(idetape_ref_sem);
+static DEFINE_MUTEX(idetape_ref_mutex);
+
+static struct class *idetape_sysfs_class;
 
 #define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
 
@@ -1022,11 +1026,11 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
 {
        struct ide_tape_obj *tape = NULL;
 
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        tape = ide_tape_g(disk);
        if (tape)
                kref_get(&tape->kref);
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
 
@@ -1034,9 +1038,9 @@ static void ide_tape_release(struct kref *);
 
 static void ide_tape_put(struct ide_tape_obj *tape)
 {
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        kref_put(&tape->kref, ide_tape_release);
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
 }
 
 /*
@@ -1288,11 +1292,11 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
 {
        struct ide_tape_obj *tape = NULL;
 
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        tape = idetape_devs[i];
        if (tape)
                kref_get(&tape->kref);
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
 
@@ -2333,7 +2337,7 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
        }
        if (time_after(jiffies, tape->insert_time))
                tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
-       if (jiffies - tape->avg_time >= HZ) {
+       if (time_after_eq(jiffies, tape->avg_time + HZ)) {
                tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024;
                tape->avg_size = 0;
                tape->avg_time = jiffies;
@@ -2494,7 +2498,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                        } else {
                                return ide_do_reset(drive);
                        }
-               } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD)
+               } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD))
                        tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
                idetape_postpone_request(drive);
                return ide_stopped;
@@ -2903,8 +2907,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
                } else if (!(tape->sense_key == 2 && tape->asc == 4 &&
                             (tape->ascq == 1 || tape->ascq == 8)))
                        return -EIO;
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(HZ / 10);
+               msleep(100);
        }
        return -EIO;
 }
@@ -4681,9 +4684,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
        idetape_add_settings(drive);
 }
 
-static int ide_tape_remove(struct device *dev)
+static void ide_tape_remove(ide_drive_t *drive)
 {
-       ide_drive_t *drive = to_ide_device(dev);
        idetape_tape_t *tape = drive->driver_data;
 
        ide_unregister_subdriver(drive, tape->driver);
@@ -4691,8 +4693,6 @@ static int ide_tape_remove(struct device *dev)
        ide_unregister_region(tape->disk);
 
        ide_tape_put(tape);
-
-       return 0;
 }
 
 static void ide_tape_release(struct kref *kref)
@@ -4705,6 +4705,10 @@ static void ide_tape_release(struct kref *kref)
 
        drive->dsc_overlap = 0;
        drive->driver_data = NULL;
+       class_device_destroy(idetape_sysfs_class,
+                       MKDEV(IDETAPE_MAJOR, tape->minor));
+       class_device_destroy(idetape_sysfs_class,
+                       MKDEV(IDETAPE_MAJOR, tape->minor + 128));
        devfs_remove("%s/mt", drive->devfs_name);
        devfs_remove("%s/mtn", drive->devfs_name);
        devfs_unregister_tape(g->number);
@@ -4740,16 +4744,16 @@ static ide_proc_entry_t idetape_proc[] = {
 
 #endif
 
-static int ide_tape_probe(struct device *);
+static int ide_tape_probe(ide_drive_t *);
 
 static ide_driver_t idetape_driver = {
-       .owner                  = THIS_MODULE,
        .gen_driver = {
+               .owner          = THIS_MODULE,
                .name           = "ide-tape",
                .bus            = &ide_bus_type,
-               .probe          = ide_tape_probe,
-               .remove         = ide_tape_remove,
        },
+       .probe                  = ide_tape_probe,
+       .remove                 = ide_tape_remove,
        .version                = IDETAPE_VERSION,
        .media                  = ide_tape,
        .supports_dsc_overlap   = 1,
@@ -4820,9 +4824,8 @@ static struct block_device_operations idetape_block_ops = {
        .ioctl          = idetape_ioctl,
 };
 
-static int ide_tape_probe(struct device *dev)
+static int ide_tape_probe(ide_drive_t *drive)
 {
-       ide_drive_t *drive = to_ide_device(dev);
        idetape_tape_t *tape;
        struct gendisk *g;
        int minor;
@@ -4845,7 +4848,7 @@ static int ide_tape_probe(struct device *dev)
                printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
                printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
        }
-       tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL);
+       tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL);
        if (tape == NULL) {
                printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
                goto failed;
@@ -4859,8 +4862,6 @@ static int ide_tape_probe(struct device *dev)
 
        ide_register_subdriver(drive, &idetape_driver);
 
-       memset(tape, 0, sizeof(*tape));
-
        kref_init(&tape->kref);
 
        tape->drive = drive;
@@ -4871,14 +4872,19 @@ static int ide_tape_probe(struct device *dev)
 
        drive->driver_data = tape;
 
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        for (minor = 0; idetape_devs[minor]; minor++)
                ;
        idetape_devs[minor] = tape;
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
 
        idetape_setup(drive, tape, minor);
 
+       class_device_create(idetape_sysfs_class, NULL,
+                       MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
+       class_device_create(idetape_sysfs_class, NULL,
+                       MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
+
        devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
                        S_IFCHR | S_IRUGO | S_IWUGO,
                        "%s/mt", drive->devfs_name);
@@ -4904,21 +4910,42 @@ MODULE_LICENSE("GPL");
 static void __exit idetape_exit (void)
 {
        driver_unregister(&idetape_driver.gen_driver);
+       class_destroy(idetape_sysfs_class);
        unregister_chrdev(IDETAPE_MAJOR, "ht");
 }
 
-/*
- *     idetape_init will register the driver for each tape.
- */
-static int idetape_init (void)
+static int __init idetape_init(void)
 {
+       int error = 1;
+       idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape");
+       if (IS_ERR(idetape_sysfs_class)) {
+               idetape_sysfs_class = NULL;
+               printk(KERN_ERR "Unable to create sysfs class for ide tapes\n");
+               error = -EBUSY;
+               goto out;
+       }
+
        if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
                printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
-               return -EBUSY;
+               error = -EBUSY;
+               goto out_free_class;
        }
-       return driver_register(&idetape_driver.gen_driver);
+
+       error = driver_register(&idetape_driver.gen_driver);
+       if (error)
+               goto out_free_driver;
+
+       return 0;
+
+out_free_driver:
+       driver_unregister(&idetape_driver.gen_driver);
+out_free_class:
+       class_destroy(idetape_sysfs_class);
+out:
+       return error;
 }
 
+MODULE_ALIAS("ide:*m-tape*");
 module_init(idetape_init);
 module_exit(idetape_exit);
 MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);