Skip to content

Commit 65ec7b7

Browse files
committed
Bluetooth: Host: Fix redundant ACL Rx buffer allocation
HCI ACL Rx buffer count is not required in addition, the calculated BT_BUF_ACL_RX_COUNT is sufficient for L2CAP recombination. But it is required to have additional Rx buffers for the HCI ACL Rx that can happen due to the generated HCI Host Number of Completed packets events. Fixes commit d382fca ("Bluetooth: Controller: Fix HCI command buffer allocation failure"). Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
1 parent 77aff10 commit 65ec7b7

File tree

3 files changed

+48
-14
lines changed

3 files changed

+48
-14
lines changed

include/zephyr/bluetooth/buf.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,20 @@ static inline enum bt_buf_type bt_buf_type_from_h4(uint8_t h4_type, enum bt_buf_
151151
* re-assembly into, and if all links are re-assembling, there will be no buffer
152152
* available for the HCI driver to allocate from.
153153
*/
154-
#define BT_BUF_ACL_RX_COUNT_EXTRA CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA
155-
#define BT_BUF_ACL_RX_COUNT (1 + BT_BUF_ACL_RX_COUNT_EXTRA)
154+
#define BT_BUF_ACL_RX_COUNT_RESERVED 1
155+
156+
/* Host will block unreferencing one Rx buffer per active ACL connection and generate HCI Host
157+
* Number of Completed packets for the rest. This means new HCI data packets will be generated by
158+
* the Controller minus the minimum number of Rx buffer count blocked unreferencing in the Host.
159+
*/
160+
#define BT_BUF_ACL_RX_COUNT_BLOCKED_MIN 1
161+
#define BT_BUF_ACL_RX_COUNT_BLOCKED_MAX CONFIG_BT_MAX_CONN
162+
163+
/* To avoid deadlock, account for maximum Rx buffers blocked in the Host */
164+
#define BT_BUF_ACL_RX_COUNT_EXTRA MAX(BT_BUF_ACL_RX_COUNT_BLOCKED_MAX, \
165+
CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA)
166+
/* ACL Rx Buffers being processed by the Host */
167+
#define BT_BUF_ACL_RX_COUNT (BT_BUF_ACL_RX_COUNT_RESERVED + BT_BUF_ACL_RX_COUNT_EXTRA)
156168
#else
157169
#define BT_BUF_ACL_RX_COUNT_EXTRA 0
158170
#define BT_BUF_ACL_RX_COUNT 0
@@ -171,9 +183,18 @@ BUILD_ASSERT(BT_BUF_ACL_RX_COUNT <= BT_BUF_ACL_RX_COUNT_MAX,
171183
BUILD_ASSERT(CONFIG_BT_BUF_EVT_RX_COUNT > CONFIG_BT_BUF_ACL_TX_COUNT,
172184
"Increase Event RX buffer count to be greater than ACL TX buffer count");
173185

186+
#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
187+
/* TODO: Introduce CONFIG_BT_BUF_HCI_ACL_RX_COUNT replace BT_BUF_HCI_ACL_RX_COUNT. For now,
188+
* hard-coded 2. We do not want the use of CONFIG_BT_BUF_EVT_RX_COUNT in the derivation of
189+
* BT_BUF_HCI_ACL_RX_COUNT.
190+
*/
191+
#define BT_BUF_RX_COUNT (2U + BT_BUF_ACL_RX_COUNT)
192+
193+
#else /* !CONFIG_BT_HCI_ACL_FLOW_CONTROL */
174194
/** Buffer count needed for HCI ACL or HCI ISO plus Event RX buffers */
175195
#define BT_BUF_RX_COUNT (CONFIG_BT_BUF_EVT_RX_COUNT + \
176196
MAX(BT_BUF_ACL_RX_COUNT, BT_BUF_ISO_RX_COUNT))
197+
#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
177198

178199
/** Data size needed for HCI Command buffers. */
179200
#define BT_BUF_CMD_TX_SIZE BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE)

subsys/bluetooth/common/hci_common_internal.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,13 @@ BUILD_ASSERT((CONFIG_BT_BUF_CMD_TX_COUNT == CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX),
4141
*
4242
* Host keeps the first, and subsequent, Rx buffers (that comes from the driver) for each connection
4343
* to do re-assembly into, up to the L2CAP SDU length required number of Rx buffers.
44-
* BT_BUF_ACL_RX_COUNT_EXTRA holds the application configured number of buffers across active
45-
* connections for recombination of HCI data packets to L2CAP SDUs.
46-
*
47-
* BT_BUF_HCI_EVT_RX_COUNT defines the number of available buffers reserved for "synchronous"
48-
* processing of HCI events like Number of Completed Packets, disconnection complete etc.
44+
* BT_BUF_ACL_RX_COUNT_BLOCKED_MAX represents the maximum number of buffers that can be blocked
45+
* across active connections for recombination of HCI data packets to L2CAP SDUs.
4946
*
5047
* BT_BUF_HCI_ACL_RX_COUNT defines the number of available buffers for Controller to Host data
5148
* flow control; keeping the application configured BT_BUF_ACL_RX_COUNT_EXTRA number of buffers
52-
* available for L2CAP recombination, and a reserved number of buffers for processing HCI events.
49+
* available for L2CAP recombination, and BT_BUF_ACL_RX_COUNT_RESERVED reserved number of buffers
50+
* for processing incoming HCI data packets.
5351
*/
5452

5553
/* FIXME: Calculate the maximum number of HCI events of different types that a connection can
@@ -67,12 +65,23 @@ BUILD_ASSERT((CONFIG_BT_BUF_CMD_TX_COUNT == CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX),
6765
* control to restrict buffers required on resource constraint devices, i.e. if these events are not
6866
* processed "synchronous".
6967
*/
70-
#define BT_BUF_HCI_EVT_RX_COUNT 1
71-
#define BT_BUF_HCI_ACL_RX_COUNT (BT_BUF_RX_COUNT - BT_BUF_HCI_EVT_RX_COUNT - \
72-
BT_BUF_ACL_RX_COUNT_EXTRA)
68+
#define BT_BUF_HCI_ACL_RX_COUNT (BT_BUF_RX_COUNT - BT_BUF_ACL_RX_COUNT_EXTRA)
69+
70+
/* During L2CAP recombination, maximum one Rx buffer per each active ACL connection can be held or
71+
* blocked unreferencing in the Host, i.e. BT_BUF_ACL_RX_COUNT_BLOCKED_MAX.
72+
*
73+
* But at the instant of generating Host Number of Completed packets events a minimum of one Rx
74+
* buffer is still blocked unreferencing, i.e. BT_BUF_ACL_RX_COUNT_BLOCKED_MIN.
75+
*
76+
* BT_BUF_HCI_ACL_RX_COUNT_EXTRA defines the outstanding number of HCI ACL data packets that the
77+
* Controller can generated.
78+
*/
79+
#define BT_BUF_HCI_ACL_RX_COUNT_EXTRA (BT_BUF_HCI_ACL_RX_COUNT - BT_BUF_ACL_RX_COUNT_RESERVED - \
80+
BT_BUF_ACL_RX_COUNT_BLOCKED_MIN)
7381
#define BT_BUF_CMD_TX_HOST_NUM_CMPLT_PKT (BT_BUF_HCI_ACL_RX_COUNT)
7482

7583
#else /* !CONFIG_BT_HCI_ACL_FLOW_CONTROL */
84+
#define BT_BUF_HCI_ACL_RX_COUNT_EXTRA 0
7685
#define BT_BUF_CMD_TX_HOST_NUM_CMPLT_PKT 0
7786
#endif /* !CONFIG_BT_HCI_ACL_FLOW_CONTROL */
7887

subsys/bluetooth/host/buf.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,13 @@ static void evt_pool_destroy(struct net_buf *buf)
8383
buf_rx_freed_notify(BT_BUF_EVT);
8484
}
8585

86-
NET_BUF_POOL_DEFINE(acl_in_pool, (BT_BUF_ACL_RX_COUNT_EXTRA + BT_BUF_HCI_ACL_RX_COUNT),
87-
BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), sizeof(struct bt_conn_rx),
88-
acl_in_pool_destroy);
86+
/* Allocate Rx buffer count sufficient to block unreferencing one Rx buffer per active ACL
87+
* connection, and additional HCI ACL data packets that the Controller can generate for the
88+
* Host Number of Completed data packets count that the Host has given back to the Controller.
89+
*/
90+
NET_BUF_POOL_DEFINE(acl_in_pool, (BT_BUF_ACL_RX_COUNT_EXTRA + BT_BUF_HCI_ACL_RX_COUNT_EXTRA),
91+
BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE),
92+
sizeof(struct bt_conn_rx), acl_in_pool_destroy);
8993

9094
NET_BUF_POOL_FIXED_DEFINE(evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, BT_BUF_EVT_RX_SIZE, 0,
9195
evt_pool_destroy);

0 commit comments

Comments
 (0)