From 969cd5ce30db18e8441282a518bba0f1ad6be2da Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Mon, 19 May 2025 11:02:37 +0530 Subject: [PATCH 1/2] Add support for host RX buffers pass to UMAC (nRF71) In nRF70, the host programmed RX buffers directly to the RPU through hardware queues. With nRF71, hardware queues are not accessible from the host side. This update adds a command handling to allow the host to pass RX buffers to UMAC firmware, which then programs them to the RPU. Signed-off-by: Ajay Parida --- CMakeLists.txt | 1 + Makefile | 1 + fw_if/umac_if/inc/fw/host_rpu_sys_if.h | 1 + fw_if/umac_if/inc/fw/host_rpu_umac_if.h | 17 +++++ fw_if/umac_if/inc/system/fmac_api.h | 15 +++++ fw_if/umac_if/inc/system/fmac_rx.h | 5 +- fw_if/umac_if/src/system/fmac_api.c | 83 +++++++++++++++++++++++ fw_if/umac_if/src/system/rx.c | 88 ++++++++++++++++++++++++- hw_if/hal/inc/system/hal_api.h | 5 ++ hw_if/hal/src/system/hal_api.c | 20 ++++++ 10 files changed, 234 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7844fc4..f462f61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ target_compile_definitions( $<$:NRF71_ON_IPC> $<$:NRF_WIFI_DYNAMIC_BANDWIDTH_SIGNALLING> $<$:NRF_WIFI_DYNAMIC_ED> + $<$:NRF71_HOST_RX_BUF_CMD> NRF_WIFI_MAX_PS_POLL_FAIL_CNT=${CONFIG_NRF_WIFI_MAX_PS_POLL_FAIL_CNT} NRF70_RX_NUM_BUFS=${CONFIG_NRF70_RX_NUM_BUFS} NRF70_MAX_TX_TOKENS=${CONFIG_NRF70_MAX_TX_TOKENS} diff --git a/Makefile b/Makefile index 9b307b8..053e9be 100644 --- a/Makefile +++ b/Makefile @@ -97,6 +97,7 @@ ccflags-y += -DNRF_WIFI_RPU_RECOVERY_PS_ACTIVE_TIMEOUT_MS=50000 ccflags-y += -DNRF_WIFI_DISPLAY_SCAN_BSS_LIMIT=150 ccflags-y += -DNRF_WIFI_RPU_MIN_TIME_TO_ENTER_SLEEP_MS=1000 ccflags-y += -DWIFI_NRF70_LOG_LEVEL=1 +#ccflags-y += -DNRF71_HOST_RX_BUF_CMD # Source files SRCS = os_if/src/osal.c \ diff --git a/fw_if/umac_if/inc/fw/host_rpu_sys_if.h b/fw_if/umac_if/inc/fw/host_rpu_sys_if.h index 647db2f..86590d9 100644 --- a/fw_if/umac_if/inc/fw/host_rpu_sys_if.h +++ b/fw_if/umac_if/inc/fw/host_rpu_sys_if.h @@ -39,6 +39,7 @@ #define MAX_TX_AGG_SIZE 16 #define MAX_RX_BUFS_PER_EVNT 64 +#define MAX_RX_BUFS_PER_CMD 32 #define MAX_MGMT_BUFS 16 /*#define ETH_ADDR_LEN 6*/ diff --git a/fw_if/umac_if/inc/fw/host_rpu_umac_if.h b/fw_if/umac_if/inc/fw/host_rpu_umac_if.h index ea3e4b2..9dab809 100644 --- a/fw_if/umac_if/inc/fw/host_rpu_umac_if.h +++ b/fw_if/umac_if/inc/fw/host_rpu_umac_if.h @@ -150,6 +150,8 @@ enum nrf_wifi_umac_commands { NRF_WIFI_UMAC_CMD_CONFIG_QUIET_PERIOD, /** Command to specify power save exit strategy */ NRF_WIFI_UMAC_CMD_PS_EXIT_STRATEGY, + /** Send host RX Buffers */ + NRF_WIFI_UMAC_CMD_CONFIG_RX_BUF, }; /** @@ -3548,4 +3550,19 @@ struct nrf_wifi_cmd_ps_exit_strategy { unsigned char ps_exit_strategy; } __NRF_WIFI_PKD; +struct nrf_wifi_rx_buf { + unsigned int skb_pointer; + unsigned short skb_desc_no; +} __NRF_WIFI_PKD; + +/** + * @brief This structure represents the command used to configure rx buffers. + * + */ +struct nrf_wifi_cmd_rx_buf_info { + struct nrf_wifi_umac_hdr umac_hdr; + unsigned int rx_buf_num; + struct nrf_wifi_rx_buf info[0]; +} __NRF_WIFI_PKD; + #endif /* __HOST_RPU_UMAC_IF_H */ diff --git a/fw_if/umac_if/inc/system/fmac_api.h b/fw_if/umac_if/inc/system/fmac_api.h index 2b6ab70..55d3c07 100644 --- a/fw_if/umac_if/inc/system/fmac_api.h +++ b/fw_if/umac_if/inc/system/fmac_api.h @@ -1175,6 +1175,21 @@ enum nrf_wifi_status nrf_wifi_sys_fmac_stats_get(struct nrf_wifi_fmac_dev_ctx *f enum rpu_op_mode op_mode, struct rpu_sys_op_stats *stats); +#ifdef NRF71_HOST_RX_BUF_CMD +/** + * @brief Configure Rx buffer to firmware. + * @param fmac_dev_ctx Pointer to the UMAC IF context for a RPU WLAN device. + * @param nrf_wifi_rx_buf RX buffer info. + * @param num_buffs Number of buffers. + * + * This function is used to send host Rx buffers to UMAC module + * + * @return Command execution status + */ +enum nrf_wifi_status nrf_wifi_sys_fmac_prog_rx_buf_info(void *fmac_dev_ctx, + struct nrf_wifi_rx_buf *rx_buf, + unsigned int num_buffs); +#endif /* NRF71_HOST_RX_BUF_CMD*/ /** * @} */ diff --git a/fw_if/umac_if/inc/system/fmac_rx.h b/fw_if/umac_if/inc/system/fmac_rx.h index 59a587f..415dfde 100644 --- a/fw_if/umac_if/inc/system/fmac_rx.h +++ b/fw_if/umac_if/inc/system/fmac_rx.h @@ -37,5 +37,8 @@ enum nrf_wifi_status nrf_wifi_fmac_rx_event_process(struct nrf_wifi_fmac_dev_ctx struct nrf_wifi_rx_buff *config); void nrf_wifi_fmac_rx_tasklet(void *data); - +#ifdef NRF71_HOST_RX_BUF_CMD +unsigned long nrf_wifi_fmac_get_rx_buf_map_addr(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + unsigned int desc_id); +#endif /* NRF71_HOST_RX_BUF_CMD */ #endif /* __FMAC_RX_H__ */ diff --git a/fw_if/umac_if/src/system/fmac_api.c b/fw_if/umac_if/src/system/fmac_api.c index 0d9b981..5ee6d72 100644 --- a/fw_if/umac_if/src/system/fmac_api.c +++ b/fw_if/umac_if/src/system/fmac_api.c @@ -3346,6 +3346,89 @@ enum nrf_wifi_status nrf_wifi_sys_fmac_set_ps_exit_strategy(void *dev_ctx, return status; } + +#ifdef NRF71_HOST_RX_BUF_CMD +enum nrf_wifi_status nrf_wifi_sys_fmac_prog_rx_buf_info(void *dev_ctx, + struct nrf_wifi_rx_buf *rx_buf, + unsigned int rx_buf_nums) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + struct nrf_wifi_cmd_rx_buf_info *rx_buf_cmd = NULL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + struct nrf_wifi_fmac_dev_ctx_def *def_dev_ctx = NULL; + struct nrf_wifi_rx_buf *rx_buf_iter = NULL; + int i = 0, remained_buf_cnt = 0, counter = 0, rx_buff_prog_cnt = 0; + + fmac_dev_ctx = dev_ctx; + def_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + + if (rx_buf_nums > MAX_RX_BUFS_PER_CMD) { + rx_buff_prog_cnt = MAX_RX_BUFS_PER_CMD; + remained_buf_cnt = rx_buf_nums % MAX_RX_BUFS_PER_CMD; + counter = rx_buf_nums / MAX_RX_BUFS_PER_CMD; + } else { + rx_buff_prog_cnt = rx_buf_nums; + counter = 1; + } + + rx_buf_iter = rx_buf; + + for (i = 0; i < counter; i++) { + rx_buf_cmd = nrf_wifi_osal_mem_zalloc(sizeof(*rx_buf_cmd) + + rx_buff_prog_cnt * + sizeof(struct nrf_wifi_rx_buf)); + if (!rx_buf_cmd) { + nrf_wifi_osal_log_err("%s: Unable to allocate memory\n", + __func__); + goto out; + } + + rx_buf_cmd->umac_hdr.cmd_evnt = NRF_WIFI_UMAC_CMD_CONFIG_RX_BUF; + nrf_wifi_osal_mem_cpy(&rx_buf_cmd->info, + rx_buf, + rx_buff_prog_cnt * sizeof(struct nrf_wifi_rx_buf)); + + rx_buf_cmd->rx_buf_num = rx_buff_prog_cnt; + + status = umac_cmd_cfg(fmac_dev_ctx, + rx_buf_cmd, + sizeof(*rx_buf_cmd) + + rx_buff_prog_cnt * + sizeof(struct nrf_wifi_rx_buf)); + if (rx_buf_cmd) { + nrf_wifi_osal_mem_free(rx_buf_cmd); + } + } + if (remained_buf_cnt > 0) { + rx_buf_cmd = nrf_wifi_osal_mem_zalloc(sizeof(*rx_buf_cmd) + + remained_buf_cnt * + sizeof(struct nrf_wifi_rx_buf)); + if (!rx_buf_cmd) { + nrf_wifi_osal_log_err("%s: Unable to allocate memory\n", + __func__); + goto out; + } + + rx_buf_cmd->umac_hdr.cmd_evnt = NRF_WIFI_UMAC_CMD_CONFIG_RX_BUF; + nrf_wifi_osal_mem_cpy(&rx_buf_cmd->info, + rx_buf + (MAX_RX_BUFS_PER_CMD), + remained_buf_cnt * sizeof(struct nrf_wifi_rx_buf)); + + rx_buf_cmd->rx_buf_num = remained_buf_cnt; + + status = umac_cmd_cfg(fmac_dev_ctx, + rx_buf_cmd, + sizeof(*rx_buf_cmd) + + remained_buf_cnt * + sizeof(struct nrf_wifi_rx_buf)); + if (rx_buf_cmd) { + nrf_wifi_osal_mem_free(rx_buf_cmd); + } + } +out: + return status; +} +#endif /* NRF71_HOST_RX_BUF_CMD */ #endif /* NRF70_STA_MODE */ enum nrf_wifi_status nrf_wifi_sys_fmac_stats_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, diff --git a/fw_if/umac_if/src/system/rx.c b/fw_if/umac_if/src/system/rx.c index 8cb1bc1..13ec334 100644 --- a/fw_if/umac_if/src/system/rx.c +++ b/fw_if/umac_if/src/system/rx.c @@ -13,6 +13,9 @@ #include "system/fmac_rx.h" #include "common/fmac_util.h" #include "system/fmac_promisc.h" +#ifdef NRF71_HOST_RX_BUF_CMD +#include "system/fmac_api.h" +#endif /* NRF71_HOST_RX_BUF_CMD */ static enum nrf_wifi_status nrf_wifi_fmac_map_desc_to_pool(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, @@ -165,6 +168,47 @@ static void nrf_wifi_convert_to_eth(void *nwb, } #endif /* NRF70_STA_MODE */ +#ifdef NRF71_HOST_RX_BUF_CMD +unsigned long nrf_wifi_fmac_get_rx_buf_map_addr(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + unsigned int desc_id) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL; + struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL; + struct nrf_wifi_fmac_buf_map_info *rx_buf_info = NULL; + struct nrf_wifi_fmac_rx_pool_map_info pool_info; + unsigned long phy_addr = 0; + + sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv); + + status = nrf_wifi_fmac_map_desc_to_pool(fmac_dev_ctx, + desc_id, + &pool_info); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: nrf_wifi_fmac_map_desc_to_pool failed\n", + __func__); + goto out; + } + + rx_buf_info = &sys_dev_ctx->rx_buf_info[desc_id]; + + if (rx_buf_info->mapped) { + phy_addr = nrf_wifi_sys_hal_get_buf_map_rx(fmac_dev_ctx->hal_dev_ctx, + pool_info.pool_id, + pool_info.buf_id); + return phy_addr; + } else { + nrf_wifi_osal_log_err("%s: rx buffer not mapped for desc_id= %d\n", + __func__, + desc_id); + } +out: + return 0; +} +#endif /* NRF71_HOST_RX_BUF_CMD */ + enum nrf_wifi_status nrf_wifi_fmac_rx_cmd_send(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, enum nrf_wifi_fmac_rx_cmd_type cmd_type, unsigned int desc_id) @@ -245,12 +289,14 @@ enum nrf_wifi_status nrf_wifi_fmac_rx_cmd_send(struct nrf_wifi_fmac_dev_ctx *fma #else rx_cmd.addr = (unsigned int)nwb_data; #endif /* NRF71_ON_IPC */ +#ifndef NRF71_HOST_RX_BUF_CMD status = nrf_wifi_sys_hal_data_cmd_send(fmac_dev_ctx->hal_dev_ctx, NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX, &rx_cmd, sizeof(rx_cmd), desc_id, pool_info.pool_id); +#endif /* NRF71_HOST_RX_BUF_CMD */ } else if (cmd_type == NRF_WIFI_FMAC_RX_CMD_TYPE_DEINIT) { #ifndef NRF71_ON_IPC /* TODO: Need to initialize a command and send it to LMAC @@ -359,6 +405,10 @@ enum nrf_wifi_status nrf_wifi_fmac_rx_event_process(struct nrf_wifi_fmac_dev_ctx #endif /* NRF70_STA_MODE */ struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL; struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL; +#ifdef NRF71_HOST_RX_BUF_CMD + unsigned int buf_addr = 0; + struct nrf_wifi_rx_buf *rx_buf_ipc = NULL, *rx_buf_info_iter = NULL; +#endif /* NRF71_HOST_RX_BUF_CMD */ sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx); sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv); @@ -373,6 +423,12 @@ enum nrf_wifi_status nrf_wifi_fmac_rx_event_process(struct nrf_wifi_fmac_dev_ctx #endif /* NRF70_STA_MODE */ num_pkts = config->rx_pkt_cnt; +#ifdef NRF71_HOST_RX_BUF_CMD + rx_buf_ipc = nrf_wifi_osal_mem_zalloc(num_pkts * + sizeof(struct nrf_wifi_rx_buf)); + rx_buf_info_iter = rx_buf_ipc; +#endif /* NRF71_HOST_RX_BUF_CMD */ + for (i = 0; i < num_pkts; i++) { desc_id = config->rx_buff_info[i].descriptor_id; pkt_len = config->rx_buff_info[i].rx_pkt_len; @@ -548,8 +604,38 @@ enum nrf_wifi_status nrf_wifi_fmac_rx_event_process(struct nrf_wifi_fmac_dev_ctx __func__); continue; } +#ifdef NRF71_HOST_RX_BUF_CMD + buf_addr = (unsigned int) nrf_wifi_fmac_get_rx_buf_map_addr(fmac_dev_ctx, + desc_id); + if (buf_addr) { + rx_buf_info_iter->skb_pointer = buf_addr; + rx_buf_info_iter->skb_desc_no = desc_id; + rx_buf_info_iter++; + } else { + nrf_wifi_osal_log_err("%s: UMAC rx buff not mapped\ + for desc_id = %d\n", + __func__, + desc_id); + continue; + } +#endif /* NRF71_HOST_RX_BUF_CMD */ } - +#ifdef NRF71_HOST_RX_BUF_CMD + status = nrf_wifi_sys_fmac_prog_rx_buf_info(fmac_dev_ctx, + rx_buf_ipc, + num_pkts); + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: UMAC rx buff\ + programming failed \n", + __func__); + status = NRF_WIFI_STATUS_FAIL; + } else { + nrf_wifi_osal_log_dbg("%s: UMAC rx buff refill\ + programmed for num_buffs= %d \n", + __func__, num_pkts); + nrf_wifi_osal_mem_free(rx_buf_ipc); + } +#endif /* NRF71_HOST_RX_BUF_CMD */ /* A single failure returns failure for the entire event */ return status; } diff --git a/hw_if/hal/inc/system/hal_api.h b/hw_if/hal/inc/system/hal_api.h index 21ad62f..a9d4c88 100644 --- a/hw_if/hal/inc/system/hal_api.h +++ b/hw_if/hal/inc/system/hal_api.h @@ -144,4 +144,9 @@ enum nrf_wifi_status nrf_wifi_hal_coex_config_sleep_ctrl_gpio_ctrl( unsigned int invert_bt_coex_grant_output); #endif /* NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL */ +#ifdef NRF71_HOST_RX_BUF_CMD +unsigned long nrf_wifi_sys_hal_get_buf_map_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, + unsigned int pool_id, + unsigned int buf_id); +#endif /* NRF71_HOST_RX_BUF_CMD */ #endif /* __HAL_API_SYS_H__ */ diff --git a/hw_if/hal/src/system/hal_api.c b/hw_if/hal/src/system/hal_api.c index 2106c39..fadc330 100644 --- a/hw_if/hal/src/system/hal_api.c +++ b/hw_if/hal/src/system/hal_api.c @@ -95,6 +95,26 @@ static void recovery_tasklet_fn(unsigned long data) &flags); } +#ifdef NRF71_HOST_RX_BUF_CMD +unsigned long nrf_wifi_sys_hal_get_buf_map_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, + unsigned int pool_id, + unsigned int buf_id) +{ + struct nrf_wifi_hal_buf_map_info *rx_buf_info = NULL; + + rx_buf_info = &hal_dev_ctx->rx_buf_info[pool_id][buf_id]; + + if (rx_buf_info->mapped) { + return rx_buf_info->phy_addr; + } else { + nrf_wifi_osal_log_err("%s: Rx buffer not mapped for pool_id = %d, buf_id=%d\n", + __func__, + pool_id, + buf_id); + } + return 0; +} +#endif /* NRF71_HOST_RX_BUF_CMD */ unsigned long nrf_wifi_sys_hal_buf_map_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, unsigned long buf, From 36b86fc2e0941ef6d49336819ab75c736998ecf2 Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Mon, 19 May 2025 07:55:55 +0530 Subject: [PATCH 2/2] Add SOFT_HPQM support SOFT_HPQM is to replace existing hardware based queue used to communicate between host and firmware. Targeted towards nrf71 based system. TX and CTRL commands are used to communicate using software queue. RX buffers are programmed to firmware at initialization are handled by firmware. Signed-off-by: Ajay Parida --- CMakeLists.txt | 1 + fw_if/umac_if/inc/fw/host_rpu_common_if.h | 24 +++ hw_if/hal/inc/common/hal_structs_common.h | 4 + hw_if/hal/inc/common/rpu_if.h | 6 +- hw_if/hal/src/common/hal_api_common.c | 252 +++++++++++++++++++++- hw_if/hal/src/common/hal_interrupt.c | 174 ++++++++++++++- 6 files changed, 457 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f462f61..2f6b441 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ target_compile_definitions( $<$:NRF_WIFI_DYNAMIC_BANDWIDTH_SIGNALLING> $<$:NRF_WIFI_DYNAMIC_ED> $<$:NRF71_HOST_RX_BUF_CMD> + $<$:NRF71_SOFT_HPQM> NRF_WIFI_MAX_PS_POLL_FAIL_CNT=${CONFIG_NRF_WIFI_MAX_PS_POLL_FAIL_CNT} NRF70_RX_NUM_BUFS=${CONFIG_NRF70_RX_NUM_BUFS} NRF70_MAX_TX_TOKENS=${CONFIG_NRF70_MAX_TX_TOKENS} diff --git a/fw_if/umac_if/inc/fw/host_rpu_common_if.h b/fw_if/umac_if/inc/fw/host_rpu_common_if.h index eaf036f..7de88d8 100644 --- a/fw_if/umac_if/inc/fw/host_rpu_common_if.h +++ b/fw_if/umac_if/inc/fw/host_rpu_common_if.h @@ -138,6 +138,30 @@ struct host_rpu_umac_info { /** OTP params */ unsigned int calib[9]; } __NRF_WIFI_PKD; + +#ifdef NRF71_SOFT_HPQM + +#define NRF_WIFI_HOST_RPU_CMD_BUFFERS 4 +#define NRF_WIFI_HOST_RPU_EVENT_BUFFERS 7 +#define NRF_WIFI_HOST_RPU_TX_DESC 12 + +struct soft_hpqm_info { + volatile unsigned int host_cmd_free_index; + volatile unsigned int rpu_cmd_busy_index; + volatile unsigned int host_event_busy_index; + volatile unsigned int rpu_event_free_index; + volatile unsigned int host_tx_cmd_busy_index; + volatile unsigned int rpu_tx_cmd_busy_index; + volatile unsigned int host_tx_done_busy_index; + volatile unsigned int rpu_tx_done_busy_index; + volatile unsigned int cmd_free_buffs[NRF_WIFI_HOST_RPU_CMD_BUFFERS]; + volatile unsigned int cmd_busy_buffs[NRF_WIFI_HOST_RPU_CMD_BUFFERS]; + volatile unsigned int event_free_buffs[NRF_WIFI_HOST_RPU_EVENT_BUFFERS]; + volatile unsigned int event_busy_buffs[NRF_WIFI_HOST_RPU_EVENT_BUFFERS]; + volatile unsigned int tx_cmd_buffs[NRF_WIFI_HOST_RPU_TX_DESC]; + volatile unsigned int tx_done_buffs[NRF_WIFI_HOST_RPU_TX_DESC]; +} __NRF_WIFI_PKD; +#endif /* NRF71_SOFT_HPQM */ /** * @} */ diff --git a/hw_if/hal/inc/common/hal_structs_common.h b/hw_if/hal/inc/common/hal_structs_common.h index 550c490..daf5ac4 100644 --- a/hw_if/hal/inc/common/hal_structs_common.h +++ b/hw_if/hal/inc/common/hal_structs_common.h @@ -116,6 +116,10 @@ enum NRF_WIFI_HAL_STATUS { * @brief Structure to hold RPU information. */ struct nrf_wifi_hal_info { +#ifdef NRF71_SOFT_HPQM + /** Host RPU soft_hpqm information */ + struct soft_hpqm_info *soft_hpq; +#endif /* NRF71_SOFT_HPQM */ /** Host RPU HPQM information */ struct host_rpu_hpqm_info hpqm_info; /** RX command base */ diff --git a/hw_if/hal/inc/common/rpu_if.h b/hw_if/hal/inc/common/rpu_if.h index 11d8397..e27daa4 100644 --- a/hw_if/hal/inc/common/rpu_if.h +++ b/hw_if/hal/inc/common/rpu_if.h @@ -215,9 +215,13 @@ struct rpu_mcu_boot_vectors { /* Address which has information about the host port queue manager (HPQM) */ #define RPU_MEM_HPQ_INFO 0xB0000024 +#ifdef NRF71_SOFT_HPQM +#define RPU_MEM_TX_CMD_BASE 0x200800B8 +#define NRF_WIFI_SOFTHPQM_INFO_START_ADDR 0x20084548 +#else /* Address which has information about the TX command base */ #define RPU_MEM_TX_CMD_BASE 0xB00000B8 - +#endif /* NRF71_SOFT_HPQM */ /* Address which has OTP location containing the factory test program version */ #define RPU_MEM_OTP_FT_PROG_VERSION 0xB0004FD8 /* Address which has the OTP flags */ diff --git a/hw_if/hal/src/common/hal_api_common.c b/hw_if/hal/src/common/hal_api_common.c index a6f53ec..a7d363d 100644 --- a/hw_if/hal/src/common/hal_api_common.c +++ b/hw_if/hal/src/common/hal_api_common.c @@ -220,6 +220,48 @@ enum nrf_wifi_status nrf_wifi_hal_get_rpu_ps_state( #endif /* NRF_WIFI_LOW_POWER */ +#ifdef NRF71_SOFT_HPQM +static bool hal_rpu_soft_hpq_is_empty(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + unsigned int val = 0; + unsigned int cur_index = 0; + unsigned long addr = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_cmd_free_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the host_event_busy_index = %x" + " address failed, val (0x%X)\n", + __func__, + (unsigned int)addr, + cur_index); + return true; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->cmd_free_buffs[cur_index]; + status = hal_rpu_mem_read(hal_dev_ctx, + &val, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from dequeue address %x failed, val (0x%X)\n", + __func__, + (unsigned int)addr, + val); + return true; + } + if (val) { + return false; + } + return true; +} +#else static bool hal_rpu_hpq_is_empty(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, struct host_rpu_hpq *hpq) { @@ -243,12 +285,27 @@ static bool hal_rpu_hpq_is_empty(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, return true; } +#endif /* NRF71_SOFT_HPQM */ static enum nrf_wifi_status hal_rpu_ready(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, enum NRF_WIFI_HAL_MSG_TYPE msg_type) { bool is_empty = false; +#ifdef NRF71_SOFT_HPQM + if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) { + is_empty = hal_rpu_soft_hpq_is_empty(hal_dev_ctx); + if (is_empty == true) { + return NRF_WIFI_STATUS_FAIL; + } + } else { + nrf_wifi_osal_log_err("%s: Invalid msg type %d", + __func__, + msg_type); + + return NRF_WIFI_STATUS_FAIL; + } +#else struct host_rpu_hpq *avl_buf_q = NULL; if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) { @@ -268,11 +325,11 @@ static enum nrf_wifi_status hal_rpu_ready(struct nrf_wifi_hal_dev_ctx *hal_dev_c if (is_empty == true) { return NRF_WIFI_STATUS_FAIL; } +#endif /* NRF71_SOFT_HPQM */ return NRF_WIFI_STATUS_SUCCESS; } - static enum nrf_wifi_status hal_rpu_ready_wait(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, enum NRF_WIFI_HAL_MSG_TYPE msg_type) { @@ -315,13 +372,124 @@ static enum nrf_wifi_status hal_rpu_msg_trigger(struct nrf_wifi_hal_dev_ctx *hal return status; } - enum nrf_wifi_status hal_rpu_msg_post(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, enum NRF_WIFI_HAL_MSG_TYPE msg_type, unsigned int queue_id, unsigned int msg_addr) { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; +#ifdef NRF71_SOFT_HPQM + unsigned int cur_index = 0; + unsigned long addr = 0; + + if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) { + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_cmd_free_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the cmd_free_index = %x " + "addr failed, val (0x%X)\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->cmd_busy_buffs[cur_index]; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)msg_addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to cmd_busy_buffs[%d] " + " addr = %x failed msg_addr = %x\n", + __func__, + cur_index, + (unsigned int)addr, + msg_addr); + goto out; + } + + cur_index++; + if (cur_index == NRF_WIFI_HOST_RPU_CMD_BUFFERS) + cur_index = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_cmd_free_index; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)cur_index, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to cmd_free_index = %x " + " failed for val =%d\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + } else if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_TX) { + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_tx_cmd_busy_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the event_busy_index = %x " + " addr failed, val (0x%X)\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->tx_cmd_buffs[cur_index]; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)msg_addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to tx_cmd_buffs[%d] " + "addr = %x failed val=%x\n", + __func__, + cur_index, + (unsigned int)addr, + msg_addr); + goto out; + } + + cur_index++; + if (cur_index == NRF_WIFI_HOST_RPU_TX_DESC) + cur_index = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_tx_cmd_busy_index; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)cur_index, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to cmd_free_index = %x failed for val =%d\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + } else if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX) { + ;/* Nothing to do */ + } else { + nrf_wifi_osal_log_err("%s: Invalid msg_type (%d)", + __func__, + msg_type); + goto out; + } +#else struct host_rpu_hpq *busy_queue = NULL; if (queue_id >= MAX_NUM_OF_RX_QUEUES) { @@ -355,6 +523,7 @@ enum nrf_wifi_status hal_rpu_msg_post(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, __func__); goto out; } +#endif /* NRF71_SOFT_HPQM */ if (msg_type != NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX) { /* Indicate to the RPU that the information has been posted */ @@ -376,6 +545,78 @@ static enum nrf_wifi_status hal_rpu_msg_get_addr(struct nrf_wifi_hal_dev_ctx *ha unsigned int *msg_addr) { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; +#ifdef NRF71_SOFT_HPQM + unsigned int val = 0; + unsigned int cur_index = 0; + unsigned long addr = 0; + + if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) { + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_cmd_free_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the event_busy_index = %x" + "addr failed, val (0x%X)\n", + __func__, + addr, + cur_index); + goto out; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->cmd_free_buffs[cur_index]; + status = hal_rpu_mem_read(hal_dev_ctx, + &val, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the cmd_free_buffs[%d] = %x" + " addr failed, val (0x%X)\n", + __func__, + cur_index, + addr, + val); + goto out; + } + } else { + nrf_wifi_osal_log_err("%s: Invalid msg type %d\n", + __func__, + msg_type); + return NRF_WIFI_STATUS_FAIL; + } + + if (!val) { + nrf_wifi_osal_log_err("%s:No valid content avaialble in the expected index \n", + __func__, + cur_index); + *msg_addr = 0; + status = NRF_WIFI_STATUS_FAIL; + goto out; + } else { + /* Valid address has been read. + * So write back 0 to same index address at cmd_free_buffs. + */ + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->cmd_free_buffs[cur_index]; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + 0x0, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Write to address %xfailed, val (0x%X)\n", + __func__, + addr, + 0x0); + return true; + } + + *msg_addr = val; /* Assign the address read from cmd_free_buffs cur_index */ + status = NRF_WIFI_STATUS_SUCCESS; + } +#else struct host_rpu_hpq *avl_queue = NULL; if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) { @@ -398,6 +639,7 @@ static enum nrf_wifi_status hal_rpu_msg_get_addr(struct nrf_wifi_hal_dev_ctx *ha *msg_addr = 0; goto out; } +#endif /*NRF71_SOFT_HPQM */ out: return status; } @@ -748,6 +990,11 @@ enum nrf_wifi_status nrf_wifi_hal_dev_init(struct nrf_wifi_hal_dev_ctx *hal_dev_ } #ifndef NRF71_ON_IPC +#ifdef NRF71_SOFT_HPQM + hal_dev_ctx->rpu_info.soft_hpq = + (struct soft_hpqm_info *)NRF_WIFI_SOFTHPQM_INFO_START_ADDR; + +#else /* Read the HPQM info for all the queues provided by the RPU * (like command, event, RX buf queues etc) */ @@ -755,6 +1002,7 @@ enum nrf_wifi_status nrf_wifi_hal_dev_init(struct nrf_wifi_hal_dev_ctx *hal_dev_ &hal_dev_ctx->rpu_info.hpqm_info, RPU_MEM_HPQ_INFO, sizeof(hal_dev_ctx->rpu_info.hpqm_info)); +#endif /* NRF71_SOFT_HPQM */ if (status != NRF_WIFI_STATUS_SUCCESS) { nrf_wifi_osal_log_err("%s: Failed to get the HPQ info", diff --git a/hw_if/hal/src/common/hal_interrupt.c b/hw_if/hal/src/common/hal_interrupt.c index 15284e7..2a98439 100644 --- a/hw_if/hal/src/common/hal_interrupt.c +++ b/hw_if/hal/src/common/hal_interrupt.c @@ -207,6 +207,60 @@ static enum nrf_wifi_status hal_rpu_event_free(struct nrf_wifi_hal_dev_ctx *hal_ unsigned int event_addr) { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; +#ifdef NRF71_SOFT_HPQM + unsigned int cur_index = 0; + unsigned long addr = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_event_busy_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the event_busy_index = %x " + "address failed, val (0x%X)\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->event_free_buffs[cur_index]; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)event_addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to freebuffs[index=%d] " + " address = %x failed for event_addr= %x\n", + __func__, + cur_index, + (unsigned int)addr, + event_addr); + goto out; + } + + cur_index++; + if (cur_index == NRF_WIFI_HOST_RPU_EVENT_BUFFERS) + cur_index = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_event_busy_index; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)cur_index, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to event_busy_index address = %x " + "failed for val =%d\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } +#else status = hal_rpu_hpq_enqueue(hal_dev_ctx, &hal_dev_ctx->rpu_info.hpqm_info.event_avl_queue, @@ -217,7 +271,7 @@ static enum nrf_wifi_status hal_rpu_event_free(struct nrf_wifi_hal_dev_ctx *hal_ __func__); goto out; } - +#endif /* NRF71_SOFT_HPQM */ out: return status; } @@ -441,7 +495,124 @@ static unsigned int hal_rpu_event_get_all(struct nrf_wifi_hal_dev_ctx *hal_dev_c while (1) { event_addr = 0; +#ifdef NRF71_SOFT_HPQM + unsigned int desc_no = 0; + unsigned int cur_index = 0; + unsigned long addr = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_event_busy_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from the event_busy_index = %x addr failed, val (0x%X)\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->event_busy_buffs[cur_index]; + status = hal_rpu_mem_read(hal_dev_ctx, + &event_addr, + (unsigned int)addr, + sizeof(unsigned int)); + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Read from event_busy_buffs[%d]= %x addr failed, val (0x%X)\n", + __func__, + cur_index, + (unsigned int)addr, + event_addr); + goto out; + } + + if (!event_addr) { + for (desc_no = 0; desc_no < NRF_WIFI_HOST_RPU_TX_DESC; desc_no++) { + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_tx_done_busy_index; + status = hal_rpu_mem_read(hal_dev_ctx, + &cur_index, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Reading tx_done_busy_index = %x failed,val(0x%X)\n", + __func__, + (unsigned int)addr, + cur_index); + goto out; + } + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->tx_done_buffs[cur_index]; + status = hal_rpu_mem_read(hal_dev_ctx, + &event_addr, + (unsigned int)addr, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Reading tx_done_buffs[%d] = %x failed, val (0x%X)\n", + __func__, + cur_index, + (unsigned char)addr, + event_addr); + goto out; + } + + if (!event_addr) { + continue; + } else { + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->tx_done_buffs[cur_index]; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + 0x0, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to tx_done_buffs[%d] = %x failed \n", + __func__, + cur_index, + (unsigned int)addr); + goto out; + } + + cur_index++; + if (cur_index == NRF_WIFI_HOST_RPU_TX_DESC) + cur_index = 0; + + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->host_tx_done_busy_index; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + (void *)(unsigned long)cur_index, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing %d to tx_done_busy_index %x failed \n", + __func__, + cur_index, + (unsigned int)addr); + goto out; + } + break; + } + } + } else { + addr = (unsigned long)&hal_dev_ctx->rpu_info.soft_hpq->event_busy_buffs[cur_index]; + status = hal_rpu_mem_write(hal_dev_ctx, + (unsigned int)addr, + 0x0, + sizeof(unsigned int)); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err("%s: Writing to event_busy_buffs[%d] = %x addr failed \n", + __func__, + cur_index, + (unsigned int)addr); + goto out; + } + } +#else /* First get the event address */ status = hal_rpu_hpq_dequeue(hal_dev_ctx, &hal_dev_ctx->rpu_info.hpqm_info.event_busy_queue, @@ -453,6 +624,7 @@ static unsigned int hal_rpu_event_get_all(struct nrf_wifi_hal_dev_ctx *hal_dev_c goto out; } +#endif /* NRF71_SOFT_HPQM */ /* No more events to read. Sometimes when low power mode is enabled * we see a wrong address, but it work after a while, so, add a * check for that.