Commit be02b6b6 authored by Samuel Ortiz's avatar Samuel Ortiz

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: default avatarThierry Escande <thierry.escande@linux.intel.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent dd2bf43f
...@@ -656,6 +656,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) ...@@ -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) { if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) {
nfc_llcp_send_symm(local->dev); nfc_llcp_send_symm(local->dev);
} else { } else {
struct sk_buff *copy_skb = NULL;
u8 ptype = nfc_llcp_ptype(skb);
int ret; int ret;
pr_debug("Sending pending skb\n"); pr_debug("Sending pending skb\n");
...@@ -663,22 +665,29 @@ static void nfc_llcp_tx_work(struct work_struct *work) ...@@ -663,22 +665,29 @@ static void nfc_llcp_tx_work(struct work_struct *work)
DUMP_PREFIX_OFFSET, 16, 1, DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb->len, true); 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_send_to_raw_sock(local, skb,
NFC_LLCP_DIRECTION_TX); NFC_LLCP_DIRECTION_TX);
ret = nfc_data_exchange(local->dev, local->target_idx, ret = nfc_data_exchange(local->dev, local->target_idx,
skb, nfc_llcp_recv, local); skb, nfc_llcp_recv, local);
if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { if (ret) {
skb = skb_get(skb); kfree_skb(copy_skb);
skb_queue_tail(&llcp_sock->tx_pending_queue, goto out;
skb);
} }
if (ptype == LLCP_PDU_I && copy_skb)
skb_queue_tail(&llcp_sock->tx_pending_queue,
copy_skb);
} }
} else { } else {
nfc_llcp_send_symm(local->dev); nfc_llcp_send_symm(local->dev);
} }
out:
mod_timer(&local->link_timer, mod_timer(&local->link_timer,
jiffies + msecs_to_jiffies(2 * local->remote_lto)); jiffies + msecs_to_jiffies(2 * local->remote_lto));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment