aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2015-10-25 22:54:20 +0100
committerSamuel Ortiz <sameo@linux.intel.com>2015-10-26 06:53:11 +0100
commit500c4ef02277eaadbfe20537f963b6221f6ac007 (patch)
treebc0675ce1c6f0f7e9ba8bd1e403ab871a4082dd9
parentNFC: st-nci: Fix incorrect spi buffer size (diff)
downloadlinux-dev-500c4ef02277eaadbfe20537f963b6221f6ac007.tar.xz
linux-dev-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>
-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);