aboutsummaryrefslogtreecommitdiff
path: root/drivers/ide/ide-gd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-gd.c')
-rw-r--r--drivers/ide/ide-gd.c58
1 files changed, 38 insertions, 20 deletions
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 753241429c2..838996a0039 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -8,6 +8,7 @@
#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)
@@ -21,6 +22,7 @@
#define IDE_GD_VERSION "1.18"
/* module parameters */
+static DEFINE_MUTEX(ide_gd_mutex);
static unsigned long debug_mask;
module_param(debug_mask, ulong, 0644);
@@ -91,7 +93,7 @@ static void ide_disk_release(struct device *dev)
/*
* On HPA drives the capacity needs to be
- * reinitilized on resume otherwise the disk
+ * reinitialized on resume otherwise the disk
* can not be used and a hard reset is required
*/
static void ide_gd_resume(ide_drive_t *drive)
@@ -236,13 +238,26 @@ out_put_idkp:
return ret;
}
-static int ide_gd_release(struct gendisk *disk, fmode_t mode)
+static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
+{
+ int ret;
+
+ mutex_lock(&ide_gd_mutex);
+ ret = ide_gd_open(bdev, mode);
+ mutex_unlock(&ide_gd_mutex);
+
+ return ret;
+}
+
+
+static void ide_gd_release(struct gendisk *disk, fmode_t mode)
{
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
ide_drive_t *drive = idkp->drive;
ide_debug_log(IDE_DBG_FUNC, "enter");
+ mutex_lock(&ide_gd_mutex);
if (idkp->openers == 1)
drive->disk_ops->flush(drive);
@@ -254,8 +269,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode)
idkp->openers--;
ide_disk_put(idkp);
-
- return 0;
+ mutex_unlock(&ide_gd_mutex);
}
static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
@@ -269,11 +283,12 @@ static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int ide_gd_media_changed(struct gendisk *disk)
+static unsigned int ide_gd_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
ide_drive_t *drive = idkp->drive;
- int ret;
+ bool ret;
/* do not scan partitions twice if this is a removable device */
if (drive->dev_flags & IDE_DFLAG_ATTACH) {
@@ -281,23 +296,26 @@ static int ide_gd_media_changed(struct gendisk *disk)
return 0;
}
- ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
+ /*
+ * The following is used to force revalidation on the first open on
+ * removeable devices, and never gets reported to userland as
+ * genhd->events is 0. This is intended as removeable ide disk
+ * can't really detect MEDIA_CHANGE events.
+ */
+ ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
- return ret;
+ return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
}
-static unsigned long long ide_gd_set_capacity(struct gendisk *disk,
- unsigned long long capacity)
+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->set_capacity)
- return disk_ops->set_capacity(drive, capacity);
-
- return drive->capacity64;
+ if (disk_ops->unlock_native_capacity)
+ disk_ops->unlock_native_capacity(drive);
}
static int ide_gd_revalidate_disk(struct gendisk *disk)
@@ -305,7 +323,7 @@ static int ide_gd_revalidate_disk(struct gendisk *disk)
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
ide_drive_t *drive = idkp->drive;
- if (ide_gd_media_changed(disk))
+ if (ide_gd_check_events(disk, 0))
drive->disk_ops->get_capacity(drive);
set_capacity(disk, ide_gd_capacity(drive));
@@ -323,12 +341,12 @@ static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
static const struct block_device_operations ide_gd_ops = {
.owner = THIS_MODULE,
- .open = ide_gd_open,
+ .open = ide_gd_unlocked_open,
.release = ide_gd_release,
- .locked_ioctl = ide_gd_ioctl,
+ .ioctl = ide_gd_ioctl,
.getgeo = ide_gd_getgeo,
- .media_changed = ide_gd_media_changed,
- .set_capacity = ide_gd_set_capacity,
+ .check_events = ide_gd_check_events,
+ .unlock_native_capacity = ide_gd_unlock_native_capacity,
.revalidate_disk = ide_gd_revalidate_disk
};
@@ -374,7 +392,7 @@ static int ide_gd_probe(ide_drive_t *drive)
idkp->dev.parent = &drive->gendev;
idkp->dev.release = ide_disk_release;
- dev_set_name(&idkp->dev, dev_name(&drive->gendev));
+ dev_set_name(&idkp->dev, "%s", dev_name(&drive->gendev));
if (device_register(&idkp->dev))
goto out_free_disk;