diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-10-26 12:20:10 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-10-26 12:26:53 -0400 |
commit | f31652a58bee6ef145c066c8d0ae6d0b11dca1e8 (patch) | |
tree | 12e8c4e7d5708cd29020bd54b6ec1d6e8b5cf8c2 /net | |
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>
Diffstat (limited to 'net')
-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) | |||
45 | write_unlock(&l->lock); | 45 | write_unlock(&l->lock); |
46 | } | 46 | } |
47 | 47 | ||
48 | static 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 | |||
48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | 72 | static 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); |