Bluetooth: controller: refactor to remove duplicated functionality

Duplicated functionality used for tx handling is moved to local proxy
functions to avoid code overhead

Signed-off-by: Erik Brockhoff <erbr@oticon.com>
This commit is contained in:
Erik Brockhoff 2022-11-16 13:54:49 +01:00 committed by Carles Cufí
commit 7c9d792211
2 changed files with 67 additions and 103 deletions

View file

@ -293,6 +293,7 @@ static struct proc_ctx *create_procedure(enum llcp_proc proc, struct llcp_mem_po
ctx->collision = 0U; ctx->collision = 0U;
ctx->done = 0U; ctx->done = 0U;
ctx->rx_greedy = 0U; ctx->rx_greedy = 0U;
ctx->tx_ack = NULL;
/* Clear procedure data */ /* Clear procedure data */
memset((void *)&ctx->data, 0, sizeof(ctx->data)); memset((void *)&ctx->data, 0, sizeof(ctx->data));

View file

@ -424,6 +424,23 @@ static void lp_comm_terminate_invalid_pdu(struct ll_conn *conn, struct proc_ctx
ctx->state = LP_COMMON_STATE_IDLE; ctx->state = LP_COMMON_STATE_IDLE;
} }
static void lp_comm_ntf_complete_proxy(struct ll_conn *conn, struct proc_ctx *ctx,
const bool valid_pdu)
{
if (valid_pdu) {
if (!llcp_ntf_alloc_is_available()) {
ctx->state = LP_COMMON_STATE_WAIT_NTF;
} else {
lp_comm_ntf(conn, ctx);
llcp_lr_complete(conn);
ctx->state = LP_COMMON_STATE_IDLE;
}
} else {
/* Illegal response opcode */
lp_comm_terminate_invalid_pdu(conn, ctx);
}
}
static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{ {
switch (ctx->proc) { switch (ctx->proc) {
@ -440,19 +457,9 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
break; break;
#endif /* CONFIG_BT_CTLR_LE_PING */ #endif /* CONFIG_BT_CTLR_LE_PING */
case PROC_FEATURE_EXCHANGE: case PROC_FEATURE_EXCHANGE:
if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP || lp_comm_ntf_complete_proxy(conn, ctx,
ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_FEATURE_RSP) { (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP ||
if (!llcp_ntf_alloc_is_available()) { ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_FEATURE_RSP));
ctx->state = LP_COMMON_STATE_WAIT_NTF;
} else {
lp_comm_ntf(conn, ctx);
llcp_lr_complete(conn);
ctx->state = LP_COMMON_STATE_IDLE;
}
} else {
/* Illegal response opcode */
lp_comm_terminate_invalid_pdu(conn, ctx);
}
break; break;
#if defined(CONFIG_BT_CTLR_MIN_USED_CHAN) && defined(CONFIG_BT_PERIPHERAL) #if defined(CONFIG_BT_CTLR_MIN_USED_CHAN) && defined(CONFIG_BT_PERIPHERAL)
case PROC_MIN_USED_CHANS: case PROC_MIN_USED_CHANS:
@ -461,18 +468,8 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
break; break;
#endif /* CONFIG_BT_CTLR_MIN_USED_CHAN && CONFIG_BT_PERIPHERAL */ #endif /* CONFIG_BT_CTLR_MIN_USED_CHAN && CONFIG_BT_PERIPHERAL */
case PROC_VERSION_EXCHANGE: case PROC_VERSION_EXCHANGE:
if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_VERSION_IND) { lp_comm_ntf_complete_proxy(conn, ctx,
if (!llcp_ntf_alloc_is_available()) { (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_VERSION_IND));
ctx->state = LP_COMMON_STATE_WAIT_NTF;
} else {
lp_comm_ntf(conn, ctx);
llcp_lr_complete(conn);
ctx->state = LP_COMMON_STATE_IDLE;
}
} else {
/* Illegal response opcode */
lp_comm_terminate_invalid_pdu(conn, ctx);
}
break; break;
case PROC_TERMINATE: case PROC_TERMINATE:
/* No notification */ /* No notification */
@ -577,36 +574,36 @@ static bool lp_cis_terminated(struct ll_conn *conn)
} }
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */ #endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
static bool lp_comm_tx_proxy(struct ll_conn *conn, struct proc_ctx *ctx, const bool extra_cond)
{
if (extra_cond || llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
/* Select correct state, depending on TX ack handling 'request' */
ctx->state = ctx->tx_ack ? LP_COMMON_STATE_WAIT_TX_ACK : LP_COMMON_STATE_WAIT_RX;
return true;
}
return false;
}
static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{ {
switch (ctx->proc) { switch (ctx->proc) {
#if defined(CONFIG_BT_CTLR_LE_PING) #if defined(CONFIG_BT_CTLR_LE_PING)
case PROC_LE_PING: case PROC_LE_PING:
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { lp_comm_tx_proxy(conn, ctx, false);
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
ctx->state = LP_COMMON_STATE_WAIT_RX;
}
break; break;
#endif /* CONFIG_BT_CTLR_LE_PING */ #endif /* CONFIG_BT_CTLR_LE_PING */
case PROC_FEATURE_EXCHANGE: case PROC_FEATURE_EXCHANGE:
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (lp_comm_tx_proxy(conn, ctx, false)) {
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
conn->llcp.fex.sent = 1; conn->llcp.fex.sent = 1;
ctx->state = LP_COMMON_STATE_WAIT_RX;
} }
break; break;
#if defined(CONFIG_BT_CTLR_MIN_USED_CHAN) && defined(CONFIG_BT_PERIPHERAL) #if defined(CONFIG_BT_CTLR_MIN_USED_CHAN) && defined(CONFIG_BT_PERIPHERAL)
case PROC_MIN_USED_CHANS: case PROC_MIN_USED_CHANS:
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { lp_comm_tx_proxy(conn, ctx, false);
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
ctx->state = LP_COMMON_STATE_WAIT_TX_ACK;
}
break; break;
#endif /* CONFIG_BT_CTLR_MIN_USED_CHAN && CONFIG_BT_PERIPHERAL */ #endif /* CONFIG_BT_CTLR_MIN_USED_CHAN && CONFIG_BT_PERIPHERAL */
case PROC_VERSION_EXCHANGE: case PROC_VERSION_EXCHANGE:
@ -614,12 +611,8 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
* one LL_VERSION_IND PDU during a connection. * one LL_VERSION_IND PDU during a connection.
*/ */
if (!conn->llcp.vex.sent) { if (!conn->llcp.vex.sent) {
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (lp_comm_tx_proxy(conn, ctx, false)) {
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
conn->llcp.vex.sent = 1; conn->llcp.vex.sent = 1;
ctx->state = LP_COMMON_STATE_WAIT_RX;
} }
} else { } else {
ctx->response_opcode = PDU_DATA_LLCTRL_TYPE_VERSION_IND; ctx->response_opcode = PDU_DATA_LLCTRL_TYPE_VERSION_IND;
@ -637,13 +630,7 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
break; break;
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case PROC_CIS_TERMINATE: case PROC_CIS_TERMINATE:
if (!lp_cis_terminated(conn) || llcp_lr_ispaused(conn) || lp_comm_tx_proxy(conn, ctx, !lp_cis_terminated(conn));
!llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
ctx->state = LP_COMMON_STATE_WAIT_TX_ACK;
}
break; break;
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */ #endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_CTLR_DATA_LENGTH) #if defined(CONFIG_BT_CTLR_DATA_LENGTH)
@ -678,13 +665,8 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
#else #else
1) { 1) {
#endif /* CONFIG_BT_CTLR_PHY */ #endif /* CONFIG_BT_CTLR_PHY */
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx) || lp_comm_tx_proxy(conn, ctx,
(llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ)) { (llcp_rr_get_paused_cmd(conn) == PROC_CTE_REQ));
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
ctx->state = LP_COMMON_STATE_WAIT_RX;
}
} else { } else {
/* The PHY was changed to CODED when the request was waiting in a local /* The PHY was changed to CODED when the request was waiting in a local
* request queue. * request queue.
@ -702,12 +684,7 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */ #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
#if defined(CONFIG_BT_CTLR_SCA_UPDATE) #if defined(CONFIG_BT_CTLR_SCA_UPDATE)
case PROC_SCA_UPDATE: case PROC_SCA_UPDATE:
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { lp_comm_tx_proxy(conn, ctx, false);
ctx->state = LP_COMMON_STATE_WAIT_TX;
} else {
lp_comm_tx(conn, ctx);
ctx->state = LP_COMMON_STATE_WAIT_RX;
}
break; break;
#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ #endif /* CONFIG_BT_CTLR_SCA_UPDATE */
default: default:
@ -1190,30 +1167,36 @@ static void rp_comm_ntf(struct ll_conn *conn, struct proc_ctx *ctx)
} }
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH */
static bool rp_comm_tx_proxy(struct ll_conn *conn, struct proc_ctx *ctx, const bool complete)
{
if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_COMMON_STATE_WAIT_TX;
return false;
}
rp_comm_tx(conn, ctx);
ctx->state = RP_COMMON_STATE_WAIT_TX_ACK;
if (complete) {
llcp_rr_complete(conn);
ctx->state = RP_COMMON_STATE_IDLE;
}
return true;
}
static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{ {
switch (ctx->proc) { switch (ctx->proc) {
#if defined(CONFIG_BT_CTLR_LE_PING) #if defined(CONFIG_BT_CTLR_LE_PING)
case PROC_LE_PING: case PROC_LE_PING:
/* Always respond on remote ping */ /* Always respond on remote ping */
if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { rp_comm_tx_proxy(conn, ctx, true);
ctx->state = RP_COMMON_STATE_WAIT_TX;
} else {
rp_comm_tx(conn, ctx);
llcp_rr_complete(conn);
ctx->state = RP_COMMON_STATE_IDLE;
}
break; break;
#endif /* CONFIG_BT_CTLR_LE_PING */ #endif /* CONFIG_BT_CTLR_LE_PING */
case PROC_FEATURE_EXCHANGE: case PROC_FEATURE_EXCHANGE:
/* Always respond on remote feature exchange */ /* Always respond on remote feature exchange */
if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (rp_comm_tx_proxy(conn, ctx, true)) {
ctx->state = RP_COMMON_STATE_WAIT_TX;
} else {
rp_comm_tx(conn, ctx);
conn->llcp.fex.sent = 1; conn->llcp.fex.sent = 1;
llcp_rr_complete(conn);
ctx->state = RP_COMMON_STATE_IDLE;
} }
break; break;
case PROC_VERSION_EXCHANGE: case PROC_VERSION_EXCHANGE:
@ -1224,13 +1207,8 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
* LL_VERSION_IND PDU to the peer device. * LL_VERSION_IND PDU to the peer device.
*/ */
if (!conn->llcp.vex.sent) { if (!conn->llcp.vex.sent) {
if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (rp_comm_tx_proxy(conn, ctx, true)) {
ctx->state = RP_COMMON_STATE_WAIT_TX;
} else {
rp_comm_tx(conn, ctx);
conn->llcp.vex.sent = 1; conn->llcp.vex.sent = 1;
llcp_rr_complete(conn);
ctx->state = RP_COMMON_STATE_IDLE;
} }
} else { } else {
/* Invalid behaviour /* Invalid behaviour
@ -1297,15 +1275,7 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */ #endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_CTLR_DATA_LENGTH) #if defined(CONFIG_BT_CTLR_DATA_LENGTH)
case PROC_DATA_LENGTH_UPDATE: case PROC_DATA_LENGTH_UPDATE:
if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { rp_comm_tx_proxy(conn, ctx, false);
ctx->state = RP_COMMON_STATE_WAIT_TX;
} else {
/* On RSP tx close the window for possible local req piggy-back */
rp_comm_tx(conn, ctx);
/* Wait for the peer to have ack'ed the RSP before updating DLE */
ctx->state = RP_COMMON_STATE_WAIT_TX_ACK;
}
break; break;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
@ -1323,14 +1293,7 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
#if defined(CONFIG_BT_CTLR_SCA_UPDATE) #if defined(CONFIG_BT_CTLR_SCA_UPDATE)
case PROC_SCA_UPDATE: case PROC_SCA_UPDATE:
/* Always respond to remote SCA */ /* Always respond to remote SCA */
if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { rp_comm_tx_proxy(conn, ctx, false);
ctx->state = RP_COMMON_STATE_WAIT_TX;
} else {
rp_comm_tx(conn, ctx);
/* Wait for the peer to have ack'ed the RSP before completing */
ctx->state = RP_COMMON_STATE_WAIT_TX_ACK;
}
break; break;
#endif /* CONFIG_BT_CTLR_SCA_UPDATE */ #endif /* CONFIG_BT_CTLR_SCA_UPDATE */
default: default: