diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
| -rw-r--r-- | net/bluetooth/hci_event.c | 25 | 
1 files changed, 23 insertions, 2 deletions
| diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index fe7cdd67ad2a..7a2174851857 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2703,7 +2703,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)  	if (!conn)  		goto unlock; -	if (status) { +	if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) {  		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,  				       conn->dst_type, status); @@ -2718,6 +2718,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)  		goto done;  	} +	/* During suspend, mark connection as closed immediately +	 * since we might not receive HCI_EV_DISCONN_COMPLETE +	 */ +	if (hdev->suspended) +		conn->state = BT_CLOSED; +  	mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);  	if (conn->type == ACL_LINK) { @@ -4398,7 +4404,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,  		if (!conn)  			continue; -		conn->sent -= count; +		/* Check if there is really enough packets outstanding before +		 * attempting to decrease the sent counter otherwise it could +		 * underflow.. +		 */ +		if (conn->sent >= count) { +			conn->sent -= count; +		} else { +			bt_dev_warn(hdev, "hcon %p sent %u < count %u", +				    conn, conn->sent, count); +			conn->sent = 0; +		}  		for (i = 0; i < count; ++i)  			hci_conn_tx_dequeue(conn); @@ -7008,6 +7024,7 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,  {  	struct hci_evt_le_big_sync_lost *ev = data;  	struct hci_conn *bis, *conn; +	bool mgmt_conn;  	bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); @@ -7026,6 +7043,10 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,  	while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,  						     BT_CONNECTED,  						     HCI_ROLE_SLAVE))) { +		mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); +		mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, +					 ev->reason, mgmt_conn); +  		clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);  		hci_disconn_cfm(bis, ev->reason);  		hci_conn_del(bis); | 
