diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 054923e3393c..32060a418a62 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -970,6 +970,10 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, transport_configure_device(&sdev->sdev_gendev); + /* The LLD can override auto suspend tunables in ->slave_configure() */ + sdev->use_rpm_auto = 0; + sdev->autosuspend_delay = SCSI_DEFAULT_AUTOSUSPEND_DELAY; + if (sdev->host->hostt->slave_configure) { ret = sdev->host->hostt->slave_configure(sdev); if (ret) { diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 21930c9ac9cd..e79c2489dd11 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1044,7 +1044,8 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) device_enable_async_suspend(&sdev->sdev_gendev); scsi_autopm_get_target(starget); pm_runtime_set_active(&sdev->sdev_gendev); - pm_runtime_forbid(&sdev->sdev_gendev); + if (!sdev->use_rpm_auto) + pm_runtime_forbid(&sdev->sdev_gendev); pm_runtime_enable(&sdev->sdev_gendev); scsi_autopm_put_target(starget); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index aa64e7de3525..79cef194b9a1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3049,6 +3049,9 @@ static void sd_probe_async(void *data, async_cookie_t cookie) } blk_pm_runtime_init(sdp->request_queue, dev); + if (sdp->autosuspend_delay >= 0) + pm_runtime_set_autosuspend_delay(dev, sdp->autosuspend_delay); + add_disk(gd); if (sdkp->capacity) sd_dif_config_host(sdkp); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index fe89d7cd67b9..f9f445be1a50 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -175,6 +175,10 @@ struct scsi_device { unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ unsigned broken_fua:1; /* Don't set FUA bit */ unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ + unsigned use_rpm_auto:1; /* Enable runtime PM auto suspend */ + +#define SCSI_DEFAULT_AUTOSUSPEND_DELAY -1 + int autosuspend_delay; atomic_t disk_events_disable_depth; /* disable depth for disk events */