From b735c46ba7106d2037f06ce7c2036e89a1b77d40 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Mon, 18 Jul 2022 19:40:34 +0800 Subject: [PATCH] component/bt: fix adv report flow control logic, give ADV report credits every 10 packets --- components/bt/host/bluedroid/hci/hci_hal_h4.c | 125 ++++++++++++++---- components/bt/host/bluedroid/hci/hci_layer.c | 3 + .../bluedroid/hci/include/hci/hci_layer.h | 7 + .../bt/host/bluedroid/stack/btm/btm_ble_gap.c | 5 +- 4 files changed, 113 insertions(+), 27 deletions(-) diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index 53e37dc154..57f7e07dbd 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -24,6 +24,9 @@ #include "hci/hci_layer.h" #include "osi/thread.h" #include "osi/pkt_queue.h" +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) +#include "osi/mutex.h" +#endif #include "esp_bt.h" #include "stack/hcimsgs.h" @@ -36,7 +39,11 @@ #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2) #define PACKET_TYPE_TO_INDEX(type) ((type) - 1) #define HCI_UPSTREAM_DATA_QUEUE_IDX (1) +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) +#define HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE (10) +#else #define HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX (200) +#endif extern bool BTU_check_queue_is_congest(void); @@ -58,7 +65,11 @@ static const uint16_t outbound_event_types[] = { typedef struct { fixed_queue_t *rx_q; struct pkt_queue *adv_rpt_q; - uint16_t adv_free_num; +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + osi_mutex_t adv_flow_lock; + int adv_credits; + int adv_credits_to_release; +#endif hci_hal_callbacks_t *callbacks; osi_thread_t *hci_h4_thread; struct osi_event *upstream_data_ready; @@ -83,7 +94,14 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr hci_hal_env.hci_h4_thread = task_thread; hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks; - hci_hal_env.adv_free_num = 0; + +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + osi_mutex_new(&hci_hal_env.adv_flow_lock); + osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT); + hci_hal_env.adv_credits = BLE_ADV_REPORT_FLOW_CONTROL_NUM; + hci_hal_env.adv_credits_to_release = 0; + osi_mutex_unlock(&hci_hal_env.adv_flow_lock); +#endif hci_hal_env.rx_q = fixed_queue_new(QUEUE_SIZE_MAX); assert(hci_hal_env.rx_q != NULL); @@ -110,6 +128,10 @@ static void hci_hal_env_deinit(void) osi_event_delete(hci_hal_env.upstream_data_ready); hci_hal_env.upstream_data_ready = NULL; +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + osi_mutex_free(&hci_hal_env.adv_flow_lock); +#endif + hci_hal_env.hci_h4_thread = NULL; memset(&hci_hal_env, 0, sizeof(hci_hal_env_t)); @@ -237,22 +259,66 @@ bool host_recv_adv_packet(uint8_t *packet) } #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) -static void hci_update_adv_report_flow_control(BT_HDR *packet) +static void hci_adv_credits_consumed(uint16_t num) { - // this is adv packet - uint8_t *data = packet->data + packet->offset; - if(host_recv_adv_packet(data)) { - // update adv free number - hci_hal_env.adv_free_num ++; - if (esp_vhci_host_check_send_available()){ - // send hci cmd - btsnd_hcic_ble_update_adv_report_flow_control(hci_hal_env.adv_free_num); - hci_hal_env.adv_free_num = 0; - } else { - //do nothing - } + osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT); + assert(hci_hal_env.adv_credits >= num); + hci_hal_env.adv_credits -= num; + osi_mutex_unlock(&hci_hal_env.adv_flow_lock); +} + +int hci_adv_credits_prep_to_release(uint16_t num) +{ + if (num == 0) { + return hci_hal_env.adv_credits_to_release; } + osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT); + int credits_to_release = hci_hal_env.adv_credits_to_release + num; + assert(hci_hal_env.adv_credits_to_release <= BLE_ADV_REPORT_FLOW_CONTROL_NUM); + hci_hal_env.adv_credits_to_release = credits_to_release; + osi_mutex_unlock(&hci_hal_env.adv_flow_lock); + + return credits_to_release; +} + +static int hci_adv_credits_release(void) +{ + osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT); + int credits_released = hci_hal_env.adv_credits_to_release; + hci_hal_env.adv_credits += credits_released; + hci_hal_env.adv_credits_to_release -= credits_released; + assert(hci_hal_env.adv_credits <= BLE_ADV_REPORT_FLOW_CONTROL_NUM); + assert(hci_hal_env.adv_credits_to_release >= 0); + osi_mutex_unlock(&hci_hal_env.adv_flow_lock); + + return credits_released; +} + +int hci_adv_credits_try_release(uint16_t num) +{ + int credits_released = 0; + if (hci_adv_credits_prep_to_release(num) >= HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE) { + credits_released = hci_adv_credits_release(); + assert(credits_released >= 0); + if (credits_released > 0) { + // TODO: handle the exception that the command is discarded due to heap exhaustion + btsnd_hcic_ble_update_adv_report_flow_control(credits_released); + } + } + return credits_released; +} + +int hci_adv_credits_force_release(uint16_t num) +{ + hci_adv_credits_prep_to_release(num); + int credits_released = hci_adv_credits_release(); + if (credits_released > 0) { + // TODO: handle the exception that the command is discarded due to heap exhaustion + btsnd_hcic_ble_update_adv_report_flow_control(credits_released); + } + + return credits_released; } #endif @@ -341,8 +407,7 @@ static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt) if (packet->len < hdr_size) { HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d", type, packet->len, hdr_size); - osi_free(linked_pkt); - return; + goto _discard_packet; } stream += hdr_size - 1; @@ -350,24 +415,26 @@ static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt) if ((length + hdr_size) != packet->len) { HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d " "pkt_len=%d", type, hdr_size, length, packet->len); - osi_free(linked_pkt); - return; + goto _discard_packet; } -#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) - hci_update_adv_report_flow_control(packet); -#endif - #if SCAN_QUEUE_CONGEST_CHECK if(BTU_check_queue_is_congest()) { HCI_TRACE_DEBUG("BtuQueue is congested"); - osi_free(linked_pkt); - return; + goto _discard_packet; } #endif packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)]; hci_hal_env.callbacks->adv_rpt_ready(linked_pkt); + + return; + +_discard_packet: + osi_free(linked_pkt); +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + hci_adv_credits_prep_to_release(1); +#endif } static void host_send_pkt_available_cb(void) @@ -413,7 +480,10 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len; linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size); if (!linked_pkt) { - // TODO: handle the adv report flow control exception +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + hci_adv_credits_consumed(1); + hci_adv_credits_prep_to_release(1); +#endif return 0; } pkt = (BT_HDR *)linked_pkt->data; @@ -422,6 +492,9 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) pkt->layer_specific = 0; memcpy(pkt->data, data, len); pkt_queue_enqueue(hci_hal_env.adv_rpt_q, linked_pkt); +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + hci_adv_credits_consumed(1); +#endif } hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT); diff --git a/components/bt/host/bluedroid/hci/hci_layer.c b/components/bt/host/bluedroid/hci/hci_layer.c index 865dd3fd1a..0365c45f93 100644 --- a/components/bt/host/bluedroid/hci/hci_layer.c +++ b/components/bt/host/bluedroid/hci/hci_layer.c @@ -530,6 +530,9 @@ static void dispatch_adv_report(pkt_linked_item_t *linked_pkt) //Tell Up-layer received packet. if (btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, linked_pkt, OSI_THREAD_MAX_TIMEOUT) == false) { osi_free(linked_pkt); +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + hci_adv_credits_try_release(1); +#endif } } // Misc internal functions diff --git a/components/bt/host/bluedroid/hci/include/hci/hci_layer.h b/components/bt/host/bluedroid/hci/include/hci/hci_layer.h index 6bfacdff5c..6ba4ccd18c 100644 --- a/components/bt/host/bluedroid/hci/include/hci/hci_layer.h +++ b/components/bt/host/bluedroid/hci/include/hci/hci_layer.h @@ -19,6 +19,7 @@ #ifndef _HCI_LAYER_H_ #define _HCI_LAYER_H_ +#include "common/bt_target.h" #include "stack/bt_types.h" #include "osi/allocator.h" #include "osi/osi.h" @@ -99,4 +100,10 @@ void hci_shut_down(void); bool hci_host_task_post(uint32_t timeout); +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) +int hci_adv_credits_prep_to_release(uint16_t num); +int hci_adv_credits_try_release(uint16_t num); +int hci_adv_credits_force_release(uint16_t num); +#endif + #endif /* _HCI_LAYER_H_ */ diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c index dd25ec039f..f1a96a497d 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -34,7 +34,7 @@ #include "device/controller.h" #include "stack/hcimsgs.h" #include "stack/gap_api.h" - +#include "hci/hci_layer.h" #if BLE_INCLUDED == TRUE #include "l2c_int.h" @@ -3486,6 +3486,9 @@ static void btm_adv_pkt_handler(void *arg) } osi_free(linked_pkt); +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + hci_adv_credits_try_release(1); +#endif } if (pkt_queue_length(p_cb->adv_rpt_queue) != 0) {