diff options
author | Thierry Escande <thierry.escande@collabora.com> | 2016-07-08 15:52:43 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2016-07-11 01:59:37 +0200 |
commit | e073eb6797191abe2fe30ca643ab0cc3d8e1e534 (patch) | |
tree | edf85a1d4546d3143eb6e6b8109d14a217b636de /net/nfc | |
parent | NFC: digital: Fix ACK & NACK PDUs handling in target mode (diff) | |
download | linux-e073eb6797191abe2fe30ca643ab0cc3d8e1e534.tar.xz linux-e073eb6797191abe2fe30ca643ab0cc3d8e1e534.zip |
NFC: digital: Rework ACK PDU handling in initiator mode
With this patch, ACK PDU sk_buffs are now freed and code has been
refactored for better errors handling.
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.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c index e0268777ab18..03bfc74745f7 100644 --- a/net/nfc/digital_dep.c +++ b/net/nfc/digital_dep.c @@ -782,6 +782,12 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, break; case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: + if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { + PROTOCOL_ERR("14.12.4.5"); + rc = -EIO; + goto exit; + } + if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { PROTOCOL_ERR("14.12.3.3"); rc = -EIO; @@ -791,22 +797,25 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); - if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { - kfree_skb(ddev->saved_skb); - ddev->saved_skb = NULL; + if (!ddev->chaining_skb) { + PROTOCOL_ERR("14.12.4.3"); + rc = -EIO; + goto exit; + } - rc = digital_in_send_dep_req(ddev, NULL, - ddev->chaining_skb, - ddev->data_exch); - if (rc) - goto error; + /* The initiator has received a valid ACK. Free the last sent + * PDU and keep on sending chained skb. + */ + kfree_skb(ddev->saved_skb); + ddev->saved_skb = NULL; - return; - } + rc = digital_in_send_dep_req(ddev, NULL, + ddev->chaining_skb, + ddev->data_exch); + if (rc) + goto error; - pr_err("Received a ACK/NACK PDU\n"); - rc = -EINVAL; - goto exit; + goto free_resp; case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */ @@ -839,6 +848,11 @@ error: if (rc) kfree_skb(resp); + + return; + +free_resp: + dev_kfree_skb(resp); } int digital_in_send_dep_req(struct nfc_digital_dev *ddev, |