Skip to content

Commit 8ef0f2c

Browse files
committed
Merge tag 'for-net-2025-03-07' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - btusb: Configure altsetting for HCI_USER_CHANNEL - hci_event: Fix enabling passive scanning - revert: "hci_core: Fix sleeping function called from invalid context" - SCO: fix sco_conn refcounting on sco_conn_ready * tag 'for-net-2025-03-07' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Revert "Bluetooth: hci_core: Fix sleeping function called from invalid context" Bluetooth: hci_event: Fix enabling passive scanning Bluetooth: SCO: fix sco_conn refcounting on sco_conn_ready Bluetooth: btusb: Configure altsetting for HCI_USER_CHANNEL ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents fc14f9c + ab6ab70 commit 8ef0f2c

File tree

9 files changed

+144
-113
lines changed

9 files changed

+144
-113
lines changed

drivers/bluetooth/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ config BT_HCIBTUSB_POLL_SYNC
5656
Say Y here to enable USB poll_sync for Bluetooth USB devices by
5757
default.
5858

59+
config BT_HCIBTUSB_AUTO_ISOC_ALT
60+
bool "Automatically adjust alternate setting for Isoc endpoints"
61+
depends on BT_HCIBTUSB
62+
default y if CHROME_PLATFORMS
63+
help
64+
Say Y here to automatically adjusting the alternate setting for
65+
HCI_USER_CHANNEL whenever a SCO link is established.
66+
67+
When enabled, btusb intercepts the HCI_EV_SYNC_CONN_COMPLETE packets
68+
and configures isoc endpoint alternate setting automatically when
69+
HCI_USER_CHANNEL is in use.
70+
5971
config BT_HCIBTUSB_BCM
6072
bool "Broadcom protocol support"
6173
depends on BT_HCIBTUSB

drivers/bluetooth/btusb.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static bool force_scofix;
3434
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
3535
static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
3636
static bool reset = true;
37+
static bool auto_isoc_alt = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT);
3738

3839
static struct usb_driver btusb_driver;
3940

@@ -1085,13 +1086,53 @@ static inline void btusb_free_frags(struct btusb_data *data)
10851086
spin_unlock_irqrestore(&data->rxlock, flags);
10861087
}
10871088

1089+
static void btusb_sco_connected(struct btusb_data *data, struct sk_buff *skb)
1090+
{
1091+
struct hci_event_hdr *hdr = (void *) skb->data;
1092+
struct hci_ev_sync_conn_complete *ev =
1093+
(void *) skb->data + sizeof(*hdr);
1094+
struct hci_dev *hdev = data->hdev;
1095+
unsigned int notify_air_mode;
1096+
1097+
if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT)
1098+
return;
1099+
1100+
if (skb->len < sizeof(*hdr) || hdr->evt != HCI_EV_SYNC_CONN_COMPLETE)
1101+
return;
1102+
1103+
if (skb->len != sizeof(*hdr) + sizeof(*ev) || ev->status)
1104+
return;
1105+
1106+
switch (ev->air_mode) {
1107+
case BT_CODEC_CVSD:
1108+
notify_air_mode = HCI_NOTIFY_ENABLE_SCO_CVSD;
1109+
break;
1110+
1111+
case BT_CODEC_TRANSPARENT:
1112+
notify_air_mode = HCI_NOTIFY_ENABLE_SCO_TRANSP;
1113+
break;
1114+
1115+
default:
1116+
return;
1117+
}
1118+
1119+
bt_dev_info(hdev, "enabling SCO with air mode %u", ev->air_mode);
1120+
data->sco_num = 1;
1121+
data->air_mode = notify_air_mode;
1122+
schedule_work(&data->work);
1123+
}
1124+
10881125
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
10891126
{
10901127
if (data->intr_interval) {
10911128
/* Trigger dequeue immediately if an event is received */
10921129
schedule_delayed_work(&data->rx_work, 0);
10931130
}
10941131

1132+
/* Configure altsetting for HCI_USER_CHANNEL on SCO connected */
1133+
if (auto_isoc_alt && hci_dev_test_flag(data->hdev, HCI_USER_CHANNEL))
1134+
btusb_sco_connected(data, skb);
1135+
10951136
return data->recv_event(data->hdev, skb);
10961137
}
10971138

include/net/bluetooth/hci_core.h

Lines changed: 38 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ struct hci_conn_params {
804804
extern struct list_head hci_dev_list;
805805
extern struct list_head hci_cb_list;
806806
extern rwlock_t hci_dev_list_lock;
807+
extern struct mutex hci_cb_list_lock;
807808

808809
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
809810
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
@@ -2010,103 +2011,68 @@ struct hci_cb {
20102011

20112012
char *name;
20122013

2013-
bool (*match) (struct hci_conn *conn);
20142014
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
20152015
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
20162016
void (*security_cfm) (struct hci_conn *conn, __u8 status,
2017-
__u8 encrypt);
2017+
__u8 encrypt);
20182018
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
20192019
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
20202020
};
20212021

