component/bt: allocate and use one static buffer for HCI adv flow control command

This commit is contained in:
Karl Wang 2022-07-20 05:48:28 +08:00 committed by wangmengyang
parent aaf1d3909d
commit 6c0c837378
5 changed files with 89 additions and 15 deletions

View File

@ -72,6 +72,8 @@ typedef struct {
osi_alarm_t *adv_flow_monitor;
int adv_credits;
int adv_credits_to_release;
pkt_linked_item_t *adv_fc_cmd_buf;
bool cmd_buf_in_use;
#endif
hci_hal_callbacks_t *callbacks;
osi_thread_t *hci_h4_thread;
@ -92,6 +94,7 @@ static bool hci_upstream_data_post(uint32_t timeout);
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
static void hci_adv_flow_monitor(void *context);
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt);
#endif
static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thread_t *task_thread)
@ -103,10 +106,13 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr
hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks;
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
hci_hal_env.adv_fc_cmd_buf = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL));
assert(hci_hal_env.adv_fc_cmd_buf != NULL);
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;
hci_hal_env.cmd_buf_in_use = false;
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
hci_hal_env.adv_flow_monitor = osi_alarm_new("adv_fc_mon", hci_adv_flow_monitor, NULL, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
assert (hci_hal_env.adv_flow_monitor != NULL);
@ -138,10 +144,13 @@ static void hci_hal_env_deinit(void)
hci_hal_env.upstream_data_ready = NULL;
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
hci_hal_env.cmd_buf_in_use = true;
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
osi_alarm_free(hci_hal_env.adv_flow_monitor);
hci_hal_env.adv_flow_monitor = NULL;
osi_mutex_free(&hci_hal_env.adv_flow_lock);
osi_free(hci_hal_env.adv_fc_cmd_buf);
hci_hal_env.adv_fc_cmd_buf = NULL;
#endif
hci_hal_env.hci_h4_thread = NULL;
@ -296,7 +305,7 @@ int hci_adv_credits_prep_to_release(uint16_t num)
hci_hal_env.adv_credits_to_release = credits_to_release;
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
if (credits_to_release == num) {
if (credits_to_release == num && num != 0) {
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
osi_alarm_set(hci_hal_env.adv_flow_monitor, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
}
@ -319,15 +328,64 @@ static int hci_adv_credits_release(void)
return credits_released;
}
static int hci_adv_credits_release_rollback(uint16_t num)
{
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
hci_hal_env.adv_credits -= num;
hci_hal_env.adv_credits_to_release += num;
assert(hci_hal_env.adv_credits >=0);
assert(hci_hal_env.adv_credits_to_release <= BLE_ADV_REPORT_FLOW_CONTROL_NUM);
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
return num;
}
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt)
{
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
hci_hal_env.cmd_buf_in_use = false;
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
hci_adv_credits_try_release(0);
}
bool hci_adv_flow_try_send_command(uint16_t credits_released)
{
bool sent = false;
bool use_static_buffer = false;
/* first try using static buffer, then dynamic buffer */
if (!hci_hal_env.cmd_buf_in_use) {
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
if (!hci_hal_env.cmd_buf_in_use) {
hci_hal_env.cmd_buf_in_use = true;
use_static_buffer = true;
}
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
}
if (use_static_buffer) {
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(hci_hal_env.adv_fc_cmd_buf->data);
BT_HDR *static_buffer = &metadata->command;
metadata->command_free_cb = hci_adv_flow_cmd_free_cb;
sent = btsnd_hcic_ble_update_adv_report_flow_control(credits_released, static_buffer);
} else {
sent = btsnd_hcic_ble_update_adv_report_flow_control(credits_released, NULL);
}
return sent;
}
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);
if (!hci_adv_flow_try_send_command(credits_released)) {
hci_adv_credits_release_rollback(credits_released);
}
} else {
assert (credits_released == 0);
}
}
return credits_released;
@ -338,8 +396,9 @@ 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);
if (!hci_adv_flow_try_send_command(credits_released)) {
hci_adv_credits_release_rollback(credits_released);
}
}
return credits_released;

View File

@ -242,9 +242,12 @@ static void transmit_command(
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_QUEUED;
// Store the command message type in the event field
// in case the upper layer didn't already
command->event = MSG_STACK_TO_HC_HCI_CMD;
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode);
BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);
@ -259,7 +262,7 @@ static future_t *transmit_command_futured(BT_HDR *command)
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_FUTURE;
metadata->flags_vnd |= (HCI_CMD_MSG_F_VND_QUEUED | HCI_CMD_MSG_F_VND_FUTURE);
future_t *future = future_new();
@ -294,8 +297,10 @@ static void event_command_ready(fixed_pkt_queue_t *queue)
command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
wait_entry = fixed_pkt_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data);
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_SENT;
metadata->flags_vnd &= ~HCI_CMD_MSG_F_VND_QUEUED;
if (metadata->flags_src & HCI_CMD_MSG_F_SRC_NOACK) {
packet_fragmenter->fragment_and_dispatch(&metadata->command);
hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func;

View File

@ -49,6 +49,8 @@
#define LOCAL_BR_EDR_CONTROLLER_ID 0
#define HCI_CMD_MSG_F_VND_FUTURE (0x01)
#define HCI_CMD_MSG_F_VND_QUEUED (0x02)
#define HCI_CMD_MSG_F_VND_SENT (0x04)
///// END LEGACY DEFINITIONS /////
typedef struct hci_hal_t hci_hal_t;

View File

@ -1028,23 +1028,31 @@ BOOLEAN btsnd_hcic_ble_set_data_length(UINT16 conn_handle, UINT16 tx_octets, UIN
return TRUE;
}
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num)
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num, BT_HDR *static_buf)
{
BT_HDR *p;
UINT8 *pp;
if (static_buf != NULL) {
p = static_buf;
} else {
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)) == NULL) {
return (FALSE);
}
}
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
metadata->flags_src = HCI_CMD_MSG_F_SRC_NOACK;
if (static_buf == p) {
assert(metadata->command_free_cb != NULL);
}
p->layer_specific = HCI_CMD_BUF_TYPE_METADATA;
pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL;
p->offset = 0;
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK;
UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL);
UINT16_TO_STREAM (pp, num);

View File

@ -939,7 +939,7 @@ BOOLEAN btsnd_hcic_read_authenticated_payload_tout(UINT16 handle);
BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
UINT16 timeout);
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num);
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num, BT_HDR *static_buf);
#if (BLE_50_FEATURE_SUPPORT == TRUE)
BOOLEAN btsnd_hcic_ble_read_phy(UINT16 conn_handle);