diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-11-01 23:36:07 +0100 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-11-19 23:57:01 +0100 |
commit | be02b6b624005d47c388f799ce23714136430217 (patch) | |
tree | 2e440fa1279d91f0791e3ee3248c2120bc4855aa | |
parent | dd2bf43ffcf0d1bba94d20abc6cc44ed294db66b (diff) | |
download | op-kernel-dev-be02b6b624005d47c388f799ce23714136430217.zip op-kernel-dev-be02b6b624005d47c388f799ce23714136430217.tar.gz |
NFC: Queue a copy of the transmitted LLCP skb
Drivers are allowed to modify the sent skb and thus we need to make a copy
of it before passing it to the driver. Without this fix, LLCP Tx skbs were
not queued properly as the ptype check was failing due to e.g. the pn533
driver skb_pushing the Tx skb.
Reported-by: Thierry Escande <thierry.escande@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | net/nfc/llcp/llcp.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index f680453..6673333 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -656,6 +656,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { nfc_llcp_send_symm(local->dev); } else { + struct sk_buff *copy_skb = NULL; + u8 ptype = nfc_llcp_ptype(skb); int ret; pr_debug("Sending pending skb\n"); @@ -663,22 +665,29 @@ static void nfc_llcp_tx_work(struct work_struct *work) DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); + if (ptype == LLCP_PDU_I) + copy_skb = skb_copy(skb, GFP_ATOMIC); + nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); ret = nfc_data_exchange(local->dev, local->target_idx, skb, nfc_llcp_recv, local); - if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { - skb = skb_get(skb); - skb_queue_tail(&llcp_sock->tx_pending_queue, - skb); + if (ret) { + kfree_skb(copy_skb); + goto out; } + + if (ptype == LLCP_PDU_I && copy_skb) + skb_queue_tail(&llcp_sock->tx_pending_queue, + copy_skb); } } else { nfc_llcp_send_symm(local->dev); } +out: mod_timer(&local->link_timer, jiffies + msecs_to_jiffies(2 * local->remote_lto)); } |