Bluetooth: Fix LE pairing scenarios when initiated remotely

Fix setting of ENCRYPTION_PENDING and Connection refcnt's that could
be out of sync due to remote slave issued security requests.

Change-Id: Ie72abd0648182db0ef60693820139f40ef2e4bf6
Signed-off-by: Brian Gix <bgix@codeaurora.org>
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a6e2aab..6838fd5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -438,6 +438,7 @@
 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
 								&reason);
 		del_timer(&hcon->smp_timer);
+		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 		mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
 		hci_conn_put(hcon);
 	} else if (hcon->cfm_pending) {
@@ -686,6 +687,8 @@
 
 	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 
+	hci_conn_hold(hcon);
+
 	return 0;
 }
 
@@ -846,6 +849,7 @@
 		reason = 0;
 		err = -EPERM;
 		del_timer(&hcon->smp_timer);
+		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 		mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[1]);
 		hci_conn_put(hcon);
 		break;
@@ -895,6 +899,7 @@
 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
 								&reason);
 		del_timer(&hcon->smp_timer);
+		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 		mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
 		hci_conn_put(hcon);
 	}
@@ -989,6 +994,7 @@
 			hcon->disconn_cfm_cb(hcon, 0);
 
 		del_timer(&hcon->smp_timer);
+		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 		mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
 		hci_conn_put(hcon);
 	}
@@ -1002,6 +1008,8 @@
 
 	BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
 
+	clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
 	if (!status && encrypt && !hcon->sec_req)
 		smp_distribute_keys(conn, 0);
 
@@ -1009,6 +1017,9 @@
 	else if (hcon->sec_req  && (status || !encrypt))
 		smp_conn_security(conn, hcon->sec_level);
 
+	else
+		hci_conn_put(hcon);
+
 	return 0;
 }
 
@@ -1020,6 +1031,7 @@
 	BT_DBG("%p", conn);
 
 	smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
+	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
 	mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
 	hci_conn_put(conn->hcon);
 }