diff options
Diffstat (limited to 'net/bluetooth/af_bluetooth.c')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index c4cf3f595004..8add9b499912 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -40,7 +40,7 @@ | |||
40 | 40 | ||
41 | #include <net/bluetooth/bluetooth.h> | 41 | #include <net/bluetooth/bluetooth.h> |
42 | 42 | ||
43 | #define VERSION "2.15" | 43 | #define VERSION "2.16" |
44 | 44 | ||
45 | /* Bluetooth sockets */ | 45 | /* Bluetooth sockets */ |
46 | #define BT_MAX_PROTO 8 | 46 | #define BT_MAX_PROTO 8 |
@@ -199,14 +199,15 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
199 | 199 | ||
200 | BT_DBG("parent %p", parent); | 200 | BT_DBG("parent %p", parent); |
201 | 201 | ||
202 | local_bh_disable(); | ||
202 | list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { | 203 | list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { |
203 | sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); | 204 | sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); |
204 | 205 | ||
205 | lock_sock(sk); | 206 | bh_lock_sock(sk); |
206 | 207 | ||
207 | /* FIXME: Is this check still needed */ | 208 | /* FIXME: Is this check still needed */ |
208 | if (sk->sk_state == BT_CLOSED) { | 209 | if (sk->sk_state == BT_CLOSED) { |
209 | release_sock(sk); | 210 | bh_unlock_sock(sk); |
210 | bt_accept_unlink(sk); | 211 | bt_accept_unlink(sk); |
211 | continue; | 212 | continue; |
212 | } | 213 | } |
@@ -216,12 +217,16 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
216 | bt_accept_unlink(sk); | 217 | bt_accept_unlink(sk); |
217 | if (newsock) | 218 | if (newsock) |
218 | sock_graft(sk, newsock); | 219 | sock_graft(sk, newsock); |
219 | release_sock(sk); | 220 | |
221 | bh_unlock_sock(sk); | ||
222 | local_bh_enable(); | ||
220 | return sk; | 223 | return sk; |
221 | } | 224 | } |
222 | 225 | ||
223 | release_sock(sk); | 226 | bh_unlock_sock(sk); |
224 | } | 227 | } |
228 | local_bh_enable(); | ||
229 | |||
225 | return NULL; | 230 | return NULL; |
226 | } | 231 | } |
227 | EXPORT_SYMBOL(bt_accept_dequeue); | 232 | EXPORT_SYMBOL(bt_accept_dequeue); |
@@ -240,7 +245,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
240 | if (flags & (MSG_OOB)) | 245 | if (flags & (MSG_OOB)) |
241 | return -EOPNOTSUPP; | 246 | return -EOPNOTSUPP; |
242 | 247 | ||
243 | if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) { | 248 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
249 | if (!skb) { | ||
244 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 250 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
245 | return 0; | 251 | return 0; |
246 | return err; | 252 | return err; |
@@ -323,7 +329,8 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
323 | if (copied >= target) | 329 | if (copied >= target) |
324 | break; | 330 | break; |
325 | 331 | ||
326 | if ((err = sock_error(sk)) != 0) | 332 | err = sock_error(sk); |
333 | if (err) | ||
327 | break; | 334 | break; |
328 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 335 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
329 | break; | 336 | break; |
@@ -390,7 +397,7 @@ static inline unsigned int bt_accept_poll(struct sock *parent) | |||
390 | return 0; | 397 | return 0; |
391 | } | 398 | } |
392 | 399 | ||
393 | unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait) | 400 | unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait) |
394 | { | 401 | { |
395 | struct sock *sk = sock->sk; | 402 | struct sock *sk = sock->sk; |
396 | unsigned int mask = 0; | 403 | unsigned int mask = 0; |
@@ -538,13 +545,39 @@ static int __init bt_init(void) | |||
538 | 545 | ||
539 | BT_INFO("HCI device and connection manager initialized"); | 546 | BT_INFO("HCI device and connection manager initialized"); |
540 | 547 | ||
541 | hci_sock_init(); | 548 | err = hci_sock_init(); |
549 | if (err < 0) | ||
550 | goto error; | ||
551 | |||
552 | err = l2cap_init(); | ||
553 | if (err < 0) | ||
554 | goto sock_err; | ||
555 | |||
556 | err = sco_init(); | ||
557 | if (err < 0) { | ||
558 | l2cap_exit(); | ||
559 | goto sock_err; | ||
560 | } | ||
542 | 561 | ||
543 | return 0; | 562 | return 0; |
563 | |||
564 | sock_err: | ||
565 | hci_sock_cleanup(); | ||
566 | |||
567 | error: | ||
568 | sock_unregister(PF_BLUETOOTH); | ||
569 | bt_sysfs_cleanup(); | ||
570 | |||
571 | return err; | ||
544 | } | 572 | } |
545 | 573 | ||
546 | static void __exit bt_exit(void) | 574 | static void __exit bt_exit(void) |
547 | { | 575 | { |
576 | |||
577 | sco_exit(); | ||
578 | |||
579 | l2cap_exit(); | ||
580 | |||
548 | hci_sock_cleanup(); | 581 | hci_sock_cleanup(); |
549 | 582 | ||
550 | sock_unregister(PF_BLUETOOTH); | 583 | sock_unregister(PF_BLUETOOTH); |