diff --git a/CMakeLists.txt b/CMakeLists.txt index 7844fc4..2f6b441 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,8 @@ target_compile_definitions( $<$:NRF71_ON_IPC> $<$: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/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_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/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/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/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/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. 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,