change(bt/bluedroid): Refactored HCI ACL datapath

This commit is contained in:
liqigan
2026-06-26 14:55:04 +08:00
committed by BOT
parent 329e7ba627
commit e590b1c8eb
4 changed files with 214 additions and 8 deletions

View File

@@ -581,8 +581,23 @@ intercepted:
static void dispatch_reassembled(BT_HDR *packet)
{
// Events should already have been dispatched before this point
//Tell Up-layer received packet.
if (btu_task_post(SIG_BTU_HCI_MSG, packet, OSI_THREAD_MAX_TIMEOUT) == false) {
// Tell Up-layer received packet.
do {
if ((packet->event & BT_EVT_MASK) == BT_EVT_TO_BTU_HCI_ACL) {
if (btu_hci_acl_data_post(packet)) {
packet = NULL;
}
// TODO: Use controller to host flow control
break;
}
if (btu_task_post(SIG_BTU_HCI_MSG, packet, OSI_THREAD_MAX_TIMEOUT)) {
packet = NULL;
break;
}
} while (0);
if (packet != NULL) {
osi_free(packet);
}
}

View File

@@ -206,6 +206,10 @@ bool BTU_StartUp(void)
goto error_exit;
}
if (!btu_acl_queue_init()) {
goto error_exit;
}
if (btu_task_post(SIG_BTU_START_UP, NULL, OSI_THREAD_MAX_TIMEOUT) == false) {
goto error_exit;
}
@@ -229,10 +233,19 @@ error_exit:;
******************************************************************************/
void BTU_ShutDown(void)
{
btu_acl_queue_close();
btu_task_shut_down();
if (btu_thread) {
osi_thread_free(btu_thread);
btu_thread = NULL;
}
btu_acl_queue_deinit();
#if BTU_DYNAMIC_MEMORY
FREE_AND_RESET(btu_cb_ptr);
#endif
btu_task_shut_down();
hash_map_free(btu_general_alarm_hash_map);
osi_mutex_free(&btu_general_alarm_lock);
@@ -243,11 +256,6 @@ void BTU_ShutDown(void)
hash_map_free(btu_l2cap_alarm_hash_map);
osi_mutex_free(&btu_l2cap_alarm_lock);
if (btu_thread) {
osi_thread_free(btu_thread);
btu_thread = NULL;
}
btu_general_alarm_hash_map = NULL;
btu_oneshot_alarm_hash_map = NULL;
btu_l2cap_alarm_hash_map = NULL;

View File

@@ -29,6 +29,7 @@
#include "btm_int.h"
#include "stack/btu.h"
#include "osi/hash_map.h"
#include "osi/pkt_queue.h"
#include "stack/hcimsgs.h"
#include "l2c_int.h"
#include "osi/osi.h"
@@ -122,6 +123,25 @@ typedef void (tUSER_TIMEOUT_FUNC) (TIMER_LIST_ENT *p_tle);
static void btu_l2cap_alarm_process(void *param);
static void btu_general_alarm_process(void *param);
static void btu_hci_msg_process(void *param);
static void btu_hci_acl_data_handler(void *param);
static bool btu_hci_acl_data_ready(uint32_t timeout);
static void btu_acl_pkt_linked_free(pkt_linked_item_t *linked_pkt);
static void btu_acl_pkt_linked_free(pkt_linked_item_t *linked_pkt)
{
do {
if (linked_pkt == NULL) {
break;
}
BT_HDR *packet = NULL;
memcpy(&packet, linked_pkt->data, sizeof(packet));
if (packet != NULL) {
osi_free(packet);
}
osi_free(linked_pkt);
} while (0);
}
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
static void btu_bta_alarm_process(void *param);
@@ -197,6 +217,57 @@ static void btu_hci_msg_process(void *param)
}
static bool btu_hci_acl_data_ready(uint32_t timeout)
{
bool status = false;
do {
if (btu_cb.acl_closing || btu_cb.acl_data_ready == NULL) {
break;
}
status = osi_thread_post_event(btu_cb.acl_data_ready, timeout);
} while (0);
return status;
}
static void btu_hci_acl_data_handler(void *param)
{
UNUSED(param);
struct pkt_queue *acl_pkt_queue = btu_cb.acl_pkt_queue;
if (acl_pkt_queue == NULL || btu_cb.acl_closing) {
return;
}
size_t pkts_to_process = pkt_queue_length(acl_pkt_queue);
if (pkts_to_process > BTU_ACL_QUEUE_BATCH_SIZE) {
pkts_to_process = BTU_ACL_QUEUE_BATCH_SIZE;
}
for (size_t i = 0; i < pkts_to_process; i++) {
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(acl_pkt_queue);
if (linked_pkt == NULL) {
break;
}
BT_HDR *packet = NULL;
memcpy(&packet, linked_pkt->data, sizeof(packet));
if (packet == NULL) {
osi_free(linked_pkt);
continue;
}
l2c_rcv_acl_data(packet);
osi_free(linked_pkt);
}
size_t pending = pkt_queue_length(acl_pkt_queue);
if (pending != 0) {
// Re-post from BTU thread itself must stay non-blocking to avoid deadlock on a full queue.
btu_hci_acl_data_ready(0);
}
}
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
static void btu_bta_alarm_process(void *param)
{
@@ -263,6 +334,109 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout)
return status;
}
bool btu_acl_queue_init(void)
{
bool status = false;
btu_cb.acl_closing = FALSE;
do {
btu_cb.acl_pkt_queue = pkt_queue_create();
if (btu_cb.acl_pkt_queue == NULL) {
break;
}
btu_cb.acl_data_ready = osi_event_create(btu_hci_acl_data_handler, NULL);
if (btu_cb.acl_data_ready == NULL) {
break;
}
if (!osi_event_bind(btu_cb.acl_data_ready, btu_thread, 0)) {
break;
}
status = true;
} while (0);
if (status == false) {
if (btu_cb.acl_data_ready != NULL) {
osi_event_delete(btu_cb.acl_data_ready);
btu_cb.acl_data_ready = NULL;
}
if (btu_cb.acl_pkt_queue != NULL) {
pkt_queue_destroy(btu_cb.acl_pkt_queue, NULL);
btu_cb.acl_pkt_queue = NULL;
}
btu_cb.acl_closing = TRUE;
}
return status;
}
void btu_acl_queue_close(void)
{
#if BTU_DYNAMIC_MEMORY == TRUE
if (!btu_cb_ptr) {
return;
}
#endif /* BTU_DYNAMIC_MEMORY == FALSE */
btu_cb.acl_closing = TRUE;
if (btu_cb.acl_data_ready != NULL) {
osi_event_delete(btu_cb.acl_data_ready);
btu_cb.acl_data_ready = NULL;
}
}
void btu_acl_queue_deinit(void)
{
#if BTU_DYNAMIC_MEMORY == TRUE
if (!btu_cb_ptr) {
return;
}
#endif /* BTU_DYNAMIC_MEMORY == FALSE */
btu_cb.acl_closing = TRUE;
if (btu_cb.acl_pkt_queue != NULL) {
pkt_queue_destroy(btu_cb.acl_pkt_queue, btu_acl_pkt_linked_free);
btu_cb.acl_pkt_queue = NULL;
}
}
bool btu_hci_acl_data_post(BT_HDR *packet)
{
bool status = false;
do {
if (packet == NULL || btu_cb.acl_closing || btu_cb.acl_pkt_queue == NULL) {
break;
}
size_t acl_q_len = pkt_queue_length(btu_cb.acl_pkt_queue);
if (acl_q_len >= BTU_ACL_QUEUE_HIGH_WATERMARK) {
HCI_TRACE_WARNING("ACL queue high watermark (len=%u)", (unsigned)acl_q_len);
break;
}
pkt_linked_item_t *linked_pkt = (pkt_linked_item_t *)osi_malloc(BT_PKT_LINKED_HDR_SIZE + sizeof(packet));
if (linked_pkt == NULL) {
HCI_TRACE_WARNING("ACL queue malloc pkt failed");
break;
}
memcpy(linked_pkt->data, &packet, sizeof(packet));
pkt_queue_enqueue(btu_cb.acl_pkt_queue, linked_pkt);
btu_hci_acl_data_ready(OSI_THREAD_MAX_TIMEOUT);
status = true;
} while (0);
return status;
}
void btu_task_start_up(void *param)
{
UNUSED(param);

View File

@@ -206,6 +206,8 @@ typedef struct {
#define BTU_MAX_REG_TIMER (2) /* max # timer callbacks which may register */
#define BTU_MAX_REG_EVENT (6) /* max # event callbacks which may register */
#define BTU_DEFAULT_DATA_SIZE (0x2a0)
#define BTU_ACL_QUEUE_BATCH_SIZE (12)
#define BTU_ACL_QUEUE_HIGH_WATERMARK (100)
#if (BLE_INCLUDED == TRUE)
#define BTU_DEFAULT_BLE_DATA_SIZE (27)
@@ -234,6 +236,9 @@ typedef struct {
typedef struct {
tBTU_TIMER_REG timer_reg[BTU_MAX_REG_TIMER];
tBTU_EVENT_REG event_reg[BTU_MAX_REG_EVENT];
struct pkt_queue *acl_pkt_queue;
struct osi_event *acl_data_ready;
BOOLEAN acl_closing;
BOOLEAN reset_complete; /* TRUE after first ack from device received */
UINT8 trace_level; /* Trace level for HCI layer */
@@ -303,6 +308,10 @@ void btu_task_shut_down(void);
UINT16 BTU_BleAclPktSize(void);
bool btu_task_post(uint32_t sig, void *param, uint32_t timeout);
bool btu_acl_queue_init(void);
void btu_acl_queue_close(void);
void btu_acl_queue_deinit(void);
bool btu_hci_acl_data_post(BT_HDR *packet);
int get_btu_work_queue_size(void);