diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2015-10-25 22:54:20 +0100 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-10-26 06:53:11 +0100 |
commit | 500c4ef02277eaadbfe20537f963b6221f6ac007 (patch) | |
tree | bc0675ce1c6f0f7e9ba8bd1e403ab871a4082dd9 /net/nfc | |
parent | a1269dd116319335db6d73013a31c038486c813e (diff) | |
download | linux-stable-500c4ef02277eaadbfe20537f963b6221f6ac007.tar.gz linux-stable-500c4ef02277eaadbfe20537f963b6221f6ac007.tar.bz2 linux-stable-500c4ef02277eaadbfe20537f963b6221f6ac007.zip |
NFC: nci: Fix incorrect data chaining when sending data
When sending HCI data over NCI, cmd information should be
present only on the first packet.
Each packet shall be specifically allocated and sent to the
NCI layer.
Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/nci/hci.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c index 609f92283d1b..321889ee2107 100644 --- a/net/nfc/nci/hci.c +++ b/net/nfc/nci/hci.c @@ -146,18 +146,18 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe, if (!conn_info) return -EPROTO; - skb = nci_skb_alloc(ndev, 2 + conn_info->max_pkt_payload_len + + i = 0; + skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len + NCI_DATA_HDR_SIZE, GFP_KERNEL); if (!skb) return -ENOMEM; - skb_reserve(skb, 2 + NCI_DATA_HDR_SIZE); + skb_reserve(skb, NCI_DATA_HDR_SIZE + 2); *skb_push(skb, 1) = data_type; - i = 0; - len = conn_info->max_pkt_payload_len; - do { + len = conn_info->max_pkt_payload_len; + /* If last packet add NCI_HFP_NO_CHAINING */ if (i + conn_info->max_pkt_payload_len - (skb->len + 1) >= data_len) { @@ -177,9 +177,15 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe, return r; i += len; + if (i < data_len) { - skb_trim(skb, 0); - skb_pull(skb, len); + skb = nci_skb_alloc(ndev, + conn_info->max_pkt_payload_len + + NCI_DATA_HDR_SIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, NCI_DATA_HDR_SIZE + 1); } } while (i < data_len); |