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_session_put(s);
+       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)
 {
 
        rfcomm_session_hold(s);
 
+       rfcomm_session_clear_timer(s);
        rfcomm_dlc_hold(d);
        list_add(&d->list, &s->dlcs);
        d->session = s;
        d->session = NULL;
        rfcomm_dlc_put(d);
 
+       if (list_empty(&s->dlcs))
+               rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT);
+
        rfcomm_session_put(s);
 }
 
 
        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;
        if (state == BT_CONNECTED)
                rfcomm_send_disc(s, 0);
 
+       rfcomm_session_clear_timer(s);
        sock_release(s->sock);
        kfree(s);
 
                __rfcomm_dlc_close(d, err);
        }
 
+       rfcomm_session_clear_timer(s);
        rfcomm_session_put(s);
 }
 
                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);
+                       continue;
+               }
+
                if (s->state == BT_LISTEN) {
                        rfcomm_accept_connection(s);
                        continue;