diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-10-26 18:20:10 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-10-26 18:26:53 +0200 |
commit | f31652a58bee6ef145c066c8d0ae6d0b11dca1e8 (patch) | |
tree | 12e8c4e7d5708cd29020bd54b6ec1d6e8b5cf8c2 | |
parent | f152218840f2dc60900e2568878d3b87460d5ae8 (diff) |
NFC: Purge LLCP socket Tx queues when being disconnected
The Tx queues are no longer valid when we receive a disconnection or when
the LLCP link goes down. In the later case we also purge the entire local
Tx queue.
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | net/nfc/llcp/llcp.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index c8b27afc16f9..2e23bd348ebd 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -45,12 +45,38 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) write_unlock(&l->lock); } +static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) +{ + struct nfc_llcp_local *local = sock->local; + struct sk_buff *s, *tmp; + + pr_debug("%p\n", &sock->sk); + + skb_queue_purge(&sock->tx_queue); + skb_queue_purge(&sock->tx_pending_queue); + skb_queue_purge(&sock->tx_backlog_queue); + + if (local == NULL) + return; + + /* Search for local pending SKBs that are related to this socket */ + skb_queue_walk_safe(&local->tx_queue, s, tmp) { + if (s->sk != &sock->sk) + continue; + + skb_unlink(s, &local->tx_queue); + kfree_skb(s); + } +} + static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) { struct sock *sk; struct hlist_node *node, *tmp; struct nfc_llcp_sock *llcp_sock; + skb_queue_purge(&local->tx_queue); + write_lock(&local->sockets.lock); sk_for_each_safe(sk, node, tmp, &local->sockets.head) { @@ -58,6 +84,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) bh_lock_sock(sk); + nfc_llcp_socket_purge(llcp_sock); + if (sk->sk_state == LLCP_CONNECTED) nfc_put_device(llcp_sock->dev); @@ -1002,6 +1030,9 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, sk = &llcp_sock->sk; lock_sock(sk); + + nfc_llcp_socket_purge(llcp_sock); + if (sk->sk_state == LLCP_CLOSED) { release_sock(sk); nfc_llcp_sock_put(llcp_sock); |