scsi: squash of multiple fixes for msm-4.4 kernel
This change is the squash of following commits from msm-4.4 kernel:
<36c183b7> ("scsi: Adjust DBD setting in mode sense for caching mode page per LLD")
<d2e7a77a> ("scsi: sd: reduce log level for suspend/resume log messages")
<c6b82e8b> ("scsi: Allow auto suspend override by low-level driver")
<edf4a84a> ("scsi: pm: fix null pointer access during sg_open")
<d8a84438> ("scsi: pm: fix deadlock condition")
<2b80aee4> ("scsi: pm: keep request queue and scsi device runtime status in sync")
<628aaf1b> ("scsi: reduce the informational log messages during initial probe")
<fe64842c> ("scsi: sd: remove check_events callback")
<2f82ca7b> ("scsi: pm: Remove use of CONFIG_PM_RUNTIME")
Change-Id: Ia8430f5c42dd66dbb044733eaa30d0ccd097b3c9
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index b44c1bb..af17066 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -16,6 +16,9 @@
#include "scsi_priv.h"
+static int do_scsi_runtime_resume(struct device *dev,
+ const struct dev_pm_ops *pm);
+
#ifdef CONFIG_PM_SLEEP
static int do_scsi_suspend(struct device *dev, const struct dev_pm_ops *pm)
@@ -77,10 +80,22 @@
scsi_device_resume(to_scsi_device(dev));
dev_dbg(dev, "scsi resume: %d\n", err);
- if (err == 0) {
+ if (err == 0 && (cb != do_scsi_runtime_resume)) {
pm_runtime_disable(dev);
- pm_runtime_set_active(dev);
+ err = pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+
+ if (!err && scsi_is_sdev_device(dev)) {
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ /*
+ * If scsi device runtime PM is managed by block layer
+ * then we should update request queue's runtime status
+ * as well.
+ */
+ if (sdev->request_queue->dev)
+ blk_post_runtime_resume(sdev->request_queue, 0);
+ }
}
return err;
@@ -223,12 +238,32 @@
#endif /* CONFIG_PM_SLEEP */
+static int do_scsi_runtime_suspend(struct device *dev,
+ const struct dev_pm_ops *pm)
+{
+ return pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0;
+}
+
+static int do_scsi_runtime_resume(struct device *dev,
+ const struct dev_pm_ops *pm)
+{
+ return pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0;
+}
+
static int sdev_runtime_suspend(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
struct scsi_device *sdev = to_scsi_device(dev);
int err = 0;
+ if (!sdev->request_queue->dev) {
+ err = scsi_dev_type_suspend(dev, do_scsi_runtime_suspend);
+ if (err == -EAGAIN)
+ pm_schedule_suspend(dev, jiffies_to_msecs(
+ round_jiffies_up_relative(HZ/10)));
+ return err;
+ }
+
err = blk_pre_runtime_suspend(sdev->request_queue);
if (err)
return err;
@@ -258,6 +293,9 @@
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int err = 0;
+ if (!sdev->request_queue->dev)
+ return scsi_dev_type_resume(dev, do_scsi_runtime_resume);
+
blk_pre_runtime_resume(sdev->request_queue);
if (pm && pm->runtime_resume)
err = pm->runtime_resume(dev);