aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/llcp')
-rw-r--r--net/nfc/llcp/llcp.c66
-rw-r--r--net/nfc/llcp/sock.c11
2 files changed, 59 insertions, 18 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 7f8266dd14cb..ee25f25f0cd6 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,11 +101,12 @@ 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
107 sock_orphan(accept_sk);
108 } 110 }
109 111
110 if (listen == true) { 112 if (listen == true) {
@@ -123,16 +125,45 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
123 continue; 125 continue;
124 } 126 }
125 127
128 if (err)
129 sk->sk_err = err;
126 sk->sk_state = LLCP_CLOSED; 130 sk->sk_state = LLCP_CLOSED;
131 sk->sk_state_change(sk);
127 132
128 bh_unlock_sock(sk); 133 bh_unlock_sock(sk);
129 134
130 sock_orphan(sk);
131
132 sk_del_node_init(sk); 135 sk_del_node_init(sk);
133 } 136 }
134 137
135 write_unlock(&local->sockets.lock); 138 write_unlock(&local->sockets.lock);
139
140 /*
141 * If we want to keep the listening sockets alive,
142 * we don't touch the RAW ones.
143 */
144 if (listen == true)
145 return;
146
147 write_lock(&local->raw_sockets.lock);
148
149 sk_for_each_safe(sk, tmp, &local->raw_sockets.head) {
150 llcp_sock = nfc_llcp_sock(sk);
151
152 bh_lock_sock(sk);
153
154 nfc_llcp_socket_purge(llcp_sock);
155
156 if (err)
157 sk->sk_err = err;
158 sk->sk_state = LLCP_CLOSED;
159 sk->sk_state_change(sk);
160
161 bh_unlock_sock(sk);
162
163 sk_del_node_init(sk);
164 }
165
166 write_unlock(&local->raw_sockets.lock);
136} 167}
137 168
138struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) 169struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
@@ -142,20 +173,25 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
142 return local; 173 return local;
143} 174}
144 175
145static void local_release(struct kref *ref) 176static void local_cleanup(struct nfc_llcp_local *local, bool listen)
146{ 177{
147 struct nfc_llcp_local *local; 178 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); 179 del_timer_sync(&local->link_timer);
154 skb_queue_purge(&local->tx_queue); 180 skb_queue_purge(&local->tx_queue);
155 cancel_work_sync(&local->tx_work); 181 cancel_work_sync(&local->tx_work);
156 cancel_work_sync(&local->rx_work); 182 cancel_work_sync(&local->rx_work);
157 cancel_work_sync(&local->timeout_work); 183 cancel_work_sync(&local->timeout_work);
158 kfree_skb(local->rx_pending); 184 kfree_skb(local->rx_pending);
185}
186
187static void local_release(struct kref *ref)
188{
189 struct nfc_llcp_local *local;
190
191 local = container_of(ref, struct nfc_llcp_local, ref);
192
193 list_del(&local->list);
194 local_cleanup(local, false);
159 kfree(local); 195 kfree(local);
160} 196}
161 197
@@ -785,7 +821,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
785 skb_get(skb); 821 skb_get(skb);
786 } else { 822 } else {
787 pr_err("Receive queue is full\n"); 823 pr_err("Receive queue is full\n");
788 kfree_skb(skb);
789 } 824 }
790 825
791 nfc_llcp_sock_put(llcp_sock); 826 nfc_llcp_sock_put(llcp_sock);
@@ -986,7 +1021,6 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
986 skb_get(skb); 1021 skb_get(skb);
987 } else { 1022 } else {
988 pr_err("Receive queue is full\n"); 1023 pr_err("Receive queue is full\n");
989 kfree_skb(skb);
990 } 1024 }
991 } 1025 }
992 1026
@@ -1348,7 +1382,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
1348 return; 1382 return;
1349 1383
1350 /* Close and purge all existing sockets */ 1384 /* Close and purge all existing sockets */
1351 nfc_llcp_socket_release(local, true); 1385 nfc_llcp_socket_release(local, true, 0);
1352} 1386}
1353 1387
1354void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, 1388void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
@@ -1427,6 +1461,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
1427 return; 1461 return;
1428 } 1462 }
1429 1463
1464 local_cleanup(local, false);
1465
1430 nfc_llcp_local_put(local); 1466 nfc_llcp_local_put(local);
1431} 1467}
1432 1468
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 5332751943a9..6c94447ec414 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -270,7 +270,9 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
270 } 270 }
271 271
272 if (sk->sk_state == LLCP_CONNECTED || !newsock) { 272 if (sk->sk_state == LLCP_CONNECTED || !newsock) {
273 nfc_llcp_accept_unlink(sk); 273 list_del_init(&lsk->accept_queue);
274 sock_put(sk);
275
274 if (newsock) 276 if (newsock)
275 sock_graft(sk, newsock); 277 sock_graft(sk, newsock);
276 278
@@ -278,6 +280,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
278 280
279 pr_debug("Returning sk state %d\n", sk->sk_state); 281 pr_debug("Returning sk state %d\n", sk->sk_state);
280 282
283 sk_acceptq_removed(parent);
284
281 return sk; 285 return sk;
282 } 286 }
283 287
@@ -462,8 +466,6 @@ static int llcp_sock_release(struct socket *sock)
462 nfc_llcp_accept_unlink(accept_sk); 466 nfc_llcp_accept_unlink(accept_sk);
463 467
464 release_sock(accept_sk); 468 release_sock(accept_sk);
465
466 sock_orphan(accept_sk);
467 } 469 }
468 } 470 }
469 471
@@ -644,6 +646,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
644 646
645 pr_debug("%p %zu\n", sk, len); 647 pr_debug("%p %zu\n", sk, len);
646 648
649 msg->msg_namelen = 0;
650
647 lock_sock(sk); 651 lock_sock(sk);
648 652
649 if (sk->sk_state == LLCP_CLOSED && 653 if (sk->sk_state == LLCP_CLOSED &&
@@ -689,6 +693,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
689 693
690 pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); 694 pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap);
691 695
696 memset(sockaddr, 0, sizeof(*sockaddr));
692 sockaddr->sa_family = AF_NFC; 697 sockaddr->sa_family = AF_NFC;
693 sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP; 698 sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP;
694 sockaddr->dsap = ui_cb->dsap; 699 sockaddr->dsap = ui_cb->dsap;