aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-03-18 09:39:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-03-18 09:39:21 -0400
commit49c87cd1eac1f798c5bad7f7eb809e6df36b6c56 (patch)
tree8d6905466a05d6539e06d189cf88b71095ac0a79 /net/nfc/llcp
parent4969b41798e512689bba57c8c44d873216eba814 (diff)
parent9437a248e7cac427c898bdb11bd1ac6844a1ead4 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts: net/nfc/llcp/llcp.c
Diffstat (limited to 'net/nfc/llcp')
-rw-r--r--net/nfc/llcp/llcp.c62
-rw-r--r--net/nfc/llcp/sock.c2
2 files changed, 55 insertions, 9 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 3361170cb262..bb67b98b9797 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
68 } 68 }
69} 69}
70 70
71static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) 71static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
72 int err)
72{ 73{
73 struct sock *sk; 74 struct sock *sk;
74 struct hlist_node *tmp; 75 struct hlist_node *tmp;
@@ -100,7 +101,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
100 101
101 nfc_llcp_accept_unlink(accept_sk); 102 nfc_llcp_accept_unlink(accept_sk);
102 103
104 if (err)
105 accept_sk->sk_err = err;
103 accept_sk->sk_state = LLCP_CLOSED; 106 accept_sk->sk_state = LLCP_CLOSED;
107 accept_sk->sk_state_change(sk);
104 108
105 bh_unlock_sock(accept_sk); 109 bh_unlock_sock(accept_sk);
106 110
@@ -123,7 +127,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
123 continue; 127 continue;
124 } 128 }
125 129
130 if (err)
131 sk->sk_err = err;
126 sk->sk_state = LLCP_CLOSED; 132 sk->sk_state = LLCP_CLOSED;
133 sk->sk_state_change(sk);
127 134
128 bh_unlock_sock(sk); 135 bh_unlock_sock(sk);
129 136
@@ -133,6 +140,36 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
133 } 140 }
134 141
135 write_unlock(&local->sockets.lock); 142 write_unlock(&local->sockets.lock);
143
144 /*
145 * If we want to keep the listening sockets alive,
146 * we don't touch the RAW ones.
147 */
148 if (listen == true)
149 return;
150
151 write_lock(&local->raw_sockets.lock);
152
153 sk_for_each_safe(sk, tmp, &local->raw_sockets.head) {
154 llcp_sock = nfc_llcp_sock(sk);
155
156 bh_lock_sock(sk);
157
158 nfc_llcp_socket_purge(llcp_sock);
159
160 if (err)
161 sk->sk_err = err;
162 sk->sk_state = LLCP_CLOSED;
163 sk->sk_state_change(sk);
164
165 bh_unlock_sock(sk);
166
167 sock_orphan(sk);
168
169 sk_del_node_init(sk);
170 }
171
172 write_unlock(&local->raw_sockets.lock);
136} 173}
137 174
138struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) 175struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
@@ -142,14 +179,9 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
142 return local; 179 return local;
143} 180}
144 181
145static void local_release(struct kref *ref) 182static void local_cleanup(struct nfc_llcp_local *local, bool listen)
146{ 183{
147 struct nfc_llcp_local *local; 184 nfc_llcp_socket_release(local, listen, ENXIO);
148
149 local = container_of(ref, struct nfc_llcp_local, ref);
150
151 list_del(&local->list);
152 nfc_llcp_socket_release(local, false);
153 del_timer_sync(&local->link_timer); 185 del_timer_sync(&local->link_timer);
154 skb_queue_purge(&local->tx_queue); 186 skb_queue_purge(&local->tx_queue);
155 cancel_work_sync(&local->tx_work); 187 cancel_work_sync(&local->tx_work);
@@ -159,6 +191,16 @@ static void local_release(struct kref *ref)
159 del_timer_sync(&local->sdreq_timer); 191 del_timer_sync(&local->sdreq_timer);
160 cancel_work_sync(&local->sdreq_timeout_work); 192 cancel_work_sync(&local->sdreq_timeout_work);
161 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); 193 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
194}
195
196static void local_release(struct kref *ref)
197{
198 struct nfc_llcp_local *local;
199
200 local = container_of(ref, struct nfc_llcp_local, ref);
201
202 list_del(&local->list);
203 local_cleanup(local, false);
162 kfree(local); 204 kfree(local);
163} 205}
164 206
@@ -1433,7 +1475,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
1433 return; 1475 return;
1434 1476
1435 /* Close and purge all existing sockets */ 1477 /* Close and purge all existing sockets */
1436 nfc_llcp_socket_release(local, true); 1478 nfc_llcp_socket_release(local, true, 0);
1437} 1479}
1438 1480
1439void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, 1481void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
@@ -1519,6 +1561,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
1519 return; 1561 return;
1520 } 1562 }
1521 1563
1564 local_cleanup(local, false);
1565
1522 nfc_llcp_local_put(local); 1566 nfc_llcp_local_put(local);
1523} 1567}
1524 1568
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 827d7d755d09..f1b377e247fe 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -396,6 +396,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
396 396
397 pr_debug("Returning sk state %d\n", sk->sk_state); 397 pr_debug("Returning sk state %d\n", sk->sk_state);
398 398
399 sk_acceptq_removed(parent);
400
399 return sk; 401 return sk;
400 } 402 }
401 403