summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2015-10-25 22:54:20 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-09 14:31:15 -0500
commit12cd7a677da483ee9d7e0d97b8fd608753e9a281 (patch)
tree97acdeaa36ec2ecc52c7f7d63d0e95fd7ba89fee /net
parent3d7594d9d9d18b712fa1542634cc5b78ee68ae7c (diff)
NFC: nci: Fix incorrect data chaining when sending data
commit 500c4ef02277eaadbfe20537f963b6221f6ac007 upstream. 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. Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/nci/hci.c20
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);