#endif
static int sd_revalidate_disk(struct gendisk *);
+static void sd_unlock_native_capacity(struct gendisk *disk);
static int sd_probe(struct device *);
static int sd_remove(struct device *);
static void sd_shutdown(struct device *);
sdev = sdkp->device;
+ retval = scsi_autopm_get_device(sdev);
+ if (retval)
+ goto error_autopm;
+
/*
* If the device is in error recovery, wait until it is done.
* If the device is offline, then disallow any access to it.
return 0;
error_out:
+ scsi_autopm_put_device(sdev);
+error_autopm:
scsi_disk_put(sdkp);
return retval;
}
* XXX and what if there are packets in flight and this close()
* XXX is followed by a "rmmod sd_mod"?
*/
+
+ scsi_autopm_put_device(sdev);
scsi_disk_put(sdkp);
return 0;
}
#endif
.media_changed = sd_media_changed,
.revalidate_disk = sd_revalidate_disk,
+ .unlock_native_capacity = sd_unlock_native_capacity,
};
static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
return 0;
}
+/**
+ * sd_unlock_native_capacity - unlock native capacity
+ * @disk: struct gendisk to set capacity for
+ *
+ * Block layer calls this function if it detects that partitions
+ * on @disk reach beyond the end of the device. If the SCSI host
+ * implements ->unlock_native_capacity() method, it's invoked to
+ * give it a chance to adjust the device capacity.
+ *
+ * CONTEXT:
+ * Defined by block layer. Might sleep.
+ */
+static void sd_unlock_native_capacity(struct gendisk *disk)
+{
+ struct scsi_device *sdev = scsi_disk(disk)->device;
+
+ if (sdev->host->hostt->unlock_native_capacity)
+ sdev->host->hostt->unlock_native_capacity(sdev);
+}
+
/**
* sd_format_disk_name - format disk name
* @prefix: name prefix - ie. "sd" for SCSI disks
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;
- dev_set_drvdata(dev, sdkp);
add_disk(gd);
sd_dif_config_host(sdkp);
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : "");
+ scsi_autopm_put_device(sdp);
put_device(&sdkp->dev);
}
}
device_initialize(&sdkp->dev);
- sdkp->dev.parent = &sdp->sdev_gendev;
+ sdkp->dev.parent = dev;
sdkp->dev.class = &sd_disk_class;
- dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev));
+ dev_set_name(&sdkp->dev, dev_name(dev));
if (device_add(&sdkp->dev))
goto out_free_index;
- get_device(&sdp->sdev_gendev);
+ get_device(dev);
+ dev_set_drvdata(dev, sdkp);
get_device(&sdkp->dev); /* prevent release before async_schedule */
async_schedule(sd_probe_async, sdkp);
{
struct scsi_disk *sdkp;
- async_synchronize_full();
sdkp = dev_get_drvdata(dev);
+ scsi_autopm_get_device(sdkp->device);
+
+ async_synchronize_full();
blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn);
device_del(&sdkp->dev);
del_gendisk(sdkp->disk);