Bluetooth: Reorder L2CAP functions to avoid forward declarations
authorJohan Hedberg <johan.hedberg@intel.com>
Fri, 17 Jan 2014 18:45:10 +0000 (20:45 +0200)
committerJohan Hedberg <johan.hedberg@intel.com>
Thu, 13 Feb 2014 07:51:36 +0000 (09:51 +0200)
This patch moves the l2cap_conn_add, is_valid_psm and l2cap_chan_connect
functions further down in l2cap_core.c. The patch doesn't contain
anything else except the relocation of these functions. By moving the
functions further down the patch enables a subsequent patch that adds a
pending RX queue to be implemented without a forward declaration of a
function.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/l2cap_core.c

index 3f0dd552cb2bc9ded817e44e794c1aa0b971e697..317a5737daf6ae5963d727feab44e7f0ccf6538d 100644 (file)
@@ -1722,66 +1722,6 @@ static void security_timeout(struct work_struct *work)
        }
 }
 
-static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
-{
-       struct l2cap_conn *conn = hcon->l2cap_data;
-       struct hci_chan *hchan;
-
-       if (conn)
-               return conn;
-
-       hchan = hci_chan_create(hcon);
-       if (!hchan)
-               return NULL;
-
-       conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
-       if (!conn) {
-               hci_chan_del(hchan);
-               return NULL;
-       }
-
-       kref_init(&conn->ref);
-       hcon->l2cap_data = conn;
-       conn->hcon = hcon;
-       hci_conn_get(conn->hcon);
-       conn->hchan = hchan;
-
-       BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
-
-       switch (hcon->type) {
-       case LE_LINK:
-               if (hcon->hdev->le_mtu) {
-                       conn->mtu = hcon->hdev->le_mtu;
-                       break;
-               }
-               /* fall through */
-       default:
-               conn->mtu = hcon->hdev->acl_mtu;
-               break;
-       }
-
-       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);
-
-       INIT_LIST_HEAD(&conn->chan_l);
-       INIT_LIST_HEAD(&conn->users);
-
-       if (hcon->type == LE_LINK)
-               INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
-       else
-               INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
-
-       conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
-
-       return conn;
-}
-
 static void l2cap_conn_free(struct kref *ref)
 {
        struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
@@ -1852,154 +1792,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
        return c1;
 }
 
-static bool is_valid_psm(u16 psm, u8 dst_type)
-{
-       if (!psm)
-               return false;
-
-       if (bdaddr_type_is_le(dst_type))
-               return (psm <= 0x00ff);
-
-       /* PSM must be odd and lsb of upper byte must be 0 */
-       return ((psm & 0x0101) == 0x0001);
-}
-
-int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
-                      bdaddr_t *dst, u8 dst_type)
-{
-       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", &chan->src, dst,
-              dst_type, __le16_to_cpu(psm));
-
-       hdev = hci_get_route(dst, &chan->src);
-       if (!hdev)
-               return -EHOSTUNREACH;
-
-       hci_dev_lock(hdev);
-
-       l2cap_chan_lock(chan);
-
-       if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
-           chan->chan_type != L2CAP_CHAN_RAW) {
-               err = -EINVAL;
-               goto done;
-       }
-
-       if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
-               err = -EINVAL;
-               goto done;
-       }
-
-       switch (chan->mode) {
-       case L2CAP_MODE_BASIC:
-               break;
-       case L2CAP_MODE_LE_FLOWCTL:
-               l2cap_le_flowctl_init(chan);
-               break;
-       case L2CAP_MODE_ERTM:
-       case L2CAP_MODE_STREAMING:
-               if (!disable_ertm)
-                       break;
-               /* fall through */
-       default:
-               err = -ENOTSUPP;
-               goto done;
-       }
-
-       switch (chan->state) {
-       case BT_CONNECT:
-       case BT_CONNECT2:
-       case BT_CONFIG:
-               /* Already connecting */
-               err = 0;
-               goto done;
-
-       case BT_CONNECTED:
-               /* Already connected */
-               err = -EISCONN;
-               goto done;
-
-       case BT_OPEN:
-       case BT_BOUND:
-               /* Can connect */
-               break;
-
-       default:
-               err = -EBADFD;
-               goto done;
-       }
-
-       /* Set destination address and psm */
-       bacpy(&chan->dst, dst);
-       chan->dst_type = dst_type;
-
-       chan->psm = psm;
-       chan->dcid = cid;
-
-       auth_type = l2cap_get_auth_type(chan);
-
-       if (bdaddr_type_is_le(dst_type))
-               hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
-                                  chan->sec_level, auth_type);
-       else
-               hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
-                                  chan->sec_level, auth_type);
-
-       if (IS_ERR(hcon)) {
-               err = PTR_ERR(hcon);
-               goto done;
-       }
-
-       conn = l2cap_conn_add(hcon);
-       if (!conn) {
-               hci_conn_drop(hcon);
-               err = -ENOMEM;
-               goto done;
-       }
-
-       if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
-               hci_conn_drop(hcon);
-               err = -EBUSY;
-               goto done;
-       }
-
-       /* Update source addr of the socket */
-       bacpy(&chan->src, &hcon->src);
-       chan->src_type = bdaddr_type(hcon, hcon->src_type);
-
-       l2cap_chan_unlock(chan);
-       l2cap_chan_add(conn, chan);
-       l2cap_chan_lock(chan);
-
-       /* l2cap_chan_add takes its own ref so we can drop this one */
-       hci_conn_drop(hcon);
-
-       l2cap_state_change(chan, BT_CONNECT);
-       __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
-
-       if (hcon->state == BT_CONNECTED) {
-               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
-                       __clear_chan_timer(chan);
-                       if (l2cap_chan_check_security(chan))
-                               l2cap_state_change(chan, BT_CONNECTED);
-               } else
-                       l2cap_do_start(chan);
-       }
-
-       err = 0;
-
-done:
-       l2cap_chan_unlock(chan);
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
-       return err;
-}
-
 static void l2cap_monitor_timeout(struct work_struct *work)
 {
        struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
@@ -7136,6 +6928,213 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
        }
 }
 
+static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
+{
+       struct l2cap_conn *conn = hcon->l2cap_data;
+       struct hci_chan *hchan;
+
+       if (conn)
+               return conn;
+
+       hchan = hci_chan_create(hcon);
+       if (!hchan)
+               return NULL;
+
+       conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
+       if (!conn) {
+               hci_chan_del(hchan);
+               return NULL;
+       }
+
+       kref_init(&conn->ref);
+       hcon->l2cap_data = conn;
+       conn->hcon = hcon;
+       hci_conn_get(conn->hcon);
+       conn->hchan = hchan;
+
+       BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
+
+       switch (hcon->type) {
+       case LE_LINK:
+               if (hcon->hdev->le_mtu) {
+                       conn->mtu = hcon->hdev->le_mtu;
+                       break;
+               }
+               /* fall through */
+       default:
+               conn->mtu = hcon->hdev->acl_mtu;
+               break;
+       }
+
+       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);
+
+       INIT_LIST_HEAD(&conn->chan_l);
+       INIT_LIST_HEAD(&conn->users);
+
+       if (hcon->type == LE_LINK)
+               INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
+       else
+               INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
+
+       conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
+
+       return conn;
+}
+
+static bool is_valid_psm(u16 psm, u8 dst_type) {
+       if (!psm)
+               return false;
+
+       if (bdaddr_type_is_le(dst_type))
+               return (psm <= 0x00ff);
+
+       /* PSM must be odd and lsb of upper byte must be 0 */
+       return ((psm & 0x0101) == 0x0001);
+}
+
+int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+                      bdaddr_t *dst, u8 dst_type)
+{
+       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", &chan->src, dst,
+              dst_type, __le16_to_cpu(psm));
+
+       hdev = hci_get_route(dst, &chan->src);
+       if (!hdev)
+               return -EHOSTUNREACH;
+
+       hci_dev_lock(hdev);
+
+       l2cap_chan_lock(chan);
+
+       if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
+           chan->chan_type != L2CAP_CHAN_RAW) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       switch (chan->mode) {
+       case L2CAP_MODE_BASIC:
+               break;
+       case L2CAP_MODE_LE_FLOWCTL:
+               l2cap_le_flowctl_init(chan);
+               break;
+       case L2CAP_MODE_ERTM:
+       case L2CAP_MODE_STREAMING:
+               if (!disable_ertm)
+                       break;
+               /* fall through */
+       default:
+               err = -ENOTSUPP;
+               goto done;
+       }
+
+       switch (chan->state) {
+       case BT_CONNECT:
+       case BT_CONNECT2:
+       case BT_CONFIG:
+               /* Already connecting */
+               err = 0;
+               goto done;
+
+       case BT_CONNECTED:
+               /* Already connected */
+               err = -EISCONN;
+               goto done;
+
+       case BT_OPEN:
+       case BT_BOUND:
+               /* Can connect */
+               break;
+
+       default:
+               err = -EBADFD;
+               goto done;
+       }
+
+       /* Set destination address and psm */
+       bacpy(&chan->dst, dst);
+       chan->dst_type = dst_type;
+
+       chan->psm = psm;
+       chan->dcid = cid;
+
+       auth_type = l2cap_get_auth_type(chan);
+
+       if (bdaddr_type_is_le(dst_type))
+               hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
+                                  chan->sec_level, auth_type);
+       else
+               hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
+                                  chan->sec_level, auth_type);
+
+       if (IS_ERR(hcon)) {
+               err = PTR_ERR(hcon);
+               goto done;
+       }
+
+       conn = l2cap_conn_add(hcon);
+       if (!conn) {
+               hci_conn_drop(hcon);
+               err = -ENOMEM;
+               goto done;
+       }
+
+       if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
+               hci_conn_drop(hcon);
+               err = -EBUSY;
+               goto done;
+       }
+
+       /* Update source addr of the socket */
+       bacpy(&chan->src, &hcon->src);
+       chan->src_type = bdaddr_type(hcon, hcon->src_type);
+
+       l2cap_chan_unlock(chan);
+       l2cap_chan_add(conn, chan);
+       l2cap_chan_lock(chan);
+
+       /* l2cap_chan_add takes its own ref so we can drop this one */
+       hci_conn_drop(hcon);
+
+       l2cap_state_change(chan, BT_CONNECT);
+       __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
+
+       if (hcon->state == BT_CONNECTED) {
+               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+                       __clear_chan_timer(chan);
+                       if (l2cap_chan_check_security(chan))
+                               l2cap_state_change(chan, BT_CONNECTED);
+               } else
+                       l2cap_do_start(chan);
+       }
+
+       err = 0;
+
+done:
+       l2cap_chan_unlock(chan);
+       hci_dev_unlock(hdev);
+       hci_dev_put(hdev);
+       return err;
+}
+
 /* ---- L2CAP interface with lower layer (HCI) ---- */
 
 int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)