aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--net/bluetooth/hci_conn.c8
-rw-r--r--net/bluetooth/hci_core.c14
-rw-r--r--net/bluetooth/hci_event.c17
4 files changed, 37 insertions, 4 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b5d5af3aa469..6f884e6c731e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -464,6 +464,8 @@ struct hci_conn_params {
464 HCI_AUTO_CONN_ALWAYS, 464 HCI_AUTO_CONN_ALWAYS,
465 HCI_AUTO_CONN_LINK_LOSS, 465 HCI_AUTO_CONN_LINK_LOSS,
466 } auto_connect; 466 } auto_connect;
467
468 struct hci_conn *conn;
467}; 469};
468 470
469extern struct list_head hci_dev_list; 471extern struct list_head hci_dev_list;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b50dabb3f86a..faff6247ac8f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -589,6 +589,14 @@ EXPORT_SYMBOL(hci_get_route);
589void hci_le_conn_failed(struct hci_conn *conn, u8 status) 589void hci_le_conn_failed(struct hci_conn *conn, u8 status)
590{ 590{
591 struct hci_dev *hdev = conn->hdev; 591 struct hci_dev *hdev = conn->hdev;
592 struct hci_conn_params *params;
593
594 params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
595 conn->dst_type);
596 if (params && params->conn) {
597 hci_conn_drop(params->conn);
598 params->conn = NULL;
599 }
592 600
593 conn->state = BT_CLOSED; 601 conn->state = BT_CLOSED;
594 602
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c32d361c0cf7..1d9c29a00568 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2536,8 +2536,13 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
2536{ 2536{
2537 struct hci_conn_params *p; 2537 struct hci_conn_params *p;
2538 2538
2539 list_for_each_entry(p, &hdev->le_conn_params, list) 2539 list_for_each_entry(p, &hdev->le_conn_params, list) {
2540 if (p->conn) {
2541 hci_conn_drop(p->conn);
2542 p->conn = NULL;
2543 }
2540 list_del_init(&p->action); 2544 list_del_init(&p->action);
2545 }
2541 2546
2542 BT_DBG("All LE pending actions cleared"); 2547 BT_DBG("All LE pending actions cleared");
2543} 2548}
@@ -2578,8 +2583,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
2578 2583
2579 hci_dev_lock(hdev); 2584 hci_dev_lock(hdev);
2580 hci_inquiry_cache_flush(hdev); 2585 hci_inquiry_cache_flush(hdev);
2581 hci_conn_hash_flush(hdev);
2582 hci_pend_le_actions_clear(hdev); 2586 hci_pend_le_actions_clear(hdev);
2587 hci_conn_hash_flush(hdev);
2583 hci_dev_unlock(hdev); 2588 hci_dev_unlock(hdev);
2584 2589
2585 hci_notify(hdev, HCI_DEV_DOWN); 2590 hci_notify(hdev, HCI_DEV_DOWN);
@@ -3727,6 +3732,9 @@ void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
3727 if (!params) 3732 if (!params)
3728 return; 3733 return;
3729 3734
3735 if (params->conn)
3736 hci_conn_drop(params->conn);
3737
3730 list_del(&params->action); 3738 list_del(&params->action);
3731 list_del(&params->list); 3739 list_del(&params->list);
3732 kfree(params); 3740 kfree(params);
@@ -3757,6 +3765,8 @@ void hci_conn_params_clear_all(struct hci_dev *hdev)
3757 struct hci_conn_params *params, *tmp; 3765 struct hci_conn_params *params, *tmp;
3758 3766
3759 list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { 3767 list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
3768 if (params->conn)
3769 hci_conn_drop(params->conn);
3760 list_del(&params->action); 3770 list_del(&params->action);
3761 list_del(&params->list); 3771 list_del(&params->list);
3762 kfree(params); 3772 kfree(params);
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: