aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-zpodd.c7
-rw-r--r--drivers/scsi/scsi_lib.c14
-rw-r--r--drivers/scsi/sr.c10
-rw-r--r--include/scsi/scsi_device.h4
4 files changed, 32 insertions, 3 deletions
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index 540b0b7904f..a7df6038353 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -178,11 +178,16 @@ bool zpodd_zpready(struct ata_device *dev)
* Enable runtime wake capability through ACPI and set the powered_off flag,
* this flag will be used during resume to decide what operations are needed
* to take.
+ *
+ * Also, media poll needs to be silenced, so that it doesn't bring the ODD
+ * back to full power state every few seconds.
*/
void zpodd_enable_run_wake(struct ata_device *dev)
{
struct zpodd *zpodd = dev->zpodd;
+ sdev_disable_disk_events(dev->sdev);
+
zpodd->powered_off = true;
device_set_run_wake(&dev->sdev->sdev_gendev, true);
acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, true);
@@ -231,6 +236,8 @@ void zpodd_post_poweron(struct ata_device *dev)
zpodd->zp_sampled = false;
zpodd->zp_ready = false;
+
+ sdev_enable_disk_events(dev->sdev);
}
static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f1bf5aff68e..765398c063c 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 2e8ddd77366..f2884ee9071 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;
}
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index e65c62e82c5..bb1371bf171 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -161,6 +161,8 @@ struct scsi_device {
unsigned wce_default_on:1; /* Cache is ON by default */
unsigned no_dif:1; /* T10 PI (DIF) should be disabled */
+ atomic_t disk_events_disable_depth; /* disable depth for disk events */
+
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
struct list_head event_list; /* asserted events */
struct work_struct event_work;
@@ -397,6 +399,8 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen,
struct scsi_sense_hdr *, int timeout, int retries,
int *resid);
+extern void sdev_disable_disk_events(struct scsi_device *sdev);
+extern void sdev_enable_disk_events(struct scsi_device *sdev);
#ifdef CONFIG_PM_RUNTIME
extern int scsi_autopm_get_device(struct scsi_device *);