From 61f80376e130098570e2b097124e8f4ccc00e7e9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 17 Jun 2019 15:54:45 +0300 Subject: [PATCH 1/2] Bluetooth: Add dedicated pool for HCI_Num_Completed_Packets HCI event This event is a priority one, so it's not safe to have it use the RX buffer pool which may be depleted due to non-priority events (e.g. advertising events). Since the event is consumed synchronously it's safe to have a single-buffer pool for it. Also introduce a new bt_buf_get_evt() API for HCI drivers to simplify the driver-side code, this effectively also deprecates bt_buf_get_cmd_complete() which now has no in-tree HCI driver users anymore. Fixes #16864 Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci/h4.c | 11 ++---- drivers/bluetooth/hci/h5.c | 11 +----- drivers/bluetooth/hci/ipm_stm32wb.c | 6 +--- drivers/bluetooth/hci/spi.c | 7 ++-- drivers/bluetooth/hci/userchan.c | 11 ++---- include/bluetooth/buf.h | 12 +++++++ subsys/bluetooth/controller/hci/hci.c | 4 +-- subsys/bluetooth/controller/hci/hci_driver.c | 3 +- subsys/bluetooth/host/hci_core.c | 35 ++++++++++++++++++++ subsys/bluetooth/host/hci_ecc.c | 2 +- subsys/bluetooth/host/hci_raw.c | 12 +++++++ tests/bluetooth/hci_prop_evt/src/main.c | 2 +- 12 files changed, 75 insertions(+), 41 deletions(-) diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index 5248c11e05643..cb886846bfc78 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -161,16 +161,11 @@ static struct net_buf *get_rx(int timeout) { BT_DBG("type 0x%02x, evt 0x%02x", rx.type, rx.evt.evt); - if (rx.type == H4_EVT && (rx.evt.evt == BT_HCI_EVT_CMD_COMPLETE || - rx.evt.evt == BT_HCI_EVT_CMD_STATUS)) { - return bt_buf_get_cmd_complete(timeout); + if (rx.type == H4_EVT) { + return bt_buf_get_evt(rx.evt.evt, timeout); } - if (rx.type == H4_ACL) { - return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); - } else { - return bt_buf_get_rx(BT_BUF_EVT, timeout); - } + return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); } static void rx_thread(void *p1, void *p2, void *p3) diff --git a/drivers/bluetooth/hci/h5.c b/drivers/bluetooth/hci/h5.c index a3c5b64bad0da..52727f7ec6366 100644 --- a/drivers/bluetooth/hci/h5.c +++ b/drivers/bluetooth/hci/h5.c @@ -408,16 +408,7 @@ static inline struct net_buf *get_evt_buf(u8_t evt) { struct net_buf *buf; - switch (evt) { - case BT_HCI_EVT_CMD_COMPLETE: - case BT_HCI_EVT_CMD_STATUS: - buf = bt_buf_get_cmd_complete(K_NO_WAIT); - break; - default: - buf = bt_buf_get_rx(BT_BUF_EVT, K_NO_WAIT); - break; - } - + buf = bt_buf_get_evt(evt, K_NO_WAIT); if (buf) { net_buf_add_u8(h5.rx_buf, evt); } diff --git a/drivers/bluetooth/hci/ipm_stm32wb.c b/drivers/bluetooth/hci/ipm_stm32wb.c index a4d14a1979f1d..9f2b95129f674 100644 --- a/drivers/bluetooth/hci/ipm_stm32wb.c +++ b/drivers/bluetooth/hci/ipm_stm32wb.c @@ -114,12 +114,8 @@ void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt) BT_ERR("Unknown evtcode type 0x%02x", hcievt->evtserial.evt.evtcode); goto out; - case BT_HCI_EVT_CMD_COMPLETE: - case BT_HCI_EVT_CMD_STATUS: - buf = bt_buf_get_cmd_complete(K_FOREVER); - break; default: - buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + buf = bt_buf_get_evt(evtserial.evt.evtcode, K_FOREVER); break; } net_buf_add_mem(buf, &hcievt->evtserial.evt, diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index 534fb860cc655..5749c35541153 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -353,12 +353,9 @@ static void bt_spi_rx_thread(void) /* Vendor events are currently unsupported */ bt_spi_handle_vendor_evt(rxmsg); continue; - case BT_HCI_EVT_CMD_COMPLETE: - case BT_HCI_EVT_CMD_STATUS: - buf = bt_buf_get_cmd_complete(K_FOREVER); - break; default: - buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT], + K_FOREVER); break; } diff --git a/drivers/bluetooth/hci/userchan.c b/drivers/bluetooth/hci/userchan.c index 1b80dc19d7b85..f2c8b3f14d115 100644 --- a/drivers/bluetooth/hci/userchan.c +++ b/drivers/bluetooth/hci/userchan.c @@ -57,16 +57,11 @@ static int bt_dev_index = -1; static struct net_buf *get_rx(const u8_t *buf) { - if (buf[0] == H4_EVT && (buf[1] == BT_HCI_EVT_CMD_COMPLETE || - buf[1] == BT_HCI_EVT_CMD_STATUS)) { - return bt_buf_get_cmd_complete(K_FOREVER); + if (buf[0] == H4_EVT) { + return bt_buf_get_evt(buf[1], K_FOREVER); } - if (buf[0] == H4_ACL) { - return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); - } else { - return bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); - } + return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); } static bool uc_ready(void) diff --git a/include/bluetooth/buf.h b/include/bluetooth/buf.h index b0b26185e6313..3110ba94ccc36 100644 --- a/include/bluetooth/buf.h +++ b/include/bluetooth/buf.h @@ -64,6 +64,18 @@ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, s32_t timeout); */ struct net_buf *bt_buf_get_cmd_complete(s32_t timeout); +/** Allocate a buffer for an HCI Event + * + * This will set the buffer type so bt_buf_set_type() does not need to + * be explicitly called before bt_recv_prio() or bt_recv(). + * + * @param evt HCI event code + * @param timeout Timeout in milliseconds, or one of the special values + * K_NO_WAIT and K_FOREVER. + * @return A new buffer. + */ +struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout); + /** Set the buffer type * * @param buf Bluetooth buffer diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 91153b119de4e..1b99bd48f4d19 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -120,7 +120,7 @@ void *hci_cmd_complete(struct net_buf **buf, u8_t plen) { struct bt_hci_evt_cmd_complete *cc; - *buf = bt_buf_get_cmd_complete(K_FOREVER); + *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, K_FOREVER); hci_evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen); @@ -137,7 +137,7 @@ static struct net_buf *cmd_status(u8_t status) struct bt_hci_evt_cmd_status *cs; struct net_buf *buf; - buf = bt_buf_get_cmd_complete(K_FOREVER); + buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, K_FOREVER); hci_evt_create(buf, BT_HCI_EVT_CMD_STATUS, sizeof(*cs)); cs = net_buf_add(buf, sizeof(*cs)); diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 814a3d20fa90a..1229c4625b87e 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -90,7 +90,8 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) #if defined(CONFIG_BT_CONN) struct net_buf *buf; - buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS, + K_FOREVER); hci_num_cmplt_encode(buf, handle, num_cmplt); BT_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt); bt_recv_prio(buf); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 8b2fcb9bd2ad5..ba32c8970f5e2 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -138,6 +138,16 @@ NET_BUF_POOL_DEFINE(hci_cmd_pool, CONFIG_BT_HCI_CMD_COUNT, NET_BUF_POOL_DEFINE(hci_rx_pool, CONFIG_BT_RX_BUF_COUNT, BT_BUF_RX_SIZE, BT_BUF_USER_DATA_MIN, NULL); +#if defined(CONFIG_BT_CONN) +/* Dedicated pool for HCI_Number_of_Completed_Packets. This event is always + * consumed synchronously by bt_recv_prio() so a single buffer is enough. + * Having a dedicated pool for it ensures that exhaustion of the RX pool + * cannot block the delivery of this priority event. + */ +NET_BUF_POOL_DEFINE(num_complete_pool, 1, BT_BUF_RX_SIZE, + BT_BUF_USER_DATA_MIN, NULL); +#endif /* CONFIG_BT_CONN */ + struct event_handler { u8_t event; u8_t min_len; @@ -5662,6 +5672,31 @@ struct net_buf *bt_buf_get_cmd_complete(s32_t timeout) return bt_buf_get_rx(BT_BUF_EVT, timeout); } +struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout) +{ + switch (evt) { +#if defined(CONFIG_BT_CONN) + case BT_HCI_EVT_NUM_COMPLETED_PACKETS: + { + struct net_buf *buf; + + buf = net_buf_alloc(&num_complete_pool, timeout); + if (buf) { + net_buf_reserve(buf, CONFIG_BT_HCI_RESERVE); + bt_buf_set_type(buf, BT_BUF_EVT); + } + + return buf; + } +#endif /* CONFIG_BT_CONN */ + case BT_HCI_EVT_CMD_COMPLETE: + case BT_HCI_EVT_CMD_STATUS: + return bt_buf_get_cmd_complete(timeout); + default: + return bt_buf_get_rx(BT_BUF_EVT, timeout); + } +} + #if defined(CONFIG_BT_BREDR) static int br_start_inquiry(const struct bt_br_discovery_param *param) { diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index a907583ec111e..7d8ee3e82b4d2 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -84,7 +84,7 @@ static void send_cmd_status(u16_t opcode, u8_t status) BT_DBG("opcode %x status %x", opcode, status); - buf = bt_buf_get_cmd_complete(K_FOREVER); + buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, K_FOREVER); bt_buf_set_type(buf, BT_BUF_EVT); hdr = net_buf_add(buf, sizeof(*hdr)); diff --git a/subsys/bluetooth/host/hci_raw.c b/subsys/bluetooth/host/hci_raw.c index f81d4e8ed3a00..6694c766ebf13 100644 --- a/subsys/bluetooth/host/hci_raw.c +++ b/subsys/bluetooth/host/hci_raw.c @@ -72,6 +72,18 @@ struct net_buf *bt_buf_get_cmd_complete(s32_t timeout) return buf; } +struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout) +{ + struct net_buf *buf; + + buf = net_buf_alloc(&hci_rx_pool, timeout); + if (buf) { + bt_buf_set_type(buf, BT_BUF_EVT); + } + + return buf; +} + int bt_recv(struct net_buf *buf) { BT_DBG("buf %p len %u", buf, buf->len); diff --git a/tests/bluetooth/hci_prop_evt/src/main.c b/tests/bluetooth/hci_prop_evt/src/main.c index a455ef3073557..75a50bc4daaad 100644 --- a/tests/bluetooth/hci_prop_evt/src/main.c +++ b/tests/bluetooth/hci_prop_evt/src/main.c @@ -53,7 +53,7 @@ static void *cmd_complete(struct net_buf **buf, u8_t plen, u16_t opcode) { struct bt_hci_evt_cmd_complete *cc; - *buf = bt_buf_get_cmd_complete(K_FOREVER); + *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, K_FOREVER); evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen); cc = net_buf_add(*buf, sizeof(*cc)); cc->ncmd = 1U; From 3684c82b5ddde0d3aa25749229ec1043f17db5a7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 28 Jun 2019 12:09:36 +0300 Subject: [PATCH 2/2] Bluetooth: Introduce separate pool for discardable events Introduce a separate buffer pool for events which the HCI driver considers discardable. Examples of such events could be e.g. Advertising Reports. The benefit of having such a pool means that the if there is a heavy inflow of such events it will not cause the allocation for other critical events to block and may even eliminate deadlocks in some cases. Also update all mesh samples not to specify explicit RX buffer counts anymore. Instead, create appropriate defaults in Kconfig so that we only need to override this in the app for cases like the bbc:microbit with limited memory. Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci/h4.c | 2 +- drivers/bluetooth/hci/h5.c | 2 +- drivers/bluetooth/hci/ipm_stm32wb.c | 3 ++- drivers/bluetooth/hci/spi.c | 2 +- drivers/bluetooth/hci/userchan.c | 2 +- include/bluetooth/buf.h | 9 ++++---- include/bluetooth/hci.h | 1 + samples/bluetooth/mesh/prj.conf | 1 - samples/bluetooth/mesh/prj_bbc_microbit.conf | 2 ++ samples/bluetooth/mesh_demo/prj.conf | 1 - samples/boards/nrf52/mesh/onoff-app/prj.conf | 1 - .../onoff_level_lighting_vnd_app/prj.conf | 1 - samples/boards/reel_board/mesh_badge/prj.conf | 1 - subsys/bluetooth/controller/hci/hci.c | 4 ++-- subsys/bluetooth/controller/hci/hci_driver.c | 5 +++-- subsys/bluetooth/host/Kconfig | 15 +++++++++++++ subsys/bluetooth/host/hci_core.c | 21 ++++++++++++++++++- subsys/bluetooth/host/hci_ecc.c | 2 +- subsys/bluetooth/host/hci_raw.c | 2 +- tests/bluetooth/hci_prop_evt/src/main.c | 2 +- tests/bluetooth/mesh/dbg.conf | 1 - tests/bluetooth/mesh/friend.conf | 1 - tests/bluetooth/mesh/gatt.conf | 1 - tests/bluetooth/mesh/lpn.conf | 1 - tests/bluetooth/mesh/pb_gatt.conf | 1 - tests/bluetooth/mesh/prj.conf | 1 - tests/bluetooth/mesh/proxy.conf | 1 - tests/bluetooth/mesh_shell/prj.conf | 1 - tests/bluetooth/shell/mesh.conf | 1 - 29 files changed, 57 insertions(+), 31 deletions(-) diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index cb886846bfc78..ba584e33ea47c 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -162,7 +162,7 @@ static struct net_buf *get_rx(int timeout) BT_DBG("type 0x%02x, evt 0x%02x", rx.type, rx.evt.evt); if (rx.type == H4_EVT) { - return bt_buf_get_evt(rx.evt.evt, timeout); + return bt_buf_get_evt(rx.evt.evt, rx.discardable, timeout); } return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); diff --git a/drivers/bluetooth/hci/h5.c b/drivers/bluetooth/hci/h5.c index 52727f7ec6366..3633ef5b385b3 100644 --- a/drivers/bluetooth/hci/h5.c +++ b/drivers/bluetooth/hci/h5.c @@ -408,7 +408,7 @@ static inline struct net_buf *get_evt_buf(u8_t evt) { struct net_buf *buf; - buf = bt_buf_get_evt(evt, K_NO_WAIT); + buf = bt_buf_get_evt(evt, false, K_NO_WAIT); if (buf) { net_buf_add_u8(h5.rx_buf, evt); } diff --git a/drivers/bluetooth/hci/ipm_stm32wb.c b/drivers/bluetooth/hci/ipm_stm32wb.c index 9f2b95129f674..029ac5a5b449e 100644 --- a/drivers/bluetooth/hci/ipm_stm32wb.c +++ b/drivers/bluetooth/hci/ipm_stm32wb.c @@ -115,7 +115,8 @@ void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt) hcievt->evtserial.evt.evtcode); goto out; default: - buf = bt_buf_get_evt(evtserial.evt.evtcode, K_FOREVER); + buf = bt_buf_get_evt(evtserial.evt.evtcode, false, + K_FOREVER); break; } net_buf_add_mem(buf, &hcievt->evtserial.evt, diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index 5749c35541153..ba0724c69457d 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -355,7 +355,7 @@ static void bt_spi_rx_thread(void) continue; default: buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT], - K_FOREVER); + false, K_FOREVER); break; } diff --git a/drivers/bluetooth/hci/userchan.c b/drivers/bluetooth/hci/userchan.c index f2c8b3f14d115..b6142eea0a7d9 100644 --- a/drivers/bluetooth/hci/userchan.c +++ b/drivers/bluetooth/hci/userchan.c @@ -58,7 +58,7 @@ static int bt_dev_index = -1; static struct net_buf *get_rx(const u8_t *buf) { if (buf[0] == H4_EVT) { - return bt_buf_get_evt(buf[1], K_FOREVER); + return bt_buf_get_evt(buf[1], false, K_FOREVER); } return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); diff --git a/include/bluetooth/buf.h b/include/bluetooth/buf.h index 3110ba94ccc36..0cc138a472187 100644 --- a/include/bluetooth/buf.h +++ b/include/bluetooth/buf.h @@ -69,12 +69,13 @@ struct net_buf *bt_buf_get_cmd_complete(s32_t timeout); * This will set the buffer type so bt_buf_set_type() does not need to * be explicitly called before bt_recv_prio() or bt_recv(). * - * @param evt HCI event code - * @param timeout Timeout in milliseconds, or one of the special values - * K_NO_WAIT and K_FOREVER. + * @param evt HCI event code + * @param discardable Whether the driver considers the event discardable. + * @param timeout Timeout in milliseconds, or one of the special values + * K_NO_WAIT and K_FOREVER. * @return A new buffer. */ -struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout); +struct net_buf *bt_buf_get_evt(u8_t evt, bool discardable, s32_t timeout); /** Set the buffer type * diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index 82a591d951211..8c3683d3b5e01 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -1362,6 +1362,7 @@ struct bt_hci_cp_le_set_privacy_mode { /* Event definitions */ +#define BT_HCI_EVT_UNKNOWN 0x00 #define BT_HCI_EVT_VENDOR 0xff #define BT_HCI_EVT_INQUIRY_COMPLETE 0x01 diff --git a/samples/bluetooth/mesh/prj.conf b/samples/bluetooth/mesh/prj.conf index 8db2bae562e31..4db81eca0c47d 100644 --- a/samples/bluetooth/mesh/prj.conf +++ b/samples/bluetooth/mesh/prj.conf @@ -26,7 +26,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 CONFIG_BT_L2CAP_TX_BUF_COUNT=5 diff --git a/samples/bluetooth/mesh/prj_bbc_microbit.conf b/samples/bluetooth/mesh/prj_bbc_microbit.conf index f70891f7f0635..79755b5ab4c04 100644 --- a/samples/bluetooth/mesh/prj_bbc_microbit.conf +++ b/samples/bluetooth/mesh/prj_bbc_microbit.conf @@ -17,6 +17,8 @@ CONFIG_SETTINGS_FCB=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_RX_STACK_SIZE=1100 +CONFIG_BT_RX_BUF_COUNT=3 +CONFIG_BT_DISCARDABLE_BUF_COUNT=3 CONFIG_BT_CTLR_DUP_FILTER_LEN=0 CONFIG_BT_OBSERVER=y diff --git a/samples/bluetooth/mesh_demo/prj.conf b/samples/bluetooth/mesh_demo/prj.conf index 38336d3ba7458..9b8ac6712f71b 100644 --- a/samples/bluetooth/mesh_demo/prj.conf +++ b/samples/bluetooth/mesh_demo/prj.conf @@ -3,7 +3,6 @@ CONFIG_MAIN_STACK_SIZE=512 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_TINYCRYPT_ECC=y #CONFIG_BT_DEBUG_LOG=y CONFIG_BT_OBSERVER=y diff --git a/samples/boards/nrf52/mesh/onoff-app/prj.conf b/samples/boards/nrf52/mesh/onoff-app/prj.conf index 92c2b3af64644..63c32c8cedc24 100644 --- a/samples/boards/nrf52/mesh/onoff-app/prj.conf +++ b/samples/boards/nrf52/mesh/onoff-app/prj.conf @@ -31,7 +31,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 CONFIG_BT_L2CAP_TX_BUF_COUNT=8 diff --git a/samples/boards/nrf52/mesh/onoff_level_lighting_vnd_app/prj.conf b/samples/boards/nrf52/mesh/onoff_level_lighting_vnd_app/prj.conf index 86199fc2c952d..bcf24f764378f 100644 --- a/samples/boards/nrf52/mesh/onoff_level_lighting_vnd_app/prj.conf +++ b/samples/boards/nrf52/mesh/onoff_level_lighting_vnd_app/prj.conf @@ -26,7 +26,6 @@ CONFIG_BT_CTLR_TX_PWR_PLUS_8=y CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_RX_STACK_SIZE=4096 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/samples/boards/reel_board/mesh_badge/prj.conf b/samples/boards/reel_board/mesh_badge/prj.conf index c3c3d80740a3b..e9c1c6138aee4 100644 --- a/samples/boards/reel_board/mesh_badge/prj.conf +++ b/samples/boards/reel_board/mesh_badge/prj.conf @@ -19,7 +19,6 @@ CONFIG_BT_MESH_DEBUG=y CONFIG_BT_OBSERVER=y CONFIG_BT_BROADCASTER=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 CONFIG_BT_L2CAP_TX_BUF_COUNT=8 diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 1b99bd48f4d19..7326561a96937 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -120,7 +120,7 @@ void *hci_cmd_complete(struct net_buf **buf, u8_t plen) { struct bt_hci_evt_cmd_complete *cc; - *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, K_FOREVER); + *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, false, K_FOREVER); hci_evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen); @@ -137,7 +137,7 @@ static struct net_buf *cmd_status(u8_t status) struct bt_hci_evt_cmd_status *cs; struct net_buf *buf; - buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, K_FOREVER); + buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, false, K_FOREVER); hci_evt_create(buf, BT_HCI_EVT_CMD_STATUS, sizeof(*cs)); cs = net_buf_add(buf, sizeof(*cs)); diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 1229c4625b87e..30c906d87f380 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -91,7 +91,7 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) struct net_buf *buf; buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS, - K_FOREVER); + false, K_FOREVER); hci_num_cmplt_encode(buf, handle, num_cmplt); BT_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt); bt_recv_prio(buf); @@ -146,7 +146,8 @@ static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx, case HCI_CLASS_EVT_REQUIRED: case HCI_CLASS_EVT_CONNECTION: if (class == HCI_CLASS_EVT_DISCARDABLE) { - buf = bt_buf_get_rx(BT_BUF_EVT, K_NO_WAIT); + buf = bt_buf_get_evt(BT_HCI_EVT_UNKNOWN, true, + K_NO_WAIT); } else { buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); } diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 0d14e11a629b0..9b5884f18a700 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -26,6 +26,7 @@ config BT_HCI_CMD_COUNT config BT_RX_BUF_COUNT int "Number of HCI RX buffers" default 3 if BT_RECV_IS_RX_THREAD + default 20 if (BT_MESH && !BT_DISCARDABLE_BUF_COUNT) default 10 range 2 255 help @@ -47,6 +48,20 @@ config BT_RX_BUF_LEN an L2CAP MTU of 65 bytes. On top of this there's the L2CAP header (4 bytes) and the ACL header (also 4 bytes) which yields 73 bytes. +config BT_DISCARDABLE_BUF_COUNT + int "Number of discardable event buffers" + range 1 255 + default 20 if BT_MESH + default 3 + depends on BT_H4 || BT_CTLR + help + Number of buffers in a separate buffer pool for events which + the HCI driver considers discardable. Examples of such events + could be e.g. Advertising Reports. The benefit of having such + a pool means that the if there is a heavy inflow of such events + it will not cause the allocation for other critical events to + block and may even eliminate deadlocks in some cases. + config BT_HCI_TX_STACK_SIZE # NOTE: This value is derived from other symbols and should not be # user-configurable. Do not give it a prompt. diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index ba32c8970f5e2..325169dd2bffa 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -148,6 +148,11 @@ NET_BUF_POOL_DEFINE(num_complete_pool, 1, BT_BUF_RX_SIZE, BT_BUF_USER_DATA_MIN, NULL); #endif /* CONFIG_BT_CONN */ +#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) +NET_BUF_POOL_DEFINE(discardable_pool, CONFIG_BT_DISCARDABLE_BUF_COUNT, + BT_BUF_RX_SIZE, BT_BUF_USER_DATA_MIN, NULL); +#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ + struct event_handler { u8_t event; u8_t min_len; @@ -5672,7 +5677,7 @@ struct net_buf *bt_buf_get_cmd_complete(s32_t timeout) return bt_buf_get_rx(BT_BUF_EVT, timeout); } -struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout) +struct net_buf *bt_buf_get_evt(u8_t evt, bool discardable, s32_t timeout) { switch (evt) { #if defined(CONFIG_BT_CONN) @@ -5693,6 +5698,20 @@ struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout) case BT_HCI_EVT_CMD_STATUS: return bt_buf_get_cmd_complete(timeout); default: +#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) + if (discardable) { + struct net_buf *buf; + + buf = net_buf_alloc(&discardable_pool, timeout); + if (buf) { + net_buf_reserve(buf, CONFIG_BT_HCI_RESERVE); + bt_buf_set_type(buf, BT_BUF_EVT); + } + + return buf; + } +#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ + return bt_buf_get_rx(BT_BUF_EVT, timeout); } } diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 7d8ee3e82b4d2..2587f1ae240b1 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -84,7 +84,7 @@ static void send_cmd_status(u16_t opcode, u8_t status) BT_DBG("opcode %x status %x", opcode, status); - buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, K_FOREVER); + buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, false, K_FOREVER); bt_buf_set_type(buf, BT_BUF_EVT); hdr = net_buf_add(buf, sizeof(*hdr)); diff --git a/subsys/bluetooth/host/hci_raw.c b/subsys/bluetooth/host/hci_raw.c index 6694c766ebf13..dd3fb18f95c7e 100644 --- a/subsys/bluetooth/host/hci_raw.c +++ b/subsys/bluetooth/host/hci_raw.c @@ -72,7 +72,7 @@ struct net_buf *bt_buf_get_cmd_complete(s32_t timeout) return buf; } -struct net_buf *bt_buf_get_evt(u8_t evt, s32_t timeout) +struct net_buf *bt_buf_get_evt(u8_t evt, bool discardable, s32_t timeout) { struct net_buf *buf; diff --git a/tests/bluetooth/hci_prop_evt/src/main.c b/tests/bluetooth/hci_prop_evt/src/main.c index 75a50bc4daaad..e458d8b728d93 100644 --- a/tests/bluetooth/hci_prop_evt/src/main.c +++ b/tests/bluetooth/hci_prop_evt/src/main.c @@ -53,7 +53,7 @@ static void *cmd_complete(struct net_buf **buf, u8_t plen, u16_t opcode) { struct bt_hci_evt_cmd_complete *cc; - *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, K_FOREVER); + *buf = bt_buf_get_evt(BT_HCI_EVT_CMD_COMPLETE, false, K_FOREVER); evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen); cc = net_buf_add(*buf, sizeof(*cc)); cc->ncmd = 1U; diff --git a/tests/bluetooth/mesh/dbg.conf b/tests/bluetooth/mesh/dbg.conf index ecb4800203816..19f44173020c4 100644 --- a/tests/bluetooth/mesh/dbg.conf +++ b/tests/bluetooth/mesh/dbg.conf @@ -19,7 +19,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/mesh/friend.conf b/tests/bluetooth/mesh/friend.conf index 055a67d3ec5c3..da39b203b749c 100644 --- a/tests/bluetooth/mesh/friend.conf +++ b/tests/bluetooth/mesh/friend.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/gatt.conf b/tests/bluetooth/mesh/gatt.conf index aa4ad455c09ed..5120ff7a86a5f 100644 --- a/tests/bluetooth/mesh/gatt.conf +++ b/tests/bluetooth/mesh/gatt.conf @@ -19,7 +19,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/mesh/lpn.conf b/tests/bluetooth/mesh/lpn.conf index d2c45c18e7ff5..5fe4922be7ede 100644 --- a/tests/bluetooth/mesh/lpn.conf +++ b/tests/bluetooth/mesh/lpn.conf @@ -19,7 +19,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/mesh/pb_gatt.conf b/tests/bluetooth/mesh/pb_gatt.conf index 752cedf9458c9..bf15568d04b42 100644 --- a/tests/bluetooth/mesh/pb_gatt.conf +++ b/tests/bluetooth/mesh/pb_gatt.conf @@ -19,7 +19,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/mesh/prj.conf b/tests/bluetooth/mesh/prj.conf index 1a17dbc042c8c..9f2e77c7fd199 100644 --- a/tests/bluetooth/mesh/prj.conf +++ b/tests/bluetooth/mesh/prj.conf @@ -19,7 +19,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/mesh/proxy.conf b/tests/bluetooth/mesh/proxy.conf index 90765913e8a59..06992610af8e3 100644 --- a/tests/bluetooth/mesh/proxy.conf +++ b/tests/bluetooth/mesh/proxy.conf @@ -19,7 +19,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT=y CONFIG_BT_TINYCRYPT_ECC=y -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/mesh_shell/prj.conf b/tests/bluetooth/mesh_shell/prj.conf index 58e45cd0d1488..ea6aae1ec5bbe 100644 --- a/tests/bluetooth/mesh_shell/prj.conf +++ b/tests/bluetooth/mesh_shell/prj.conf @@ -34,7 +34,6 @@ CONFIG_BT_CTLR_MIN_USED_CHAN=n CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_CTLR_PRIVACY=n -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 CONFIG_BT_L2CAP_TX_BUF_COUNT=4 diff --git a/tests/bluetooth/shell/mesh.conf b/tests/bluetooth/shell/mesh.conf index 937d47f60dd99..723848040c24f 100644 --- a/tests/bluetooth/shell/mesh.conf +++ b/tests/bluetooth/shell/mesh.conf @@ -18,7 +18,6 @@ CONFIG_BT_SHELL=y CONFIG_BT_DEVICE_NAME="test shell" CONFIG_BT_L2CAP_TX_BUF_COUNT=6 -CONFIG_BT_RX_BUF_COUNT=30 CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69