]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
mei: fix deadlock on mei reset
authorTomas Winkler <tomas.winkler@intel.com>
Sun, 5 Mar 2017 19:40:41 +0000 (21:40 +0200)
committerTim Gardner <tim.gardner@canonical.com>
Thu, 30 Mar 2017 12:35:45 +0000 (06:35 -0600)
BugLink: http://bugs.launchpad.net/bugs/1677589
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@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
drivers/misc/mei/init.c

index 41e5760a6886dfee96840ecceaed372c9e45194a..a13abc8fa1bce6ba20238068d5bb5355733d0690 100644 (file)
@@ -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_struct *work)
                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;