block,ide: simplify bdops->set_capacity() to ->unlock_native_capacity()
[safe/jmp/linux-2.6] / drivers / ide / ide-gd.c
index d367473..c102d23 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/mutex.h>
 #include <linux/ide.h>
 #include <linux/hdreg.h>
+#include <linux/dmi.h>
+#include <linux/slab.h>
 
 #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
 #define IDE_DISK_MINORS                (1 << PARTN_BITS)
@@ -25,7 +27,7 @@ module_param(debug_mask, ulong, 0644);
 
 static DEFINE_MUTEX(ide_disk_ref_mutex);
 
-static void ide_disk_release(struct kref *);
+static void ide_disk_release(struct device *);
 
 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
 {
@@ -37,7 +39,7 @@ static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
                if (ide_device_get(idkp->drive))
                        idkp = NULL;
                else
-                       kref_get(&idkp->kref);
+                       get_device(&idkp->dev);
        }
        mutex_unlock(&ide_disk_ref_mutex);
        return idkp;
@@ -48,7 +50,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
        ide_drive_t *drive = idkp->drive;
 
        mutex_lock(&ide_disk_ref_mutex);
-       kref_put(&idkp->kref, ide_disk_release);
+       put_device(&idkp->dev);
        ide_device_put(drive);
        mutex_unlock(&ide_disk_ref_mutex);
 }
@@ -66,17 +68,18 @@ static void ide_gd_remove(ide_drive_t *drive)
        struct gendisk *g = idkp->disk;
 
        ide_proc_unregister_driver(drive, idkp->driver);
-
+       device_del(&idkp->dev);
        del_gendisk(g);
-
        drive->disk_ops->flush(drive);
 
-       ide_disk_put(idkp);
+       mutex_lock(&ide_disk_ref_mutex);
+       put_device(&idkp->dev);
+       mutex_unlock(&ide_disk_ref_mutex);
 }
 
-static void ide_disk_release(struct kref *kref)
+static void ide_disk_release(struct device *dev)
 {
-       struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj);
+       struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
        ide_drive_t *drive = idkp->drive;
        struct gendisk *g = idkp->disk;
 
@@ -98,6 +101,19 @@ static void ide_gd_resume(ide_drive_t *drive)
                (void)drive->disk_ops->get_capacity(drive);
 }
 
