l2cap_conn_start(conn);
 }
 
+static void l2cap_conn_del(struct hci_conn *hcon, int err)
+{
+       struct l2cap_conn *conn = hcon->l2cap_data;
+       struct l2cap_chan *chan, *l;
+       struct sock *sk;
+
+       if (!conn)
+               return;
+
+       BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
+
+       kfree_skb(conn->rx_skb);
+
+       /* Kill channels */
+       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+               sk = chan->sk;
+               bh_lock_sock(sk);
+               l2cap_chan_del(chan, err);
+               bh_unlock_sock(sk);
+               chan->ops->close(chan->data);
+       }
+
+       if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
+               del_timer_sync(&conn->info_timer);
+
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+               del_timer(&conn->security_timer);
+
+       hcon->l2cap_data = NULL;
+       kfree(conn);
+}
+
+static void security_timeout(unsigned long arg)
+{
+       struct l2cap_conn *conn = (void *) arg;
+
+       l2cap_conn_del(conn->hcon, ETIMEDOUT);
+}
+
 static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
 
        INIT_LIST_HEAD(&conn->chan_l);
 
-       if (hcon->type != LE_LINK)
+       if (hcon->type == LE_LINK)
+               setup_timer(&conn->security_timer, security_timeout,
+                                               (unsigned long) conn);
+       else
                setup_timer(&conn->info_timer, l2cap_info_timeout,
                                                (unsigned long) conn);
 
        return conn;
 }
 
-static void l2cap_conn_del(struct hci_conn *hcon, int err)
-{
-       struct l2cap_conn *conn = hcon->l2cap_data;
-       struct l2cap_chan *chan, *l;
-       struct sock *sk;
-
-       if (!conn)
-               return;
-
-       BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
-
-       kfree_skb(conn->rx_skb);
-
-       /* Kill channels */
-       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
-               sk = chan->sk;
-               bh_lock_sock(sk);
-               l2cap_chan_del(chan, err);
-               bh_unlock_sock(sk);
-               chan->ops->close(chan->data);
-       }
-
-       if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
-               del_timer_sync(&conn->info_timer);
-
-       hcon->l2cap_data = NULL;
-       kfree(conn);
-}
-
 static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
        write_lock_bh(&conn->chan_lock);
                if (chan->scid == L2CAP_CID_LE_DATA) {
                        if (!status && encrypt) {
                                chan->sec_level = hcon->sec_level;
+                               del_timer(&conn->security_timer);
                                l2cap_chan_ready(sk);
                        }
 
 
 #include <linux/crypto.h>
 #include <crypto/b128ops.h>
 
+#define SMP_TIMEOUT 30000 /* 30 seconds */
+
 static inline void swap128(u8 src[16], u8 dst[16])
 {
        int i;
 
        smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
 
+       mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
        return 0;
 }
 
                smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
        }
 
+       mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
        return 0;
 }
 
 
        smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
 
+       mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
        set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 
        return 0;
                conn->preq[0] = SMP_CMD_PAIRING_REQ;
                memcpy(&conn->preq[1], &cp, sizeof(cp));
 
+               mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
                smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
        } else {
                struct smp_cmd_security_req cp;