diff options
-rw-r--r-- | net/bluetooth/l2cap.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4ed38272df78..18a802cc0469 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
83 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); | 83 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); |
84 | 84 | ||
85 | /* ---- L2CAP timers ---- */ | 85 | /* ---- L2CAP timers ---- */ |
86 | static void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
87 | { | ||
88 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
89 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
90 | } | ||
91 | |||
92 | static void l2cap_sock_clear_timer(struct sock *sk) | ||
93 | { | ||
94 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
95 | sk_stop_timer(sk, &sk->sk_timer); | ||
96 | } | ||
97 | |||
86 | static void l2cap_sock_timeout(unsigned long arg) | 98 | static void l2cap_sock_timeout(unsigned long arg) |
87 | { | 99 | { |
88 | struct sock *sk = (struct sock *) arg; | 100 | struct sock *sk = (struct sock *) arg; |
@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
92 | 104 | ||
93 | bh_lock_sock(sk); | 105 | bh_lock_sock(sk); |
94 | 106 | ||
107 | if (sock_owned_by_user(sk)) { | ||
108 | /* sk is owned by user. Try again later */ | ||
109 | l2cap_sock_set_timer(sk, HZ / 5); | ||
110 | bh_unlock_sock(sk); | ||
111 | sock_put(sk); | ||
112 | return; | ||
113 | } | ||
114 | |||
95 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | 115 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) |
96 | reason = ECONNREFUSED; | 116 | reason = ECONNREFUSED; |
97 | else if (sk->sk_state == BT_CONNECT && | 117 | else if (sk->sk_state == BT_CONNECT && |
@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
108 | sock_put(sk); | 128 | sock_put(sk); |
109 | } | 129 | } |
110 | 130 | ||
111 | static void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
112 | { | ||
113 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
114 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
115 | } | ||
116 | |||
117 | static void l2cap_sock_clear_timer(struct sock *sk) | ||
118 | { | ||
119 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
120 | sk_stop_timer(sk, &sk->sk_timer); | ||
121 | } | ||
122 | |||
123 | /* ---- L2CAP channels ---- */ | 131 | /* ---- L2CAP channels ---- */ |
124 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) | 132 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) |
125 | { | 133 | { |