component/bt: fix adv report flow control logic, give ADV report credits every 10 packets

This commit is contained in:
wangmengyang 2022-07-18 19:40:34 +08:00
parent 2ef0627c2c
commit b735c46ba7
4 changed files with 113 additions and 27 deletions

View File

@ -24,6 +24,9 @@
#include "hci/hci_layer.h" #include "hci/hci_layer.h"
#include "osi/thread.h" #include "osi/thread.h"
#include "osi/pkt_queue.h" #include "osi/pkt_queue.h"
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
#include "osi/mutex.h"
#endif
#include "esp_bt.h" #include "esp_bt.h"
#include "stack/hcimsgs.h" #include "stack/hcimsgs.h"
@ -36,7 +39,11 @@
#define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2) #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
#define PACKET_TYPE_TO_INDEX(type) ((type) - 1) #define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
#define HCI_UPSTREAM_DATA_QUEUE_IDX (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) #define HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX (200)
#endif
extern bool BTU_check_queue_is_congest(void); extern bool BTU_check_queue_is_congest(void);
@ -58,7 +65,11 @@ static const uint16_t outbound_event_types[] = {
typedef struct { typedef struct {
fixed_queue_t *rx_q; fixed_queue_t *rx_q;
struct pkt_queue *adv_rpt_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; hci_hal_callbacks_t *callbacks;
osi_thread_t *hci_h4_thread; osi_thread_t *hci_h4_thread;
struct osi_event *upstream_data_ready; 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.hci_h4_thread = task_thread;
hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks; 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); hci_hal_env.rx_q = fixed_queue_new(QUEUE_SIZE_MAX);
assert(hci_hal_env.rx_q != NULL); 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); osi_event_delete(hci_hal_env.upstream_data_ready);
hci_hal_env.upstream_data_ready = NULL; 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; hci_hal_env.hci_h4_thread = NULL;
memset(&hci_hal_env, 0, sizeof(hci_hal_env_t)); 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) #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 osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
uint8_t *data = packet->data + packet->offset; assert(hci_hal_env.adv_credits >= num);
if(host_recv_adv_packet(data)) { hci_hal_env.adv_credits -= num;
// update adv free number osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
hci_hal_env.adv_free_num ++; }
if (esp_vhci_host_check_send_available()){
// send hci cmd int hci_adv_credits_prep_to_release(uint16_t num)
btsnd_hcic_ble_update_adv_report_flow_control(hci_hal_env.adv_free_num); {
hci_hal_env.adv_free_num = 0; if (num == 0) {
} else { return hci_hal_env.adv_credits_to_release;
//do nothing
}
} }
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 #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) { if (packet->len < hdr_size) {
HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d", HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d",
type, packet->len, hdr_size); type, packet->len, hdr_size);
osi_free(linked_pkt); goto _discard_packet;
return;
} }
stream += hdr_size - 1; 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) { if ((length + hdr_size) != packet->len) {
HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d " HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
"pkt_len=%d", type, hdr_size, length, packet->len); "pkt_len=%d", type, hdr_size, length, packet->len);
osi_free(linked_pkt); goto _discard_packet;
return;
} }
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
hci_update_adv_report_flow_control(packet);
#endif
#if SCAN_QUEUE_CONGEST_CHECK #if SCAN_QUEUE_CONGEST_CHECK
if(BTU_check_queue_is_congest()) { if(BTU_check_queue_is_congest()) {
HCI_TRACE_DEBUG("BtuQueue is congested"); HCI_TRACE_DEBUG("BtuQueue is congested");
osi_free(linked_pkt); goto _discard_packet;
return;
} }
#endif #endif
packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)]; packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
hci_hal_env.callbacks->adv_rpt_ready(linked_pkt); 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) 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; pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len;
linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size); linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size);
if (!linked_pkt) { 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; return 0;
} }
pkt = (BT_HDR *)linked_pkt->data; 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; pkt->layer_specific = 0;
memcpy(pkt->data, data, len); memcpy(pkt->data, data, len);
pkt_queue_enqueue(hci_hal_env.adv_rpt_q, linked_pkt); 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); hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);

View File

@ -530,6 +530,9 @@ static void dispatch_adv_report(pkt_linked_item_t *linked_pkt)
//Tell Up-layer received packet. //Tell Up-layer received packet.
if (btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, linked_pkt, OSI_THREAD_MAX_TIMEOUT) == false) { if (btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, linked_pkt, OSI_THREAD_MAX_TIMEOUT) == false) {
osi_free(linked_pkt); osi_free(linked_pkt);
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
hci_adv_credits_try_release(1);
#endif
} }
} }
// Misc internal functions // Misc internal functions

View File

@ -19,6 +19,7 @@
#ifndef _HCI_LAYER_H_ #ifndef _HCI_LAYER_H_
#define _HCI_LAYER_H_ #define _HCI_LAYER_H_
#include "common/bt_target.h"
#include "stack/bt_types.h" #include "stack/bt_types.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/osi.h" #include "osi/osi.h"
@ -99,4 +100,10 @@ void hci_shut_down(void);
bool hci_host_task_post(uint32_t timeout); 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_ */ #endif /* _HCI_LAYER_H_ */

View File

@ -34,7 +34,7 @@
#include "device/controller.h" #include "device/controller.h"
#include "stack/hcimsgs.h" #include "stack/hcimsgs.h"
#include "stack/gap_api.h" #include "stack/gap_api.h"
#include "hci/hci_layer.h"
#if BLE_INCLUDED == TRUE #if BLE_INCLUDED == TRUE
#include "l2c_int.h" #include "l2c_int.h"
@ -3486,6 +3486,9 @@ static void btm_adv_pkt_handler(void *arg)
} }
osi_free(linked_pkt); 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) { if (pkt_queue_length(p_cb->adv_rpt_queue) != 0) {