Skip to content

Commit 8b54f08

Browse files
LingaoMjhedberg
authored andcommitted
drivers: bluetooth: Add discard mechanism to avoid waiting timeout
The Bluetooth receiving thread may not be able to process broadcast packets because the system API(bt_hci_cmd_send_sync) is in block state. If HCI driver is still waiting buffer for adv report, an assertion will be triggered. Fixes: #30955 Signed-off-by: Lingao Meng <[email protected]>
1 parent d510f1f commit 8b54f08

File tree

5 files changed

+51
-5
lines changed

5 files changed

+51
-5
lines changed

drivers/bluetooth/hci/h4.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ static inline void get_evt_hdr(void)
154154

155155
if (!rx.remaining) {
156156
if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT &&
157-
rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
157+
(rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
158+
rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
158159
BT_DBG("Marking adv report as discardable");
159160
rx.discardable = true;
160161
}

drivers/bluetooth/hci/ipm_stm32wb.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,13 @@ void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt)
152152
static void bt_ipm_rx_thread(void)
153153
{
154154
while (true) {
155+
bool discardable = false;
156+
k_timeout_t timeout = K_FOREVER;
155157
static TL_EvtPacket_t *hcievt;
156158
struct net_buf *buf = NULL;
157159
struct bt_hci_acl_hdr acl_hdr;
158160
TL_AclDataSerial_t *acl;
161+
struct bt_hci_evt_le_meta_event *mev;
159162

160163
hcievt = k_fifo_get(&ipm_rx_events_fifo, K_FOREVER);
161164

@@ -173,10 +176,23 @@ static void bt_ipm_rx_thread(void)
173176
TL_MM_EvtDone(hcievt);
174177
goto end_loop;
175178
default:
179+
mev = (void *)&hcievt->evtserial.evt.payload;
180+
if (hcievt->evtserial.evt.evtcode == BT_HCI_EVT_LE_META_EVENT &&
181+
(mev->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
182+
mev->subevent == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
183+
discardable = true;
184+
timeout = K_NO_WAIT;
185+
}
186+
176187
buf = bt_buf_get_evt(
177188
hcievt->evtserial.evt.evtcode,
178-
false, K_FOREVER);
189+
discardable, timeout);
190+
if (!buf) {
191+
BT_DBG("Discard adv report due to insufficient buf");
192+
goto end_loop;
193+
}
179194
}
195+
180196
tryfix_event(&hcievt->evtserial.evt);
181197
net_buf_add_mem(buf, &hcievt->evtserial.evt,
182198
hcievt->evtserial.evt.plen + 2);

drivers/bluetooth/hci/rpmsg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ static bool is_hci_event_discardable(const uint8_t *evt_data)
3939
switch (subevt_type) {
4040
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
4141
return true;
42+
case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT:
43+
return true;
4244
default:
4345
return false;
4446
}

drivers/bluetooth/hci/spi.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ static int bt_spi_send_aci_config_data_controller_mode(void)
307307

308308
static void bt_spi_rx_thread(void)
309309
{
310+
bool discardable = false;
311+
k_timeout_t timeout = K_FOREVER;
310312
struct net_buf *buf;
311313
uint8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 };
312314
uint8_t header_slave[5];
@@ -367,9 +369,19 @@ static void bt_spi_rx_thread(void)
367369
bt_spi_handle_vendor_evt(rxmsg);
368370
continue;
369371
default:
372+
if (rxmsg[1] == BT_HCI_EVT_LE_META_EVENT &&
373+
(rxmsg[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
374+
rxmsg[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
375+
discardable = true;
376+
timeout = K_NO_WAIT;
377+
}
378+
370379
buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT],
371-
false, K_FOREVER);
372-
break;
380+
discardable, timeout);
381+
if (!buf) {
382+
BT_DBG("Discard adv report due to insufficient buf");
383+
continue;
384+
}
373385
}
374386

375387
net_buf_add_mem(buf, &rxmsg[1],

drivers/bluetooth/hci/userchan.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,19 @@ static int bt_dev_index = -1;
5858

5959
static struct net_buf *get_rx(const uint8_t *buf)
6060
{
61+
bool discardable = false;
62+
k_timeout_t timeout = K_FOREVER;
63+
6164
switch (buf[0]) {
6265
case H4_EVT:
63-
return bt_buf_get_evt(buf[1], false, K_FOREVER);
66+
if (buf[1] == BT_HCI_EVT_LE_META_EVENT &&
67+
(buf[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
68+
buf[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
69+
discardable = true;
70+
timeout = K_NO_WAIT;
71+
}
72+
73+
return bt_buf_get_evt(buf[1], discardable, timeout);
6474
case H4_ACL:
6575
return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
6676
case H4_ISO:
@@ -116,6 +126,11 @@ static void rx_thread(void *p1, void *p2, void *p3)
116126
}
117127

118128
buf = get_rx(frame);
129+
if (!buf) {
130+
BT_DBG("Discard adv report due to insufficient buf");
131+
continue;
132+
}
133+
119134
net_buf_add_mem(buf, &frame[1], len - 1);
120135

121136
BT_DBG("Calling bt_recv(%p)", buf);

0 commit comments

Comments
 (0)