|
@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
|
|
|
static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
|
|
|
|
|
|
/* ---- L2CAP timers ---- */
|
|
|
+static 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);
|
|
|
+}
|
|
|
+
|
|
|
+static 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 void l2cap_sock_timeout(unsigned long arg)
|
|
|
{
|
|
|
struct sock *sk = (struct sock *) arg;
|
|
@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)
|
|
|
|
|
|
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 &&
|
|
@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg)
|
|
|
sock_put(sk);
|
|
|
}
|
|
|
|
|
|
-static 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);
|
|
|
-}
|
|
|
-
|
|
|
-static 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);
|
|
|
-}
|
|
|
-
|
|
|
/* ---- L2CAP channels ---- */
|
|
|
static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
|
|
|
{
|