diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-05-02 17:25:01 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-06-08 15:58:16 -0400 |
commit | ab07801d28985090ac38047b5a4d8952a7e1689f (patch) | |
tree | 9ae945f55141b32b779c6a5969806725b39c09c3 /net | |
parent | 715ec005cd10c5d53109ffe513e4d403644e3e48 (diff) |
Bluetooth: create channel timer to replace sk_timer
The new timer does not belong to struct sock, tought it still touch some
sock things, but this will be sorted out soon.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 100 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 50 |
2 files changed, 76 insertions, 74 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index f5e50bf7ace0..fce48f9b85bf 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -208,6 +208,56 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | |||
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
210 | 210 | ||
211 | static void l2cap_chan_set_timer(struct l2cap_chan *chan, long timeout) | ||
212 | { | ||
213 | BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->sk->sk_state, | ||
214 | timeout); | ||
215 | if (!mod_timer(&chan->chan_timer, jiffies + timeout)) | ||
216 | sock_hold(chan->sk); | ||
217 | } | ||
218 | |||
219 | void l2cap_chan_clear_timer(struct l2cap_chan *chan) | ||
220 | { | ||
221 | BT_DBG("chan %p state %d", chan, chan->sk->sk_state); | ||
222 | |||
223 | if (timer_pending(&chan->chan_timer) && del_timer(&chan->chan_timer)) | ||
224 | __sock_put(chan->sk); | ||
225 | } | ||
226 | |||
227 | static void l2cap_chan_timeout(unsigned long arg) | ||
228 | { | ||
229 | struct l2cap_chan *chan = (struct l2cap_chan *) arg; | ||
230 | struct sock *sk = chan->sk; | ||
231 | int reason; | ||
232 | |||
233 | BT_DBG("chan %p state %d", chan, sk->sk_state); | ||
234 | |||
235 | bh_lock_sock(sk); | ||
236 | |||
237 | if (sock_owned_by_user(sk)) { | ||
238 | /* sk is owned by user. Try again later */ | ||
239 | l2cap_chan_set_timer(chan, HZ / 5); | ||
240 | bh_unlock_sock(sk); | ||
241 | sock_put(sk); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | ||
246 | reason = ECONNREFUSED; | ||
247 | else if (sk->sk_state == BT_CONNECT && | ||
248 | chan->sec_level != BT_SECURITY_SDP) | ||
249 | reason = ECONNREFUSED; | ||
250 | else | ||
251 | reason = ETIMEDOUT; | ||
252 | |||
253 | __l2cap_chan_close(chan, reason); | ||
254 | |||
255 | bh_unlock_sock(sk); | ||
256 | |||
257 | l2cap_sock_kill(sk); | ||
258 | sock_put(sk); | ||
259 | } | ||
260 | |||
211 | struct l2cap_chan *l2cap_chan_create(struct sock *sk) | 261 | struct l2cap_chan *l2cap_chan_create(struct sock *sk) |
212 | { | 262 | { |
213 | struct l2cap_chan *chan; | 263 | struct l2cap_chan *chan; |
@@ -222,6 +272,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) | |||
222 | list_add(&chan->global_l, &chan_list); | 272 | list_add(&chan->global_l, &chan_list); |
223 | write_unlock_bh(&chan_list_lock); | 273 | write_unlock_bh(&chan_list_lock); |
224 | 274 | ||
275 | setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan); | ||
276 | |||
225 | return chan; | 277 | return chan; |
226 | } | 278 | } |
227 | 279 | ||
@@ -281,7 +333,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
281 | struct l2cap_conn *conn = chan->conn; | 333 | struct l2cap_conn *conn = chan->conn; |
282 | struct sock *parent = bt_sk(sk)->parent; | 334 | struct sock *parent = bt_sk(sk)->parent; |
283 | 335 | ||
284 | l2cap_sock_clear_timer(sk); | 336 | l2cap_chan_clear_timer(chan); |
285 | 337 | ||
286 | BT_DBG("chan %p, conn %p, err %d", chan, conn, err); | 338 | BT_DBG("chan %p, conn %p, err %d", chan, conn, err); |
287 | 339 | ||
@@ -334,7 +386,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
334 | /* Must be called on unlocked socket. */ | 386 | /* Must be called on unlocked socket. */ |
335 | static void l2cap_chan_close(struct sock *sk) | 387 | static void l2cap_chan_close(struct sock *sk) |
336 | { | 388 | { |
337 | l2cap_sock_clear_timer(sk); | 389 | l2cap_chan_clear_timer(l2cap_pi(sk)->chan); |
338 | lock_sock(sk); | 390 | lock_sock(sk); |
339 | __l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET); | 391 | __l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET); |
340 | release_sock(sk); | 392 | release_sock(sk); |
@@ -371,7 +423,7 @@ void __l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
371 | case BT_CONFIG: | 423 | case BT_CONFIG: |
372 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && | 424 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
373 | conn->hcon->type == ACL_LINK) { | 425 | conn->hcon->type == ACL_LINK) { |
374 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 426 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); |
375 | l2cap_send_disconn_req(conn, chan, reason); | 427 | l2cap_send_disconn_req(conn, chan, reason); |
376 | } else | 428 | } else |
377 | l2cap_chan_del(chan, reason); | 429 | l2cap_chan_del(chan, reason); |
@@ -814,7 +866,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
814 | 866 | ||
815 | __l2cap_chan_add(conn, chan); | 867 | __l2cap_chan_add(conn, chan); |
816 | 868 | ||
817 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 869 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); |
818 | 870 | ||
819 | sk->sk_state = BT_CONNECTED; | 871 | sk->sk_state = BT_CONNECTED; |
820 | parent->sk_data_ready(parent, 0); | 872 | parent->sk_data_ready(parent, 0); |
@@ -842,13 +894,13 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
842 | bh_lock_sock(sk); | 894 | bh_lock_sock(sk); |
843 | 895 | ||
844 | if (conn->hcon->type == LE_LINK) { | 896 | if (conn->hcon->type == LE_LINK) { |
845 | l2cap_sock_clear_timer(sk); | 897 | l2cap_chan_clear_timer(chan); |
846 | sk->sk_state = BT_CONNECTED; | 898 | sk->sk_state = BT_CONNECTED; |
847 | sk->sk_state_change(sk); | 899 | sk->sk_state_change(sk); |
848 | } | 900 | } |
849 | 901 | ||
850 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 902 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
851 | l2cap_sock_clear_timer(sk); | 903 | l2cap_chan_clear_timer(chan); |
852 | sk->sk_state = BT_CONNECTED; | 904 | sk->sk_state = BT_CONNECTED; |
853 | sk->sk_state_change(sk); | 905 | sk->sk_state_change(sk); |
854 | } else if (sk->sk_state == BT_CONNECT) | 906 | } else if (sk->sk_state == BT_CONNECT) |
@@ -1047,11 +1099,11 @@ int l2cap_chan_connect(struct l2cap_chan *chan) | |||
1047 | l2cap_chan_add(conn, chan); | 1099 | l2cap_chan_add(conn, chan); |
1048 | 1100 | ||
1049 | sk->sk_state = BT_CONNECT; | 1101 | sk->sk_state = BT_CONNECT; |
1050 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 1102 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); |
1051 | 1103 | ||
1052 | if (hcon->state == BT_CONNECTED) { | 1104 | if (hcon->state == BT_CONNECTED) { |
1053 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 1105 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
1054 | l2cap_sock_clear_timer(sk); | 1106 | l2cap_chan_clear_timer(chan); |
1055 | if (l2cap_check_security(chan)) | 1107 | if (l2cap_check_security(chan)) |
1056 | sk->sk_state = BT_CONNECTED; | 1108 | sk->sk_state = BT_CONNECTED; |
1057 | } else | 1109 | } else |
@@ -1615,7 +1667,7 @@ static void l2cap_chan_ready(struct sock *sk) | |||
1615 | BT_DBG("sk %p, parent %p", sk, parent); | 1667 | BT_DBG("sk %p, parent %p", sk, parent); |
1616 | 1668 | ||
1617 | chan->conf_state = 0; | 1669 | chan->conf_state = 0; |
1618 | l2cap_sock_clear_timer(sk); | 1670 | l2cap_chan_clear_timer(chan); |
1619 | 1671 | ||
1620 | if (!parent) { | 1672 | if (!parent) { |
1621 | /* Outgoing channel. | 1673 | /* Outgoing channel. |
@@ -2317,7 +2369,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2317 | 2369 | ||
2318 | dcid = chan->scid; | 2370 | dcid = chan->scid; |
2319 | 2371 | ||
2320 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 2372 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); |
2321 | 2373 | ||
2322 | chan->ident = cmd->ident; | 2374 | chan->ident = cmd->ident; |
2323 | 2375 | ||
@@ -2434,8 +2486,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2434 | /* don't delete l2cap channel if sk is owned by user */ | 2486 | /* don't delete l2cap channel if sk is owned by user */ |
2435 | if (sock_owned_by_user(sk)) { | 2487 | if (sock_owned_by_user(sk)) { |
2436 | sk->sk_state = BT_DISCONN; | 2488 | sk->sk_state = BT_DISCONN; |
2437 | l2cap_sock_clear_timer(sk); | 2489 | l2cap_chan_clear_timer(chan); |
2438 | l2cap_sock_set_timer(sk, HZ / 5); | 2490 | l2cap_chan_set_timer(chan, HZ / 5); |
2439 | break; | 2491 | break; |
2440 | } | 2492 | } |
2441 | 2493 | ||
@@ -2608,7 +2660,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2608 | 2660 | ||
2609 | default: | 2661 | default: |
2610 | sk->sk_err = ECONNRESET; | 2662 | sk->sk_err = ECONNRESET; |
2611 | l2cap_sock_set_timer(sk, HZ * 5); | 2663 | l2cap_chan_set_timer(chan, HZ * 5); |
2612 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 2664 | l2cap_send_disconn_req(conn, chan, ECONNRESET); |
2613 | goto done; | 2665 | goto done; |
2614 | } | 2666 | } |
@@ -2664,8 +2716,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2664 | /* don't delete l2cap channel if sk is owned by user */ | 2716 | /* don't delete l2cap channel if sk is owned by user */ |
2665 | if (sock_owned_by_user(sk)) { | 2717 | if (sock_owned_by_user(sk)) { |
2666 | sk->sk_state = BT_DISCONN; | 2718 | sk->sk_state = BT_DISCONN; |
2667 | l2cap_sock_clear_timer(sk); | 2719 | l2cap_chan_clear_timer(chan); |
2668 | l2cap_sock_set_timer(sk, HZ / 5); | 2720 | l2cap_chan_set_timer(chan, HZ / 5); |
2669 | bh_unlock_sock(sk); | 2721 | bh_unlock_sock(sk); |
2670 | return 0; | 2722 | return 0; |
2671 | } | 2723 | } |
@@ -2698,8 +2750,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2698 | /* don't delete l2cap channel if sk is owned by user */ | 2750 | /* don't delete l2cap channel if sk is owned by user */ |
2699 | if (sock_owned_by_user(sk)) { | 2751 | if (sock_owned_by_user(sk)) { |
2700 | sk->sk_state = BT_DISCONN; | 2752 | sk->sk_state = BT_DISCONN; |
2701 | l2cap_sock_clear_timer(sk); | 2753 | l2cap_chan_clear_timer(chan); |
2702 | l2cap_sock_set_timer(sk, HZ / 5); | 2754 | l2cap_chan_set_timer(chan, HZ / 5); |
2703 | bh_unlock_sock(sk); | 2755 | bh_unlock_sock(sk); |
2704 | return 0; | 2756 | return 0; |
2705 | } | 2757 | } |
@@ -4090,20 +4142,18 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | |||
4090 | 4142 | ||
4091 | static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) | 4143 | static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) |
4092 | { | 4144 | { |
4093 | struct sock *sk = chan->sk; | ||
4094 | |||
4095 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) | 4145 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) |
4096 | return; | 4146 | return; |
4097 | 4147 | ||
4098 | if (encrypt == 0x00) { | 4148 | if (encrypt == 0x00) { |
4099 | if (chan->sec_level == BT_SECURITY_MEDIUM) { | 4149 | if (chan->sec_level == BT_SECURITY_MEDIUM) { |
4100 | l2cap_sock_clear_timer(sk); | 4150 | l2cap_chan_clear_timer(chan); |
4101 | l2cap_sock_set_timer(sk, HZ * 5); | 4151 | l2cap_chan_set_timer(chan, HZ * 5); |
4102 | } else if (chan->sec_level == BT_SECURITY_HIGH) | 4152 | } else if (chan->sec_level == BT_SECURITY_HIGH) |
4103 | __l2cap_chan_close(chan, ECONNREFUSED); | 4153 | __l2cap_chan_close(chan, ECONNREFUSED); |
4104 | } else { | 4154 | } else { |
4105 | if (chan->sec_level == BT_SECURITY_MEDIUM) | 4155 | if (chan->sec_level == BT_SECURITY_MEDIUM) |
4106 | l2cap_sock_clear_timer(sk); | 4156 | l2cap_chan_clear_timer(chan); |
4107 | } | 4157 | } |
4108 | } | 4158 | } |
4109 | 4159 | ||
@@ -4148,8 +4198,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4148 | l2cap_send_cmd(conn, chan->ident, | 4198 | l2cap_send_cmd(conn, chan->ident, |
4149 | L2CAP_CONN_REQ, sizeof(req), &req); | 4199 | L2CAP_CONN_REQ, sizeof(req), &req); |
4150 | } else { | 4200 | } else { |
4151 | l2cap_sock_clear_timer(sk); | 4201 | l2cap_chan_clear_timer(chan); |
4152 | l2cap_sock_set_timer(sk, HZ / 10); | 4202 | l2cap_chan_set_timer(chan, HZ / 10); |
4153 | } | 4203 | } |
4154 | } else if (sk->sk_state == BT_CONNECT2) { | 4204 | } else if (sk->sk_state == BT_CONNECT2) { |
4155 | struct l2cap_conn_rsp rsp; | 4205 | struct l2cap_conn_rsp rsp; |
@@ -4160,7 +4210,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4160 | result = L2CAP_CR_SUCCESS; | 4210 | result = L2CAP_CR_SUCCESS; |
4161 | } else { | 4211 | } else { |
4162 | sk->sk_state = BT_DISCONN; | 4212 | sk->sk_state = BT_DISCONN; |
4163 | l2cap_sock_set_timer(sk, HZ / 10); | 4213 | l2cap_chan_set_timer(chan, HZ / 10); |
4164 | result = L2CAP_CR_SEC_BLOCK; | 4214 | result = L2CAP_CR_SEC_BLOCK; |
4165 | } | 4215 | } |
4166 | 4216 | ||
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 2fcdf5eacb4d..89433a439bd8 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -32,52 +32,6 @@ | |||
32 | 32 | ||
33 | static const struct proto_ops l2cap_sock_ops; | 33 | static const struct proto_ops l2cap_sock_ops; |
34 | 34 | ||
35 | /* ---- L2CAP timers ---- */ | ||
36 | static void l2cap_sock_timeout(unsigned long arg) | ||
37 | { | ||
38 | struct sock *sk = (struct sock *) arg; | ||
39 | int reason; | ||
40 | |||
41 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
42 | |||
43 | bh_lock_sock(sk); | ||
44 | |||
45 | if (sock_owned_by_user(sk)) { | ||
46 | /* sk is owned by user. Try again later */ | ||
47 | l2cap_sock_set_timer(sk, HZ / 5); | ||
48 | bh_unlock_sock(sk); | ||
49 | sock_put(sk); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | ||
54 | reason = ECONNREFUSED; | ||
55 | else if (sk->sk_state == BT_CONNECT && | ||
56 | l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP) | ||
57 | reason = ECONNREFUSED; | ||
58 | else | ||
59 | reason = ETIMEDOUT; | ||
60 | |||
61 | __l2cap_chan_close(l2cap_pi(sk)->chan, reason); | ||
62 | |||
63 | bh_unlock_sock(sk); | ||
64 | |||
65 | l2cap_sock_kill(sk); | ||
66 | sock_put(sk); | ||
67 | } | ||
68 | |||
69 | void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
70 | { | ||
71 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
72 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
73 | } | ||
74 | |||
75 | void l2cap_sock_clear_timer(struct sock *sk) | ||
76 | { | ||
77 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
78 | sk_stop_timer(sk, &sk->sk_timer); | ||
79 | } | ||
80 | |||
81 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | 35 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) |
82 | { | 36 | { |
83 | struct sock *sk = sock->sk; | 37 | struct sock *sk = sock->sk; |
@@ -753,7 +707,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
753 | err = __l2cap_wait_ack(sk); | 707 | err = __l2cap_wait_ack(sk); |
754 | 708 | ||
755 | sk->sk_shutdown = SHUTDOWN_MASK; | 709 | sk->sk_shutdown = SHUTDOWN_MASK; |
756 | l2cap_sock_clear_timer(sk); | 710 | l2cap_chan_clear_timer(chan); |
757 | __l2cap_chan_close(chan, 0); | 711 | __l2cap_chan_close(chan, 0); |
758 | 712 | ||
759 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 713 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) |
@@ -879,8 +833,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g | |||
879 | sk->sk_protocol = proto; | 833 | sk->sk_protocol = proto; |
880 | sk->sk_state = BT_OPEN; | 834 | sk->sk_state = BT_OPEN; |
881 | 835 | ||
882 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); | ||
883 | |||
884 | return sk; | 836 | return sk; |
885 | } | 837 | } |
886 | 838 | ||