]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 15 Nov 2013 19:18:45 +0000 (14:18 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 15 Nov 2013 19:18:45 +0000 (14:18 -0500)
1  2 
net/bluetooth/l2cap_core.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/smp.c

index 0cef677078381315c7ce3e58abb6573136bc227b,11b5d097f602b0d4f2cd304ee457a22e55b67037..4af3821df880f70dd17cd36161eff766c3e49334
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/l2cap.h>
 -#include <net/bluetooth/smp.h>
 -#include <net/bluetooth/a2mp.h>
 -#include <net/bluetooth/amp.h>
 +
 +#include "smp.h"
 +#include "a2mp.h"
 +#include "amp.h"
  
  bool disable_ertm;
  
 -static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
 -static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
 +static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
 +static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
  
  static LIST_HEAD(chan_list);
  static DEFINE_RWLOCK(chan_list_lock);
@@@ -59,18 -58,6 +59,18 @@@ static void l2cap_send_disconn_req(stru
  static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
                     struct sk_buff_head *skbs, u8 event);
  
 +static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type)
 +{
 +      if (hcon->type == LE_LINK) {
 +              if (type == ADDR_LE_DEV_PUBLIC)
 +                      return BDADDR_LE_PUBLIC;
 +              else
 +                      return BDADDR_LE_RANDOM;
 +      }
 +
 +      return BDADDR_BREDR;
 +}
 +
  /* ---- L2CAP channels ---- */
  
  static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
@@@ -161,7 -148,7 +161,7 @@@ static struct l2cap_chan *__l2cap_globa
        struct l2cap_chan *c;
  
        list_for_each_entry(c, &chan_list, global_l) {
 -              if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
 +              if (c->sport == psm && !bacmp(&c->src, src))
                        return c;
        }
        return NULL;
@@@ -223,25 -210,38 +223,25 @@@ static u16 l2cap_alloc_cid(struct l2cap
        return 0;
  }
  
 -static void __l2cap_state_change(struct l2cap_chan *chan, int state)
 +static void l2cap_state_change(struct l2cap_chan *chan, int state)
  {
        BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
               state_to_string(state));
  
        chan->state = state;
 -      chan->ops->state_change(chan, state);
 -}
 -
 -static void l2cap_state_change(struct l2cap_chan *chan, int state)
 -{
 -      struct sock *sk = chan->sk;
 -
 -      lock_sock(sk);
 -      __l2cap_state_change(chan, state);
 -      release_sock(sk);
 +      chan->ops->state_change(chan, state, 0);
  }
  
 -static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
 +static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
 +                                              int state, int err)
  {
 -      struct sock *sk = chan->sk;
 -
 -      sk->sk_err = err;
 +      chan->state = state;
 +      chan->ops->state_change(chan, chan->state, err);
  }
  
  static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
  {
 -      struct sock *sk = chan->sk;
 -
 -      lock_sock(sk);
 -      __l2cap_chan_set_err(chan, err);
 -      release_sock(sk);
 +      chan->ops->state_change(chan, chan->state, err);
  }
  
  static void __set_retrans_timer(struct l2cap_chan *chan)
@@@ -620,8 -620,10 +620,8 @@@ void l2cap_chan_del(struct l2cap_chan *
  void l2cap_chan_close(struct l2cap_chan *chan, int reason)
  {
        struct l2cap_conn *conn = chan->conn;
 -      struct sock *sk = chan->sk;
  
 -      BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state),
 -             sk);
 +      BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
  
        switch (chan->state) {
        case BT_LISTEN:
        case BT_CONFIG:
                if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
                    conn->hcon->type == ACL_LINK) {
 -                      __set_chan_timer(chan, sk->sk_sndtimeo);
 +                      __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
                        l2cap_send_disconn_req(chan, reason);
                } else
                        l2cap_chan_del(chan, reason);
                        struct l2cap_conn_rsp rsp;
                        __u16 result;
  
 -                      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
 +                      if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
                                result = L2CAP_CR_SEC_BLOCK;
                        else
                                result = L2CAP_CR_BAD_PSM;
 +
                        l2cap_state_change(chan, BT_DISCONN);
  
                        rsp.scid   = cpu_to_le16(chan->dcid);
  
  static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
  {
 -      if (chan->chan_type == L2CAP_CHAN_RAW) {
 +      switch (chan->chan_type) {
 +      case L2CAP_CHAN_RAW:
                switch (chan->sec_level) {
                case BT_SECURITY_HIGH:
                        return HCI_AT_DEDICATED_BONDING_MITM;
                default:
                        return HCI_AT_NO_BONDING;
                }
 -      } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
 -              if (chan->sec_level == BT_SECURITY_LOW)
 -                      chan->sec_level = BT_SECURITY_SDP;
 -
 +              break;
 +      case L2CAP_CHAN_CONN_LESS:
 +              if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
 +                      if (chan->sec_level == BT_SECURITY_LOW)
 +                              chan->sec_level = BT_SECURITY_SDP;
 +              }
                if (chan->sec_level == BT_SECURITY_HIGH)
                        return HCI_AT_NO_BONDING_MITM;
                else
                        return HCI_AT_NO_BONDING;
 -      } else {
 +              break;
 +      case L2CAP_CHAN_CONN_ORIENTED:
 +              if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
 +                      if (chan->sec_level == BT_SECURITY_LOW)
 +                              chan->sec_level = BT_SECURITY_SDP;
 +
 +                      if (chan->sec_level == BT_SECURITY_HIGH)
 +                              return HCI_AT_NO_BONDING_MITM;
 +                      else
 +                              return HCI_AT_NO_BONDING;
 +              }
 +              /* fall through */
 +      default:
                switch (chan->sec_level) {
                case BT_SECURITY_HIGH:
                        return HCI_AT_GENERAL_BONDING_MITM;
                default:
                        return HCI_AT_NO_BONDING;
                }
 +              break;
        }
  }
  
@@@ -1030,29 -1015,14 +1030,29 @@@ static inline int __l2cap_no_conn_pendi
  static bool __amp_capable(struct l2cap_chan *chan)
  {
        struct l2cap_conn *conn = chan->conn;
 +      struct hci_dev *hdev;
 +      bool amp_available = false;
  
 -      if (enable_hs &&
 -          hci_amp_capable() &&
 -          chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
 -          conn->fixed_chan_mask & L2CAP_FC_A2MP)
 -              return true;
 -      else
 +      if (!conn->hs_enabled)
                return false;
 +
 +      if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
 +              return false;
 +
 +      read_lock(&hci_dev_list_lock);
 +      list_for_each_entry(hdev, &hci_dev_list, list) {
 +              if (hdev->amp_type != AMP_TYPE_BREDR &&
 +                  test_bit(HCI_UP, &hdev->flags)) {
 +                      amp_available = true;
 +                      break;
 +              }
 +      }
 +      read_unlock(&hci_dev_list_lock);
 +
 +      if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
 +              return amp_available;
 +
 +      return false;
  }
  
  static bool l2cap_check_efs(struct l2cap_chan *chan)
@@@ -1216,6 -1186,7 +1216,6 @@@ static inline int l2cap_mode_supported(
  
  static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
  {
 -      struct sock *sk = chan->sk;
        struct l2cap_conn *conn = chan->conn;
        struct l2cap_disconn_req req;
  
        l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
                       sizeof(req), &req);
  
 -      lock_sock(sk);
 -      __l2cap_state_change(chan, BT_DISCONN);
 -      __l2cap_chan_set_err(chan, err);
 -      release_sock(sk);
 +      l2cap_state_change_and_error(chan, BT_DISCONN, err);
  }
  
  /* ---- L2CAP connections ---- */
@@@ -1251,6 -1225,8 +1251,6 @@@ static void l2cap_conn_start(struct l2c
        mutex_lock(&conn->chan_lock);
  
        list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
 -              struct sock *sk = chan->sk;
 -
                l2cap_chan_lock(chan);
  
                if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
                        rsp.dcid = cpu_to_le16(chan->scid);
  
                        if (l2cap_chan_check_security(chan)) {
 -                              lock_sock(sk);
 -                              if (test_bit(BT_SK_DEFER_SETUP,
 -                                           &bt_sk(sk)->flags)) {
 +                              if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
                                        rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
                                        rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
                                        chan->ops->defer(chan);
  
                                } else {
 -                                      __l2cap_state_change(chan, BT_CONFIG);
 +                                      l2cap_state_change(chan, BT_CONFIG);
                                        rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
                                        rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
                                }
 -                              release_sock(sk);
                        } else {
                                rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
                                rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
@@@ -1330,6 -1309,8 +1330,6 @@@ static struct l2cap_chan *l2cap_global_
        read_lock(&chan_list_lock);
  
        list_for_each_entry(c, &chan_list, global_l) {
 -              struct sock *sk = c->sk;
 -
                if (state && c->state != state)
                        continue;
  
                        int src_any, dst_any;
  
                        /* Exact match. */
 -                      src_match = !bacmp(&bt_sk(sk)->src, src);
 -                      dst_match = !bacmp(&bt_sk(sk)->dst, dst);
 +                      src_match = !bacmp(&c->src, src);
 +                      dst_match = !bacmp(&c->dst, dst);
                        if (src_match && dst_match) {
                                read_unlock(&chan_list_lock);
                                return c;
                        }
  
                        /* Closest match */
 -                      src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
 -                      dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
 +                      src_any = !bacmp(&c->src, BDADDR_ANY);
 +                      dst_any = !bacmp(&c->dst, BDADDR_ANY);
                        if ((src_match && dst_any) || (src_any && dst_match) ||
                            (src_any && dst_any))
                                c1 = c;
  
  static void l2cap_le_conn_ready(struct l2cap_conn *conn)
  {
 -      struct sock *parent;
 +      struct hci_conn *hcon = conn->hcon;
        struct l2cap_chan *chan, *pchan;
 +      u8 dst_type;
  
        BT_DBG("");
  
        /* Check if we have socket listening on cid */
        pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
 -                                        conn->src, conn->dst);
 +                                        &hcon->src, &hcon->dst);
        if (!pchan)
                return;
  
        if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
                return;
  
 -      parent = pchan->sk;
 +      dst_type = bdaddr_type(hcon, hcon->dst_type);
 +
 +      /* If device is blocked, do not create a channel for it */
 +      if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
 +              return;
  
 -      lock_sock(parent);
 +      l2cap_chan_lock(pchan);
  
        chan = pchan->ops->new_connection(pchan);
        if (!chan)
  
        chan->dcid = L2CAP_CID_ATT;
  
 -      bacpy(&bt_sk(chan->sk)->src, conn->src);
 -      bacpy(&bt_sk(chan->sk)->dst, conn->dst);
 +      bacpy(&chan->src, &hcon->src);
 +      bacpy(&chan->dst, &hcon->dst);
 +      chan->src_type = bdaddr_type(hcon, hcon->src_type);
 +      chan->dst_type = dst_type;
  
        __l2cap_chan_add(conn, chan);
  
  clean:
 -      release_sock(parent);
 +      l2cap_chan_unlock(pchan);
  }
  
  static void l2cap_conn_ready(struct l2cap_conn *conn)
                                l2cap_chan_ready(chan);
  
                } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
 -                      struct sock *sk = chan->sk;
 -                      __clear_chan_timer(chan);
 -                      lock_sock(sk);
 -                      __l2cap_state_change(chan, BT_CONNECTED);
 -                      sk->sk_state_change(sk);
 -                      release_sock(sk);
 +                      l2cap_chan_ready(chan);
  
                } else if (chan->state == BT_CONNECT) {
                        l2cap_do_start(chan);
@@@ -1654,12 -1633,11 +1654,12 @@@ static struct l2cap_conn *l2cap_conn_ad
                break;
        }
  
 -      conn->src = &hcon->hdev->bdaddr;
 -      conn->dst = &hcon->dst;
 -
        conn->feat_mask = 0;
  
 +      if (hcon->type == ACL_LINK)
 +              conn->hs_enabled = test_bit(HCI_HS_ENABLED,
 +                                          &hcon->hdev->dev_flags);
 +
        spin_lock_init(&conn->lock);
        mutex_init(&conn->chan_lock);
  
@@@ -1710,6 -1688,8 +1710,6 @@@ static struct l2cap_chan *l2cap_global_
        read_lock(&chan_list_lock);
  
        list_for_each_entry(c, &chan_list, global_l) {
 -              struct sock *sk = c->sk;
 -
                if (state && c->state != state)
                        continue;
  
                        int src_any, dst_any;
  
                        /* Exact match. */
 -                      src_match = !bacmp(&bt_sk(sk)->src, src);
 -                      dst_match = !bacmp(&bt_sk(sk)->dst, dst);
 +                      src_match = !bacmp(&c->src, src);
 +                      dst_match = !bacmp(&c->dst, dst);
                        if (src_match && dst_match) {
                                read_unlock(&chan_list_lock);
                                return c;
                        }
  
                        /* Closest match */
 -                      src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
 -                      dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
 +                      src_any = !bacmp(&c->src, BDADDR_ANY);
 +                      dst_any = !bacmp(&c->dst, BDADDR_ANY);
                        if ((src_match && dst_any) || (src_any && dst_match) ||
                            (src_any && dst_any))
                                c1 = c;
  int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                       bdaddr_t *dst, u8 dst_type)
  {
 -      struct sock *sk = chan->sk;
 -      bdaddr_t *src = &bt_sk(sk)->src;
        struct l2cap_conn *conn;
        struct hci_conn *hcon;
        struct hci_dev *hdev;
        __u8 auth_type;
        int err;
  
 -      BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst,
 +      BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
               dst_type, __le16_to_cpu(psm));
  
 -      hdev = hci_get_route(dst, src);
 +      hdev = hci_get_route(dst, &chan->src);
        if (!hdev)
                return -EHOSTUNREACH;
  
        }
  
        /* Set destination address and psm */
 -      lock_sock(sk);
 -      bacpy(&bt_sk(sk)->dst, dst);
 -      release_sock(sk);
 +      bacpy(&chan->dst, dst);
 +      chan->dst_type = dst_type;
  
        chan->psm = psm;
        chan->dcid = cid;
        }
  
        /* Update source addr of the socket */
 -      bacpy(src, conn->src);
 +      bacpy(&chan->src, &hcon->src);
 +      chan->src_type = bdaddr_type(hcon, hcon->src_type);
  
        l2cap_chan_unlock(chan);
        l2cap_chan_add(conn, chan);
        hci_conn_drop(hcon);
  
        l2cap_state_change(chan, BT_CONNECT);
 -      __set_chan_timer(chan, sk->sk_sndtimeo);
 +      __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
  
        if (hcon->state == BT_CONNECTED) {
                if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
@@@ -1873,6 -1855,38 +1873,6 @@@ done
        return err;
  }
  
 -int __l2cap_wait_ack(struct sock *sk)
 -{
 -      struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 -      DECLARE_WAITQUEUE(wait, current);
 -      int err = 0;
 -      int timeo = HZ/5;
 -
 -      add_wait_queue(sk_sleep(sk), &wait);
 -      set_current_state(TASK_INTERRUPTIBLE);
 -      while (chan->unacked_frames > 0 && chan->conn) {
 -              if (!timeo)
 -                      timeo = HZ/5;
 -
 -              if (signal_pending(current)) {
 -                      err = sock_intr_errno(timeo);
 -                      break;
 -              }
 -
 -              release_sock(sk);
 -              timeo = schedule_timeout(timeo);
 -              lock_sock(sk);
 -              set_current_state(TASK_INTERRUPTIBLE);
 -
 -              err = sock_error(sk);
 -              if (err)
 -                      break;
 -      }
 -      set_current_state(TASK_RUNNING);
 -      remove_wait_queue(sk_sleep(sk), &wait);
 -      return err;
 -}
 -
  static void l2cap_monitor_timeout(struct work_struct *work)
  {
        struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
@@@ -2249,8 -2263,7 +2249,8 @@@ static struct sk_buff *l2cap_create_con
        int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
        struct l2cap_hdr *lh;
  
 -      BT_DBG("chan %p len %zu priority %u", chan, len, priority);
 +      BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan,
 +             __le16_to_cpu(chan->psm), len, priority);
  
        count = min_t(unsigned int, (conn->mtu - hlen), len);
  
        lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
        lh->cid = cpu_to_le16(chan->dcid);
        lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
 -      put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
 +      put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
  
        err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
        if (unlikely(err < 0)) {
@@@ -2439,6 -2452,9 +2439,9 @@@ int l2cap_chan_send(struct l2cap_chan *
        int err;
        struct sk_buff_head seg_queue;
  
+       if (!chan->conn)
+               return -ENOTCONN;
        /* Connectionless channel */
        if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
                skb = l2cap_create_connless_pdu(chan, msg, len, priority);
@@@ -2813,16 -2829,17 +2816,16 @@@ static void l2cap_raw_recv(struct l2cap
        mutex_lock(&conn->chan_lock);
  
        list_for_each_entry(chan, &conn->chan_l, list) {
 -              struct sock *sk = chan->sk;
                if (chan->chan_type != L2CAP_CHAN_RAW)
                        continue;
  
 -              /* Don't send frame to the socket it came from */
 -              if (skb->sk == sk)
 +              /* Don't send frame to the channel it came from */
 +              if (bt_cb(skb)->chan == chan)
                        continue;
 +
                nskb = skb_clone(skb, GFP_KERNEL);
                if (!nskb)
                        continue;
 -
                if (chan->ops->recv(chan, nskb))
                        kfree_skb(nskb);
        }
@@@ -3029,8 -3046,8 +3032,8 @@@ int l2cap_ertm_init(struct l2cap_chan *
  
        skb_queue_head_init(&chan->tx_q);
  
 -      chan->local_amp_id = 0;
 -      chan->move_id = 0;
 +      chan->local_amp_id = AMP_ID_BREDR;
 +      chan->move_id = AMP_ID_BREDR;
        chan->move_state = L2CAP_MOVE_STABLE;
        chan->move_role = L2CAP_MOVE_ROLE_NONE;
  
@@@ -3070,20 -3087,20 +3073,20 @@@ static inline __u8 l2cap_select_mode(__
        }
  }
  
 -static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
 +static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
  {
 -      return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
 +      return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
  }
  
 -static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
 +static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
  {
 -      return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
 +      return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
  }
  
  static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
                                      struct l2cap_conf_rfc *rfc)
  {
 -      if (chan->local_amp_id && chan->hs_hcon) {
 +      if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
                u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
  
                /* Class 1 devices have must have ERTM timeouts
  static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
  {
        if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
 -          __l2cap_ews_supported(chan)) {
 +          __l2cap_ews_supported(chan->conn)) {
                /* use extended control field */
                set_bit(FLAG_EXT_CTRL, &chan->flags);
                chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
@@@ -3151,7 -3168,7 +3154,7 @@@ static int l2cap_build_conf_req(struct 
                if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
                        break;
  
 -              if (__l2cap_efs_supported(chan))
 +              if (__l2cap_efs_supported(chan->conn))
                        set_bit(FLAG_EFS_ENABLE, &chan->flags);
  
                /* fall through */
@@@ -3303,7 -3320,7 +3306,7 @@@ static int l2cap_parse_conf_req(struct 
                        break;
  
                case L2CAP_CONF_EWS:
 -                      if (!enable_hs)
 +                      if (!chan->conn->hs_enabled)
                                return -ECONNREFUSED;
  
                        set_bit(FLAG_EXT_CTRL, &chan->flags);
                }
  
                if (remote_efs) {
 -                      if (__l2cap_efs_supported(chan))
 +                      if (__l2cap_efs_supported(chan->conn))
                                set_bit(FLAG_EFS_ENABLE, &chan->flags);
                        else
                                return -ECONNREFUSED;
@@@ -3701,6 -3718,7 +3704,6 @@@ static struct l2cap_chan *l2cap_connect
        struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
        struct l2cap_conn_rsp rsp;
        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);
        BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
  
        /* Check if we have socket listening on psm */
 -      pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
 +      pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
 +                                       &conn->hcon->dst);
        if (!pchan) {
                result = L2CAP_CR_BAD_PSM;
                goto sendresp;
        }
  
 -      parent = pchan->sk;
 -
        mutex_lock(&conn->chan_lock);
 -      lock_sock(parent);
 +      l2cap_chan_lock(pchan);
  
        /* Check if the ACL is secure enough (if not SDP) */
        if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
        if (!chan)
                goto response;
  
 -      sk = chan->sk;
 -
        /* For certain devices (ex: HID mouse), support for authentication,
         * pairing and bonding is optional. For such devices, inorder to avoid
         * the ACL alive for too long after L2CAP disconnection, reset the ACL
         */
        conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
  
 -      bacpy(&bt_sk(sk)->src, conn->src);
 -      bacpy(&bt_sk(sk)->dst, conn->dst);
 +      bacpy(&chan->src, &conn->hcon->src);
 +      bacpy(&chan->dst, &conn->hcon->dst);
 +      chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
 +      chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
        chan->psm  = psm;
        chan->dcid = scid;
        chan->local_amp_id = amp_id;
  
        dcid = chan->scid;
  
 -      __set_chan_timer(chan, sk->sk_sndtimeo);
 +      __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
  
        chan->ident = cmd->ident;
  
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
                if (l2cap_chan_check_security(chan)) {
 -                      if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
 -                              __l2cap_state_change(chan, BT_CONNECT2);
 +                      if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
 +                              l2cap_state_change(chan, BT_CONNECT2);
                                result = L2CAP_CR_PEND;
                                status = L2CAP_CS_AUTHOR_PEND;
                                chan->ops->defer(chan);
                                 * The connection will succeed after the
                                 * physical link is up.
                                 */
 -                              if (amp_id) {
 -                                      __l2cap_state_change(chan, BT_CONNECT2);
 -                                      result = L2CAP_CR_PEND;
 -                              } else {
 -                                      __l2cap_state_change(chan, BT_CONFIG);
 +                              if (amp_id == AMP_ID_BREDR) {
 +                                      l2cap_state_change(chan, BT_CONFIG);
                                        result = L2CAP_CR_SUCCESS;
 +                              } else {
 +                                      l2cap_state_change(chan, BT_CONNECT2);
 +                                      result = L2CAP_CR_PEND;
                                }
                                status = L2CAP_CS_NO_INFO;
                        }
                } else {
 -                      __l2cap_state_change(chan, BT_CONNECT2);
 +                      l2cap_state_change(chan, BT_CONNECT2);
                        result = L2CAP_CR_PEND;
                        status = L2CAP_CS_AUTHEN_PEND;
                }
        } else {
 -              __l2cap_state_change(chan, BT_CONNECT2);
 +              l2cap_state_change(chan, BT_CONNECT2);
                result = L2CAP_CR_PEND;
                status = L2CAP_CS_NO_INFO;
        }
  
  response:
 -      release_sock(parent);
 +      l2cap_chan_unlock(pchan);
        mutex_unlock(&conn->chan_lock);
  
  sendresp:
@@@ -3875,13 -3894,13 +3878,13 @@@ static int l2cap_connect_create_rsp(str
        if (scid) {
                chan = __l2cap_get_chan_by_scid(conn, scid);
                if (!chan) {
 -                      err = -EFAULT;
 +                      err = -EBADSLT;
                        goto unlock;
                }
        } else {
                chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
                if (!chan) {
 -                      err = -EFAULT;
 +                      err = -EBADSLT;
                        goto unlock;
                }
        }
@@@ -3949,18 -3968,6 +3952,18 @@@ static void l2cap_send_efs_conf_rsp(str
                                            L2CAP_CONF_SUCCESS, flags), data);
  }
  
 +static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
 +                                 u16 scid, u16 dcid)
 +{
 +      struct l2cap_cmd_rej_cid rej;
 +
 +      rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
 +      rej.scid = __cpu_to_le16(scid);
 +      rej.dcid = __cpu_to_le16(dcid);
 +
 +      l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
 +}
 +
  static inline int l2cap_config_req(struct l2cap_conn *conn,
                                   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
                                   u8 *data)
        BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
  
        chan = l2cap_get_chan_by_scid(conn, dcid);
 -      if (!chan)
 -              return -ENOENT;
 +      if (!chan) {
 +              cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
 +              return 0;
 +      }
  
        if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
 -              struct l2cap_cmd_rej_cid rej;
 -
 -              rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
 -              rej.scid = cpu_to_le16(chan->scid);
 -              rej.dcid = cpu_to_le16(chan->dcid);
 -
 -              l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
 -                             sizeof(rej), &rej);
 +              cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
 +                                     chan->dcid);
                goto unlock;
        }
  
@@@ -4190,6 -4201,7 +4193,6 @@@ static inline int l2cap_disconnect_req(
        struct l2cap_disconn_rsp rsp;
        u16 dcid, scid;
        struct l2cap_chan *chan;
 -      struct sock *sk;
  
        if (cmd_len != sizeof(*req))
                return -EPROTO;
        chan = __l2cap_get_chan_by_scid(conn, dcid);
        if (!chan) {
                mutex_unlock(&conn->chan_lock);
 +              cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
                return 0;
        }
  
        l2cap_chan_lock(chan);
  
 -      sk = chan->sk;
 -
        rsp.dcid = cpu_to_le16(chan->scid);
        rsp.scid = cpu_to_le16(chan->dcid);
        l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
  
 -      lock_sock(sk);
 -      sk->sk_shutdown = SHUTDOWN_MASK;
 -      release_sock(sk);
 +      chan->ops->set_shutdown(chan);
  
        l2cap_chan_hold(chan);
        l2cap_chan_del(chan, ECONNRESET);
@@@ -4291,7 -4306,7 +4294,7 @@@ static inline int l2cap_information_req
                if (!disable_ertm)
                        feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
                                | L2CAP_FEAT_FCS;
 -              if (enable_hs)
 +              if (conn->hs_enabled)
                        feat_mask |= L2CAP_FEAT_EXT_FLOW
                                | L2CAP_FEAT_EXT_WINDOW;
  
                u8 buf[12];
                struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
  
 -              if (enable_hs)
 +              if (conn->hs_enabled)
                        l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
                else
                        l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
@@@ -4399,7 -4414,7 +4402,7 @@@ static int l2cap_create_channel_req(str
        if (cmd_len != sizeof(*req))
                return -EPROTO;
  
 -      if (!enable_hs)
 +      if (!conn->hs_enabled)
                return -EINVAL;
  
        psm = le16_to_cpu(req->psm);
        BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
  
        /* For controller id 0 make BR/EDR connection */
 -      if (req->amp_id == HCI_BREDR_ID) {
 +      if (req->amp_id == AMP_ID_BREDR) {
                l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
                              req->amp_id);
                return 0;
                struct amp_mgr *mgr = conn->hcon->amp_mgr;
                struct hci_conn *hs_hcon;
  
 -              hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst);
 +              hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
 +                                                &conn->hcon->dst);
                if (!hs_hcon) {
                        hci_dev_put(hdev);
 -                      return -EFAULT;
 +                      cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
 +                                             chan->dcid);
 +                      return 0;
                }
  
                BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
@@@ -4460,7 -4472,7 +4463,7 @@@ error
        l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
                       sizeof(rsp), &rsp);
  
 -      return -EFAULT;
 +      return 0;
  }
  
  static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
@@@ -4646,7 -4658,7 +4649,7 @@@ void l2cap_logical_cfm(struct l2cap_cha
  
        if (chan->state != BT_CONNECTED) {
                /* Ignore logical link if channel is on BR/EDR */
 -              if (chan->local_amp_id)
 +              if (chan->local_amp_id != AMP_ID_BREDR)
                        l2cap_logical_finish_create(chan, hchan);
        } else {
                l2cap_logical_finish_move(chan, hchan);
@@@ -4657,7 -4669,7 +4660,7 @@@ void l2cap_move_start(struct l2cap_cha
  {
        BT_DBG("chan %p", chan);
  
 -      if (chan->local_amp_id == HCI_BREDR_ID) {
 +      if (chan->local_amp_id == AMP_ID_BREDR) {
                if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
                        return;
                chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
@@@ -4714,7 -4726,7 +4717,7 @@@ static void l2cap_do_create(struct l2ca
                               sizeof(rsp), &rsp);
  
                if (result == L2CAP_CR_SUCCESS) {
 -                      __l2cap_state_change(chan, BT_CONFIG);
 +                      l2cap_state_change(chan, BT_CONFIG);
                        set_bit(CONF_REQ_SENT, &chan->conf_state);
                        l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
                                       L2CAP_CONF_REQ,
@@@ -4829,7 -4841,7 +4832,7 @@@ static inline int l2cap_move_channel_re
  
        BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
  
 -      if (!enable_hs)
 +      if (!conn->hs_enabled)
                return -EINVAL;
  
        chan = l2cap_get_chan_by_dcid(conn, icid);
                goto send_move_response;
        }
  
 -      if (req->dest_amp_id) {
 +      if (req->dest_amp_id != AMP_ID_BREDR) {
                struct hci_dev *hdev;
                hdev = hci_dev_get(req->dest_amp_id);
                if (!hdev || hdev->dev_type != HCI_AMP ||
         */
        if ((__chan_is_moving(chan) ||
             chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
 -          bacmp(conn->src, conn->dst) > 0) {
 +          bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
                result = L2CAP_MR_COLLISION;
                goto send_move_response;
        }
        chan->move_id = req->dest_amp_id;
        icid = chan->dcid;
  
 -      if (!req->dest_amp_id) {
 +      if (req->dest_amp_id == AMP_ID_BREDR) {
                /* Moving to BR/EDR */
                if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
                        chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
@@@ -5078,7 -5090,7 +5081,7 @@@ static int l2cap_move_channel_confirm(s
        if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
                if (result == L2CAP_MC_CONFIRMED) {
                        chan->local_amp_id = chan->move_id;
 -                      if (!chan->local_amp_id)
 +                      if (chan->local_amp_id == AMP_ID_BREDR)
                                __release_logical_link(chan);
                } else {
                        chan->move_id = chan->local_amp_id;
@@@ -5118,7 -5130,7 +5121,7 @@@ static inline int l2cap_move_channel_co
        if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
                chan->local_amp_id = chan->move_id;
  
 -              if (!chan->local_amp_id && chan->hs_hchan)
 +              if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
                        __release_logical_link(chan);
  
                l2cap_move_done(chan);
@@@ -5210,7 -5222,7 +5213,7 @@@ static inline int l2cap_bredr_sig_cmd(s
  
        case L2CAP_CONN_RSP:
        case L2CAP_CREATE_CHAN_RSP:
 -              err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
 +              l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
                break;
  
        case L2CAP_CONF_REQ:
                break;
  
        case L2CAP_CONF_RSP:
 -              err = l2cap_config_rsp(conn, cmd, cmd_len, data);
 +              l2cap_config_rsp(conn, cmd, cmd_len, data);
                break;
  
        case L2CAP_DISCONN_REQ:
                break;
  
        case L2CAP_DISCONN_RSP:
 -              err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
 +              l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
                break;
  
        case L2CAP_ECHO_REQ:
                break;
  
        case L2CAP_INFO_RSP:
 -              err = l2cap_information_rsp(conn, cmd, cmd_len, data);
 +              l2cap_information_rsp(conn, cmd, cmd_len, data);
                break;
  
        case L2CAP_CREATE_CHAN_REQ:
                break;
  
        case L2CAP_MOVE_CHAN_RSP:
 -              err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
 +              l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
                break;
  
        case L2CAP_MOVE_CHAN_CFM:
                break;
  
        case L2CAP_MOVE_CHAN_CFM_RSP:
 -              err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
 +              l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
                break;
  
        default:
@@@ -5295,48 -5307,51 +5298,48 @@@ static inline int l2cap_le_sig_cmd(stru
  static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
                                        struct sk_buff *skb)
  {
 -      u8 *data = skb->data;
 -      int len = skb->len;
 -      struct l2cap_cmd_hdr cmd;
 +      struct hci_conn *hcon = conn->hcon;
 +      struct l2cap_cmd_hdr *cmd;
 +      u16 len;
        int err;
  
 -      l2cap_raw_recv(conn, skb);
 +      if (hcon->type != LE_LINK)
 +              goto drop;
  
 -      while (len >= L2CAP_CMD_HDR_SIZE) {
 -              u16 cmd_len;
 -              memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
 -              data += L2CAP_CMD_HDR_SIZE;
 -              len  -= L2CAP_CMD_HDR_SIZE;
 +      if (skb->len < L2CAP_CMD_HDR_SIZE)
 +              goto drop;
  
 -              cmd_len = le16_to_cpu(cmd.len);
 +      cmd = (void *) skb->data;
 +      skb_pull(skb, L2CAP_CMD_HDR_SIZE);
  
 -              BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
 -                     cmd.ident);
 +      len = le16_to_cpu(cmd->len);
  
 -              if (cmd_len > len || !cmd.ident) {
 -                      BT_DBG("corrupted command");
 -                      break;
 -              }
 +      BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
  
 -              err = l2cap_le_sig_cmd(conn, &cmd, data);
 -              if (err) {
 -                      struct l2cap_cmd_rej_unk rej;
 +      if (len != skb->len || !cmd->ident) {
 +              BT_DBG("corrupted command");
 +              goto drop;
 +      }
  
 -                      BT_ERR("Wrong link type (%d)", err);
 +      err = l2cap_le_sig_cmd(conn, cmd, skb->data);
 +      if (err) {
 +              struct l2cap_cmd_rej_unk rej;
  
 -                      /* FIXME: Map err to a valid reason */
 -                      rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
 -                      l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
 -                                     sizeof(rej), &rej);
 -              }
 +              BT_ERR("Wrong link type (%d)", err);
  
 -              data += cmd_len;
 -              len  -= cmd_len;
 +              rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
 +              l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
 +                             sizeof(rej), &rej);
        }
  
 +drop:
        kfree_skb(skb);
  }
  
  static inline void l2cap_sig_channel(struct l2cap_conn *conn,
                                     struct sk_buff *skb)
  {
 +      struct hci_conn *hcon = conn->hcon;
        u8 *data = skb->data;
        int len = skb->len;
        struct l2cap_cmd_hdr cmd;
  
        l2cap_raw_recv(conn, skb);
  
 +      if (hcon->type != ACL_LINK)
 +              goto drop;
 +
        while (len >= L2CAP_CMD_HDR_SIZE) {
                u16 cmd_len;
                memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
  
                        BT_ERR("Wrong link type (%d)", err);
  
 -                      /* FIXME: Map err to a valid reason */
                        rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
                        l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
                                       sizeof(rej), &rej);
                len  -= cmd_len;
        }
  
 +drop:
        kfree_skb(skb);
  }
  
@@@ -5775,7 -5787,7 +5778,7 @@@ static int l2cap_rx_state_recv(struct l
                               struct sk_buff *skb, u8 event)
  {
        int err = 0;
 -      bool skb_in_use = 0;
 +      bool skb_in_use = false;
  
        BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
               event);
                                                           control->txseq);
  
                        chan->buffer_seq = chan->expected_tx_seq;
 -                      skb_in_use = 1;
 +                      skb_in_use = true;
  
                        err = l2cap_reassemble_sdu(chan, skb, control);
                        if (err)
                         * current frame is stored for later use.
                         */
                        skb_queue_tail(&chan->srej_q, skb);
 -                      skb_in_use = 1;
 +                      skb_in_use = true;
                        BT_DBG("Queued %p (queue len %d)", skb,
                               skb_queue_len(&chan->srej_q));
  
@@@ -5910,7 -5922,7 +5913,7 @@@ static int l2cap_rx_state_srej_sent(str
  {
        int err = 0;
        u16 txseq = control->txseq;
 -      bool skb_in_use = 0;
 +      bool skb_in_use = false;
  
        BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
               event);
                        /* Keep frame for reassembly later */
                        l2cap_pass_to_tx(chan, control);
                        skb_queue_tail(&chan->srej_q, skb);
 -                      skb_in_use = 1;
 +                      skb_in_use = true;
                        BT_DBG("Queued %p (queue len %d)", skb,
                               skb_queue_len(&chan->srej_q));
  
  
                        l2cap_pass_to_tx(chan, control);
                        skb_queue_tail(&chan->srej_q, skb);
 -                      skb_in_use = 1;
 +                      skb_in_use = true;
                        BT_DBG("Queued %p (queue len %d)", skb,
                               skb_queue_len(&chan->srej_q));
  
                         * the missing frames.
                         */
                        skb_queue_tail(&chan->srej_q, skb);
 -                      skb_in_use = 1;
 +                      skb_in_use = true;
                        BT_DBG("Queued %p (queue len %d)", skb,
                               skb_queue_len(&chan->srej_q));
  
                         * SREJ'd frames.
                         */
                        skb_queue_tail(&chan->srej_q, skb);
 -                      skb_in_use = 1;
 +                      skb_in_use = true;
                        BT_DBG("Queued %p (queue len %d)", skb,
                               skb_queue_len(&chan->srej_q));
  
@@@ -6371,13 -6383,9 +6374,13 @@@ done
  static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
                                  struct sk_buff *skb)
  {
 +      struct hci_conn *hcon = conn->hcon;
        struct l2cap_chan *chan;
  
 -      chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
 +      if (hcon->type != ACL_LINK)
 +              goto drop;
 +
 +      chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst);
        if (!chan)
                goto drop;
  
        if (chan->imtu < skb->len)
                goto drop;
  
 +      /* Store remote BD_ADDR and PSM for msg_name */
 +      bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
 +      bt_cb(skb)->psm = psm;
 +
        if (!chan->ops->recv(chan, skb))
                return;
  
@@@ -6403,22 -6407,15 +6406,22 @@@ drop
  static void l2cap_att_channel(struct l2cap_conn *conn,
                              struct sk_buff *skb)
  {
 +      struct hci_conn *hcon = conn->hcon;
        struct l2cap_chan *chan;
  
 +      if (hcon->type != LE_LINK)
 +              goto drop;
 +
        chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
 -                                       conn->src, conn->dst);
 +                                       &hcon->src, &hcon->dst);
        if (!chan)
                goto drop;
  
        BT_DBG("chan %p, len %d", chan, skb->len);
  
 +      if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type))
 +              goto drop;
 +
        if (chan->imtu < skb->len)
                goto drop;
  
@@@ -6447,6 -6444,9 +6450,6 @@@ static void l2cap_recv_frame(struct l2c
        BT_DBG("len %d, cid 0x%4.4x", len, cid);
  
        switch (cid) {
 -      case L2CAP_CID_LE_SIGNALING:
 -              l2cap_le_sig_channel(conn, skb);
 -              break;
        case L2CAP_CID_SIGNALING:
                l2cap_sig_channel(conn, skb);
                break;
                l2cap_att_channel(conn, skb);
                break;
  
 +      case L2CAP_CID_LE_SIGNALING:
 +              l2cap_le_sig_channel(conn, skb);
 +              break;
 +
        case L2CAP_CID_SMP:
                if (smp_sig_channel(conn, skb))
                        l2cap_conn_del(conn->hcon, EACCES);
@@@ -6488,15 -6484,17 +6491,15 @@@ int l2cap_connect_ind(struct hci_dev *h
        /* Find listening sockets and check their link_mode */
        read_lock(&chan_list_lock);
        list_for_each_entry(c, &chan_list, global_l) {
 -              struct sock *sk = c->sk;
 -
                if (c->state != BT_LISTEN)
                        continue;
  
 -              if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
 +              if (!bacmp(&c->src, &hdev->bdaddr)) {
                        lm1 |= HCI_LM_ACCEPT;
                        if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
                                lm1 |= HCI_LM_MASTER;
                        exact++;
 -              } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
 +              } else if (!bacmp(&c->src, BDADDR_ANY)) {
                        lm2 |= HCI_LM_ACCEPT;
                        if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
                                lm2 |= HCI_LM_MASTER;
@@@ -6602,7 -6600,11 +6605,7 @@@ int l2cap_security_cfm(struct hci_conn 
  
                if (!status && (chan->state == BT_CONNECTED ||
                                chan->state == BT_CONFIG)) {
 -                      struct sock *sk = chan->sk;
 -
 -                      clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
 -                      sk->sk_state_change(sk);
 -
 +                      chan->ops->resume(chan);
                        l2cap_check_encryption(chan, encrypt);
                        l2cap_chan_unlock(chan);
                        continue;
                                __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                        }
                } else if (chan->state == BT_CONNECT2) {
 -                      struct sock *sk = chan->sk;
                        struct l2cap_conn_rsp rsp;
                        __u16 res, stat;
  
 -                      lock_sock(sk);
 -
                        if (!status) {
 -                              if (test_bit(BT_SK_DEFER_SETUP,
 -                                           &bt_sk(sk)->flags)) {
 +                              if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
                                        res = L2CAP_CR_PEND;
                                        stat = L2CAP_CS_AUTHOR_PEND;
                                        chan->ops->defer(chan);
                                } else {
 -                                      __l2cap_state_change(chan, BT_CONFIG);
 +                                      l2cap_state_change(chan, BT_CONFIG);
                                        res = L2CAP_CR_SUCCESS;
                                        stat = L2CAP_CS_NO_INFO;
                                }
                        } else {
 -                              __l2cap_state_change(chan, BT_DISCONN);
 +                              l2cap_state_change(chan, BT_DISCONN);
                                __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                                res = L2CAP_CR_SEC_BLOCK;
                                stat = L2CAP_CS_NO_INFO;
                        }
  
 -                      release_sock(sk);
 -
                        rsp.scid   = cpu_to_le16(chan->dcid);
                        rsp.dcid   = cpu_to_le16(chan->scid);
                        rsp.result = cpu_to_le16(res);
@@@ -6751,13 -6759,9 +6754,13 @@@ int l2cap_recv_acldata(struct hci_conn 
                conn->rx_len -= skb->len;
  
                if (!conn->rx_len) {
 -                      /* Complete frame received */
 -                      l2cap_recv_frame(conn, conn->rx_skb);
 +                      /* Complete frame received. l2cap_recv_frame
 +                       * takes ownership of the skb so set the global
 +                       * rx_skb pointer to NULL first.
 +                       */
 +                      struct sk_buff *rx_skb = conn->rx_skb;
                        conn->rx_skb = NULL;
 +                      l2cap_recv_frame(conn, rx_skb);
                }
                break;
        }
@@@ -6774,8 -6778,10 +6777,8 @@@ static int l2cap_debugfs_show(struct se
        read_lock(&chan_list_lock);
  
        list_for_each_entry(c, &chan_list, global_l) {
 -              struct sock *sk = c->sk;
 -
                seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
 -                         &bt_sk(sk)->src, &bt_sk(sk)->dst,
 +                         &c->src, &c->dst,
                           c->state, __le16_to_cpu(c->psm),
                           c->scid, c->dcid, c->imtu, c->omtu,
                           c->sec_level, c->mode);
@@@ -6808,11 -6814,12 +6811,11 @@@ int __init l2cap_init(void
        if (err < 0)
                return err;
  
 -      if (bt_debugfs) {
 -              l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
 -                                                  NULL, &l2cap_debugfs_fops);
 -              if (!l2cap_debugfs)
 -                      BT_ERR("Failed to create L2CAP debug file");
 -      }
 +      if (IS_ERR_OR_NULL(bt_debugfs))
 +              return 0;
 +
 +      l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
 +                                          NULL, &l2cap_debugfs_fops);
  
        return 0;
  }
index 94d06cbfbc184a6e827aa5c3cbd15d4693eca49a,ce7521120d69f5a4267dc2c7e9b74843772729ec..facd8a79c0383eb8898fca8dc905c87ed623202a
@@@ -641,13 -641,13 +641,13 @@@ static struct rfcomm_session *rfcomm_se
  {
        struct rfcomm_session *s;
        struct list_head *p, *n;
 -      struct bt_sock *sk;
 +      struct l2cap_chan *chan;
        list_for_each_safe(p, n, &session_list) {
                s = list_entry(p, struct rfcomm_session, list);
 -              sk = bt_sk(s->sock->sk);
 +              chan = l2cap_pi(s->sock->sk)->chan;
  
 -              if ((!bacmp(src, BDADDR_ANY) || !bacmp(&sk->src, src)) &&
 -                              !bacmp(&sk->dst, dst))
 +              if ((!bacmp(src, BDADDR_ANY) || !bacmp(&chan->src, src)) &&
 +                  !bacmp(&chan->dst, dst))
                        return s;
        }
        return NULL;
@@@ -694,6 -694,7 +694,7 @@@ static struct rfcomm_session *rfcomm_se
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = 0;
        addr.l2_cid    = 0;
+       addr.l2_bdaddr_type = BDADDR_BREDR;
        *err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (*err < 0)
                goto failed;
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = __constant_cpu_to_le16(RFCOMM_PSM);
        addr.l2_cid    = 0;
+       addr.l2_bdaddr_type = BDADDR_BREDR;
        *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
        if (*err == 0 || *err == -EINPROGRESS)
                return s;
@@@ -732,11 -734,11 +734,11 @@@ failed
  
  void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst)
  {
 -      struct sock *sk = s->sock->sk;
 +      struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan;
        if (src)
 -              bacpy(src, &bt_sk(sk)->src);
 +              bacpy(src, &chan->src);
        if (dst)
 -              bacpy(dst, &bt_sk(sk)->dst);
 +              bacpy(dst, &chan->dst);
  }
  
  /* ---- RFCOMM frame sending ---- */
@@@ -1983,6 -1985,7 +1985,7 @@@ static int rfcomm_add_listener(bdaddr_
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = __constant_cpu_to_le16(RFCOMM_PSM);
        addr.l2_cid    = 0;
+       addr.l2_bdaddr_type = BDADDR_BREDR;
        err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (err < 0) {
                BT_ERR("Bind failed %d", err);
@@@ -2112,11 -2115,12 +2115,11 @@@ static int rfcomm_dlc_debugfs_show(stru
        rfcomm_lock();
  
        list_for_each_entry(s, &session_list, list) {
 +              struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan;
                struct rfcomm_dlc *d;
                list_for_each_entry(d, &s->dlcs, list) {
 -                      struct sock *sk = s->sock->sk;
 -
                        seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n",
 -                                 &bt_sk(sk)->src, &bt_sk(sk)->dst,
 +                                 &chan->src, &chan->dst,
                                   d->state, d->dlci, d->mtu,
                                   d->rx_credits, d->tx_credits);
                }
@@@ -2154,6 -2158,13 +2157,6 @@@ static int __init rfcomm_init(void
                goto unregister;
        }
  
 -      if (bt_debugfs) {
 -              rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444,
 -                              bt_debugfs, NULL, &rfcomm_dlc_debugfs_fops);
 -              if (!rfcomm_dlc_debugfs)
 -                      BT_ERR("Failed to create RFCOMM debug file");
 -      }
 -
        err = rfcomm_init_ttys();
        if (err < 0)
                goto stop;
  
        BT_INFO("RFCOMM ver %s", VERSION);
  
 +      if (IS_ERR_OR_NULL(bt_debugfs))
 +              return 0;
 +
 +      rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444,
 +                                               bt_debugfs, NULL,
 +                                               &rfcomm_dlc_debugfs_fops);
 +
        return 0;
  
  cleanup:
index c4d3d423f89b84d41b9ff0e6919e9f37786f4960,7096cfe3bd5a365fc34a9db0e86f100ad482590d..0be7619c5e5e8aba93cc1af7b7b1bc056c9776aa
@@@ -87,8 -87,7 +87,8 @@@ static void rfcomm_sk_state_change(stru
                parent->sk_data_ready(parent, 0);
        } else {
                if (d->state == BT_CONNECTED)
 -                      rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL);
 +                      rfcomm_session_getaddr(d->session,
 +                                             &rfcomm_pi(sk)->src, NULL);
                sk->sk_state_change(sk);
        }
  
@@@ -111,7 -110,7 +111,7 @@@ static struct sock *__rfcomm_get_sock_b
  
        sk_for_each(sk, &rfcomm_sk_list.head) {
                if (rfcomm_pi(sk)->channel == channel &&
 -                              !bacmp(&bt_sk(sk)->src, src))
 +                              !bacmp(&rfcomm_pi(sk)->src, src))
                        break;
        }
  
@@@ -133,11 -132,11 +133,11 @@@ static struct sock *rfcomm_get_sock_by_
  
                if (rfcomm_pi(sk)->channel == channel) {
                        /* Exact match. */
 -                      if (!bacmp(&bt_sk(sk)->src, src))
 +                      if (!bacmp(&rfcomm_pi(sk)->src, src))
                                break;
  
                        /* Closest match */
 -                      if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
 +                      if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
                                sk1 = sk;
                }
        }
@@@ -356,7 -355,7 +356,7 @@@ static int rfcomm_sock_bind(struct sock
                err = -EADDRINUSE;
        } else {
                /* Save source address */
 -              bacpy(&bt_sk(sk)->src, &sa->rc_bdaddr);
 +              bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr);
                rfcomm_pi(sk)->channel = sa->rc_channel;
                sk->sk_state = BT_BOUND;
        }
@@@ -394,14 -393,13 +394,14 @@@ static int rfcomm_sock_connect(struct s
        }
  
        sk->sk_state = BT_CONNECT;
 -      bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr);
 +      bacpy(&rfcomm_pi(sk)->dst, &sa->rc_bdaddr);
        rfcomm_pi(sk)->channel = sa->rc_channel;
  
        d->sec_level = rfcomm_pi(sk)->sec_level;
        d->role_switch = rfcomm_pi(sk)->role_switch;
  
 -      err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
 +      err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr,
 +                            sa->rc_channel);
        if (!err)
                err = bt_sock_wait_state(sk, BT_CONNECTED,
                                sock_sndtimeo(sk, flags & O_NONBLOCK));
@@@ -431,7 -429,7 +431,7 @@@ static int rfcomm_sock_listen(struct so
        }
  
        if (!rfcomm_pi(sk)->channel) {
 -              bdaddr_t *src = &bt_sk(sk)->src;
 +              bdaddr_t *src = &rfcomm_pi(sk)->src;
                u8 channel;
  
                err = -EINVAL;
@@@ -532,9 -530,9 +532,9 @@@ static int rfcomm_sock_getname(struct s
        sa->rc_family  = AF_BLUETOOTH;
        sa->rc_channel = rfcomm_pi(sk)->channel;
        if (peer)
 -              bacpy(&sa->rc_bdaddr, &bt_sk(sk)->dst);
 +              bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->dst);
        else
 -              bacpy(&sa->rc_bdaddr, &bt_sk(sk)->src);
 +              bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->src);
  
        *len = sizeof(struct sockaddr_rc);
        return 0;
@@@ -546,7 -544,7 +546,7 @@@ static int rfcomm_sock_sendmsg(struct k
        struct sock *sk = sock->sk;
        struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
        struct sk_buff *skb;
 -      int sent = 0;
 +      int sent;
  
        if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))
                return -ENOTCONN;
  
        lock_sock(sk);
  
 +      sent = bt_sock_wait_ready(sk, msg->msg_flags);
 +      if (sent)
 +              goto done;
 +
        while (len) {
                size_t size = min_t(size_t, len, d->mtu);
                int err;
                len  -= size;
        }
  
 +done:
        release_sock(sk);
  
        return sent;
@@@ -739,8 -732,9 +739,9 @@@ static int rfcomm_sock_setsockopt(struc
  static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
  {
        struct sock *sk = sock->sk;
+       struct sock *l2cap_sk;
+       struct l2cap_conn *conn;
        struct rfcomm_conninfo cinfo;
-       struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
        int len, err = 0;
        u32 opt;
  
                        break;
                }
  
+               l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
+               conn = l2cap_pi(l2cap_sk)->chan->conn;
                memset(&cinfo, 0, sizeof(cinfo));
                cinfo.hci_handle = conn->hcon->handle;
                memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
@@@ -953,8 -950,8 +957,8 @@@ int rfcomm_connect_ind(struct rfcomm_se
        bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM);
  
        rfcomm_sock_init(sk, parent);
 -      bacpy(&bt_sk(sk)->src, &src);
 -      bacpy(&bt_sk(sk)->dst, &dst);
 +      bacpy(&rfcomm_pi(sk)->src, &src);
 +      bacpy(&rfcomm_pi(sk)->dst, &dst);
        rfcomm_pi(sk)->channel = channel;
  
        sk->sk_state = BT_CONFIG;
@@@ -981,7 -978,7 +985,7 @@@ static int rfcomm_sock_debugfs_show(str
  
        sk_for_each(sk, &rfcomm_sk_list.head) {
                seq_printf(f, "%pMR %pMR %d %d\n",
 -                         &bt_sk(sk)->src, &bt_sk(sk)->dst,
 +                         &rfcomm_pi(sk)->src, &rfcomm_pi(sk)->dst,
                           sk->sk_state, rfcomm_pi(sk)->channel);
        }
  
@@@ -1051,15 -1048,15 +1055,15 @@@ int __init rfcomm_init_sockets(void
                goto error;
        }
  
 -      if (bt_debugfs) {
 -              rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
 -                              bt_debugfs, NULL, &rfcomm_sock_debugfs_fops);
 -              if (!rfcomm_sock_debugfs)
 -                      BT_ERR("Failed to create RFCOMM debug file");
 -      }
 -
        BT_INFO("RFCOMM socket layer initialized");
  
 +      if (IS_ERR_OR_NULL(bt_debugfs))
 +              return 0;
 +
 +      rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
 +                                                bt_debugfs, NULL,
 +                                                &rfcomm_sock_debugfs_fops);
 +
        return 0;
  
  error:
diff --combined net/bluetooth/smp.c
index 85a2796cac61bcc423ef724f1911f2a794667aff,ccad6c1e3ec320659a6b1e512d90cbd66ad04c49..4b07acb8293c3df3542e2a1661a6ae07bcfa6596
@@@ -28,8 -28,7 +28,8 @@@
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/l2cap.h>
  #include <net/bluetooth/mgmt.h>
 -#include <net/bluetooth/smp.h>
 +
 +#include "smp.h"
  
  #define SMP_TIMEOUT   msecs_to_jiffies(30000)
  
@@@ -86,8 -85,8 +86,8 @@@ static int smp_e(struct crypto_blkciphe
  }
  
  static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
 -              u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
 -              u8 _rat, bdaddr_t *ra, u8 res[16])
 +                u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
 +                u8 _rat, bdaddr_t *ra, u8 res[16])
  {
        u8 p1[16], p2[16];
        int err;
        return err;
  }
  
 -static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
 -                      u8 r1[16], u8 r2[16], u8 _r[16])
 +static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
 +                u8 r2[16], u8 _r[16])
  {
        int err;
  
@@@ -151,7 -150,7 +151,7 @@@ static int smp_rand(u8 *buf
  }
  
  static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
 -                                              u16 dlen, void *data)
 +                                   u16 dlen, void *data)
  {
        struct sk_buff *skb;
        struct l2cap_hdr *lh;
@@@ -214,8 -213,9 +214,8 @@@ static __u8 seclevel_to_authreq(__u8 se
  }
  
  static void build_pairing_cmd(struct l2cap_conn *conn,
 -                              struct smp_cmd_pairing *req,
 -                              struct smp_cmd_pairing *rsp,
 -                              __u8 authreq)
 +                            struct smp_cmd_pairing *req,
 +                            struct smp_cmd_pairing *rsp, __u8 authreq)
  {
        u8 dist_keys = 0;
  
@@@ -249,7 -249,7 +249,7 @@@ static u8 check_enc_key_size(struct l2c
        struct smp_chan *smp = conn->smp_chan;
  
        if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
 -                      (max_key_size < SMP_MIN_ENC_KEY_SIZE))
 +          (max_key_size < SMP_MIN_ENC_KEY_SIZE))
                return SMP_ENC_KEY_SIZE;
  
        smp->enc_key_size = max_key_size;
@@@ -263,15 -263,15 +263,15 @@@ static void smp_failure(struct l2cap_co
  
        if (send)
                smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
 -                                                              &reason);
 +                           &reason);
  
 -      clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
 -      mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
 -                       hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
 +      clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
 +      mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
 +                       HCI_ERROR_AUTH_FAILURE);
  
        cancel_delayed_work_sync(&conn->security_timer);
  
 -      if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
 +      if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
                smp_chan_destroy(conn);
  }
  
@@@ -309,8 -309,8 +309,8 @@@ static int tk_request(struct l2cap_con
        /* If either side has unknown io_caps, use JUST WORKS */
        /* Otherwise, look up method from the table */
        if (!(auth & SMP_AUTH_MITM) ||
 -                      local_io > SMP_IO_KEYBOARD_DISPLAY ||
 -                      remote_io > SMP_IO_KEYBOARD_DISPLAY)
 +          local_io > SMP_IO_KEYBOARD_DISPLAY ||
 +          remote_io > SMP_IO_KEYBOARD_DISPLAY)
                method = JUST_WORKS;
        else
                method = gen_method[remote_io][local_io];
        hci_dev_lock(hcon->hdev);
  
        if (method == REQ_PASSKEY)
 -              ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
 +              ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
                                                hcon->type, hcon->dst_type);
        else
 -              ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
 +              ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
                                                hcon->type, hcon->dst_type,
                                                cpu_to_le32(passkey), 0);
  
@@@ -386,13 -386,12 +386,13 @@@ static void confirm_work(struct work_st
        smp->tfm = tfm;
  
        if (conn->hcon->out)
 -              ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
 -                           conn->src, conn->hcon->dst_type, conn->dst, res);
 +              ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
 +                           conn->hcon->src_type, &conn->hcon->src,
 +                           conn->hcon->dst_type, &conn->hcon->dst, res);
        else
                ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
 -                           conn->hcon->dst_type, conn->dst, 0, conn->src,
 -                           res);
 +                           conn->hcon->dst_type, &conn->hcon->dst,
 +                           conn->hcon->src_type, &conn->hcon->src, res);
        if (ret) {
                reason = SMP_UNSPECIFIED;
                goto error;
@@@ -426,13 -425,11 +426,13 @@@ static void random_work(struct work_str
        BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
  
        if (hcon->out)
 -              ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
 -                           conn->src, hcon->dst_type, conn->dst, res);
 +              ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
 +                           hcon->src_type, &hcon->src,
 +                           hcon->dst_type, &hcon->dst, res);
        else
                ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
 -                           hcon->dst_type, conn->dst, 0, conn->src, res);
 +                           hcon->dst_type, &hcon->dst,
 +                           hcon->src_type, &hcon->src, res);
        if (ret) {
                reason = SMP_UNSPECIFIED;
                goto error;
                swap128(key, stk);
  
                memset(stk + smp->enc_key_size, 0,
 -                              SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
 +                     SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
  
 -              hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
 +              hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
                            HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
                            ediv, rand);
        }
