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 <menglingao@xiaomi.com>
This commit is contained in:
parent
d510f1f84d
commit
8b54f08a69
5 changed files with 51 additions and 5 deletions
|
@ -154,7 +154,8 @@ static inline void get_evt_hdr(void)
|
||||||
|
|
||||||
if (!rx.remaining) {
|
if (!rx.remaining) {
|
||||||
if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT &&
|
if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT &&
|
||||||
rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
|
(rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
|
||||||
|
rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
|
||||||
BT_DBG("Marking adv report as discardable");
|
BT_DBG("Marking adv report as discardable");
|
||||||
rx.discardable = true;
|
rx.discardable = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,10 +152,13 @@ void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt)
|
||||||
static void bt_ipm_rx_thread(void)
|
static void bt_ipm_rx_thread(void)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
|
bool discardable = false;
|
||||||
|
k_timeout_t timeout = K_FOREVER;
|
||||||
static TL_EvtPacket_t *hcievt;
|
static TL_EvtPacket_t *hcievt;
|
||||||
struct net_buf *buf = NULL;
|
struct net_buf *buf = NULL;
|
||||||
struct bt_hci_acl_hdr acl_hdr;
|
struct bt_hci_acl_hdr acl_hdr;
|
||||||
TL_AclDataSerial_t *acl;
|
TL_AclDataSerial_t *acl;
|
||||||
|
struct bt_hci_evt_le_meta_event *mev;
|
||||||
|
|
||||||
hcievt = k_fifo_get(&ipm_rx_events_fifo, K_FOREVER);
|
hcievt = k_fifo_get(&ipm_rx_events_fifo, K_FOREVER);
|
||||||
|
|
||||||
|
@ -173,10 +176,23 @@ static void bt_ipm_rx_thread(void)
|
||||||
TL_MM_EvtDone(hcievt);
|
TL_MM_EvtDone(hcievt);
|
||||||
goto end_loop;
|
goto end_loop;
|
||||||
default:
|
default:
|
||||||
|
mev = (void *)&hcievt->evtserial.evt.payload;
|
||||||
|
if (hcievt->evtserial.evt.evtcode == BT_HCI_EVT_LE_META_EVENT &&
|
||||||
|
(mev->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
|
||||||
|
mev->subevent == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
|
||||||
|
discardable = true;
|
||||||
|
timeout = K_NO_WAIT;
|
||||||
|
}
|
||||||
|
|
||||||
buf = bt_buf_get_evt(
|
buf = bt_buf_get_evt(
|
||||||
hcievt->evtserial.evt.evtcode,
|
hcievt->evtserial.evt.evtcode,
|
||||||
false, K_FOREVER);
|
discardable, timeout);
|
||||||
|
if (!buf) {
|
||||||
|
BT_DBG("Discard adv report due to insufficient buf");
|
||||||
|
goto end_loop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tryfix_event(&hcievt->evtserial.evt);
|
tryfix_event(&hcievt->evtserial.evt);
|
||||||
net_buf_add_mem(buf, &hcievt->evtserial.evt,
|
net_buf_add_mem(buf, &hcievt->evtserial.evt,
|
||||||
hcievt->evtserial.evt.plen + 2);
|
hcievt->evtserial.evt.plen + 2);
|
||||||
|
|
|
@ -39,6 +39,8 @@ static bool is_hci_event_discardable(const uint8_t *evt_data)
|
||||||
switch (subevt_type) {
|
switch (subevt_type) {
|
||||||
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
|
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
|
||||||
return true;
|
return true;
|
||||||
|
case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT:
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,8 @@ static int bt_spi_send_aci_config_data_controller_mode(void)
|
||||||
|
|
||||||
static void bt_spi_rx_thread(void)
|
static void bt_spi_rx_thread(void)
|
||||||
{
|
{
|
||||||
|
bool discardable = false;
|
||||||
|
k_timeout_t timeout = K_FOREVER;
|
||||||
struct net_buf *buf;
|
struct net_buf *buf;
|
||||||
uint8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 };
|
uint8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 };
|
||||||
uint8_t header_slave[5];
|
uint8_t header_slave[5];
|
||||||
|
@ -367,9 +369,19 @@ static void bt_spi_rx_thread(void)
|
||||||
bt_spi_handle_vendor_evt(rxmsg);
|
bt_spi_handle_vendor_evt(rxmsg);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
if (rxmsg[1] == BT_HCI_EVT_LE_META_EVENT &&
|
||||||
|
(rxmsg[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
|
||||||
|
rxmsg[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
|
||||||
|
discardable = true;
|
||||||
|
timeout = K_NO_WAIT;
|
||||||
|
}
|
||||||
|
|
||||||
buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT],
|
buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT],
|
||||||
false, K_FOREVER);
|
discardable, timeout);
|
||||||
break;
|
if (!buf) {
|
||||||
|
BT_DBG("Discard adv report due to insufficient buf");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
net_buf_add_mem(buf, &rxmsg[1],
|
net_buf_add_mem(buf, &rxmsg[1],
|
||||||
|
|
|
@ -58,9 +58,19 @@ static int bt_dev_index = -1;
|
||||||
|
|
||||||
static struct net_buf *get_rx(const uint8_t *buf)
|
static struct net_buf *get_rx(const uint8_t *buf)
|
||||||
{
|
{
|
||||||
|
bool discardable = false;
|
||||||
|
k_timeout_t timeout = K_FOREVER;
|
||||||
|
|
||||||
switch (buf[0]) {
|
switch (buf[0]) {
|
||||||
case H4_EVT:
|
case H4_EVT:
|
||||||
return bt_buf_get_evt(buf[1], false, K_FOREVER);
|
if (buf[1] == BT_HCI_EVT_LE_META_EVENT &&
|
||||||
|
(buf[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT ||
|
||||||
|
buf[3] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT)) {
|
||||||
|
discardable = true;
|
||||||
|
timeout = K_NO_WAIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bt_buf_get_evt(buf[1], discardable, timeout);
|
||||||
case H4_ACL:
|
case H4_ACL:
|
||||||
return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
|
return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
|
||||||
case H4_ISO:
|
case H4_ISO:
|
||||||
|
@ -116,6 +126,11 @@ static void rx_thread(void *p1, void *p2, void *p3)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = get_rx(frame);
|
buf = get_rx(frame);
|
||||||
|
if (!buf) {
|
||||||
|
BT_DBG("Discard adv report due to insufficient buf");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
net_buf_add_mem(buf, &frame[1], len - 1);
|
net_buf_add_mem(buf, &frame[1], len - 1);
|
||||||
|
|
||||||
BT_DBG("Calling bt_recv(%p)", buf);
|
BT_DBG("Calling bt_recv(%p)", buf);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue