Bluetooth: Controller: legacy: Fix conn upd instant passed on data tx
Fix legacy control procedure implementation to avoid connection update procedure with reason instant passed (0x28). Connection Update Indication PDU is enqueued after data enqueue to LLL context is paused and the enqueue resumes when already enqueued data PDUs are all acknowledged. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
807ad96e21
commit
5e848761c5
4 changed files with 35 additions and 0 deletions
|
@ -1121,6 +1121,7 @@ uint8_t ll_adv_enable(uint8_t enable)
|
||||||
conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0;
|
conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0;
|
||||||
conn->llcp_rx = NULL;
|
conn->llcp_rx = NULL;
|
||||||
conn->llcp_cu.req = conn->llcp_cu.ack = 0;
|
conn->llcp_cu.req = conn->llcp_cu.ack = 0;
|
||||||
|
conn->llcp_cu.pause_tx = 0U;
|
||||||
conn->llcp_feature.req = conn->llcp_feature.ack = 0;
|
conn->llcp_feature.req = conn->llcp_feature.ack = 0;
|
||||||
conn->llcp_feature.features_conn = ll_feat_get();
|
conn->llcp_feature.features_conn = ll_feat_get();
|
||||||
conn->llcp_feature.features_peer = 0;
|
conn->llcp_feature.features_peer = 0;
|
||||||
|
|
|
@ -314,6 +314,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
|
||||||
conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0U;
|
conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0U;
|
||||||
conn->llcp_rx = NULL;
|
conn->llcp_rx = NULL;
|
||||||
conn->llcp_cu.req = conn->llcp_cu.ack = 0;
|
conn->llcp_cu.req = conn->llcp_cu.ack = 0;
|
||||||
|
conn->llcp_cu.pause_tx = 0U;
|
||||||
conn->llcp_feature.req = conn->llcp_feature.ack = 0;
|
conn->llcp_feature.req = conn->llcp_feature.ack = 0;
|
||||||
conn->llcp_feature.features_conn = ll_feat_get();
|
conn->llcp_feature.features_conn = ll_feat_get();
|
||||||
conn->llcp_feature.features_peer = 0;
|
conn->llcp_feature.features_peer = 0;
|
||||||
|
|
|
@ -1204,6 +1204,17 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
||||||
|
|
||||||
/* check if connection update procedure is requested */
|
/* check if connection update procedure is requested */
|
||||||
if (conn->llcp_cu.ack != conn->llcp_cu.req) {
|
if (conn->llcp_cu.ack != conn->llcp_cu.req) {
|
||||||
|
/* Delay until all pending Tx in LLL is acknowledged,
|
||||||
|
* new Tx PDUs will not be enqueued until we proceed to
|
||||||
|
* initiate connection update and get acknowledged.
|
||||||
|
* This is required to ensure PDU with instant can be
|
||||||
|
* transmitted before instant expires.
|
||||||
|
*/
|
||||||
|
if (memq_peek(conn->lll.memq_tx.head,
|
||||||
|
conn->lll.memq_tx.tail, NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* switch to LLCP_CONN_UPD state machine */
|
/* switch to LLCP_CONN_UPD state machine */
|
||||||
conn->llcp_type = LLCP_CONN_UPD;
|
conn->llcp_type = LLCP_CONN_UPD;
|
||||||
conn->llcp_ack -= 2U;
|
conn->llcp_ack -= 2U;
|
||||||
|
@ -2019,6 +2030,7 @@ void ull_conn_tx_lll_enqueue(struct ll_conn *conn, uint8_t count)
|
||||||
|
|
||||||
while (conn->tx_head &&
|
while (conn->tx_head &&
|
||||||
((
|
((
|
||||||
|
(conn->llcp_cu.req == conn->llcp_cu.ack) &&
|
||||||
#if defined(CONFIG_BT_CTLR_PHY)
|
#if defined(CONFIG_BT_CTLR_PHY)
|
||||||
!conn->llcp_phy.pause_tx &&
|
!conn->llcp_phy.pause_tx &&
|
||||||
#endif /* CONFIG_BT_CTLR_PHY */
|
#endif /* CONFIG_BT_CTLR_PHY */
|
||||||
|
@ -2938,6 +2950,7 @@ static inline void ctrl_tx_pause_enqueue(struct ll_conn *conn,
|
||||||
if (
|
if (
|
||||||
/* data/ctrl packet is in the head */
|
/* data/ctrl packet is in the head */
|
||||||
conn->tx_head &&
|
conn->tx_head &&
|
||||||
|
!conn->llcp_cu.pause_tx &&
|
||||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||||
!conn->llcp_enc.pause_tx &&
|
!conn->llcp_enc.pause_tx &&
|
||||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||||
|
@ -3287,8 +3300,15 @@ static inline int event_conn_upd_prep(struct ll_conn *conn, uint16_t lazy,
|
||||||
llctrl.conn_update_ind.win_offset);
|
llctrl.conn_update_ind.win_offset);
|
||||||
pdu_ctrl_tx->llctrl.conn_update_ind.instant =
|
pdu_ctrl_tx->llctrl.conn_update_ind.instant =
|
||||||
sys_cpu_to_le16(conn->llcp.conn_upd.instant);
|
sys_cpu_to_le16(conn->llcp.conn_upd.instant);
|
||||||
|
|
||||||
/* move to in progress */
|
/* move to in progress */
|
||||||
conn->llcp_cu.state = LLCP_CUI_STATE_INPROG;
|
conn->llcp_cu.state = LLCP_CUI_STATE_INPROG;
|
||||||
|
|
||||||
|
/* Data PDU tx paused, as we ensure PDUs in LLL have all
|
||||||
|
* been ack-ed.
|
||||||
|
*/
|
||||||
|
conn->llcp_cu.pause_tx = 1U;
|
||||||
|
|
||||||
/* enqueue control PDU */
|
/* enqueue control PDU */
|
||||||
tx = CONTAINER_OF(pdu_ctrl_tx, struct node_tx, pdu);
|
tx = CONTAINER_OF(pdu_ctrl_tx, struct node_tx, pdu);
|
||||||
ctrl_tx_enqueue(conn, tx);
|
ctrl_tx_enqueue(conn, tx);
|
||||||
|
@ -3335,6 +3355,12 @@ static inline int event_conn_upd_prep(struct ll_conn *conn, uint16_t lazy,
|
||||||
conn->lll.latency + 6;
|
conn->lll.latency + 6;
|
||||||
pdu_ctrl_tx->llctrl.conn_update_ind.instant =
|
pdu_ctrl_tx->llctrl.conn_update_ind.instant =
|
||||||
sys_cpu_to_le16(conn->llcp.conn_upd.instant);
|
sys_cpu_to_le16(conn->llcp.conn_upd.instant);
|
||||||
|
|
||||||
|
/* Data PDU tx paused, as we ensure PDUs in LLL have all been
|
||||||
|
* ack-ed.
|
||||||
|
*/
|
||||||
|
conn->llcp_cu.pause_tx = 1U;
|
||||||
|
|
||||||
/* enqueue control PDU */
|
/* enqueue control PDU */
|
||||||
ctrl_tx_enqueue(conn, tx);
|
ctrl_tx_enqueue(conn, tx);
|
||||||
#endif /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
|
#endif /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
|
||||||
|
@ -6647,6 +6673,12 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
||||||
conn->common.txn_lock = 0U;
|
conn->common.txn_lock = 0U;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND:
|
||||||
|
conn->llcp_cu.pause_tx = 0U;
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_BT_CENTRAL */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||||
#if defined(CONFIG_BT_CENTRAL)
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
|
case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
|
||||||
|
|
|
@ -169,6 +169,7 @@ struct ll_conn {
|
||||||
LLCP_CUI_STATE_REJECT,
|
LLCP_CUI_STATE_REJECT,
|
||||||
} state:3 __packed;
|
} state:3 __packed;
|
||||||
uint8_t cmd:1;
|
uint8_t cmd:1;
|
||||||
|
uint8_t pause_tx:1;
|
||||||
uint16_t interval;
|
uint16_t interval;
|
||||||
uint16_t latency;
|
uint16_t latency;
|
||||||
uint16_t timeout;
|
uint16_t timeout;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue