summaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/amthif.c
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2016-07-26 01:06:09 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-30 14:39:43 +0200
commite728ae271f4cf71218ec06a6daf61b79466cb466 (patch)
treee3e4ebd68c9a27c32527b5baa3c41dc0c1e14938 /drivers/misc/mei/amthif.c
parent80293c47a6774848c72a2f79816b7de1769c5e85 (diff)
downloadlinux-stable-e728ae271f4cf71218ec06a6daf61b79466cb466.tar.gz
linux-stable-e728ae271f4cf71218ec06a6daf61b79466cb466.tar.bz2
linux-stable-e728ae271f4cf71218ec06a6daf61b79466cb466.zip
mei: amthif: fix deadlock in initialization during a reset
The device lock was unnecessary obtained in bus rescan work before the amthif client search. That causes incorrect lock ordering and task hang: ... [88004.613213] INFO: task kworker/1:14:21832 blocked for more than 120 seconds. ... [88004.645934] Workqueue: events mei_cl_bus_rescan_work ... The correct lock order is cl_bus_lock device_lock me_clients_rwsem Move device_lock into amthif init function that called after me_clients_rwsem is released. This fixes regression introduced by commit: commit 025fb792bac3 ("mei: split amthif client init from end of clients enumeration") Cc: <stable@vger.kernel.org> # 4.6+ Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/amthif.c')
-rw-r--r--drivers/misc/mei/amthif.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 2222b60e9208..082462ea90c9 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -66,8 +66,12 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
struct mei_cl *cl = &dev->iamthif_cl;
int ret;
- if (mei_cl_is_connected(cl))
- return 0;
+ mutex_lock(&dev->device_lock);
+
+ if (mei_cl_is_connected(cl)) {
+ ret = 0;
+ goto out;
+ }
dev->iamthif_state = MEI_IAMTHIF_IDLE;
@@ -76,11 +80,13 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
ret = mei_cl_link(cl);
if (ret < 0) {
dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
- return ret;
+ goto out;
}
ret = mei_cl_connect(cl, me_cl, NULL);
+out:
+ mutex_unlock(&dev->device_lock);
return ret;
}