diff options
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r-- | net/bluetooth/sco.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 51ae0c3e470a..13c27f17192c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -359,20 +359,9 @@ static void sco_sock_kill(struct sock *sk) | |||
359 | sock_put(sk); | 359 | sock_put(sk); |
360 | } | 360 | } |
361 | 361 | ||
362 | /* Close socket. | 362 | static void __sco_sock_close(struct sock *sk) |
363 | * Must be called on unlocked socket. | ||
364 | */ | ||
365 | static void sco_sock_close(struct sock *sk) | ||
366 | { | 363 | { |
367 | struct sco_conn *conn; | 364 | BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); |
368 | |||
369 | sco_sock_clear_timer(sk); | ||
370 | |||
371 | lock_sock(sk); | ||
372 | |||
373 | conn = sco_pi(sk)->conn; | ||
374 | |||
375 | BT_DBG("sk %p state %d conn %p socket %p", sk, sk->sk_state, conn, sk->sk_socket); | ||
376 | 365 | ||
377 | switch (sk->sk_state) { | 366 | switch (sk->sk_state) { |
378 | case BT_LISTEN: | 367 | case BT_LISTEN: |
@@ -390,9 +379,15 @@ static void sco_sock_close(struct sock *sk) | |||
390 | sock_set_flag(sk, SOCK_ZAPPED); | 379 | sock_set_flag(sk, SOCK_ZAPPED); |
391 | break; | 380 | break; |
392 | } | 381 | } |
382 | } | ||
393 | 383 | ||
384 | /* Must be called on unlocked socket. */ | ||
385 | static void sco_sock_close(struct sock *sk) | ||
386 | { | ||
387 | sco_sock_clear_timer(sk); | ||
388 | lock_sock(sk); | ||
389 | __sco_sock_close(sk); | ||
394 | release_sock(sk); | 390 | release_sock(sk); |
395 | |||
396 | sco_sock_kill(sk); | 391 | sco_sock_kill(sk); |
397 | } | 392 | } |
398 | 393 | ||
@@ -748,6 +743,30 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char | |||
748 | return err; | 743 | return err; |
749 | } | 744 | } |
750 | 745 | ||
746 | static int sco_sock_shutdown(struct socket *sock, int how) | ||
747 | { | ||
748 | struct sock *sk = sock->sk; | ||
749 | int err = 0; | ||
750 | |||
751 | BT_DBG("sock %p, sk %p", sock, sk); | ||
752 | |||
753 | if (!sk) | ||
754 | return 0; | ||
755 | |||
756 | lock_sock(sk); | ||
757 | if (!sk->sk_shutdown) { | ||
758 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
759 | sco_sock_clear_timer(sk); | ||
760 | __sco_sock_close(sk); | ||
761 | |||
762 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | ||
763 | err = bt_sock_wait_state(sk, BT_CLOSED, | ||
764 | sk->sk_lingertime); | ||
765 | } | ||
766 | release_sock(sk); | ||
767 | return err; | ||
768 | } | ||
769 | |||
751 | static int sco_sock_release(struct socket *sock) | 770 | static int sco_sock_release(struct socket *sock) |
752 | { | 771 | { |
753 | struct sock *sk = sock->sk; | 772 | struct sock *sk = sock->sk; |
@@ -969,7 +988,7 @@ static const struct proto_ops sco_sock_ops = { | |||
969 | .ioctl = bt_sock_ioctl, | 988 | .ioctl = bt_sock_ioctl, |
970 | .mmap = sock_no_mmap, | 989 | .mmap = sock_no_mmap, |
971 | .socketpair = sock_no_socketpair, | 990 | .socketpair = sock_no_socketpair, |
972 | .shutdown = sock_no_shutdown, | 991 | .shutdown = sco_sock_shutdown, |
973 | .setsockopt = sco_sock_setsockopt, | 992 | .setsockopt = sco_sock_setsockopt, |
974 | .getsockopt = sco_sock_getsockopt | 993 | .getsockopt = sco_sock_getsockopt |
975 | }; | 994 | }; |