Bluetooth: Avoid deadlock in management ops code
Fixes a deadlock issue due to spinlock being acquired
first in the process context and followed by a second
acquisition in the interrupt context
CRs-fixed: 319052
Change-Id: If17be9fa6f020dd1abd248f8999c2614251fc509
Signed-off-by: Subramanian Srinivasan <subrsrin@codeaurora.org>
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a27358f..e1a90f8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -581,8 +581,11 @@
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->flags) &&
- hdev->dev_type == HCI_BREDR)
+ hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock_bh(hdev);
mgmt_powered(hdev->id, 1);
+ hci_dev_unlock_bh(hdev);
+ }
} else {
/* Init failed, cleanup */
tasklet_kill(&hdev->rx_task);
@@ -668,8 +671,11 @@
* and no tasks are scheduled. */
hdev->close(hdev);
- if (hdev->dev_type == HCI_BREDR)
+ if (hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock_bh(hdev);
mgmt_powered(hdev->id, 0);
+ hci_dev_unlock_bh(hdev);
+ }
/* Clear only non-persistent flags */
if (test_bit(HCI_MGMT, &hdev->flags))
@@ -1547,8 +1553,11 @@
if (!test_bit(HCI_INIT, &hdev->flags) &&
!test_bit(HCI_SETUP, &hdev->flags) &&
- hdev->dev_type == HCI_BREDR)
+ hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock_bh(hdev);
mgmt_index_removed(hdev->id);
+ hci_dev_unlock_bh(hdev);
+ }
if (!IS_ERR(hdev->tfm))
crypto_free_blkcipher(hdev->tfm);