Commit ab07801d authored by Gustavo F. Padovan's avatar Gustavo F. Padovan

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: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent 715ec005
...@@ -340,6 +340,7 @@ struct l2cap_chan { ...@@ -340,6 +340,7 @@ struct l2cap_chan {
__u8 remote_max_tx; __u8 remote_max_tx;
__u16 remote_mps; __u16 remote_mps;
struct timer_list chan_timer;
struct timer_list retrans_timer; struct timer_list retrans_timer;
struct timer_list monitor_timer; struct timer_list monitor_timer;
struct timer_list ack_timer; struct timer_list ack_timer;
...@@ -457,12 +458,12 @@ int __l2cap_wait_ack(struct sock *sk); ...@@ -457,12 +458,12 @@ int __l2cap_wait_ack(struct sock *sk);
int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
void l2cap_sock_set_timer(struct sock *sk, long timeout);
void l2cap_sock_clear_timer(struct sock *sk);
void l2cap_sock_kill(struct sock *sk); void l2cap_sock_kill(struct sock *sk);
void l2cap_sock_init(struct sock *sk, struct sock *parent); void l2cap_sock_init(struct sock *sk, struct sock *parent);
struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
int proto, gfp_t prio); int proto, gfp_t prio);
void l2cap_chan_clear_timer(struct l2cap_chan *chan);
struct l2cap_chan *l2cap_chan_create(struct sock *sk); struct l2cap_chan *l2cap_chan_create(struct sock *sk);
void __l2cap_chan_close(struct l2cap_chan *chan, int reason); void __l2cap_chan_close(struct l2cap_chan *chan, int reason);
void l2cap_chan_destroy(struct l2cap_chan *chan); void l2cap_chan_destroy(struct l2cap_chan *chan);
......
...@@ -208,6 +208,56 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) ...@@ -208,6 +208,56 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
return 0; return 0;
} }
static void l2cap_chan_set_timer(struct l2cap_chan *chan, long timeout)
{
BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->sk->sk_state,
timeout);
if (!mod_timer(&chan->chan_timer, jiffies + timeout))
sock_hold(chan->sk);
}
void l2cap_chan_clear_timer(struct l2cap_chan *chan)
{
BT_DBG("chan %p state %d", chan, chan->sk->sk_state);
if (timer_pending(&chan->chan_timer) && del_timer(&chan->chan_timer))
__sock_put(chan->sk);
}
static void l2cap_chan_timeout(unsigned long arg)
{
struct l2cap_chan *chan = (struct l2cap_chan *) arg;
struct sock *sk = chan->sk;
int reason;
BT_DBG("chan %p state %d", chan, sk->sk_state);
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* sk is owned by user. Try again later */
l2cap_chan_set_timer(chan, HZ / 5);
bh_unlock_sock(sk);
sock_put(sk);
return;
}
if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
reason = ECONNREFUSED;
else if (sk->sk_state == BT_CONNECT &&
chan->sec_level != BT_SECURITY_SDP)
reason = ECONNREFUSED;
else
reason = ETIMEDOUT;
__l2cap_chan_close(chan, reason);
bh_unlock_sock(sk);
l2cap_sock_kill(sk);
sock_put(sk);
}
struct l2cap_chan *l2cap_chan_create(struct sock *sk) struct l2cap_chan *l2cap_chan_create(struct sock *sk)
{ {
struct l2cap_chan *chan; struct l2cap_chan *chan;
...@@ -222,6 +272,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) ...@@ -222,6 +272,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk)
list_add(&chan->global_l, &chan_list); list_add(&chan->global_l, &chan_list);
write_unlock_bh(&chan_list_lock); write_unlock_bh(&chan_list_lock);
setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
return chan; return chan;
} }
...@@ -281,7 +333,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) ...@@ -281,7 +333,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
struct l2cap_conn *conn = chan->conn; struct l2cap_conn *conn = chan->conn;
struct sock *parent = bt_sk(sk)->parent; struct sock *parent = bt_sk(sk)->parent;
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
BT_DBG("chan %p, conn %p, err %d", chan, conn, err); BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
...@@ -334,7 +386,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) ...@@ -334,7 +386,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
/* Must be called on unlocked socket. */ /* Must be called on unlocked socket. */
static void l2cap_chan_close(struct sock *sk) static void l2cap_chan_close(struct sock *sk)
{ {
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(l2cap_pi(sk)->chan);
lock_sock(sk); lock_sock(sk);
__l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET); __l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET);
release_sock(sk); release_sock(sk);
...@@ -371,7 +423,7 @@ void __l2cap_chan_close(struct l2cap_chan *chan, int reason) ...@@ -371,7 +423,7 @@ void __l2cap_chan_close(struct l2cap_chan *chan, int reason)
case BT_CONFIG: case BT_CONFIG:
if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
conn->hcon->type == ACL_LINK) { conn->hcon->type == ACL_LINK) {
l2cap_sock_set_timer(sk, sk->sk_sndtimeo); l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
l2cap_send_disconn_req(conn, chan, reason); l2cap_send_disconn_req(conn, chan, reason);
} else } else
l2cap_chan_del(chan, reason); l2cap_chan_del(chan, reason);
...@@ -814,7 +866,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) ...@@ -814,7 +866,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
__l2cap_chan_add(conn, chan); __l2cap_chan_add(conn, chan);
l2cap_sock_set_timer(sk, sk->sk_sndtimeo); l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
parent->sk_data_ready(parent, 0); parent->sk_data_ready(parent, 0);
...@@ -842,13 +894,13 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) ...@@ -842,13 +894,13 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
bh_lock_sock(sk); bh_lock_sock(sk);
if (conn->hcon->type == LE_LINK) { if (conn->hcon->type == LE_LINK) {
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
sk->sk_state_change(sk); sk->sk_state_change(sk);
} }
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
sk->sk_state_change(sk); sk->sk_state_change(sk);
} else if (sk->sk_state == BT_CONNECT) } else if (sk->sk_state == BT_CONNECT)
...@@ -1047,11 +1099,11 @@ int l2cap_chan_connect(struct l2cap_chan *chan) ...@@ -1047,11 +1099,11 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
l2cap_chan_add(conn, chan); l2cap_chan_add(conn, chan);
sk->sk_state = BT_CONNECT; sk->sk_state = BT_CONNECT;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo); l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
if (hcon->state == BT_CONNECTED) { if (hcon->state == BT_CONNECTED) {
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
if (l2cap_check_security(chan)) if (l2cap_check_security(chan))
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
} else } else
...@@ -1615,7 +1667,7 @@ static void l2cap_chan_ready(struct sock *sk) ...@@ -1615,7 +1667,7 @@ static void l2cap_chan_ready(struct sock *sk)
BT_DBG("sk %p, parent %p", sk, parent); BT_DBG("sk %p, parent %p", sk, parent);
chan->conf_state = 0; chan->conf_state = 0;
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
if (!parent) { if (!parent) {
/* Outgoing channel. /* Outgoing channel.
...@@ -2317,7 +2369,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -2317,7 +2369,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
dcid = chan->scid; dcid = chan->scid;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo); l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
chan->ident = cmd->ident; chan->ident = cmd->ident;
...@@ -2434,8 +2486,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -2434,8 +2486,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
/* don't delete l2cap channel if sk is owned by user */ /* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) { if (sock_owned_by_user(sk)) {
sk->sk_state = BT_DISCONN; sk->sk_state = BT_DISCONN;
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
l2cap_sock_set_timer(sk, HZ / 5); l2cap_chan_set_timer(chan, HZ / 5);
break; break;
} }
...@@ -2608,7 +2660,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -2608,7 +2660,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
default: default:
sk->sk_err = ECONNRESET; sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5); l2cap_chan_set_timer(chan, HZ * 5);
l2cap_send_disconn_req(conn, chan, ECONNRESET); l2cap_send_disconn_req(conn, chan, ECONNRESET);
goto done; goto done;
} }
...@@ -2664,8 +2716,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -2664,8 +2716,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
/* don't delete l2cap channel if sk is owned by user */ /* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) { if (sock_owned_by_user(sk)) {
sk->sk_state = BT_DISCONN; sk->sk_state = BT_DISCONN;
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
l2cap_sock_set_timer(sk, HZ / 5); l2cap_chan_set_timer(chan, HZ / 5);
bh_unlock_sock(sk); bh_unlock_sock(sk);
return 0; return 0;
} }
...@@ -2698,8 +2750,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -2698,8 +2750,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
/* don't delete l2cap channel if sk is owned by user */ /* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) { if (sock_owned_by_user(sk)) {
sk->sk_state = BT_DISCONN; sk->sk_state = BT_DISCONN;
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
l2cap_sock_set_timer(sk, HZ / 5); l2cap_chan_set_timer(chan, HZ / 5);
bh_unlock_sock(sk); bh_unlock_sock(sk);
return 0; return 0;
} }
...@@ -4090,20 +4142,18 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) ...@@ -4090,20 +4142,18 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
{ {
struct sock *sk = chan->sk;
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
return; return;
if (encrypt == 0x00) { if (encrypt == 0x00) {
if (chan->sec_level == BT_SECURITY_MEDIUM) { if (chan->sec_level == BT_SECURITY_MEDIUM) {
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
l2cap_sock_set_timer(sk, HZ * 5); l2cap_chan_set_timer(chan, HZ * 5);
} else if (chan->sec_level == BT_SECURITY_HIGH) } else if (chan->sec_level == BT_SECURITY_HIGH)
__l2cap_chan_close(chan, ECONNREFUSED); __l2cap_chan_close(chan, ECONNREFUSED);
} else { } else {
if (chan->sec_level == BT_SECURITY_MEDIUM) if (chan->sec_level == BT_SECURITY_MEDIUM)
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
} }
} }
...@@ -4148,8 +4198,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) ...@@ -4148,8 +4198,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
l2cap_send_cmd(conn, chan->ident, l2cap_send_cmd(conn, chan->ident,
L2CAP_CONN_REQ, sizeof(req), &req); L2CAP_CONN_REQ, sizeof(req), &req);
} else { } else {
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
l2cap_sock_set_timer(sk, HZ / 10); l2cap_chan_set_timer(chan, HZ / 10);
} }
} else if (sk->sk_state == BT_CONNECT2) { } else if (sk->sk_state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp; struct l2cap_conn_rsp rsp;
...@@ -4160,7 +4210,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) ...@@ -4160,7 +4210,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
result = L2CAP_CR_SUCCESS; result = L2CAP_CR_SUCCESS;
} else { } else {
sk->sk_state = BT_DISCONN; sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ / 10); l2cap_chan_set_timer(chan, HZ / 10);
result = L2CAP_CR_SEC_BLOCK; result = L2CAP_CR_SEC_BLOCK;
} }
......
...@@ -32,52 +32,6 @@ ...@@ -32,52 +32,6 @@
static const struct proto_ops l2cap_sock_ops; static const struct proto_ops l2cap_sock_ops;
/* ---- L2CAP timers ---- */
static void l2cap_sock_timeout(unsigned long arg)
{
struct sock *sk = (struct sock *) arg;
int reason;
BT_DBG("sock %p state %d", sk, sk->sk_state);
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* sk is owned by user. Try again later */
l2cap_sock_set_timer(sk, HZ / 5);
bh_unlock_sock(sk);
sock_put(sk);
return;
}
if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
reason = ECONNREFUSED;
else if (sk->sk_state == BT_CONNECT &&
l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
reason = ECONNREFUSED;
else
reason = ETIMEDOUT;
__l2cap_chan_close(l2cap_pi(sk)->chan, reason);
bh_unlock_sock(sk);
l2cap_sock_kill(sk);
sock_put(sk);
}
void l2cap_sock_set_timer(struct sock *sk, long timeout)
{
BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
}
void l2cap_sock_clear_timer(struct sock *sk)
{
BT_DBG("sock %p state %d", sk, sk->sk_state);
sk_stop_timer(sk, &sk->sk_timer);
}
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -753,7 +707,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) ...@@ -753,7 +707,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
err = __l2cap_wait_ack(sk); err = __l2cap_wait_ack(sk);
sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_shutdown = SHUTDOWN_MASK;
l2cap_sock_clear_timer(sk); l2cap_chan_clear_timer(chan);
__l2cap_chan_close(chan, 0); __l2cap_chan_close(chan, 0);
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) 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,8 +833,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
sk->sk_protocol = proto; sk->sk_protocol = proto;
sk->sk_state = BT_OPEN; sk->sk_state = BT_OPEN;
setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
return sk; return sk;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment