aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-10-26 12:20:10 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-10-26 12:26:53 -0400
commitf31652a58bee6ef145c066c8d0ae6d0b11dca1e8 (patch)
tree12e8c4e7d5708cd29020bd54b6ec1d6e8b5cf8c2 /net
parentf152218840f2dc60900e2568878d3b87460d5ae8 (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>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/llcp/llcp.c31
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)
45 write_unlock(&l->lock); 45 write_unlock(&l->lock);
46} 46}
47 47
48static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
49{
50 struct nfc_llcp_local *local = sock->local;
51 struct sk_buff *s, *tmp;
52
53 pr_debug("%p\n", &sock->sk);
54
55 skb_queue_purge(&sock->tx_queue);
56 skb_queue_purge(&sock->tx_pending_queue);
57 skb_queue_purge(&sock->tx_backlog_queue);
58
59 if (local == NULL)
60 return;
61
62 /* Search for local pending SKBs that are related to this socket */
63 skb_queue_walk_safe(&local->tx_queue, s, tmp) {
64 if (s->sk != &sock->sk)
65 continue;
66
67 skb_unlink(s, &local->tx_queue);
68 kfree_skb(s);
69 }
70}
71
48static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) 72static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
49{ 73{
50 struct sock *sk; 74 struct sock *sk;
51 struct hlist_node *node, *tmp; 75 struct hlist_node *node, *tmp;
52 struct nfc_llcp_sock *llcp_sock; 76 struct nfc_llcp_sock *llcp_sock;
53 77
78 skb_queue_purge(&local->tx_queue);
79
54 write_lock(&local->sockets.lock); 80 write_lock(&local->sockets.lock);
55 81
56 sk_for_each_safe(sk, node, tmp, &local->sockets.head) { 82 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)
58 84
59 bh_lock_sock(sk); 85 bh_lock_sock(sk);
60 86
87 nfc_llcp_socket_purge(llcp_sock);
88
61 if (sk->sk_state == LLCP_CONNECTED) 89 if (sk->sk_state == LLCP_CONNECTED)
62 nfc_put_device(llcp_sock->dev); 90 nfc_put_device(llcp_sock->dev);
63 91
@@ -1002,6 +1030,9 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
1002 1030
1003 sk = &llcp_sock->sk; 1031 sk = &llcp_sock->sk;
1004 lock_sock(sk); 1032 lock_sock(sk);
1033
1034 nfc_llcp_socket_purge(llcp_sock);
1035
1005 if (sk->sk_state == LLCP_CLOSED) { 1036 if (sk->sk_state == LLCP_CLOSED) {
1006 release_sock(sk); 1037 release_sock(sk);
1007 nfc_llcp_sock_put(llcp_sock); 1038 nfc_llcp_sock_put(llcp_sock);