summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_pm.c
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2015-06-05 18:50:24 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:00:57 -0700
commitd8a844389a22602a9d43f147be1b2158ff69062b (patch)
tree833738997f1972cd3d66c3dd208306c85dbd6194 /drivers/scsi/scsi_pm.c
parentedf4a84a0b60800e7195fdf140eb93241726e09e (diff)
scsi: pm: fix deadlock condition
We are seeing deadlock in scsi runtime resume context, here is the call trace: __switch_to+0x70/0x7c __schedule+0x4e0/0x734 schedule+0x70/0x7c __pm_runtime_barrier+0xdc/0x108 __pm_runtime_disable+0x60/0xf4 scsi_dev_type_resume+0x74/0xb4 scsi_runtime_resume+0x5c/0xbc __rpm_callback+0x3c/0x74 rpm_callback+0x60/0x84 rpm_resume+0x368/0x47c __pm_runtime_resume+0x6c/0x94 scsi_autopm_get_device+0x28/0x60 sg_open+0x148/0x5c0 chrdev_open+0x134/0x16c do_dentry_open+0x260/0x2dc vfs_open+0x3c/0x48 do_last+0x844/0xae8 path_openat+0x220/0x5c4 do_filp_open+0x2c/0x80 do_sys_open+0x160/0x1fc SyS_openat+0xc/0x18 It seems commit 3c31b52f96f7 ("scsi: async sd resume") has introduced a bug where runtime resume (for scsi devices not managed by upper level driver) context end up calling pm_runtime_disable() which waits for the runtime resume to finish and hence causing the deadlock. This change fixes this issue by making sure that we don't call pm_runtime_disable() if we are in runtime PM context. Change-Id: I770060c062ee828ef9117b8e5a4c248f48381f35 Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Diffstat (limited to 'drivers/scsi/scsi_pm.c')
-rw-r--r--drivers/scsi/scsi_pm.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 6bd26acd1985..055b7cd933e6 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -16,6 +16,11 @@
#include "scsi_priv.h"
+#ifdef CONFIG_PM_RUNTIME
+static int do_scsi_runtime_resume(struct device *dev,
+ const struct dev_pm_ops *pm);
+#endif
+
#ifdef CONFIG_PM_SLEEP
static int do_scsi_suspend(struct device *dev, const struct dev_pm_ops *pm)
@@ -77,7 +82,7 @@ static int scsi_dev_type_resume(struct device *dev,
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);
pm_runtime_enable(dev);