Bluetooth: controller: split: Fix advertising for multiple peripherals
When multiple simultaneous peripheral connections are supported, restarting connectable advertising by host on peripheral connection establishment failed in controller. This prevented establishing new connections while first connection was active. The failure was caused by a bug in the way controller was using quota for Rx PDU buffers. As the quota count was release before the connection complete event rx PDU buffer being released, the Rx PDUs needed to reserve for connection complete event for new connectable advertising was not available. This caused the connectable advertising enable to fail. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
5dff214d57
commit
9d6c170e22
1 changed files with 70 additions and 106 deletions
|
@ -479,10 +479,6 @@ void ll_rx_dequeue(void)
|
|||
struct node_rx_hdr *rx = NULL;
|
||||
memq_link_t *link;
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
struct node_rx_cc *cc = NULL;
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
link = memq_dequeue(memq_ll_rx.tail, &memq_ll_rx.head,
|
||||
(void **)&rx);
|
||||
LL_ASSERT(link);
|
||||
|
@ -491,24 +487,73 @@ void ll_rx_dequeue(void)
|
|||
|
||||
/* handle object specific clean up */
|
||||
switch (rx->type) {
|
||||
#if defined(CONFIG_BT_OBSERVER) || \
|
||||
defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) || \
|
||||
defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
|
||||
defined(CONFIG_BT_CTLR_ADV_INDICATION) || \
|
||||
defined(CONFIG_BT_CTLR_SCAN_INDICATION) || \
|
||||
defined(CONFIG_BT_CTLR_USER_EXT) || \
|
||||
defined(CONFIG_BT_CONN)
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
/* fallthrough */
|
||||
case NODE_RX_TYPE_CONNECTION:
|
||||
{
|
||||
cc = (void *)((struct node_rx_pdu *)rx)->pdu;
|
||||
if (cc->status) {
|
||||
break;
|
||||
struct node_rx_cc *cc = (void *)((struct node_rx_pdu *)rx)->pdu;
|
||||
struct node_rx_ftr *ftr = &(rx->rx_ftr);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
((cc->status == BT_HCI_ERR_ADV_TIMEOUT) || cc->role)) {
|
||||
struct lll_adv *lll = ftr->param;
|
||||
struct ll_adv_set *adv = (void *)HDR_LLL2EVT(lll);
|
||||
|
||||
if (cc->status == BT_HCI_ERR_ADV_TIMEOUT) {
|
||||
struct lll_conn *conn_lll;
|
||||
struct ll_conn *conn;
|
||||
memq_link_t *link;
|
||||
|
||||
conn_lll = lll->conn;
|
||||
LL_ASSERT(conn_lll);
|
||||
|
||||
LL_ASSERT(!conn_lll->link_tx_free);
|
||||
link = memq_deinit(&conn_lll->memq_tx.head,
|
||||
&conn_lll->memq_tx.tail);
|
||||
LL_ASSERT(link);
|
||||
conn_lll->link_tx_free = link;
|
||||
|
||||
conn = (void *)HDR_LLL2EVT(conn_lll);
|
||||
ll_conn_release(conn);
|
||||
|
||||
lll->conn = NULL;
|
||||
} else {
|
||||
/* Release un-utilized node rx */
|
||||
if (adv->node_rx_cc_free) {
|
||||
void *rx_free;
|
||||
|
||||
rx_free = adv->node_rx_cc_free;
|
||||
adv->node_rx_cc_free = NULL;
|
||||
|
||||
ll_rx_release(rx_free);
|
||||
}
|
||||
}
|
||||
|
||||
adv->is_enabled = 0U;
|
||||
} else if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
|
||||
struct lll_scan *lll = ftr->param;
|
||||
struct ll_scan_set *scan = (void *)HDR_LLL2EVT(lll);
|
||||
|
||||
scan->is_enabled = 0U;
|
||||
} else {
|
||||
LL_ASSERT(0);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) {
|
||||
u8_t bm;
|
||||
|
||||
bm = (IS_ENABLED(CONFIG_BT_OBSERVER) &&
|
||||
ull_scan_is_enabled(0) << 1) |
|
||||
(IS_ENABLED(CONFIG_BT_BROADCASTER) &&
|
||||
ull_adv_is_enabled(0));
|
||||
|
||||
if (!bm) {
|
||||
ull_filter_adv_scan_state_cb(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_RX_TYPE_TERMINATE:
|
||||
case NODE_RX_TYPE_DC_PDU:
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
|
@ -545,7 +590,6 @@ void ll_rx_dequeue(void)
|
|||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
|
||||
/* fallthrough */
|
||||
case NODE_RX_TYPE_PROFILE:
|
||||
#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
|
||||
|
||||
|
@ -565,104 +609,23 @@ void ll_rx_dequeue(void)
|
|||
#if defined(CONFIG_BT_CTLR_USER_EXT)
|
||||
case NODE_RX_TYPE_USER_START ... NODE_RX_TYPE_USER_END:
|
||||
#endif /* CONFIG_BT_CTLR_USER_EXT */
|
||||
/*
|
||||
* We have just dequeued from memq_ll_rx; that frees up some
|
||||
* quota for Link Layer. Note that we threw away the rx node
|
||||
* we have just dequeued from memq_ll_rx. But, this is OK,
|
||||
* since prio_recv_thread() peeked in memq_ll_rx via
|
||||
* ll_rx_get() before.
|
||||
*/
|
||||
ll_rx_link_inc_quota(1);
|
||||
break;
|
||||
#endif /* CONFIG_BT_OBSERVER ||
|
||||
* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY ||
|
||||
* CONFIG_BT_CTLR_PROFILE_ISR ||
|
||||
* CONFIG_BT_CTLR_ADV_INDICATION ||
|
||||
* CONFIG_BT_CTLR_SCAN_INDICATION ||
|
||||
* CONFIG_BT_CTLR_USER_EXT ||
|
||||
* CONFIG_BT_CONN
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
/* fallthrough */
|
||||
case NODE_RX_TYPE_TERMINATE:
|
||||
/* Did not use data link quota */
|
||||
/* fall through */
|
||||
|
||||
/* Ensure that at least one 'case' statement is present for this
|
||||
* code block.
|
||||
*/
|
||||
case NODE_RX_TYPE_NONE:
|
||||
LL_ASSERT(rx->type != NODE_RX_TYPE_NONE);
|
||||
break;
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: clean up when porting Mesh Ext. */
|
||||
if (0) {
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
} else if (rx->type == NODE_RX_TYPE_CONNECTION) {
|
||||
struct node_rx_ftr *ftr;
|
||||
|
||||
ftr = &(rx->rx_ftr);
|
||||
|
||||
if (0) {
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
} else if ((cc->status == 0x3c) || cc->role) {
|
||||
struct lll_adv *lll = ftr->param;
|
||||
struct ll_adv_set *adv = (void *)HDR_LLL2EVT(lll);
|
||||
|
||||
if (cc->status == 0x3c) {
|
||||
struct lll_conn *conn_lll;
|
||||
struct ll_conn *conn;
|
||||
memq_link_t *link;
|
||||
|
||||
conn_lll = lll->conn;
|
||||
LL_ASSERT(conn_lll);
|
||||
|
||||
LL_ASSERT(!conn_lll->link_tx_free);
|
||||
link = memq_deinit(&conn_lll->memq_tx.head,
|
||||
&conn_lll->memq_tx.tail);
|
||||
LL_ASSERT(link);
|
||||
conn_lll->link_tx_free = link;
|
||||
|
||||
conn = (void *)HDR_LLL2EVT(conn_lll);
|
||||
ll_conn_release(conn);
|
||||
|
||||
lll->conn = NULL;
|
||||
} else {
|
||||
/* Release un-utilized node rx */
|
||||
if (adv->node_rx_cc_free) {
|
||||
void *rx_free;
|
||||
|
||||
rx_free = adv->node_rx_cc_free;
|
||||
adv->node_rx_cc_free = NULL;
|
||||
|
||||
ll_rx_release(rx_free);
|
||||
}
|
||||
}
|
||||
|
||||
adv->is_enabled = 0U;
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
#if defined(CONFIG_BT_CENTRAL)
|
||||
} else {
|
||||
struct lll_scan *lll = ftr->param;
|
||||
struct ll_scan_set *scan = (void *)HDR_LLL2EVT(lll);
|
||||
|
||||
scan->is_enabled = 0U;
|
||||
#endif /* CONFIG_BT_CENTRAL */
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) {
|
||||
u8_t bm;
|
||||
|
||||
bm = (IS_ENABLED(CONFIG_BT_OBSERVER) &&
|
||||
ull_scan_is_enabled(0) << 1) |
|
||||
(IS_ENABLED(CONFIG_BT_BROADCASTER) &&
|
||||
ull_adv_is_enabled(0));
|
||||
|
||||
if (!bm) {
|
||||
ull_filter_adv_scan_state_cb(0);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
#if defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
} else if (rx->type == NODE_RX_TYPE_MESH_ADV_CPLT) {
|
||||
struct ll_adv_set *adv;
|
||||
|
@ -800,6 +763,7 @@ void ll_rx_mem_release(void **node_rx)
|
|||
*/
|
||||
case NODE_RX_TYPE_NONE:
|
||||
LL_ASSERT(rx_free->type != NODE_RX_TYPE_NONE);
|
||||
ll_rx_link_inc_quota(1);
|
||||
mem_release(rx_free, &mem_pdu_rx.free);
|
||||
break;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue