Move source tree closer to the 2.6.32.17 mainline
/net/bluetooth/rfcomm/core.c
blob:483b8ab62f062ea490fd0089023881623b72ae3b -> blob:ef3abf28c12039cd9d538b2f826a410dc647d545
--- net/bluetooth/rfcomm/core.c
+++ net/bluetooth/rfcomm/core.c
@@ -244,6 +244,32 @@ static inline int rfcomm_check_security(
auth_type);
}
+static void rfcomm_session_timeout(unsigned long arg)
+{
+ struct rfcomm_session *s = (void *) arg;
+
+ BT_DBG("session %p state %ld", s, s->state);
+
+ set_bit(RFCOMM_TIMED_OUT, &s->flags);
+ rfcomm_schedule(RFCOMM_SCHED_TIMEO);
+}
+
+static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout)
+{
+ BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout);
+
+ if (!mod_timer(&s->timer, jiffies + timeout))
+ rfcomm_session_hold(s);
+}
+
+static void rfcomm_session_clear_timer(struct rfcomm_session *s)
+{
+ BT_DBG("session %p state %ld", s, s->state);
+
+ if (timer_pending(&s->timer) && del_timer(&s->timer))
+ rfcomm_session_put(s);
+}
+
/* ---- RFCOMM DLCs ---- */
static void rfcomm_dlc_timeout(unsigned long arg)
{
@@ -320,6 +346,7 @@ static void rfcomm_dlc_link(struct rfcom
rfcomm_session_hold(s);
+ rfcomm_session_clear_timer(s);
rfcomm_dlc_hold(d);
list_add(&d->list, &s->dlcs);
d->session = s;
@@ -335,6 +362,9 @@ static void rfcomm_dlc_unlink(struct rfc
d->session = NULL;
rfcomm_dlc_put(d);
+ if (list_empty(&s->dlcs))
+ rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT);
+
rfcomm_session_put(s);
}
@@ -428,6 +458,7 @@ static int __rfcomm_dlc_close(struct rfc
switch (d->state) {
case BT_CONNECT:
+ case BT_CONFIG:
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
rfcomm_schedule(RFCOMM_SCHED_AUTH);
@@ -447,6 +478,7 @@ static int __rfcomm_dlc_close(struct rfc
break;
case BT_OPEN:
+ case BT_CONNECT2:
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
rfcomm_schedule(RFCOMM_SCHED_AUTH);
@@ -565,6 +597,8 @@ static struct rfcomm_session *rfcomm_ses
BT_DBG("session %p sock %p", s, sock);
+ setup_timer(&s->timer, rfcomm_session_timeout, (unsigned long) s);
+
INIT_LIST_HEAD(&s->dlcs);
s->state = state;
s->sock = sock;
@@ -596,6 +630,7 @@ static void rfcomm_session_del(struct rf
if (state == BT_CONNECTED)
rfcomm_send_disc(s, 0);
+ rfcomm_session_clear_timer(s);
sock_release(s->sock);
kfree(s);
@@ -637,6 +672,7 @@ static void rfcomm_session_close(struct
__rfcomm_dlc_close(d, err);
}
+ rfcomm_session_clear_timer(s);
rfcomm_session_put(s);
}
@@ -1111,8 +1147,7 @@ static int rfcomm_recv_ua(struct rfcomm_
break;
case BT_DISCONN:
- if (s->sock->sk->sk_state != BT_CLOSED)
- rfcomm_session_put(s);
+ rfcomm_session_put(s);
break;
}
}
@@ -1193,6 +1228,8 @@ void rfcomm_dlc_accept(struct rfcomm_dlc
rfcomm_send_ua(d->session, d->dlci);
+ rfcomm_dlc_clear_timer(d);
+
rfcomm_dlc_lock(d);
d->state = BT_CONNECTED;
d->state_change(d, 0);
@@ -1210,6 +1247,11 @@ static void rfcomm_check_accept(struct r
if (d->defer_setup) {
set_bit(RFCOMM_DEFER_SETUP, &d->flags);
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
+
+ rfcomm_dlc_lock(d);
+ d->state = BT_CONNECT2;
+ d->state_change(d, 0);
+ rfcomm_dlc_unlock(d);
} else
rfcomm_dlc_accept(d);
} else {
@@ -1751,6 +1793,11 @@ static inline void rfcomm_process_dlcs(s
if (d->defer_setup) {
set_bit(RFCOMM_DEFER_SETUP, &d->flags);
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
+
+ rfcomm_dlc_lock(d);
+ d->state = BT_CONNECT2;
+ d->state_change(d, 0);
+ rfcomm_dlc_unlock(d);
} else
rfcomm_dlc_accept(d);
}
@@ -1866,6 +1913,13 @@ static inline void rfcomm_process_sessio
struct rfcomm_session *s;
s = list_entry(p, struct rfcomm_session, list);
+ if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
+ s->state = BT_DISCONN;
+ rfcomm_send_disc(s, 0);
+ rfcomm_session_put(s);
+ continue;
+ }
+
if (s->state == BT_LISTEN) {
rfcomm_accept_connection(s);
continue;
@@ -2042,6 +2096,7 @@ static ssize_t rfcomm_dlc_sysfs_show(str
struct rfcomm_session *s;
struct list_head *pp, *p;
char *str = buf;
+ int size = PAGE_SIZE;
rfcomm_lock();
@@ -2050,11 +2105,21 @@ static ssize_t rfcomm_dlc_sysfs_show(str
list_for_each(pp, &s->dlcs) {
struct sock *sk = s->sock->sk;
struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list);
+ int len;
- str += sprintf(str, "%s %s %ld %d %d %d %d\n",
+ len = snprintf(str, size, "%s %s %ld %d %d %d %d\n",
batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits);
+
+ size -= len;
+ if (size <= 0)
+ break;
+
+ str += len;
}
+
+ if (size <= 0)
+ break;
}
rfcomm_unlock();