diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2015-07-07 17:22:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-07 18:04:12 -0400 |
commit | 4f273959b850569253299987eee611927f048de7 (patch) | |
tree | 384abc27b134c3570ad8bcc7b6461e4128e7ed6a | |
parent | c7e9ad7da219cf3f8a7cc45eb1c02fdd91199e8d (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.c | 16 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/nfc.c | 3 |
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 | ||
555 | void 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 | |||
571 | int __init mei_cl_bus_init(void) | 555 | int __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 | } |