aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-07-07 17:22:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-07 18:04:12 -0400
commit4f273959b850569253299987eee611927f048de7 (patch)
tree384abc27b134c3570ad8bcc7b6461e4128e7ed6a
parentc7e9ad7da219cf3f8a7cc45eb1c02fdd91199e8d (diff)
mei: nfc: fix deadlock on shutdown/suspend path
In function mei_nfc_host_exit mei_cl_remove_device cannot be called under the device mutex as device removing flow invokes the device driver remove handler that calls in turn to mei_cl_disable_device which naturally acquires the device mutex. Also remove mei_cl_bus_remove_devices which has the same issue, but is never executed as currently the only device on the mei client bus is NFC and a new device cannot be easily added till the bus revamp is completed. This fixes regression caused by commit be9b720a0ccb ("mei_phy: move all nfc logic from mei driver to nfc") Prior to this change the nfc driver remove handler called to no-op disable function while actual nfc device was disabled directly from the mei driver. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/misc/mei/bus.c16
-rw-r--r--drivers/misc/mei/init.c2
-rw-r--r--drivers/misc/mei/nfc.c3
3 files changed, 2 insertions, 19 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 357b6ae4d207..458aa5a09c52 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -552,22 +552,6 @@ void mei_cl_bus_rx_event(struct mei_cl *cl)
552 schedule_work(&device->event_work); 552 schedule_work(&device->event_work);
553} 553}
554 554
555void mei_cl_bus_remove_devices(struct mei_device *dev)
556{
557 struct mei_cl *cl, *next;
558
559 mutex_lock(&dev->device_lock);
560 list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
561 if (cl->device)
562 mei_cl_remove_device(cl->device);
563
564 list_del(&cl->device_link);
565 mei_cl_unlink(cl);
566 kfree(cl);
567 }
568 mutex_unlock(&dev->device_lock);
569}
570
571int __init mei_cl_bus_init(void) 555int __init mei_cl_bus_init(void)
572{ 556{
573 return bus_register(&mei_cl_bus_type); 557 return bus_register(&mei_cl_bus_type);
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 94514b2c7a50..00c3865ca3b1 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -333,8 +333,6 @@ void mei_stop(struct mei_device *dev)
333 333
334 mei_nfc_host_exit(dev); 334 mei_nfc_host_exit(dev);
335 335
336 mei_cl_bus_remove_devices(dev);
337
338 mutex_lock(&dev->device_lock); 336 mutex_lock(&dev->device_lock);
339 337
340 mei_wd_stop(dev); 338 mei_wd_stop(dev);
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
index b983c4ecad38..290ef3037437 100644
--- a/drivers/misc/mei/nfc.c
+++ b/drivers/misc/mei/nfc.c
@@ -402,11 +402,12 @@ void mei_nfc_host_exit(struct mei_device *dev)
402 402
403 cldev->priv_data = NULL; 403 cldev->priv_data = NULL;
404 404
405 mutex_lock(&dev->device_lock);
406 /* Need to remove the device here 405 /* Need to remove the device here
407 * since mei_nfc_free will unlink the clients 406 * since mei_nfc_free will unlink the clients
408 */ 407 */
409 mei_cl_remove_device(cldev); 408 mei_cl_remove_device(cldev);
409
410 mutex_lock(&dev->device_lock);
410 mei_nfc_free(ndev); 411 mei_nfc_free(ndev);
411 mutex_unlock(&dev->device_lock); 412 mutex_unlock(&dev->device_lock);
412} 413}