Bluetooth: Fix Deadlock on Legacy Scan/Pair

Fix nested calls to hci_dev_lock().

Signed-off-by: Brian Gix <bgix@codeaurora.org>
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 1e59cb3..2276428 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3088,12 +3088,16 @@
 	num_reports = skb->data[0];
 	ev = (void *) &skb->data[1];
 
+	hci_dev_lock(hdev);
+
 	while (num_reports--) {
 		mgmt_device_found(hdev->id, &ev->bdaddr, ev->bdaddr_type,
 				1, NULL, 0, ev->length, ev->data);
 		hci_add_adv_entry(hdev, ev);
 		ev = (void *) (ev->data + ev->length + 1);
 	}
+
+	hci_dev_unlock(hdev);
 }
 
 static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 79e0891..72d249e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2426,8 +2426,6 @@
 	if (!hdev)
 		return -ENODEV;
 
-	hci_dev_lock(hdev);
-
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
 
 	ev.auto_confirm = 0;
@@ -2452,7 +2450,6 @@
 	ev.event = event;
 	put_unaligned_le32(value, &ev.value);
 
-	hci_dev_unlock(hdev);
 	hci_dev_put(hdev);
 
 	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
@@ -2623,8 +2620,6 @@
 			struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
 			struct hci_cp_le_set_scan_enable le_cp = {0, 0};
 
-			hci_dev_lock(hdev);
-
 			ilp->int_phase *= 2;
 			ilp->int_count = 0;
 			if (ilp->mode == SCAN_LE) {
@@ -2638,7 +2633,6 @@
 				ilp->mode = SCAN_BR;
 				del_timer_sync(&ilp->le_timer);
 			}
-			hci_dev_unlock(hdev);
 		}
 
 		if (hdev)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 9089e65..8943510 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -292,6 +292,7 @@
 	struct hci_conn *hcon = conn->hcon;
 	u8 method;
 	u32 passkey = 0;
+	int ret = 0;
 
 	/* Initialize key to JUST WORKS */
 	memset(hcon->tk, 0, sizeof(hcon->tk));
@@ -356,15 +357,23 @@
 	}
 
 agent_request:
+	hci_dev_lock(hcon->hdev);
+
 	switch (method) {
 	case SMP_REQ_PASSKEY:
-		return mgmt_user_confirm_request(0, HCI_EV_USER_PASSKEY_REQUEST,
-								conn->dst, 0);
+		ret = mgmt_user_confirm_request(hcon->hdev->id,
+				HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
+		break;
 	case SMP_CFM_PASSKEY:
 	default:
-		return mgmt_user_confirm_request(0, HCI_EV_USER_CONFIRM_REQUEST,
-							conn->dst, passkey);
+		ret = mgmt_user_confirm_request(hcon->hdev->id,
+			HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
+		break;
 	}
+
+	hci_dev_unlock(hcon->hdev);
+
+	return ret;
 }
 
 static int send_pairing_confirm(struct l2cap_conn *conn)