[PATCH 4.10 063/111] mei: fix deadlock on mei reset

From: Greg Kroah-Hartman
Date: Tue Mar 28 2017 - 09:24:57 EST


4.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tomas Winkler <tomas.winkler@xxxxxxxxx>

commit a733ded50b6ea846200073e7381a302df71e13b3 upstream.

This patch fixes 'mei: synchronize irq before initiating a reset'
The patch had introduced a deadlock between irq thread and mei_reset()
as they are both holding the same device lock.

---> device_lock:
mei_reset()
<---- interrupt thread
device_lock
---> synchornize_irq()
wait on interrupt thread == (dead lock)

The fix is to call synchronize_irq
prior to call locked mei_reset function.

Fixes: f302bb0de6ac (mei: synchronize irq before initiating a reset)
Signed-off-by: Tomas Winkler <tomas.winkler@xxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/misc/mei/init.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -124,8 +124,6 @@ int mei_reset(struct mei_device *dev)

mei_clear_interrupts(dev);

- mei_synchronize_irq(dev);
-
/* we're already in reset, cancel the init timer
* if the reset was called due the hbm protocol error
* we need to call it before hw start
@@ -304,6 +302,9 @@ static void mei_reset_work(struct work_s
container_of(work, struct mei_device, reset_work);
int ret;

+ mei_clear_interrupts(dev);
+ mei_synchronize_irq(dev);
+
mutex_lock(&dev->device_lock);

ret = mei_reset(dev);
@@ -328,6 +329,9 @@ void mei_stop(struct mei_device *dev)

mei_cancel_work(dev);

+ mei_clear_interrupts(dev);
+ mei_synchronize_irq(dev);
+
mutex_lock(&dev->device_lock);

dev->dev_state = MEI_DEV_POWER_DOWN;