diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 8 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 14 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 17 |
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 | ||
469 | extern struct list_head hci_dev_list; | 471 | extern 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); | |||
589 | void hci_le_conn_failed(struct hci_conn *conn, u8 status) | 589 | void 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(¶ms->action); | 3738 | list_del(¶ms->action); |
3731 | list_del(¶ms->list); | 3739 | list_del(¶ms->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(¶ms->action); | 3770 | list_del(¶ms->action); |
3761 | list_del(¶ms->list); | 3771 | list_del(¶ms->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(¶ms->action); | 4225 | list_del_init(¶ms->action); |
4226 | if (params->conn) { | ||
4227 | hci_conn_drop(params->conn); | ||
4228 | params->conn = NULL; | ||
4229 | } | ||
4230 | } | ||
4226 | 4231 | ||
4227 | unlock: | 4232 | unlock: |
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: |