diff options
author | Dean Jenkins <Dean_Jenkins@mentor.com> | 2015-06-23 12:59:33 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-07-23 11:10:51 -0400 |
commit | f65468f6e26c3bd05e642e10e80a485b99b7de05 (patch) | |
tree | acf84d5f1bf435c379c78ac51fc6a43b9b990c45 /net/bluetooth | |
parent | 2baea85dec1aebe0b100d4836dee8bcf29a51e94 (diff) |
Bluetooth: Make __l2cap_wait_ack more efficient
Use chan->state instead of chan->conn because waiting
for ACK's is only possible in the BT_CONNECTED state.
Also avoids reference to the conn structure so makes
locking easier.
Only call __l2cap_wait_ack() when the needed condition
of chan->unacked_frames > 0 && chan->state == BT_CONNECTED
is true and convert the while loop to a do while loop.
__l2cap_wait_ack() change the function prototype to
pass in the chan variable as chan is already available
in the calling function l2cap_sock_shutdown(). Avoids
locking issues.
Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 3794c2386c21..29042880c449 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -1054,16 +1054,15 @@ static void l2cap_sock_kill(struct sock *sk) | |||
1054 | sock_put(sk); | 1054 | sock_put(sk); |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | static int __l2cap_wait_ack(struct sock *sk) | 1057 | static int __l2cap_wait_ack(struct sock *sk, struct l2cap_chan *chan) |
1058 | { | 1058 | { |
1059 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
1060 | DECLARE_WAITQUEUE(wait, current); | 1059 | DECLARE_WAITQUEUE(wait, current); |
1061 | int err = 0; | 1060 | int err = 0; |
1062 | int timeo = HZ/5; | 1061 | int timeo = HZ/5; |
1063 | 1062 | ||
1064 | add_wait_queue(sk_sleep(sk), &wait); | 1063 | add_wait_queue(sk_sleep(sk), &wait); |
1065 | set_current_state(TASK_INTERRUPTIBLE); | 1064 | set_current_state(TASK_INTERRUPTIBLE); |
1066 | while (chan->unacked_frames > 0 && chan->conn) { | 1065 | do { |
1067 | if (!timeo) | 1066 | if (!timeo) |
1068 | timeo = HZ/5; | 1067 | timeo = HZ/5; |
1069 | 1068 | ||
@@ -1080,7 +1079,10 @@ static int __l2cap_wait_ack(struct sock *sk) | |||
1080 | err = sock_error(sk); | 1079 | err = sock_error(sk); |
1081 | if (err) | 1080 | if (err) |
1082 | break; | 1081 | break; |
1083 | } | 1082 | |
1083 | } while (chan->unacked_frames > 0 && | ||
1084 | chan->state == BT_CONNECTED); | ||
1085 | |||
1084 | set_current_state(TASK_RUNNING); | 1086 | set_current_state(TASK_RUNNING); |
1085 | remove_wait_queue(sk_sleep(sk), &wait); | 1087 | remove_wait_queue(sk_sleep(sk), &wait); |
1086 | return err; | 1088 | return err; |
@@ -1115,8 +1117,10 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1115 | lock_sock(sk); | 1117 | lock_sock(sk); |
1116 | 1118 | ||
1117 | if (!sk->sk_shutdown) { | 1119 | if (!sk->sk_shutdown) { |
1118 | if (chan->mode == L2CAP_MODE_ERTM) | 1120 | if (chan->mode == L2CAP_MODE_ERTM && |
1119 | err = __l2cap_wait_ack(sk); | 1121 | chan->unacked_frames > 0 && |
1122 | chan->state == BT_CONNECTED) | ||
1123 | err = __l2cap_wait_ack(sk, chan); | ||
1120 | 1124 | ||
1121 | sk->sk_shutdown = SHUTDOWN_MASK; | 1125 | sk->sk_shutdown = SHUTDOWN_MASK; |
1122 | 1126 | ||