2022-
static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
2023-
{
2024-
struct hci_cb *cb, *cpy;
2025-
2026-
rcu_read_lock();
2027-
list_for_each_entry_rcu(cb, &hci_cb_list, list) {
2028-
if (cb->match && cb->match(conn)) {
2029-
cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
2030-
if (!cpy)
2031-
break;
2032-
2033-
*cpy = *cb;
2034-
INIT_LIST_HEAD(&cpy->list);
2035-
list_add_rcu(&cpy->list, list);
2036-
}
2037-
}
2038-
rcu_read_unlock();
2039-
}
2040-
20412022
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
20422023
{
2043-
struct list_head list;
2044-
struct hci_cb *cb, *tmp;
2045-
2046-
INIT_LIST_HEAD(&list);
2047-
hci_cb_lookup(conn, &list);
2024+
struct hci_cb *cb;
20482025

2049-
list_for_each_entry_safe(cb, tmp, &list, list) {
2026+
mutex_lock(&hci_cb_list_lock);
2027+
list_for_each_entry(cb, &hci_cb_list, list) {
20502028
if (cb->connect_cfm)
20512029
cb->connect_cfm(conn, status);
2052-
kfree(cb);
20532030
}
2031+
mutex_unlock(&hci_cb_list_lock);
20542032

20552033
if (conn->connect_cfm_cb)
20562034
conn->connect_cfm_cb(conn, status);
20572035
}
20582036

20592037
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
20602038
{
2061-
struct list_head list;
2062-
struct hci_cb *cb, *tmp;
2063-
2064-
INIT_LIST_HEAD(&list);
2065-
hci_cb_lookup(conn, &list);
2039+
struct hci_cb *cb;
20662040

2067-
list_for_each_entry_safe(cb, tmp, &list, list) {
2041+
mutex_lock(&hci_cb_list_lock);
2042+
list_for_each_entry(cb, &hci_cb_list, list) {
20682043
if (cb->disconn_cfm)
20692044
cb->disconn_cfm(conn, reason);
2070-
kfree(cb);
20712045
}
2046+
mutex_unlock(&hci_cb_list_lock);
20722047

20732048
if (conn->disconn_cfm_cb)
20742049
conn->disconn_cfm_cb(conn, reason);
20752050
}
20762051

2077-
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
2078-
__u8 encrypt)
2079-
{
2080-
struct list_head list;
2081-
struct hci_cb *cb, *tmp;
2082-
2083-
INIT_LIST_HEAD(&list);
2084-
hci_cb_lookup(conn, &list);
2085-
2086-
list_for_each_entry_safe(cb, tmp, &list, list) {
2087-
if (cb->security_cfm)
2088-
cb->security_cfm(conn, status, encrypt);
2089-
kfree(cb);
2090-
}
2091-
2092-
if (conn->security_cfm_cb)
2093-
conn->security_cfm_cb(conn, status);
2094-
}
2095-
20962052
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
20972053
{
2054+
struct hci_cb *cb;
20982055
__u8 encrypt;
20992056

21002057
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
21012058
return;
21022059

21032060
encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
21042061

2105-
hci_security_cfm(conn, status, encrypt);
2062+
mutex_lock(&hci_cb_list_lock);
2063+
list_for_each_entry(cb, &hci_cb_list, list) {
2064+
if (cb->security_cfm)
2065+
cb->security_cfm(conn, status, encrypt);
2066+
}
2067+
mutex_unlock(&hci_cb_list_lock);
2068+
2069+
if (conn->security_cfm_cb)
2070+
conn->security_cfm_cb(conn, status);
21062071
}
21072072

21082073
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21092074
{
2075+
struct hci_cb *cb;
21102076
__u8 encrypt;
21112077

21122078
if (conn->state == BT_CONFIG) {
@@ -2133,38 +2099,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21332099
conn->sec_level = conn->pending_sec_level;
21342100
}
21352101

2136-
hci_security_cfm(conn, status, encrypt);
2102+
mutex_lock(&hci_cb_list_lock);
2103+
list_for_each_entry(cb, &hci_cb_list, list) {
2104+
if (cb->security_cfm)
2105+
cb->security_cfm(conn, status, encrypt);
2106+
}
2107+
mutex_unlock(&hci_cb_list_lock);
2108+
2109+
if (conn->security_cfm_cb)
2110+
conn->security_cfm_cb(conn, status);
21372111
}
21382112

21392113
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
21402114
{
2141-
struct list_head list;
2142-
struct hci_cb *cb, *tmp;
2143-
2144-
INIT_LIST_HEAD(&list);
2145-
hci_cb_lookup(conn, &list);
2115+
struct hci_cb *cb;
21462116

2147-
list_for_each_entry_safe(cb, tmp, &list, list) {
2117+
mutex_lock(&hci_cb_list_lock);
2118+
list_for_each_entry(cb, &hci_cb_list, list) {
21482119
if (cb->key_change_cfm)
21492120
cb->key_change_cfm(conn, status);
2150-
kfree(cb);
21512121
}
2122+
mutex_unlock(&hci_cb_list_lock);
21522123
}
21532124

21542125
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
21552126
__u8 role)
21562127
{
2157-
struct list_head list;
2158-
struct hci_cb *cb, *tmp;
2159-
2160-
INIT_LIST_HEAD(&list);
2161-
hci_cb_lookup(conn, &list);
2128+
struct hci_cb *cb;
21622129

2163-
list_for_each_entry_safe(cb, tmp, &list, list) {
2130+
mutex_lock(&hci_cb_list_lock);
2131+
list_for_each_entry(cb, &hci_cb_list, list) {
21642132
if (cb->role_switch_cfm)
21652133
cb->role_switch_cfm(conn, status, role);
2166-
kfree(cb);
21672134
}
2135+
mutex_unlock(&hci_cb_list_lock);
21682136
}
21692137

21702138
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)

net/bluetooth/hci_core.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ DEFINE_RWLOCK(hci_dev_list_lock);
5757

5858
/* HCI callback list */
5959
LIST_HEAD(hci_cb_list);
60+
DEFINE_MUTEX(hci_cb_list_lock);
6061

6162
/* HCI ID Numbering */
6263
static DEFINE_IDA(hci_index_ida);
@@ -2972,7 +2973,9 @@ int hci_register_cb(struct hci_cb *cb)
29722973
{
29732974
BT_DBG("%p name %s", cb, cb->name);
29742975

2975-
list_add_tail_rcu(&cb->list, &hci_cb_list);
2976+
mutex_lock(&hci_cb_list_lock);
2977+
list_add_tail(&cb->list, &hci_cb_list);
2978+
mutex_unlock(&hci_cb_list_lock);
29762979

29772980
return 0;
29782981
}
@@ -2982,8 +2985,9 @@ int hci_unregister_cb(struct hci_cb *cb)
29822985
{
29832986
BT_DBG("%p name %s", cb, cb->name);
29842987

2985-
list_del_rcu(&cb->list);
2986-
synchronize_rcu();
2988+
mutex_lock(&hci_cb_list_lock);
2989+
list_del(&cb->list);
2990+
mutex_unlock(&hci_cb_list_lock);
29872991

29882992
return 0;
29892993
}

net/bluetooth/hci_event.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3391,23 +3391,30 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
33913391
hci_update_scan(hdev);
33923392
}
33933393

