aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-08-15 14:06:54 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2014-08-20 14:57:39 -0400
commitf161dd4122ffa73e4e12000309dca65bec80d416 (patch)
tree333834ba4d1f8194c8b72b042f27c58bddd738e5 /net/bluetooth/hci_event.c
parent6697dabe27e03302ddfddc975275e6401defe2dd (diff)
Bluetooth: Fix hci_conn reference counting for auto-connections
Recently the LE passive scanning and auto-connections feature was introduced. It uses the hci_connect_le() API which returns a hci_conn along with a reference count to that object. All previous users would tie this returned reference to some existing object, such as an L2CAP channel, and there'd be no leaked references this way. For auto-connections however the reference was returned but not stored anywhere, leaving established connections with one higher reference count than they should have. Instead of playing special tricks with hci_conn_hold/drop this patch associates the returned reference from hci_connect_le() with the object that in practice does own this reference, i.e. the hci_conn_params struct that caused us to initiate a connection in the first place. Once the connection is established or fails to establish this reference is removed appropriately. One extra thing needed is to call hci_pend_le_actions_clear() before calling hci_conn_hash_flush() so that the reference is cleared before the hci_conn objects are fully removed. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index be35598984d9..a6000823f0ff 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4221,8 +4221,13 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
4221 hci_proto_connect_cfm(conn, ev->status); 4221 hci_proto_connect_cfm(conn, ev->status);
4222 4222
4223 params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); 4223 params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
4224 if (params) 4224 if (params) {
4225 list_del_init(&params->action); 4225 list_del_init(&params->action);
4226 if (params->conn) {
4227 hci_conn_drop(params->conn);
4228 params->conn = NULL;
4229 }
4230 }
4226 4231
4227unlock: 4232unlock:
4228 hci_update_background_scan(hdev); 4233 hci_update_background_scan(hdev);
@@ -4304,8 +4309,16 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
4304 4309
4305 conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 4310 conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
4306 HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); 4311 HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
4307 if (!IS_ERR(conn)) 4312 if (!IS_ERR(conn)) {
4313 /* Store the pointer since we don't really have any
4314 * other owner of the object besides the params that
4315 * triggered it. This way we can abort the connection if
4316 * the parameters get removed and keep the reference
4317 * count consistent once the connection is established.
4318 */
4319 params->conn = conn;
4308 return; 4320 return;
4321 }
4309 4322
4310 switch (PTR_ERR(conn)) { 4323 switch (PTR_ERR(conn)) {
4311 case -EBUSY: 4324 case -EBUSY: