Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: hci_event: Fix not handling PA Sync Lost event

This handles PA Sync Lost event which previously was assumed to be
handled with BIG Sync Lost but their lifetime are not the same thus why
there are 2 different events to inform when each sync is lost.

Fixes: b2a5f2e1c127 ("Bluetooth: hci_event: Add support for handling LE BIG Sync Lost event")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

+40 -14
+5
include/net/bluetooth/hci.h
··· 2783 2783 __u8 data[]; 2784 2784 } __packed; 2785 2785 2786 + #define HCI_EV_LE_PA_SYNC_LOST 0x10 2787 + struct hci_ev_le_pa_sync_lost { 2788 + __le16 handle; 2789 + } __packed; 2790 + 2786 2791 #define LE_PA_DATA_COMPLETE 0x00 2787 2792 #define LE_PA_DATA_MORE_TO_COME 0x01 2788 2793 #define LE_PA_DATA_TRUNCATED 0x02
+35 -14
net/bluetooth/hci_event.c
··· 5843 5843 le16_to_cpu(ev->supervision_timeout)); 5844 5844 } 5845 5845 5846 + static void hci_le_pa_sync_lost_evt(struct hci_dev *hdev, void *data, 5847 + struct sk_buff *skb) 5848 + { 5849 + struct hci_ev_le_pa_sync_lost *ev = data; 5850 + u16 handle = le16_to_cpu(ev->handle); 5851 + struct hci_conn *conn; 5852 + 5853 + bt_dev_dbg(hdev, "sync handle 0x%4.4x", handle); 5854 + 5855 + hci_dev_lock(hdev); 5856 + 5857 + /* Delete the pa sync connection */ 5858 + conn = hci_conn_hash_lookup_pa_sync_handle(hdev, handle); 5859 + if (conn) { 5860 + clear_bit(HCI_CONN_BIG_SYNC, &conn->flags); 5861 + clear_bit(HCI_CONN_PA_SYNC, &conn->flags); 5862 + hci_disconn_cfm(conn, HCI_ERROR_REMOTE_USER_TERM); 5863 + hci_conn_del(conn); 5864 + } 5865 + 5866 + hci_dev_unlock(hdev); 5867 + } 5868 + 5846 5869 static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data, 5847 5870 struct sk_buff *skb) 5848 5871 { ··· 7069 7046 struct sk_buff *skb) 7070 7047 { 7071 7048 struct hci_evt_le_big_sync_lost *ev = data; 7072 - struct hci_conn *bis, *conn; 7073 - bool mgmt_conn; 7049 + struct hci_conn *bis; 7050 + bool mgmt_conn = false; 7074 7051 7075 7052 bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); 7076 7053 7077 7054 hci_dev_lock(hdev); 7078 7055 7079 - /* Delete the pa sync connection */ 7080 - bis = hci_conn_hash_lookup_pa_sync_big_handle(hdev, ev->handle); 7081 - if (bis) { 7082 - conn = hci_conn_hash_lookup_pa_sync_handle(hdev, 7083 - bis->sync_handle); 7084 - if (conn) 7085 - hci_conn_del(conn); 7086 - } 7087 - 7088 7056 /* Delete each bis connection */ 7089 7057 while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, 7090 7058 BT_CONNECTED, 7091 7059 HCI_ROLE_SLAVE))) { 7092 - mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); 7093 - mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, 7094 - ev->reason, mgmt_conn); 7060 + if (!mgmt_conn) { 7061 + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, 7062 + &bis->flags); 7063 + mgmt_device_disconnected(hdev, &bis->dst, bis->type, 7064 + bis->dst_type, ev->reason, 7065 + mgmt_conn); 7066 + } 7095 7067 7096 7068 clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); 7097 7069 hci_disconn_cfm(bis, ev->reason); ··· 7200 7182 hci_le_per_adv_report_evt, 7201 7183 sizeof(struct hci_ev_le_per_adv_report), 7202 7184 HCI_MAX_EVENT_SIZE), 7185 + /* [0x10 = HCI_EV_LE_PA_SYNC_LOST] */ 7186 + HCI_LE_EV(HCI_EV_LE_PA_SYNC_LOST, hci_le_pa_sync_lost_evt, 7187 + sizeof(struct hci_ev_le_pa_sync_lost)), 7203 7188 /* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */ 7204 7189 HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt, 7205 7190 sizeof(struct hci_evt_le_ext_adv_set_term)),