summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2013-01-23 15:09:32 +0800
committerJeff Garzik <jgarzik@redhat.com>2013-01-25 15:36:43 -0500
commit6f4c827e68a78731c6c75df69bf7b75b029ec70c (patch)
tree5113f12fc6fd5c7e2769aa19c2a1bb59ea647652 /drivers/scsi
parent6c7f1e2f12f6f37ddda01180c9e5c407eccce616 (diff)
downloadlinux-6f4c827e68a78731c6c75df69bf7b75b029ec70c.tar.gz
linux-6f4c827e68a78731c6c75df69bf7b75b029ec70c.tar.bz2
linux-6f4c827e68a78731c6c75df69bf7b75b029ec70c.zip
[libata] scsi: no poll when ODD is powered off
When the ODD is powered off, any action the user did to the ODD that would generate a media event will trigger an ACPI interrupt, so the poll for media event is no longer necessary. And the poll will also cause a runtime status change, which will stop the ODD from staying in powered off state, so the poll should better be stopped. But since we don't have access to the gendisk structure in LLDs, here comes the disk_events_disable_depth for scsi device. This field is a hint set by LLDs to convey information to upper layer drivers. A value of 0 means media poll is necessary for the device, while values above 0 means media poll is not needed and should better be skipped. So we can increase its value when we are to power off the ODD in ATA layer and decrease its value when the ODD is powered on, effectively silence the media events poll. Signed-off-by: Aaron Lu <aaron.lu@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_lib.c14
-rw-r--r--drivers/scsi/sr.c10
2 files changed, 21 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 2e8ddd77366f..f2884ee90710 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -602,9 +602,13 @@ static unsigned int sr_block_check_events(struct gendisk *disk,
struct scsi_cd *cd = scsi_cd(disk);
unsigned int ret;
- scsi_autopm_get_device(cd->device);
- ret = cdrom_check_events(&cd->cdi, clearing);
- scsi_autopm_put_device(cd->device);
+ 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;
}