+static const struct dmi_system_id ide_coldreboot_table[] = {
+       {
+               /* Acer TravelMate 66x cuts power during reboot */
+               .ident   = "Acer TravelMate 660",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
+               },
+       },
+
+       { }     /* terminate list */
+};
+
 static void ide_gd_shutdown(ide_drive_t *drive)
 {
 #ifdef CONFIG_ALPHA
@@ -114,7 +130,8 @@ static void ide_gd_shutdown(ide_drive_t *drive)
           the disk to expire its write cache. */
        if (system_state != SYSTEM_POWER_OFF) {
 #else
-       if (system_state == SYSTEM_RESTART) {
+       if (system_state == SYSTEM_RESTART &&
+               !dmi_check_system(ide_coldreboot_table)) {
 #endif
                drive->disk_ops->flush(drive);
                return;
@@ -144,12 +161,7 @@ static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
        return drive->disk_ops->do_request(drive, rq, sector);
 }
 
-static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs)
-{
-       return drive->disk_ops->end_request(drive, uptodate, nrsecs);
-}
-
-static ide_driver_t ide_gd_driver = {
+static struct ide_driver ide_gd_driver = {
        .gen_driver = {
                .owner          = THIS_MODULE,
                .name           = "ide-gd",
@@ -161,17 +173,15 @@ static ide_driver_t ide_gd_driver = {
        .shutdown               = ide_gd_shutdown,
        .version                = IDE_GD_VERSION,
        .do_request             = ide_gd_do_request,
-       .end_request            = ide_gd_end_request,
-       .error                  = __ide_error,
 #ifdef CONFIG_IDE_PROC_FS
        .proc_entries           = ide_disk_proc_entries,
        .proc_devsets           = ide_disk_proc_devsets,
 #endif
 };
 
-static int ide_gd_open(struct inode *inode, struct file *filp)
+static int ide_gd_open(struct block_device *bdev, fmode_t mode)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct gendisk *disk = bdev->bd_disk;
        struct ide_disk_obj *idkp;
        ide_drive_t *drive;
        int ret = 0;
@@ -182,7 +192,7 @@ static int ide_gd_open(struct inode *inode, struct file *filp)
 
        drive = idkp->drive;
 
-       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+       ide_debug_log(IDE_DBG_FUNC, "enter");
 
        idkp->openers++;
 
@@ -197,12 +207,12 @@ static int ide_gd_open(struct inode *inode, struct file *filp)
                 * unreadable disk, so that we can get the format capacity
                 * of the drive or begin the format - Sam
                 */
-               if (ret && (filp->f_flags & O_NDELAY) == 0) {
+               if (ret && (mode & FMODE_NDELAY) == 0) {
                        ret = -EIO;
                        goto out_put_idkp;
                }
 
-               if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & FMODE_WRITE)) {
+               if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
                        ret = -EROFS;
                        goto out_put_idkp;
                }
@@ -214,7 +224,7 @@ static int ide_gd_open(struct inode *inode, struct file *filp)
                 */
                drive->disk_ops->set_doorlock(drive, disk, 1);
                drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
-               check_disk_change(inode->i_bdev);
+               check_disk_change(bdev);
        } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
                ret = -EBUSY;
                goto out_put_idkp;
@@ -227,13 +237,12 @@ out_put_idkp:
        return ret;
 }
 
-static int ide_gd_release(struct inode *inode, struct file *filp)
+static int ide_gd_release(struct gendisk *disk, fmode_t mode)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
        struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
        ide_drive_t *drive = idkp->drive;
 
-       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+       ide_debug_log(IDE_DBG_FUNC, "enter");
 
        if (idkp->openers == 1)
                drive->disk_ops->flush(drive);
@@ -279,30 +288,45 @@ static int ide_gd_media_changed(struct gendisk *disk)
        return ret;
 }
 
+static void ide_gd_unlock_native_capacity(struct gendisk *disk)
+{
+       struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
+       ide_drive_t *drive = idkp->drive;
+       const struct ide_disk_ops *disk_ops = drive->disk_ops;
+
+       if (disk_ops->unlock_native_capacity)
+               disk_ops->unlock_native_capacity(drive);
+}
+
 static int ide_gd_revalidate_disk(struct gendisk *disk)
 {
        struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
-       set_capacity(disk, ide_gd_capacity(idkp->drive));
+       ide_drive_t *drive = idkp->drive;
+
+       if (ide_gd_media_changed(disk))
+               drive->disk_ops->get_capacity(drive);
+
+       set_capacity(disk, ide_gd_capacity(drive));
        return 0;
 }
 
-static int ide_gd_ioctl(struct inode *inode, struct file *file,
+static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
                             unsigned int cmd, unsigned long arg)
 {
-       struct block_device *bdev = inode->i_bdev;
        struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
        ide_drive_t *drive = idkp->drive;
 
-       return drive->disk_ops->ioctl(drive, inode, file, cmd, arg);
+       return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
 }
 
-static struct block_device_operations ide_gd_ops = {
+static const struct block_device_operations ide_gd_ops = {
        .owner                  = THIS_MODULE,
        .open                   = ide_gd_open,
        .release                = ide_gd_release,
-       .ioctl                  = ide_gd_ioctl,
+       .locked_ioctl           = ide_gd_ioctl,
        .getgeo                 = ide_gd_getgeo,
        .media_changed          = ide_gd_media_changed,
+       .unlock_native_capacity = ide_gd_unlock_native_capacity,
        .revalidate_disk        = ide_gd_revalidate_disk
 };
 
@@ -346,7 +370,12 @@ static int ide_gd_probe(ide_drive_t *drive)
 
        ide_init_disk(g, drive);
 
-       kref_init(&idkp->kref);
+       idkp->dev.parent = &drive->gendev;
+       idkp->dev.release = ide_disk_release;
+       dev_set_name(&idkp->dev, dev_name(&drive->gendev));
+
+       if (device_register(&idkp->dev))
+               goto out_free_disk;
 
        idkp->drive = drive;
        idkp->driver = &ide_gd_driver;
@@ -371,6 +400,8 @@ static int ide_gd_probe(ide_drive_t *drive)
        add_disk(g);
        return 0;
 
+out_free_disk:
+       put_disk(g);
 out_free_idkp:
        kfree(idkp);
 failed: