summaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@collabora.com>2016-07-08 09:52:41 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2016-07-10 19:57:50 -0400
commitf23a9868b1c45e77ec6082eb95508885111ffda1 (patch)
tree56cd191b65e22625bf3a32f00e4057746316a5ff /net/nfc
parente8e7f4217564fc115b60a9373646afb193aa08cf (diff)
NFC: digital: Fix target DEP_REQ I-PDU handling after ATN PDU
When the initiator sends a DEP_REQ I-PDU, the target device may not reply in a timely manner. In this case the initiator device must send an attention PDU (ATN) and if the recipient replies with an ATN PDU in return, then the last I-PDU must be sent again by the initiator. This patch fixes how the target handles I-PDU received after an ATN PDU has been received. There are 2 possible cases: - The target has received the initial DEP_REQ and sends back the DEP_RES but the initiator did not receive it. In this case, after the initiator has sent an ATN PDU and the target replied it (with an ATN as well), the initiator sends the saved skb of the initial DEP_REQ again and the target replies with the saved skb of the initial DEP_RES. - Or the target did not even received the initial DEP_REQ. In this case, after the ATN PDUs exchange, the initiator sends the saved skb and the target simply passes it up, just as usual. This behavior is controlled using the atn_count and the PNI field of the digital device structure. Signed-off-by: Thierry Escande <thierry.escande@collabora.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/digital_dep.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index ed3a52971d65..1778c23751d4 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -1086,22 +1086,38 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
1086 case DIGITAL_NFC_DEP_PFB_I_PDU: 1086 case DIGITAL_NFC_DEP_PFB_I_PDU:
1087 pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); 1087 pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
1088 1088
1089 if ((ddev->atn_count && (DIGITAL_NFC_DEP_PFB_PNI(pfb - 1) !=
1090 ddev->curr_nfc_dep_pni)) ||
1091 (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni)) {
1092 PROTOCOL_ERR("14.12.3.4");
1093 rc = -EIO;
1094 goto exit;
1095 }
1096
1097 if (ddev->atn_count) { 1089 if (ddev->atn_count) {
1090 /* The target has received (and replied to) at least one
1091 * ATN DEP_REQ.
1092 */
1098 ddev->atn_count = 0; 1093 ddev->atn_count = 0;
1099 1094
1100 rc = digital_tg_send_saved_skb(ddev); 1095 /* pni of resp PDU equal to the target current pni - 1
1101 if (rc) 1096 * means resp is the previous DEP_REQ PDU received from
1102 goto exit; 1097 * the initiator so the target replies with saved_skb
1098 * which is the previous DEP_RES saved in
1099 * digital_tg_send_dep_res().
1100 */
1101 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) ==
1102 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni - 1)) {
1103 rc = digital_tg_send_saved_skb(ddev);
1104 if (rc)
1105 goto exit;
1103 1106
1104 return; 1107 goto free_resp;
1108 }
1109
1110 /* atn_count > 0 and PDU pni != curr_nfc_dep_pni - 1
1111 * means the target probably did not received the last
1112 * DEP_REQ PDU sent by the initiator. The target
1113 * fallbacks to normal processing then.
1114 */
1115 }
1116
1117 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
1118 PROTOCOL_ERR("14.12.3.4");
1119 rc = -EIO;
1120 goto exit;
1105 } 1121 }
1106 1122
1107 kfree_skb(ddev->saved_skb); 1123 kfree_skb(ddev->saved_skb);
@@ -1197,6 +1213,11 @@ exit:
1197 1213
1198 if (rc) 1214 if (rc)
1199 kfree_skb(resp); 1215 kfree_skb(resp);
1216
1217 return;
1218
1219free_resp:
1220 dev_kfree_skb(resp);
1200} 1221}
1201 1222
1202int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) 1223int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)