#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)
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)
{
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;
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);
}
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;
(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
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;
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",
.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;
drive = idkp->drive;
- ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "enter");
idkp->openers++;
* 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;
}
*/
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;
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);
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
};
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;
add_disk(g);
return 0;
+out_free_disk:
+ put_disk(g);
out_free_idkp:
kfree(idkp);
failed: