aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-24 17:32:15 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-24 17:32:15 -0800
commitd9978ec5680059d727b39d6c706777c6973587f2 (patch)
tree8fad9cf8cf9599af58757e4acbf27c602df9ed79 /drivers/scsi
parenta883b70d8e0a88278c0a1f80753b4dc99962b541 (diff)
parent53637e0760d56274177be7e6d630490bc49766c1 (diff)
Merge tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
Pull libata updates from Jeff Garzik: 1) apply, and then revert, the sysfs export of ATA host controller number. Discussion was continuing after patch application, trying to figure out how to best mesh exported data with the installers, boot-time agents and other parties that want this info. 2) Merge Zero-Power Optical Device Driver (ZPODD) support, bringing the wonderfulness of sane power management to your CD/DVD device. Includes one SCSI-subsystem patch (with appropriate ACKs), adding runtime PM support to 'sr' driver. That is the ZPODD interaction bits. Patchset went through some 13 revisions before it got here; kudos to Intel for persistence. 3) pata_samsung_cf: use devm_clk_get() 4) more ata_piix, ahci PCI IDs 5) Add SATA driver for R-Car SoC 6) Convert libata to use devm_ioremap_resource (Note: I think Greg sent this to you, also) 7) Set proper Sense Key (SK) in the SCSI simulator when ATA passthrough indicates check condition. Google and specification hawks everywhere shall rejoice. * tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (22 commits) [libata] fix smatch warning for zpodd_wake_dev [libata] Set proper SK when CK_COND is set. [libata] Convert to devm_ioremap_resource() libata: add R-Car SATA driver ahci: Add Device IDs for Intel Wellsburg PCH ata_piix: Add Device IDs for Intel Wellsburg PCH [SCSI] remove can_power_off flag from scsi_device [libata] scsi: no poll when ODD is powered off [SCSI] sr: support runtime pm ahci: AHCI-mode SATA patch for Intel Avoton DeviceIDs ata_piix: IDE-mode SATA patch for Intel Avoton DeviceIDs [libata] PM code cleanup for ata port [libata] pm: differentiate system and runtime pm for ata port Revert "libata: export host controller number thru /sys" libata: do not suspend port if normal ODD is attached libata: expose pm qos flags for ata device libata: handle power transition of ODD libata: check zero power ready status for ZPODD libata: move acpi notification code to zpodd libata: identify and init ZPODD devices ...
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_lib.c14
-rw-r--r--drivers/scsi/sr.c46
2 files changed, 57 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f1bf5aff68ed..765398c063c7 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -2617,3 +2617,17 @@ void scsi_kunmap_atomic_sg(void *virt)
kunmap_atomic(virt);
}
EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
+
+void sdev_disable_disk_events(struct scsi_device *sdev)
+{
+ atomic_inc(&sdev->disk_events_disable_depth);
+}
+EXPORT_SYMBOL(sdev_disable_disk_events);
+
+void sdev_enable_disk_events(struct scsi_device *sdev)
+{
+ if (WARN_ON_ONCE(atomic_read(&sdev->disk_events_disable_depth) <= 0))
+ return;
+ atomic_dec(&sdev->disk_events_disable_depth);
+}
+EXPORT_SYMBOL(sdev_enable_disk_events);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 5fc97d2ba2fd..f2884ee90710 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -45,6 +45,7 @@
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -79,6 +80,11 @@ static DEFINE_MUTEX(sr_mutex);
static int sr_probe(struct device *);
static int sr_remove(struct device *);
static int sr_done(struct scsi_cmnd *);
+static int sr_runtime_suspend(struct device *dev);
+
+static struct dev_pm_ops sr_pm_ops = {
+ .runtime_suspend = sr_runtime_suspend,
+};
static struct scsi_driver sr_template = {
.owner = THIS_MODULE,
@@ -86,6 +92,7 @@ static struct scsi_driver sr_template = {
.name = "sr",
.probe = sr_probe,
.remove = sr_remove,
+ .pm = &sr_pm_ops,
},
.done = sr_done,
};
@@ -131,6 +138,16 @@ static inline struct scsi_cd *scsi_cd(struct gendisk *disk)
return container_of(disk->private_data, struct scsi_cd, driver);
}
+static int sr_runtime_suspend(struct device *dev)
+{
+ struct scsi_cd *cd = dev_get_drvdata(dev);
+
+ if (cd->media_present)
+ return -EBUSY;
+ else
+ return 0;
+}
+
/*
* The get and put routines for the struct scsi_cd. Note this entity
* has a scsi_device pointer and owns a reference to this.
@@ -146,7 +163,8 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
kref_get(&cd->kref);
if (scsi_device_get(cd->device))
goto out_put;
- goto out;
+ if (!scsi_autopm_get_device(cd->device))
+ goto out;
out_put:
kref_put(&cd->kref, sr_kref_release);
@@ -162,6 +180,7 @@ static void scsi_cd_put(struct scsi_cd *cd)
mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
+ scsi_autopm_put_device(sdev);
scsi_device_put(sdev);
mutex_unlock(&sr_ref_mutex);
}
@@ -540,6 +559,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
void __user *argp = (void __user *)arg;
int ret;
+ scsi_autopm_get_device(cd->device);
+
mutex_lock(&sr_mutex);
/*
@@ -571,6 +592,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
out:
mutex_unlock(&sr_mutex);
+ scsi_autopm_put_device(cd->device);
return ret;
}
@@ -578,7 +600,17 @@ static unsigned int sr_block_check_events(struct gendisk *disk,
unsigned int clearing)
{
struct scsi_cd *cd = scsi_cd(disk);
- return cdrom_check_events(&cd->cdi, clearing);
+ unsigned int ret;
+
+ if (atomic_read(&cd->device->disk_events_disable_depth) == 0) {
+ scsi_autopm_get_device(cd->device);
+ ret = cdrom_check_events(&cd->cdi, clearing);
+ scsi_autopm_put_device(cd->device);
+ } else {
+ ret = 0;
+ }
+
+ return ret;
}
static int sr_block_revalidate_disk(struct gendisk *disk)
@@ -586,12 +618,16 @@ static int sr_block_revalidate_disk(struct gendisk *disk)
struct scsi_cd *cd = scsi_cd(disk);
struct scsi_sense_hdr sshdr;
+ scsi_autopm_get_device(cd->device);
+
/* if the unit is not ready, nothing more to do */
if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
- return 0;
+ goto out;
sr_cd_check(&cd->cdi);
get_sectorsize(cd);
+out:
+ scsi_autopm_put_device(cd->device);
return 0;
}
@@ -718,6 +754,8 @@ static int sr_probe(struct device *dev)
sdev_printk(KERN_DEBUG, sdev,
"Attached scsi CD-ROM %s\n", cd->cdi.name);
+ scsi_autopm_put_device(cd->device);
+
return 0;
fail_put:
@@ -965,6 +1003,8 @@ static int sr_remove(struct device *dev)
{
struct scsi_cd *cd = dev_get_drvdata(dev);
+ scsi_autopm_get_device(cd->device);
+
blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
del_gendisk(cd->disk);