static struct workqueue_struct *_busy_wq;
 
-struct bt_sock_list l2cap_sk_list = {
-       .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
-};
+LIST_HEAD(chan_list);
+DEFINE_RWLOCK(chan_list_lock);
 
 static void l2cap_busy_work(struct work_struct *work);
 
        return c;
 }
 
-static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
 {
-       struct sock *sk;
-       struct hlist_node *node;
-       sk_for_each(sk, node, &l2cap_sk_list.head) {
-               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       struct l2cap_chan *c;
 
-               if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+       list_for_each_entry(c, &chan_list, global_l) {
+               if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
                        goto found;
        }
 
-       sk = NULL;
+       c = NULL;
 found:
-       return sk;
+       return c;
 }
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 {
        int err;
 
-       write_lock_bh(&l2cap_sk_list.lock);
+       write_lock_bh(&chan_list_lock);
 
-       if (psm && __l2cap_get_sock_by_addr(psm, src)) {
+       if (psm && __l2cap_global_chan_by_addr(psm, src)) {
                err = -EADDRINUSE;
                goto done;
        }
 
                err = -EINVAL;
                for (p = 0x1001; p < 0x1100; p += 2)
-                       if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) {
+                       if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
                                chan->psm   = cpu_to_le16(p);
                                chan->sport = cpu_to_le16(p);
                                err = 0;
        }
 
 done:
-       write_unlock_bh(&l2cap_sk_list.lock);
+       write_unlock_bh(&chan_list_lock);
        return err;
 }
 
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
 {
-       write_lock_bh(&l2cap_sk_list.lock);
+       write_lock_bh(&chan_list_lock);
 
        chan->scid = scid;
 
-       write_unlock_bh(&l2cap_sk_list.lock);
+       write_unlock_bh(&chan_list_lock);
 
        return 0;
 }
        return 0;
 }
 
-struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
+struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 {
        struct l2cap_chan *chan;
 
 
        chan->sk = sk;
 
+       write_lock_bh(&chan_list_lock);
+       list_add(&chan->global_l, &chan_list);
+       write_unlock_bh(&chan_list_lock);
+
        return chan;
 }
 
-void l2cap_chan_free(struct l2cap_chan *chan)
+void l2cap_chan_destroy(struct l2cap_chan *chan)
 {
+       write_lock_bh(&chan_list_lock);
+       list_del(&chan->global_l);
+       write_unlock_bh(&chan_list_lock);
+
        kfree(chan);
 }
 
 /* Find socket with cid and source bdaddr.
  * Returns closest match, locked.
  */
