Bluetooth: controller: Add deferred procedure complete event
Added implementation to defer procedure complete event until actual on-air connection event instant. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
b60fa21f93
commit
35bbf148f2
2 changed files with 172 additions and 29 deletions
|
@ -577,6 +577,13 @@ config BT_CTLR_LLID_DATA_START_EMPTY
|
|||
help
|
||||
Handle zero length L2CAP start frame.
|
||||
|
||||
config BT_CTLR_RX_ENQUEUE_HOLD
|
||||
bool "Procedure Complete after on-air instant"
|
||||
default y if BT_HCI_RAW
|
||||
help
|
||||
Hold enqueue of Procedure Complete events with instant until after the
|
||||
on-air instant is reached.
|
||||
|
||||
config BT_CTLR_TX_RETRY_DISABLE
|
||||
bool "Disable Tx Retry"
|
||||
help
|
||||
|
|
|
@ -319,6 +319,11 @@ static void rx_packet_set(struct connection *conn,
|
|||
static void packet_rx_allocate(u8_t max);
|
||||
static inline u8_t packet_rx_acquired_count_get(void);
|
||||
static inline struct radio_pdu_node_rx *packet_rx_reserve_get(u8_t count);
|
||||
static void packet_rx_callback(void);
|
||||
static inline struct radio_pdu_node_rx *packet_rx_enqueue_get(void);
|
||||
static inline void packet_rx_enqueue_commit(struct radio_pdu_node_rx *node_rx);
|
||||
static inline void packet_rx_enqueue_hold(struct radio_pdu_node_rx *node_rx);
|
||||
static inline void packet_rx_enqueue_forward(void);
|
||||
static void packet_rx_enqueue(void);
|
||||
static void packet_tx_enqueue(u8_t max);
|
||||
static void pdu_node_tx_release(u16_t handle,
|
||||
|
@ -3871,6 +3876,11 @@ isr_rx_conn_exit:
|
|||
|
||||
/* release tx node and generate event for num complete */
|
||||
if (tx_release) {
|
||||
/* forward held rx nodes */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
packet_rx_enqueue_forward();
|
||||
}
|
||||
|
||||
pdu_node_tx_release(_radio.conn_curr->handle, tx_release);
|
||||
}
|
||||
|
||||
|
@ -3884,6 +3894,15 @@ isr_rx_conn_exit:
|
|||
packet_rx_enqueue();
|
||||
}
|
||||
|
||||
/* forward held rx nodes, if any, and no tx release or rx enqueued */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD) && !tx_release &&
|
||||
!rx_enqueue) {
|
||||
packet_rx_enqueue_forward();
|
||||
|
||||
/* callback to trigger application action */
|
||||
packet_rx_callback();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
|
||||
/* Collect RSSI for connection */
|
||||
if (rssi_ready) {
|
||||
|
@ -7251,7 +7270,14 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
|
|||
/* enqueue connection update complete structure
|
||||
* into queue.
|
||||
*/
|
||||
packet_rx_enqueue();
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
packet_rx_enqueue_get(); /* ignore return as its
|
||||
* same node_rx
|
||||
*/
|
||||
packet_rx_enqueue_hold(node_rx);
|
||||
} else {
|
||||
packet_rx_enqueue();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
|
||||
|
@ -8554,8 +8580,16 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
|
|||
upd->tx = conn->phy_tx;
|
||||
upd->rx = conn->phy_rx;
|
||||
|
||||
/* enqueue phy update structure into rx queue */
|
||||
packet_rx_enqueue();
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
/* deferred enqueue phy update structure into rx queue
|
||||
*/
|
||||
packet_rx_enqueue_get(); /* ignore return as its same
|
||||
* node_rx
|
||||
*/
|
||||
packet_rx_enqueue_hold(node_rx);
|
||||
} else {
|
||||
packet_rx_enqueue();
|
||||
}
|
||||
|
||||
/* Update max tx and/or max rx if changed */
|
||||
if ((eff_tx_time == conn->max_tx_time) &&
|
||||
|
@ -8591,8 +8625,17 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
|
|||
lr->max_rx_time = conn->max_rx_time;
|
||||
lr->max_tx_time = conn->max_tx_time;
|
||||
|
||||
/* enqueue length rsp structure into rx queue */
|
||||
packet_rx_enqueue();
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
/* deferred enqueue data length update structure into
|
||||
* rx queue
|
||||
*/
|
||||
packet_rx_enqueue_get(); /* ignore return as its same
|
||||
* node_rx
|
||||
*/
|
||||
packet_rx_enqueue_hold(node_rx);
|
||||
} else {
|
||||
packet_rx_enqueue();
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
}
|
||||
}
|
||||
|
@ -9231,7 +9274,7 @@ static void packet_rx_allocate(u8_t max)
|
|||
}
|
||||
|
||||
while ((max--) && (acquire != _radio.packet_rx_last)) {
|
||||
void *link;
|
||||
memq_link_t *link;
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
|
||||
link = mem_acquire(&_radio.link_rx_free);
|
||||
|
@ -9245,6 +9288,10 @@ static void packet_rx_allocate(u8_t max)
|
|||
break;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
link->next = link->mem = NULL;
|
||||
}
|
||||
|
||||
node_rx->hdr.link = link;
|
||||
|
||||
_radio.packet_rx[_radio.packet_rx_acquire] = node_rx;
|
||||
|
@ -9299,22 +9346,14 @@ static void packet_rx_callback(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void packet_rx_enqueue(void)
|
||||
static inline struct radio_pdu_node_rx *packet_rx_enqueue_get(void)
|
||||
{
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
memq_link_t *link;
|
||||
u8_t last;
|
||||
|
||||
LL_ASSERT(_radio.packet_rx_last != _radio.packet_rx_acquire);
|
||||
|
||||
/* Remember the rx node and acquired link mem */
|
||||
node_rx = _radio.packet_rx[_radio.packet_rx_last];
|
||||
link = node_rx->hdr.link;
|
||||
|
||||
/* serialize release queue with rx queue by storing reference to last
|
||||
* element in release queue
|
||||
*/
|
||||
node_rx->hdr.packet_release_last = _radio.packet_release_last;
|
||||
|
||||
/* dequeue from acquired rx queue */
|
||||
last = _radio.packet_rx_last + 1;
|
||||
|
@ -9323,9 +9362,103 @@ static void packet_rx_enqueue(void)
|
|||
}
|
||||
_radio.packet_rx_last = last;
|
||||
|
||||
return node_rx;
|
||||
}
|
||||
|
||||
static inline void packet_rx_enqueue_commit(struct radio_pdu_node_rx *node_rx)
|
||||
{
|
||||
memq_link_t *link;
|
||||
|
||||
/* back up link stored in rx node */
|
||||
link = node_rx->hdr.link;
|
||||
|
||||
/* serialize release queue with rx queue by storing reference to last
|
||||
* element in release queue
|
||||
*/
|
||||
node_rx->hdr.packet_release_last = _radio.packet_release_last;
|
||||
|
||||
/* Enqueue into event-cum-data queue */
|
||||
link = memq_enqueue(link, node_rx, (void *)&_radio.link_rx_tail);
|
||||
LL_ASSERT(link);
|
||||
}
|
||||
|
||||
static inline void packet_rx_enqueue_hold(struct radio_pdu_node_rx *node_rx)
|
||||
{
|
||||
struct radio_pdu_node_rx *next;
|
||||
memq_link_t *link, *link_last;
|
||||
|
||||
LL_ASSERT(_radio.packet_rx_last != _radio.packet_rx_acquire);
|
||||
|
||||
/* fetch the next available free rx node */
|
||||
next = _radio.packet_rx[_radio.packet_rx_last];
|
||||
|
||||
/* hold the rx node inside the link of the first free rx node */
|
||||
link = next->hdr.link;
|
||||
if (!link->next) {
|
||||
link_last = (void *)node_rx->hdr.link;
|
||||
if (!link_last->next) {
|
||||
link->mem = (void *)node_rx;
|
||||
link->next = (void *)node_rx;
|
||||
} else {
|
||||
struct radio_pdu_node_rx *last = (void *)link_last->mem;
|
||||
|
||||
link->mem = node_rx;
|
||||
link->next = link_last->next;
|
||||
link_last->next = NULL;
|
||||
|
||||
link_last = last->hdr.link;
|
||||
link_last->next = (void *)node_rx;
|
||||
}
|
||||
} else {
|
||||
struct radio_pdu_node_rx *last = (void *)link->mem;
|
||||
|
||||
link_last = (void *)last->hdr.link;
|
||||
link_last->next = (void *)node_rx;
|
||||
link_last = (void *)node_rx->hdr.link;
|
||||
link->mem = link_last->mem;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void packet_rx_enqueue_forward(void)
|
||||
{
|
||||
struct radio_pdu_node_rx *next, *p;
|
||||
memq_link_t *link;
|
||||
|
||||
/* fetch the next available free rx node */
|
||||
next = _radio.packet_rx[_radio.packet_rx_last];
|
||||
|
||||
link = next->hdr.link;
|
||||
p = (void *)link->next;
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
link->next = link->mem = NULL;
|
||||
|
||||
do {
|
||||
struct radio_pdu_node_rx *node_rx = p;
|
||||
|
||||
link = p->hdr.link;
|
||||
p = (void *)link->next;
|
||||
|
||||
packet_rx_enqueue_commit(node_rx);
|
||||
} while (p);
|
||||
}
|
||||
|
||||
static void packet_rx_enqueue(void)
|
||||
{
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
|
||||
/* forward held rx nodes */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
packet_rx_enqueue_forward();
|
||||
}
|
||||
|
||||
/* Get the populated rx node from the free queue */
|
||||
node_rx = packet_rx_enqueue_get();
|
||||
|
||||
/* Link the rx node with tx ack queue and enqueue towards host */
|
||||
packet_rx_enqueue_commit(node_rx);
|
||||
|
||||
/* callback to trigger application action */
|
||||
packet_rx_callback();
|
||||
|
@ -9851,7 +9984,11 @@ static void connection_release(struct connection *conn)
|
|||
static void terminate_ind_rx_enqueue(struct connection *conn, u8_t reason)
|
||||
{
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
memq_link_t *link;
|
||||
|
||||
/* forward held rx nodes */
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
packet_rx_enqueue_forward();
|
||||
}
|
||||
|
||||
/* Prepare the rx packet structure */
|
||||
node_rx = (void *)&conn->llcp_terminate.radio_pdu_node_rx;
|
||||
|
@ -9861,17 +9998,8 @@ static void terminate_ind_rx_enqueue(struct connection *conn, u8_t reason)
|
|||
node_rx->hdr.type = NODE_RX_TYPE_TERMINATE;
|
||||
*((u8_t *)node_rx->pdu_data) = reason;
|
||||
|
||||
/* Get the link mem reserved in the connection context */
|
||||
link = node_rx->hdr.link;
|
||||
|
||||
/* Serialize release queue with rx queue by storing reference to
|
||||
* last element in release queue
|
||||
*/
|
||||
node_rx->hdr.packet_release_last = _radio.packet_release_last;
|
||||
|
||||
/* Enqueue into event-cum-data queue */
|
||||
link = memq_enqueue(link, node_rx, (void *)&_radio.link_rx_tail);
|
||||
LL_ASSERT(link);
|
||||
/* Link the rx node with tx ack queue and enqueue towards host */
|
||||
packet_rx_enqueue_commit(node_rx);
|
||||
|
||||
/* callback to trigger application action */
|
||||
packet_rx_callback();
|
||||
|
@ -10884,7 +11012,7 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
|
|||
[_radio.advertiser.adv_data.last][0];
|
||||
if ((pdu_adv->type == PDU_ADV_TYPE_ADV_IND) ||
|
||||
(pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND)) {
|
||||
void *link;
|
||||
memq_link_t *link;
|
||||
|
||||
if (_radio.advertiser.conn) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
|
@ -10958,6 +11086,10 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
|
|||
conn->llcp_terminate.reason_peer = 0U;
|
||||
conn->llcp_terminate.radio_pdu_node_rx.hdr.link = link;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
link->next = link->mem = NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
conn->llcp_enc.req = 0U;
|
||||
conn->llcp_enc.ack = 0U;
|
||||
|
@ -11392,7 +11524,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
|
|||
struct connection *conn;
|
||||
u32_t conn_interval_us;
|
||||
u32_t access_addr;
|
||||
void *link;
|
||||
memq_link_t *link;
|
||||
|
||||
if (_radio.scanner.conn) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
|
@ -11495,6 +11627,10 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
|
|||
conn->llcp_terminate.reason_peer = 0U;
|
||||
conn->llcp_terminate.radio_pdu_node_rx.hdr.link = link;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_RX_ENQUEUE_HOLD)) {
|
||||
link->next = link->mem = NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
conn->llcp_enc.req = 0U;
|
||||
conn->llcp_enc.ack = 0U;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue