Bluetooth: Simplify hci_conn_hold/drop logic for L2CAP
authorJohan Hedberg <johan.hedberg@intel.com>
Mon, 29 Apr 2013 16:35:43 +0000 (19:35 +0300)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Sat, 22 Jun 2013 23:23:49 +0000 (00:23 +0100)
The L2CAP code has been incrementing the hci_conn reference for each
l2cap_chan instance in the l2cap_conn list. Likewise, the reference is
dropped each time an l2cap_chan is removed from the list. The reference
counting policy with respect to removal has been clear and explicit in
the l2cap_chan_del function, however for addition the function
calling 2cap_chan_add has always had to do a separate hci_conn_hold
call.

What made the counting even more hard to follow is that the
hci_connect() procedure increments the reference and the L2CAP layer
making this call took advantage of it to use it as its own reference.

This patch aims to clarify things by having the call to hci_conn_hold
inside __l2cap_chan_add, thereby removing the need to do it in the
functions calling __l2cap_chan_add. The reference count for hci_connect
is still kept as it's necessary for users such as mgmt_pair_device,
however for the L2CAP layer it means that an extra call to hci_conn_drop
must be performed once l2cap_chan_add has been done.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
net/bluetooth/l2cap_core.c

index 55c6836796f7dbc01fe739fa1d6ce12c2ce5585b..d7b501ba2716114cf865825de273cf81e1170826 100644 (file)
@@ -545,6 +545,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 
        l2cap_chan_hold(chan);
 
+       hci_conn_hold(conn->hcon);
+
        list_add(&chan->list, &conn->chan_l);
 }
 
@@ -1361,7 +1363,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        chan->dcid = L2CAP_CID_ATT;
 
-       hci_conn_hold(conn->hcon);
        conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
 
        bacpy(&bt_sk(chan->sk)->src, conn->src);
@@ -1827,6 +1828,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
        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, sk->sk_sndtimeo);
 
@@ -3748,8 +3752,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
        sk = chan->sk;
 
-       hci_conn_hold(conn->hcon);
-
        bacpy(&bt_sk(sk)->src, conn->src);
        bacpy(&bt_sk(sk)->dst, conn->dst);
        chan->psm  = psm;