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:
parent
a53d89450a
commit
eece00e4b0
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user