-static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
+static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
 {
-       struct sock *sk = NULL, *sk1 = NULL;
-       struct hlist_node *node;
+       struct l2cap_chan *c, *c1 = NULL;
 
-       read_lock(&l2cap_sk_list.lock);
+       read_lock(&chan_list_lock);
 
-       sk_for_each(sk, node, &l2cap_sk_list.head) {
-               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       list_for_each_entry(c, &chan_list, global_l) {
+               struct sock *sk = c->sk;
 
                if (state && sk->sk_state != state)
                        continue;
 
-               if (chan->scid == cid) {
+               if (c->scid == cid) {
                        /* Exact match. */
-                       if (!bacmp(&bt_sk(sk)->src, src))
-                               break;
+                       if (!bacmp(&bt_sk(sk)->src, src)) {
+                               read_unlock(&chan_list_lock);
+                               return c;
+                       }
 
                        /* Closest match */
                        if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-                               sk1 = sk;
+                               c1 = c;
                }
        }
 
-       read_unlock(&l2cap_sk_list.lock);
+       read_unlock(&chan_list_lock);
 
-       return node ? sk : sk1;
+       return c1;
 }
 
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
        struct sock *parent, *sk;
-       struct l2cap_chan *chan;
+       struct l2cap_chan *chan, *pchan;
 
        BT_DBG("");
 
        /* Check if we have socket listening on cid */
-       parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
+       pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
                                                        conn->src);
-       if (!parent)
+       if (!pchan)
                return;
 
+       parent = pchan->sk;
+
        bh_lock_sock(parent);
 
        /* Check for backlog size */
        if (!sk)
                goto clean;
 
-       chan = l2cap_chan_alloc(sk);
+       chan = l2cap_chan_create(sk);
        if (!chan) {
                l2cap_sock_kill(sk);
                goto clean;
 /* Find socket with psm and source bdaddr.
  * Returns closest match.
  */
-static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
+static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
 {
-       struct sock *sk = NULL, *sk1 = NULL;
-       struct hlist_node *node;
+       struct l2cap_chan *c, *c1 = NULL;
 
-       read_lock(&l2cap_sk_list.lock);
+       read_lock(&chan_list_lock);
 
-       sk_for_each(sk, node, &l2cap_sk_list.head) {
-               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       list_for_each_entry(c, &chan_list, global_l) {
+               struct sock *sk = c->sk;
 
                if (state && sk->sk_state != state)
                        continue;
 
-               if (chan->psm == psm) {
+               if (c->psm == psm) {
                        /* Exact match. */
-                       if (!bacmp(&bt_sk(sk)->src, src))
-                               break;
+                       if (!bacmp(&bt_sk(sk)->src, src)) {
+                               read_unlock_bh(&chan_list_lock);
+                               return c;
+                       }
 
                        /* Closest match */
                        if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-                               sk1 = sk;
+                               c1 = c;
                }
        }
 
-       read_unlock(&l2cap_sk_list.lock);
+       read_unlock(&chan_list_lock);
 
-       return node ? sk : sk1;
+       return c1;
 }
 
 int l2cap_chan_connect(struct l2cap_chan *chan)
 {
        struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
        struct l2cap_conn_rsp rsp;
-       struct l2cap_chan *chan = NULL;
+       struct l2cap_chan *chan = NULL, *pchan;
        struct sock *parent, *sk = NULL;
        int result, status = L2CAP_CS_NO_INFO;
 
        u16 dcid = 0, scid = __le16_to_cpu(req->scid);
        __le16 psm = req->psm;
 
-       BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
+       BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
        /* Check if we have socket listening on psm */
-       parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
-       if (!parent) {
+       pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
+       if (!pchan) {
                result = L2CAP_CR_BAD_PSM;
                goto sendresp;
        }
 
+       BT_ERR("%p 0x%2.2x", pchan, pchan->psm);
+
+       parent = pchan->sk;
+
        bh_lock_sock(parent);
 
        /* Check if the ACL is secure enough (if not SDP) */
        if (!sk)
                goto response;
 
-       chan = l2cap_chan_alloc(sk);
+       chan = l2cap_chan_create(sk);
        if (!chan) {
                l2cap_sock_kill(sk);
                goto response;
 static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
 {
        struct sock *sk;
+       struct l2cap_chan *chan;
 
-       sk = l2cap_get_sock_by_psm(0, psm, conn->src);
-       if (!sk)
+       chan = l2cap_global_chan_by_psm(0, psm, conn->src);
+       if (!chan)
                goto drop;
 
+       sk = chan->sk;
+
        bh_lock_sock(sk);
 
        BT_DBG("sk %p, len %d", sk, skb->len);
 static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
 {
        struct sock *sk;
+       struct l2cap_chan *chan;
 
-       sk = l2cap_get_sock_by_scid(0, cid, conn->src);
-       if (!sk)
+       chan = l2cap_global_chan_by_scid(0, cid, conn->src);
+       if (!chan)
                goto drop;
 
+       sk = chan->sk;
+
        bh_lock_sock(sk);
 
        BT_DBG("sk %p, len %d", sk, skb->len);
 static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 {
        int exact = 0, lm1 = 0, lm2 = 0;
-       register struct sock *sk;
-       struct hlist_node *node;
+       struct l2cap_chan *c;
 
        if (type != ACL_LINK)
                return -EINVAL;
        BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
        /* Find listening sockets and check their link_mode */
-       read_lock(&l2cap_sk_list.lock);
-       sk_for_each(sk, node, &l2cap_sk_list.head) {
-               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       read_lock(&chan_list_lock);
+       list_for_each_entry(c, &chan_list, global_l) {
+               struct sock *sk = c->sk;
 
                if (sk->sk_state != BT_LISTEN)
                        continue;
 
                if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
                        lm1 |= HCI_LM_ACCEPT;
-                       if (chan->role_switch)
+                       if (c->role_switch)
                                lm1 |= HCI_LM_MASTER;
                        exact++;
                } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
                        lm2 |= HCI_LM_ACCEPT;
-                       if (chan->role_switch)
+                       if (c->role_switch)
                                lm2 |= HCI_LM_MASTER;
                }
        }
-       read_unlock(&l2cap_sk_list.lock);
+       read_unlock(&chan_list_lock);
 
        return exact ? lm1 : lm2;
 }
 
 static int l2cap_debugfs_show(struct seq_file *f, void *p)
 {
-       struct sock *sk;
-       struct hlist_node *node;
+       struct l2cap_chan *c;
 
-       read_lock_bh(&l2cap_sk_list.lock);
+       read_lock_bh(&chan_list_lock);
 
-       sk_for_each(sk, node, &l2cap_sk_list.head) {
-               struct l2cap_pinfo *pi = l2cap_pi(sk);
-               struct l2cap_chan *chan = pi->chan;
+       list_for_each_entry(c, &chan_list, global_l) {
+               struct sock *sk = c->sk;
 
                seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
                                        batostr(&bt_sk(sk)->src),
                                        batostr(&bt_sk(sk)->dst),
-                                       sk->sk_state, __le16_to_cpu(chan->psm),
-                                       chan->scid, chan->dcid,
-                                       chan->imtu, chan->omtu, chan->sec_level,
-                                       chan->mode);
+                                       sk->sk_state, __le16_to_cpu(c->psm),
+                                       c->scid, c->dcid, c->imtu, c->omtu,
+                                       c->sec_level, c->mode);
        }
 
-       read_unlock_bh(&l2cap_sk_list.lock);
+       read_unlock_bh(&chan_list_lock);
 
        return 0;
 }