Bluetooth: controller: updating TX node pre-alloc store mechanism

Instead of using the node ref used for TX ack for storing a TX node
pre-allocated in case of NTF RX node availability delay, introduce a
separate store to TX node. This to avoid misunderstanding on clean-up
in terminate flow.

Signed-off-by: Erik Brockhoff <erbr@oticon.com>
This commit is contained in:
Erik Brockhoff 2023-03-17 11:29:04 +01:00 committed by Carles Cufí
parent a53d89450a
commit eece00e4b0
5 changed files with 44 additions and 60 deletions

View File

@ -190,9 +190,9 @@ static void llcp_rp_cc_tx_reject(struct ll_conn *conn, struct proc_ctx *ctx, uin
struct pdu_data *pdu;
/* Allocate tx node */
tx = ctx->node_ref.tx_ack;
tx = ctx->node_ref.tx;
LL_ASSERT(tx);
ctx->node_ref.tx_ack = NULL;
ctx->node_ref.tx = NULL;
pdu = (struct pdu_data *)tx->pdu;
@ -252,7 +252,7 @@ static void rp_cc_send_reject_ind(struct ll_conn *conn, struct proc_ctx *ctx, ui
ctx->state = RP_CC_STATE_WAIT_TX_REJECT_IND;
} else {
/* Allocate TX node to use, store in case we need to wait for NTF node */
ctx->node_ref.tx_ack = llcp_tx_alloc(conn, ctx);
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
if (ctx->data.cis_create.error == BT_HCI_ERR_CONN_ACCEPT_TIMEOUT) {
/* We complete with error, so we must generate NTF, thus we must make sure
* we have a node to use for NTF before TX'ing

View File

@ -150,11 +150,6 @@ static void lp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx)
pdu = (struct pdu_data *)tx->pdu;
/* Clear tx_ack/rx node reference due to dual/union functionality
* rx node might be !=NULL and thus tx_ack !=NULL
*/
ctx->node_ref.tx_ack = NULL;
/* Encode LL Control PDU */
switch (ctx->proc) {
#if defined(CONFIG_BT_CTLR_LE_PING)
@ -1042,9 +1037,6 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx)
pdu = (struct pdu_data *)tx->pdu;
/* Clear tx_ack/rx node reference */
ctx->node_ref.tx_ack = NULL;
/* Encode LL Control PDU */
switch (ctx->proc) {
#if defined(CONFIG_BT_CTLR_LE_PING)
@ -1346,7 +1338,6 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u
/* Apply changes in data lengths/times */
uint8_t dle_changed = ull_dle_update_eff_tx(conn);
ctx->node_ref.tx_ack = NULL;
dle_changed |= ctx->data.dle.ntf_dle;
llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_DATA_LENGTH);
@ -1359,7 +1350,6 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
case PROC_CTE_REQ: {
/* add PHY update pause = false here */
ctx->node_ref.tx_ack = NULL;
llcp_rr_set_paused_cmd(conn, PROC_NONE);
llcp_rr_complete(conn);
ctx->state = RP_COMMON_STATE_IDLE;
@ -1367,7 +1357,6 @@ static void rp_comm_st_wait_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, u
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
case PROC_SCA_UPDATE: {
ctx->node_ref.tx_ack = NULL;
#if defined(CONFIG_BT_PERIPHERAL)
if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) {
conn->periph.sca = ctx->data.sca_update.sca;

View File

@ -277,9 +277,8 @@ static void lp_cu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode)
struct pdu_data *pdu;
/* Get pre-allocated tx node */
tx = ctx->node_ref.tx_ack;
/* Clear to not trigger tx-ack*/
ctx->node_ref.tx_ack = NULL;
tx = ctx->node_ref.tx;
ctx->node_ref.tx = NULL;
if (!tx) {
/* Allocate tx node if non pre-alloc'ed */
@ -426,7 +425,7 @@ static void lp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ct
ctx->state = LP_CU_STATE_WAIT_TX_CONN_UPDATE_IND;
} else {
/* ensure alloc of TX node, before possibly waiting for NTF node */
ctx->node_ref.tx_ack = llcp_tx_alloc(conn, ctx);
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
if (ctx->node_ref.rx == NULL && !llcp_ntf_alloc_is_available()) {
/* No RX node piggy, and no NTF avail, so go wait for one, before TX'ing */
ctx->state = LP_CU_STATE_WAIT_NTF_AVAIL;
@ -747,8 +746,8 @@ static void rp_cu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode)
struct pdu_data *pdu;
/* Get pre-allocated tx node */
tx = ctx->node_ref.tx_ack;
ctx->node_ref.tx_ack = NULL;
tx = ctx->node_ref.tx;
ctx->node_ref.tx = NULL;
if (!tx) {
/* Allocate tx node if non pre-alloc'ed */
@ -861,7 +860,7 @@ static void rp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ct
ctx->state = RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND;
} else {
/* ensure alloc of TX node, before possibly waiting for NTF node */
ctx->node_ref.tx_ack = llcp_tx_alloc(conn, ctx);
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
if (!llcp_ntf_alloc_is_available()) {
/* No RX node piggy, and no NTF avail, so go wait for one, before TX'ing */
ctx->state = RP_CU_STATE_WAIT_NTF_AVAIL;

View File

@ -163,6 +163,8 @@ struct proc_ctx {
struct node_tx *tx_ack;
/* most recent RX node */
struct node_rx_pdu *rx;
/* pre-allocated TX node */
struct node_tx *tx;
} node_ref;
/*
* This flag is set to 1 when we are finished with the control

View File

@ -377,13 +377,9 @@ static void lp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo
struct node_tx *tx;
struct pdu_data *pdu;
/* Allocate tx node, but only do it if not already done */
if (ctx->node_ref.tx_ack == NULL) {
ctx->node_ref.tx_ack = llcp_tx_alloc(conn, ctx);
LL_ASSERT(ctx->node_ref.tx_ack);
}
LL_ASSERT(ctx->node_ref.tx);
#if defined(CONFIG_BT_CENTRAL)
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
if (!((ctx->tx_opcode == PDU_DATA_LLCTRL_TYPE_PHY_REQ) &&
(conn->lll.role == BT_HCI_ROLE_CENTRAL))) {
if (!llcp_ntf_alloc_is_available()) {
@ -391,14 +387,14 @@ static void lp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo
ctx->state = LP_PU_STATE_WAIT_NTF_AVAIL;
return;
}
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
ctx->data.pu.ntf_dle_node = llcp_ntf_alloc();
LL_ASSERT(ctx->data.pu.ntf_dle_node);
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
}
#endif
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
tx = ctx->node_ref.tx_ack;
tx = ctx->node_ref.tx;
ctx->node_ref.tx = NULL;
ctx->node_ref.tx_ack = tx;
pdu = (struct pdu_data *)tx->pdu;
/* Encode LL Control PDU */
@ -526,12 +522,6 @@ static void lp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e
* Instead postpone completion/NTF to the beginning of RX handling
*/
ctx->state = LP_PU_STATE_WAIT_INSTANT_ON_AIR;
if (ctx->node_ref.rx) {
/* Mark RX node to NOT release */
llcp_rx_node_retain(ctx);
}
}
static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
@ -544,6 +534,9 @@ static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8
llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE);
llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ);
ctx->tx_opcode = PDU_DATA_LLCTRL_TYPE_PHY_REQ;
/* Allocate TX node */
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
lp_pu_tx(conn, ctx, evt, param);
}
}
@ -556,6 +549,9 @@ static void lp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx
ctx->state = LP_PU_STATE_WAIT_TX_PHY_UPDATE_IND;
} else {
ctx->tx_opcode = PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND;
/* Allocate TX node */
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
lp_pu_tx(conn, ctx, evt, param);
}
}
@ -749,28 +745,18 @@ static void lp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct
llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE);
break;
case LP_PU_EVT_REJECT:
llcp_rr_set_incompat(conn, INCOMPAT_NO_COLLISION);
llcp_pdu_decode_reject_ext_ind(ctx, (struct pdu_data *) param);
/* Mark RX node to NOT release */
llcp_rx_node_retain(ctx);
llcp_pdu_decode_reject_ext_ind(ctx, (struct pdu_data *)param);
ctx->data.pu.error = ctx->reject_ext_ind.error_code;
ctx->data.pu.ntf_pu = 1;
lp_pu_complete(conn, ctx, evt, param);
llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE);
break;
/* Fallthrough */
case LP_PU_EVT_UNKNOWN:
llcp_rr_set_incompat(conn, INCOMPAT_NO_COLLISION);
/* Unsupported in peer, so disable locally for this connection
* Peer does not accept PHY UPDATE, so disable non 1M phys on current connection
*/
feature_unmask_features(conn, LL_FEAT_BIT_PHY_2M | LL_FEAT_BIT_PHY_CODED);
if (evt == LP_PU_EVT_UNKNOWN) {
feature_unmask_features(conn, LL_FEAT_BIT_PHY_2M | LL_FEAT_BIT_PHY_CODED);
ctx->data.pu.error = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
}
/* Mark RX node to NOT release */
llcp_rx_node_retain(ctx);
ctx->data.pu.error = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
ctx->data.pu.ntf_pu = 1;
lp_pu_complete(conn, ctx, evt, param);
llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE);
@ -825,6 +811,7 @@ static void lp_pu_st_wait_instant_on_air(struct ll_conn *conn, struct proc_ctx *
}
}
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
static void lp_pu_st_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
@ -837,6 +824,7 @@ static void lp_pu_st_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx,
break;
}
}
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
static void lp_pu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{
@ -872,9 +860,11 @@ static void lp_pu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_
case LP_PU_STATE_WAIT_INSTANT_ON_AIR:
lp_pu_st_wait_instant_on_air(conn, ctx, evt, param);
break;
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
case LP_PU_STATE_WAIT_NTF_AVAIL:
lp_pu_st_wait_ntf_avail(conn, ctx, evt, param);
break;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
default:
/* Unknown state */
LL_ASSERT(0);
@ -945,25 +935,23 @@ static void rp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo
struct node_tx *tx;
struct pdu_data *pdu;
/* (pre)allocate tx node, but only do it if not already done */
if (ctx->node_ref.tx_ack == NULL) {
ctx->node_ref.tx_ack = llcp_tx_alloc(conn, ctx);
LL_ASSERT(ctx->node_ref.tx_ack);
}
LL_ASSERT(ctx->node_ref.tx);
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
if (!llcp_ntf_alloc_is_available()) {
/* No NTF nodes avail, so we need to hold off TX */
ctx->state = RP_PU_STATE_WAIT_NTF_AVAIL;
return;
}
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
ctx->data.pu.ntf_dle_node = llcp_ntf_alloc();
LL_ASSERT(ctx->data.pu.ntf_dle_node);
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
tx = ctx->node_ref.tx_ack;
tx = ctx->node_ref.tx;
ctx->node_ref.tx = NULL;
pdu = (struct pdu_data *)tx->pdu;
ctx->node_ref.tx_ack = tx;
/* Encode LL Control PDU */
switch (ctx->tx_opcode) {
@ -1032,6 +1020,7 @@ static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx
} else {
llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ);
ctx->tx_opcode = PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND;
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
rp_pu_tx(conn, ctx, evt, param);
}
@ -1047,6 +1036,7 @@ static void rp_pu_send_phy_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8
} else {
llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ);
ctx->tx_opcode = PDU_DATA_LLCTRL_TYPE_PHY_RSP;
ctx->node_ref.tx = llcp_tx_alloc(conn, ctx);
rp_pu_tx(conn, ctx, evt, param);
}
}
@ -1247,6 +1237,7 @@ static void rp_pu_st_wait_instant_on_air(struct ll_conn *conn, struct proc_ctx *
}
}
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
static void rp_pu_st_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
@ -1259,6 +1250,7 @@ static void rp_pu_st_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx,
break;
}
}
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
static void rp_pu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{
@ -1294,9 +1286,11 @@ static void rp_pu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_
case RP_PU_STATE_WAIT_INSTANT_ON_AIR:
rp_pu_st_wait_instant_on_air(conn, ctx, evt, param);
break;
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
case RP_PU_STATE_WAIT_NTF_AVAIL:
rp_pu_st_wait_ntf_avail(conn, ctx, evt, param);
break;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
default:
/* Unknown state */
LL_ASSERT(0);