diff options
| author | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-05-01 15:15:44 -0400 |
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2010-05-10 03:28:53 -0400 |
| commit | 6161c0382bbab883a634d284f7367a88bbe88534 (patch) | |
| tree | 86b4de3160054b0507d37a47351260e48073f579 | |
| parent | 1890d36bb556a27684ad29654a9898ab9a5f57ee (diff) | |
Bluetooth: Add wait_queue to wait ack of all sent packets
To guarantee that all packets we sent were received we need to wait for
theirs ack before shutdown the socket.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
| -rw-r--r-- | net/bluetooth/l2cap.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 103e4b54a86a..9d514f9dbc0f 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
| @@ -1242,6 +1242,37 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l | |||
| 1242 | return 0; | 1242 | return 0; |
| 1243 | } | 1243 | } |
| 1244 | 1244 | ||
| 1245 | static int __l2cap_wait_ack(struct sock *sk) | ||
| 1246 | { | ||
| 1247 | DECLARE_WAITQUEUE(wait, current); | ||
| 1248 | int err = 0; | ||
| 1249 | int timeo = HZ/5; | ||
| 1250 | |||
| 1251 | add_wait_queue(sk->sk_sleep, &wait); | ||
| 1252 | while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { | ||
| 1253 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 1254 | |||
| 1255 | if (!timeo) | ||
| 1256 | timeo = HZ/5; | ||
| 1257 | |||
| 1258 | if (signal_pending(current)) { | ||
| 1259 | err = sock_intr_errno(timeo); | ||
| 1260 | break; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | release_sock(sk); | ||
| 1264 | timeo = schedule_timeout(timeo); | ||
| 1265 | lock_sock(sk); | ||
| 1266 | |||
| 1267 | err = sock_error(sk); | ||
| 1268 | if (err) | ||
| 1269 | break; | ||
| 1270 | } | ||
| 1271 | set_current_state(TASK_RUNNING); | ||
| 1272 | remove_wait_queue(sk->sk_sleep, &wait); | ||
| 1273 | return err; | ||
| 1274 | } | ||
| 1275 | |||
| 1245 | static void l2cap_monitor_timeout(unsigned long arg) | 1276 | static void l2cap_monitor_timeout(unsigned long arg) |
| 1246 | { | 1277 | { |
| 1247 | struct sock *sk = (void *) arg; | 1278 | struct sock *sk = (void *) arg; |
| @@ -2059,6 +2090,9 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
| 2059 | 2090 | ||
| 2060 | lock_sock(sk); | 2091 | lock_sock(sk); |
| 2061 | if (!sk->sk_shutdown) { | 2092 | if (!sk->sk_shutdown) { |
| 2093 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) | ||
| 2094 | err = __l2cap_wait_ack(sk); | ||
| 2095 | |||
| 2062 | sk->sk_shutdown = SHUTDOWN_MASK; | 2096 | sk->sk_shutdown = SHUTDOWN_MASK; |
| 2063 | l2cap_sock_clear_timer(sk); | 2097 | l2cap_sock_clear_timer(sk); |
| 2064 | __l2cap_sock_close(sk, 0); | 2098 | __l2cap_sock_close(sk, 0); |
