From 3aacd7fe552b093fc24a8082e16467eb26c2fa32 Mon Sep 17 00:00:00 2001
From: Christophe Ricard <christophe.ricard@gmail.com>
Date: Sat, 30 Apr 2016 09:12:53 +0200
Subject: nfc: st-nci: Move loopback usage from HCI to NCI

NCI provides possible way to run loopback testing has done over HCI.

For us it offers many advantages:
- It simplifies the code: No more need for a vendor_cmds structure
- Loopback over HCI may not be supported in future st-nci firmware

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/st-nci/se.c          |  5 ----
 drivers/nfc/st-nci/st-nci.h      | 13 ++-------
 drivers/nfc/st-nci/vendor_cmds.c | 62 ++++++++--------------------------------
 3 files changed, 14 insertions(+), 66 deletions(-)

(limited to 'drivers/nfc')

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 420f019cc42f..56f2112e0cd8 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -113,8 +113,6 @@ static struct nci_hci_gate st_nci_gates[] = {
 
 	{NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
 					ST_NCI_HOST_CONTROLLER_ID},
-	{NCI_HCI_LOOPBACK_GATE, NCI_HCI_INVALID_PIPE,
-					ST_NCI_HOST_CONTROLLER_ID},
 
 	/* Secure element pipes are created by secure element host */
 	{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
@@ -385,9 +383,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
 	case ST_NCI_CONNECTIVITY_GATE:
 		st_nci_hci_connectivity_event_received(ndev, host, event, skb);
 	break;
-	case NCI_HCI_LOOPBACK_GATE:
-		st_nci_hci_loopback_event_received(ndev, event, skb);
-	break;
 	}
 }
 EXPORT_SYMBOL_GPL(st_nci_hci_event_received);
diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index 8783f9594d65..afaf138b7e1b 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -92,8 +92,7 @@ struct st_nci_se_info {
  *	white list).
  * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
  *	technology. When using this command to anti-collision is done.
- * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
- *	connectivity.
+ * @LOOPBACK: Allow to echo a command and test the Dh to CLF connectivity.
  * @HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
  *	CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
  * @HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
@@ -115,7 +114,7 @@ enum nfc_vendor_cmds {
 	HCI_DM_RESET,
 	HCI_GET_PARAM,
 	HCI_DM_FIELD_GENERATOR,
-	HCI_LOOPBACK,
+	LOOPBACK,
 	HCI_DM_FWUPD_START,
 	HCI_DM_FWUPD_END,
 	HCI_DM_VDC_MEASUREMENT_VALUE,
@@ -123,17 +122,11 @@ enum nfc_vendor_cmds {
 	MANUFACTURER_SPECIFIC,
 };
 
-struct st_nci_vendor_info {
-	struct completion req_completion;
-	struct sk_buff *rx_skb;
-};
-
 struct st_nci_info {
 	struct llt_ndlc *ndlc;
 	unsigned long flags;
 
 	struct st_nci_se_info se_info;
-	struct st_nci_vendor_info vendor_info;
 };
 
 void st_nci_remove(struct nci_dev *ndev);
@@ -155,8 +148,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
 void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
 						struct sk_buff *skb);
 
-void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
-					struct sk_buff *skb);
 int st_nci_vendor_cmds_init(struct nci_dev *ndev);
 
 #endif /* __LOCAL_ST_NCI_H_ */
diff --git a/drivers/nfc/st-nci/vendor_cmds.c b/drivers/nfc/st-nci/vendor_cmds.c
index b5debce4ae0b..1a836c77c268 100644
--- a/drivers/nfc/st-nci/vendor_cmds.c
+++ b/drivers/nfc/st-nci/vendor_cmds.c
@@ -333,62 +333,28 @@ exit:
 	return r;
 }
 
-void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
-					struct sk_buff *skb)
-{
-	struct st_nci_info *info = nci_get_drvdata(ndev);
-
-	switch (event) {
-	case ST_NCI_EVT_POST_DATA:
-		info->vendor_info.rx_skb = skb;
-	break;
-	default:
-		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on loopback gate\n");
-	}
-	complete(&info->vendor_info.req_completion);
-}
-EXPORT_SYMBOL(st_nci_hci_loopback_event_received);
-
-static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
-			       size_t data_len)
+static int st_nci_loopback(struct nfc_dev *dev, void *data,
+			   size_t data_len)
 {
 	int r;
-	struct sk_buff *msg;
+	struct sk_buff *msg, *skb;
 	struct nci_dev *ndev = nfc_get_drvdata(dev);
-	struct st_nci_info *info = nci_get_drvdata(ndev);
 
 	if (data_len <= 0)
 		return -EPROTO;
 
-	reinit_completion(&info->vendor_info.req_completion);
-	info->vendor_info.rx_skb = NULL;
+	r = nci_nfcc_loopback(ndev, data, data_len, &skb);
+	if (r < 0)
+		return r;
 
-	r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
-			       ST_NCI_EVT_POST_DATA, data, data_len);
-	if (r != data_len) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	wait_for_completion_interruptible(&info->vendor_info.req_completion);
-
-	if (!info->vendor_info.rx_skb ||
-	    info->vendor_info.rx_skb->len != data_len) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
-					ST_NCI_VENDOR_OUI,
-					HCI_LOOPBACK,
-					info->vendor_info.rx_skb->len);
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+					     LOOPBACK, skb->len);
 	if (!msg) {
 		r = -ENOMEM;
 		goto free_skb;
 	}
 
-	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
-		    info->vendor_info.rx_skb->data)) {
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
 		kfree_skb(msg);
 		r = -ENOBUFS;
 		goto free_skb;
@@ -396,8 +362,7 @@ static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
 
 	r = nfc_vendor_cmd_reply(msg);
 free_skb:
-	kfree_skb(info->vendor_info.rx_skb);
-exit:
+	kfree_skb(skb);
 	return r;
 }
 
@@ -485,8 +450,8 @@ static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
 	},
 	{
 		.vendor_id = ST_NCI_VENDOR_OUI,
-		.subcmd = HCI_LOOPBACK,
-		.doit = st_nci_hci_loopback,
+		.subcmd = LOOPBACK,
+		.doit = st_nci_loopback,
 	},
 	{
 		.vendor_id = ST_NCI_VENDOR_OUI,
@@ -507,9 +472,6 @@ static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
 
 int st_nci_vendor_cmds_init(struct nci_dev *ndev)
 {
-	struct st_nci_info *info = nci_get_drvdata(ndev);
-
-	init_completion(&info->vendor_info.req_completion);
 	return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
 				   sizeof(st_nci_vendor_cmds));
 }
-- 
cgit v1.2.3