@@@ -497,7 -494,7 +497,7 @@@ static struct smp_chan *smp_chan_create
  {
        struct smp_chan *smp;
  
 -      smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
 +      smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
        if (!smp)
                return NULL;
  
@@@ -652,7 -649,7 +652,7 @@@ static u8 smp_cmd_pairing_rsp(struct l2
        memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
  
        if ((req->auth_req & SMP_AUTH_BONDING) &&
 -                      (rsp->auth_req & SMP_AUTH_BONDING))
 +          (rsp->auth_req & SMP_AUTH_BONDING))
                auth = SMP_AUTH_BONDING;
  
        auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
@@@ -687,7 -684,7 +687,7 @@@ static u8 smp_cmd_pairing_confirm(struc
  
                swap128(smp->prnd, random);
                smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
 -                                                              random);
 +                           random);
        } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
                queue_work(hdev->workqueue, &smp->confirm);
        } else {
@@@ -717,7 -714,7 +717,7 @@@ static u8 smp_ltk_encrypt(struct l2cap_
        struct smp_ltk *key;
        struct hci_conn *hcon = conn->hcon;
  
 -      key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
 +      key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type);
        if (!key)
                return 0;
  
        hcon->enc_key_size = key->enc_size;
  
        return 1;
 -
  }
 +
  static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
  {
        struct smp_cmd_security_req *rp = (void *) skb->data;
  
        BT_DBG("conn %p", conn);
  
+       if (!(conn->hcon->link_mode & HCI_LM_MASTER))
+               return SMP_CMD_NOTSUPP;
        hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
  
        if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
@@@ -838,9 -838,9 +841,9 @@@ static int smp_cmd_master_ident(struct 
        skb_pull(skb, sizeof(*rp));
  
        hci_dev_lock(hdev);
 -      authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
 -      hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
 -                  HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
 +      authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
 +      hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
 +                  authenticated, smp->tk, smp->enc_key_size,
                    rp->ediv, rp->rand);
        smp_distribute_keys(conn, 1);
        hci_dev_unlock(hdev);
  
  int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
  {
 -      __u8 code = skb->data[0];
 -      __u8 reason;
 +      struct hci_conn *hcon = conn->hcon;
 +      __u8 code, reason;
        int err = 0;
  
 -      if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
 +      if (hcon->type != LE_LINK) {
 +              kfree_skb(skb);
 +              return 0;
 +      }
 +
 +      if (skb->len < 1) {
 +              kfree_skb(skb);
 +              return -EILSEQ;
 +      }
 +
 +      if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
                err = -ENOTSUPP;
                reason = SMP_PAIRING_NOTSUPP;
                goto done;
        }
  
 +      code = skb->data[0];
        skb_pull(skb, sizeof(code));
  
        /*
@@@ -988,7 -977,7 +991,7 @@@ int smp_distribute_keys(struct l2cap_co
                smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
  
                authenticated = hcon->sec_level == BT_SECURITY_HIGH;
 -              hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
 +              hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
                            HCI_SMP_LTK_SLAVE, 1, authenticated,
                            enc.ltk, smp->enc_key_size, ediv, ident.rand);
  
  
                /* Just public address */
                memset(&addrinfo, 0, sizeof(addrinfo));
 -              bacpy(&addrinfo.bdaddr, conn->src);
 +              bacpy(&addrinfo.bdaddr, &conn->hcon->src);
  
                smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
 -                                                              &addrinfo);
 +                           &addrinfo);
  
                *keydist &= ~SMP_DIST_ID_KEY;
        }