3394-
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
3395-
if (params) {
3396-
switch (params->auto_connect) {
3397-
case HCI_AUTO_CONN_LINK_LOSS:
3398-
if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
3394+
/* Re-enable passive scanning if disconnected device is marked
3395+
* as auto-connectable.
3396+
*/
3397+
if (conn->type == LE_LINK) {
3398+
params = hci_conn_params_lookup(hdev, &conn->dst,
3399+
conn->dst_type);
3400+
if (params) {
3401+
switch (params->auto_connect) {
3402+
case HCI_AUTO_CONN_LINK_LOSS:
3403+
if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
3404+
break;
3405+
fallthrough;
3406+
3407+
case HCI_AUTO_CONN_DIRECT:
3408+
case HCI_AUTO_CONN_ALWAYS:
3409+
hci_pend_le_list_del_init(params);
3410+
hci_pend_le_list_add(params,
3411+
&hdev->pend_le_conns);
3412+
hci_update_passive_scan(hdev);
33993413
break;
3400-
fallthrough;
34013414

3402-
case HCI_AUTO_CONN_DIRECT:
3403-
case HCI_AUTO_CONN_ALWAYS:
3404-
hci_pend_le_list_del_init(params);
3405-
hci_pend_le_list_add(params, &hdev->pend_le_conns);
3406-
hci_update_passive_scan(hdev);
3407-
break;
3408-
3409-
default:
3410-
break;
3415+
default:
3416+
break;
3417+
}
34113418
}
34123419
}
34133420

net/bluetooth/iso.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,11 +2187,6 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
21872187
return HCI_LM_ACCEPT;
21882188
}
21892189

2190-
static bool iso_match(struct hci_conn *hcon)
2191-
{
2192-
return hcon->type == ISO_LINK || hcon->type == LE_LINK;
2193-
}
2194-
21952190
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
21962191
{
21972192
if (hcon->type != ISO_LINK) {
@@ -2373,7 +2368,6 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
23732368

23742369
static struct hci_cb iso_cb = {
23752370
.name = "ISO",
2376-
.match = iso_match,
23772371
.connect_cfm = iso_connect_cfm,
23782372
.disconn_cfm = iso_disconn_cfm,
23792373
};

0 commit comments

Comments
 (0)