diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 14eaf08d469..49a82966614 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -1121,6 +1121,7 @@ uint8_t ll_adv_enable(uint8_t enable) conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0; conn->llcp_rx = NULL; 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.features_conn = ll_feat_get(); conn->llcp_feature.features_peer = 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index 0d236f34f8f..f78fba071eb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -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_rx = NULL; 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.features_conn = ll_feat_get(); conn->llcp_feature.features_peer = 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 336cfa7ae87..d31c9093008 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -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 */ 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 */ conn->llcp_type = LLCP_CONN_UPD; 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 && (( + (conn->llcp_cu.req == conn->llcp_cu.ack) && #if defined(CONFIG_BT_CTLR_PHY) !conn->llcp_phy.pause_tx && #endif /* CONFIG_BT_CTLR_PHY */ @@ -2938,6 +2950,7 @@ static inline void ctrl_tx_pause_enqueue(struct ll_conn *conn, if ( /* data/ctrl packet is in the head */ conn->tx_head && + !conn->llcp_cu.pause_tx && #if defined(CONFIG_BT_CTLR_LE_ENC) !conn->llcp_enc.pause_tx && #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); pdu_ctrl_tx->llctrl.conn_update_ind.instant = sys_cpu_to_le16(conn->llcp.conn_upd.instant); + /* move to in progress */ 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 */ tx = CONTAINER_OF(pdu_ctrl_tx, struct node_tx, pdu); 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; pdu_ctrl_tx->llctrl.conn_update_ind.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 */ ctrl_tx_enqueue(conn, tx); #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; 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_CENTRAL) case PDU_DATA_LLCTRL_TYPE_ENC_REQ: diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index ee791521c9b..437b3c025bd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -169,6 +169,7 @@ struct ll_conn { LLCP_CUI_STATE_REJECT, } state:3 __packed; uint8_t cmd:1; + uint8_t pause_tx:1; uint16_t interval; uint16_t latency; uint16_t timeout;