NFC: nci: Move logical connection structure allocation

conn_info is currently allocated only after nfcee_discovery_ntf
which is not generic enough for logical connection other than
NFCEE. The corresponding conn_info is now created in
nci_core_conn_create_rsp().

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.c b/drivers/nfc/st21nfcb/st21nfcb_se.c
index 3b465e4..d23e8f2 100644
--- a/drivers/nfc/st21nfcb/st21nfcb_se.c
+++ b/drivers/nfc/st21nfcb/st21nfcb_se.c
@@ -513,7 +513,7 @@
 
 	dest_params->type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE;
 	dest_params->length = sizeof(struct dest_spec_params);
-	spec_params.id = ndev->hci_dev->conn_info->id;
+	spec_params.id = ndev->hci_dev->nfcee_id;
 	spec_params.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS;
 	memcpy(dest_params->value, &spec_params, sizeof(struct dest_spec_params));
 	r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCEE, 1,
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index d34c1b2..ff87f86 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -159,6 +159,7 @@
 #define NCI_HCI_MAX_GATES          256
 
 struct nci_hci_dev {
+	u8 nfcee_id;
 	struct nci_dev *ndev;
 	struct nci_conn_info *conn_info;
 
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index ecf2539..ed54ec5 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -615,12 +615,20 @@
 
 int nci_hci_dev_session_init(struct nci_dev *ndev)
 {
+	struct nci_conn_info    *conn_info;
 	struct sk_buff *skb;
 	int r;
 
 	ndev->hci_dev->count_pipes = 0;
 	ndev->hci_dev->expected_pipes = 0;
 
+	conn_info = ndev->hci_dev->conn_info;
+	if (!conn_info)
+		return -EPROTO;
+
+	conn_info->data_exchange_cb = nci_hci_data_received_cb;
+	conn_info->data_exchange_cb_context = ndev;
+
 	nci_hci_reset_pipes(ndev->hci_dev);
 
 	if (ndev->hci_dev->init_data.gates[0].gate != NCI_HCI_ADMIN_GATE)
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 6bbbf6fda..3218071 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -723,7 +723,6 @@
 					  struct sk_buff *skb)
 {
 	u8 status = NCI_STATUS_OK;
-	struct nci_conn_info    *conn_info;
 	struct nci_nfcee_discover_ntf   *nfcee_ntf =
 				(struct nci_nfcee_discover_ntf *)skb->data;
 
@@ -734,27 +733,9 @@
 	 * and only one, NFCEE_DISCOVER_NTF with a Protocol type of
 	 * “HCI Access”, even if the HCI Network contains multiple NFCEEs.
 	 */
-	if (!ndev->hci_dev->conn_info) {
-		conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
-					 sizeof(*conn_info), GFP_KERNEL);
-		if (!conn_info) {
-			status = NCI_STATUS_REJECTED;
-			goto exit;
-		}
+	ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id;
+	ndev->cur_id = nfcee_ntf->nfcee_id;
 
-		conn_info->id = nfcee_ntf->nfcee_id;
-		conn_info->conn_id = NCI_INVALID_CONN_ID;
-
-		conn_info->data_exchange_cb = nci_hci_data_received_cb;
-		conn_info->data_exchange_cb_context = ndev;
-
-		INIT_LIST_HEAD(&conn_info->list);
-		list_add(&conn_info->list, &ndev->conn_info_list);
-
-		ndev->hci_dev->conn_info = conn_info;
-	}
-
-exit:
 	nci_req_complete(ndev, status);
 }
 
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index b419fed..02486bc 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -233,16 +233,27 @@
 
 	if (status == NCI_STATUS_OK) {
 		rsp = (struct nci_core_conn_create_rsp *)skb->data;
-		list_for_each_entry(conn_info, &ndev->conn_info_list, list) {
-			if (conn_info->id == ndev->cur_id)
-				break;
-		}
 
-		if (!conn_info || conn_info->id != ndev->cur_id) {
+		conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
+					 sizeof(*conn_info), GFP_KERNEL);
+		if (!conn_info) {
 			status = NCI_STATUS_REJECTED;
 			goto exit;
 		}
 
+		conn_info->id = ndev->cur_id;
+		conn_info->conn_id = rsp->conn_id;
+
+		/* Note: data_exchange_cb and data_exchange_cb_context need to
+		 * be specify out of nci_core_conn_create_rsp_packet
+		 */
+
+		INIT_LIST_HEAD(&conn_info->list);
+		list_add(&conn_info->list, &ndev->conn_info_list);
+
+		if (ndev->cur_id == ndev->hci_dev->nfcee_id)
+			ndev->hci_dev->conn_info = conn_info;
+
 		conn_info->conn_id = rsp->conn_id;
 		conn_info->max_pkt_payload_len = rsp->max_ctrl_pkt_payload_len;
 		atomic_set(&conn_info->credits_cnt, rsp->credits_cnt);
@@ -255,9 +266,17 @@
 static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
 					   struct sk_buff *skb)
 {
+	struct nci_conn_info *conn_info;
 	__u8 status = skb->data[0];
 
 	pr_debug("status 0x%x\n", status);
+	if (status == NCI_STATUS_OK) {
+		conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_id);
+		if (conn_info) {
+			list_del(&conn_info->list);
+			devm_kfree(&ndev->nfc_dev->dev, conn_info);
+		}
+	}
 	nci_req_complete(ndev, status);
 }