diff --git a/esp_hosted_fg/esp/esp_driver/network_adapter/main/app_main.c b/esp_hosted_fg/esp/esp_driver/network_adapter/main/app_main.c index 8649486c35..e64cb59fee 100644 --- a/esp_hosted_fg/esp/esp_driver/network_adapter/main/app_main.c +++ b/esp_hosted_fg/esp/esp_driver/network_adapter/main/app_main.c @@ -90,6 +90,10 @@ interface_handle_t *if_handle = NULL; static QueueHandle_t meta_to_host_queue = NULL; static QueueHandle_t to_host_queue[MAX_PRIORITY_QUEUES] = {NULL}; +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE +static interface_buffer_handle_t s_wifi_tx_buffer_handle[BUFFER_NUM]; +#endif + static protocomm_t *pc_pserial; @@ -369,7 +373,7 @@ void process_serial_rx_pkt(uint8_t *buf) } } -void process_rx_pkt(interface_buffer_handle_t *buf_handle) +int process_rx_pkt(interface_buffer_handle_t *buf_handle) { struct esp_payload_header *header = NULL; uint8_t *payload = NULL; @@ -385,6 +389,11 @@ void process_rx_pkt(interface_buffer_handle_t *buf_handle) if ((buf_handle->if_type == ESP_STA_IF) && station_connected) { /* Forward data to wlan driver */ +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + if (esp_wifi_internal_tx(ESP_IF_WIFI_STA, payload, payload_len) == ESP_ERR_NO_MEM) { + ret = ESP_FAIL; + } +#else int retry = 6; do { @@ -399,10 +408,17 @@ void process_rx_pkt(interface_buffer_handle_t *buf_handle) } } while (ret && retry); +#endif /*ESP_LOG_BUFFER_HEXDUMP("spi_sta_rx", payload, payload_len, ESP_LOG_INFO);*/ } else if (buf_handle->if_type == ESP_AP_IF && softap_started) { /* Forward data to wlan driver */ +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + if (esp_wifi_internal_tx(ESP_IF_WIFI_AP, payload, payload_len) == ESP_ERR_NO_MEM) { + ret = ESP_FAIL; + } +#else esp_wifi_internal_tx(ESP_IF_WIFI_AP, payload, payload_len); +#endif } else if (buf_handle->if_type == ESP_SERIAL_IF) { process_serial_rx_pkt(buf_handle->payload); } @@ -418,10 +434,19 @@ void process_rx_pkt(interface_buffer_handle_t *buf_handle) #endif /* Free buffer handle */ +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + if (ret == ESP_OK && buf_handle->free_buf_handle && buf_handle->priv_buffer_handle) { + buf_handle->free_buf_handle(buf_handle->priv_buffer_handle); + buf_handle->priv_buffer_handle = NULL; + } + return ret; +#else if (buf_handle->free_buf_handle && buf_handle->priv_buffer_handle) { buf_handle->free_buf_handle(buf_handle->priv_buffer_handle); buf_handle->priv_buffer_handle = NULL; } + return 0; +#endif } /* Get data from host */ @@ -429,6 +454,12 @@ void recv_task(void* pvParameters) { interface_buffer_handle_t buf_handle = {0}; +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + memset(s_wifi_tx_buffer_handle, 0, sizeof(s_wifi_tx_buffer_handle)); + uint32_t start_index = 0; + uint32_t store_num = 0; +#endif + for (;;) { if (!datapath) { @@ -439,14 +470,39 @@ void recv_task(void* pvParameters) /* receive data from transport layer */ if (if_context && if_context->if_ops && if_context->if_ops->read) { +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + TickType_t wait_tick = store_num ? 1 : portMAX_DELAY; + int len = if_context->if_ops->read(if_handle, &buf_handle, wait_tick); + while (store_num) { + if (process_rx_pkt(&s_wifi_tx_buffer_handle[start_index]) != ESP_OK) { + break; + } + start_index++; + store_num--; + if (start_index >= BUFFER_NUM) { + start_index = 0; + } + } +#else int len = if_context->if_ops->read(if_handle, &buf_handle); +#endif if (len <= 0) { usleep(10*1000); continue; } } - +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + if (process_rx_pkt(&buf_handle) != ESP_OK) { + uint32_t end_index = start_index + store_num; + if (end_index >= BUFFER_NUM) { + end_index -= BUFFER_NUM; + } + s_wifi_tx_buffer_handle[end_index] = buf_handle; + store_num++; + } +#else process_rx_pkt(&buf_handle); +#endif } } diff --git a/esp_hosted_fg/esp/esp_driver/network_adapter/main/interface.h b/esp_hosted_fg/esp/esp_driver/network_adapter/main/interface.h index 712f80581c..c8e3cd4f12 100644 --- a/esp_hosted_fg/esp/esp_driver/network_adapter/main/interface.h +++ b/esp_hosted_fg/esp/esp_driver/network_adapter/main/interface.h @@ -26,6 +26,8 @@ #error "SDIO is not supported for this chipset" #endif +#include "sdio_slave_api.h" + #endif typedef enum { @@ -78,7 +80,11 @@ typedef struct { typedef struct { interface_handle_t * (*init)(void); int32_t (*write)(interface_handle_t *handle, interface_buffer_handle_t *buf_handle); +#ifdef CONFIG_ESP_SDIO_HOST_INTERFACE + int (*read)(interface_handle_t *handle, interface_buffer_handle_t *buf_handle, TickType_t wait); +#else int (*read)(interface_handle_t *handle, interface_buffer_handle_t *buf_handle); +#endif esp_err_t (*reset)(interface_handle_t *handle); void (*deinit)(interface_handle_t *handle); } if_ops_t; diff --git a/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.c b/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.c index 4ef31efed7..17ed5f0f01 100644 --- a/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.c +++ b/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.c @@ -30,7 +30,7 @@ #define SDIO_SLAVE_QUEUE_SIZE 20 #define BUFFER_SIZE 1536 /* 512*3 */ -#define BUFFER_NUM 10 + static uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE]; #define SDIO_MEMPOOL_NUM_BLOCKS 40 @@ -43,7 +43,7 @@ static const char TAG[] = "SDIO_SLAVE"; static interface_handle_t * sdio_init(void); static int32_t sdio_write(interface_handle_t *handle, interface_buffer_handle_t *buf_handle); -static int sdio_read(interface_handle_t *if_handle, interface_buffer_handle_t *buf_handle); +static int sdio_read(interface_handle_t *if_handle, interface_buffer_handle_t *buf_handle, TickType_t wait); static esp_err_t sdio_reset(interface_handle_t *handle); static void sdio_deinit(interface_handle_t *handle); @@ -339,7 +339,7 @@ static int32_t sdio_write(interface_handle_t *handle, interface_buffer_handle_t return buf_handle->payload_len; } -static int sdio_read(interface_handle_t *if_handle, interface_buffer_handle_t *buf_handle) +static int sdio_read(interface_handle_t *if_handle, interface_buffer_handle_t *buf_handle, TickType_t wait) { esp_err_t ret = ESP_OK; struct esp_payload_header *header = NULL; @@ -359,7 +359,7 @@ static int sdio_read(interface_handle_t *if_handle, interface_buffer_handle_t *b return ESP_FAIL; ret = sdio_slave_recv(&(buf_handle->sdio_buf_handle), &(buf_handle->payload), - &(sdio_read_len), portMAX_DELAY); + &(sdio_read_len), wait); if (ret) { ESP_LOGD(TAG, "sdio_slave_recv returned failure"); return ESP_FAIL; diff --git a/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.h b/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.h index 4a251bca4a..73106aa008 100644 --- a/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.h +++ b/esp_hosted_fg/esp/esp_driver/network_adapter/main/sdio_slave_api.h @@ -22,4 +22,6 @@ #error "SDIO is not supported for ESP32S2. Please use SPI" #endif +#define BUFFER_NUM 10 + #endif diff --git a/esp_hosted_fg/host/linux/host_driver/esp32/sdio/esp_sdio.c b/esp_hosted_fg/host/linux/host_driver/esp32/sdio/esp_sdio.c index de1220b7f6..38ad0d2c0a 100644 --- a/esp_hosted_fg/host/linux/host_driver/esp32/sdio/esp_sdio.c +++ b/esp_hosted_fg/host/linux/host_driver/esp32/sdio/esp_sdio.c @@ -37,8 +37,10 @@ #include "esp_fw_verify.h" #define MAX_WRITE_RETRIES 2 -#define TX_MAX_PENDING_COUNT 200 -#define TX_RESUME_THRESHOLD (TX_MAX_PENDING_COUNT/5) +/* Pause wifi tx if pending skb > this */ +#define FLOW_CTL_PAUSE_THRES 100 +/* Resume wifi tx if pending skb < this */ +#define FLOW_CTL_RESUME_THRES (FLOW_CTL_PAUSE_THRES * 4 / 5) #define CHECK_SDIO_RW_ERROR(ret) do { \ if (ret) \ @@ -58,7 +60,6 @@ #endif struct esp_sdio_context sdio_context; -static atomic_t tx_pending; static atomic_t queue_items[MAX_PRIORITY_QUEUES]; struct task_struct *tx_thread; @@ -509,15 +510,6 @@ static int write_packet(struct esp_adapter *adapter, struct sk_buff *skb) return -EPERM; } - if (atomic_read(&tx_pending) >= TX_MAX_PENDING_COUNT) { - esp_tx_pause(); - dev_kfree_skb(skb); - return -EBUSY; - } - - /* Enqueue SKB in tx_q */ - atomic_inc(&tx_pending); - /* Notify to process queue */ if (payload_header->if_type == ESP_SERIAL_IF) { atomic_inc(&queue_items[PRIO_Q_SERIAL]); @@ -526,6 +518,11 @@ static int write_packet(struct esp_adapter *adapter, struct sk_buff *skb) atomic_inc(&queue_items[PRIO_Q_BT]); skb_queue_tail(&(sdio_context.tx_q[PRIO_Q_BT]), skb); } else { + if (atomic_read(&queue_items[PRIO_Q_OTHERS]) >= FLOW_CTL_PAUSE_THRES) { + esp_tx_pause(); + dev_kfree_skb(skb); + return -EBUSY; + } atomic_inc(&queue_items[PRIO_Q_OTHERS]); skb_queue_tail(&(sdio_context.tx_q[PRIO_Q_OTHERS]), skb); } @@ -533,55 +530,14 @@ static int write_packet(struct esp_adapter *adapter, struct sk_buff *skb) return 0; } -static int is_sdio_write_buffer_available(u32 buf_needed) -{ -#define BUFFER_AVAILABLE 1 -#define BUFFER_UNAVAILABLE 0 - - int ret = 0; - static u32 buf_available = 0; - struct esp_sdio_context *context = &sdio_context; - u8 retry = MAX_WRITE_RETRIES; - - /*If buffer needed are less than buffer available - then only read for available buffer number from slave*/ - if (buf_available < buf_needed) { - while (retry) { - ret = esp_slave_get_tx_buffer_num(context, &buf_available, ACQUIRE_LOCK); - - if (buf_available < buf_needed) { - - /* Release SDIO and retry after delay*/ - retry--; - usleep_range(10,50); - continue; - } - - break; - } - } - - if (buf_available >= buf_needed) - buf_available -= buf_needed; - - if (!retry) { - esp_verbose("slave buffer unavailable\n"); - /* No buffer available at slave */ - return BUFFER_UNAVAILABLE; - } - - return BUFFER_AVAILABLE; -} - static int tx_process(void *data) { int ret = 0; - u32 block_cnt = 0; - u32 buf_needed = 0; - u8 *pos = NULL; - u32 data_left, len_to_send, pad; + u32 len_to_send; struct sk_buff *tx_skb = NULL; struct esp_sdio_context *context = &sdio_context; + u32 buf_available = 0; + u8 retry; while (!kthread_should_stop()) { @@ -591,6 +547,23 @@ static int tx_process(void *data) continue; } + if (buf_available < 2) { + retry = MAX_WRITE_RETRIES; + while (1) { + ret = esp_slave_get_tx_buffer_num(context, &buf_available, ACQUIRE_LOCK); + if (buf_available > 0 && retry <= 1) { + break; + } + retry--; + usleep_range(10, 50); + } + + if (buf_available < 1) { + msleep(1); + continue; + } + } + if (atomic_read(&queue_items[PRIO_Q_SERIAL]) > 0) { tx_skb = skb_dequeue(&(context->tx_q[PRIO_Q_SERIAL])); if (!tx_skb) { @@ -603,7 +576,7 @@ static int tx_process(void *data) continue; } atomic_dec(&queue_items[PRIO_Q_BT]); - } else if (atomic_read(&queue_items[PRIO_Q_OTHERS]) > 0) { + } else if (buf_available >= 2 && atomic_read(&queue_items[PRIO_Q_OTHERS]) > 0) { tx_skb = skb_dequeue(&(context->tx_q[PRIO_Q_OTHERS])); if (!tx_skb) { continue; @@ -614,50 +587,26 @@ static int tx_process(void *data) continue; } - if (atomic_read(&tx_pending)) - atomic_dec(&tx_pending); - /* resume network tx queue if bearable load */ - if (atomic_read(&tx_pending) < TX_RESUME_THRESHOLD) { + if (atomic_read(&queue_items[PRIO_Q_OTHERS]) < FLOW_CTL_RESUME_THRES) { esp_tx_resume(); #if TEST_RAW_TP esp_raw_tp_queue_resume(); #endif } - buf_needed = (tx_skb->len + ESP_RX_BUFFER_SIZE - 1) / ESP_RX_BUFFER_SIZE; - - /*If SDIO slave buffer is available to write then only write data - else wait till buffer is available*/ - ret = is_sdio_write_buffer_available(buf_needed); - if(!ret) { - dev_kfree_skb(tx_skb); - continue; - } - - pos = tx_skb->data; - data_left = len_to_send = 0; - - data_left = tx_skb->len; - pad = ESP_BLOCK_SIZE - (data_left % ESP_BLOCK_SIZE); - data_left += pad; + /*write_packet limits the maximum length of data sent to ESP_RX_BUFFER_SIZE, + so a buffer is always required.*/ + buf_available--; esp_hex_dump_dbg("sdio_tx: ", tx_skb->data, 32); - do { - block_cnt = data_left / ESP_BLOCK_SIZE; - len_to_send = data_left; - ret = esp_write_block(context, ESP_SLAVE_CMD53_END_ADDR - len_to_send, - pos, (len_to_send + 3) & (~3), ACQUIRE_LOCK); - - if (ret) { - esp_err("Failed to send data: %d %d %d\n", ret, len_to_send, data_left); - break; - } - - data_left -= len_to_send; - pos += len_to_send; - } while (data_left); + len_to_send = tx_skb->len; + if (len_to_send % ESP_BLOCK_SIZE > 0) { + len_to_send += (ESP_BLOCK_SIZE - (len_to_send % ESP_BLOCK_SIZE)); + } + ret = esp_write_block(context, ESP_SLAVE_CMD53_END_ADDR - len_to_send, + tx_skb->data, (len_to_send + 3) & (~3), ACQUIRE_LOCK); if (ret) { /* drop the packet */ @@ -665,7 +614,7 @@ static int tx_process(void *data) continue; } - context->tx_buffer_count += buf_needed; + context->tx_buffer_count ++; context->tx_buffer_count = context->tx_buffer_count % ESP_TX_BUFFER_MAX; dev_kfree_skb(tx_skb); @@ -732,7 +681,6 @@ static int esp_probe(struct sdio_func *func, esp_info("ESP network device detected\n"); context = init_sdio_func(func, &ret); - atomic_set(&tx_pending, 0); if (!context) { if (ret)