diff options
Diffstat (limited to 'drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c')
-rw-r--r-- | drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c | 1959 |
1 files changed, 1959 insertions, 0 deletions
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c new file mode 100644 index 000000000000..e81299d690a4 --- /dev/null +++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlan/mlan_init.c @@ -0,0 +1,1959 @@ +/** @file mlan_init.c + * + * @brief This file contains the initialization for FW + * and HW. + * + * + * Copyright 2014-2020 NXP + * + * This software file (the File) is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 + * (the License). You may use, redistribute and/or modify the File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ + +/******************************************************** +Change log: + 10/13/2008: initial version +********************************************************/ + +#include "mlan.h" +#ifdef STA_SUPPORT +#include "mlan_join.h" +#endif +#include "mlan_util.h" +#include "mlan_fw.h" +#include "mlan_main.h" +#include "mlan_init.h" +#include "mlan_wmm.h" +#include "mlan_11n.h" +#include "mlan_11ac.h" +#include "mlan_11h.h" +#include "mlan_meas.h" +#ifdef SDIO +#include "mlan_sdio.h" +#endif +#ifdef PCIE +#include "mlan_pcie.h" +#endif /* PCIE */ +#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT) +#include "hostsa_init.h" +#endif +#include "mlan_11ax.h" + +/******************************************************** + Global Variables +********************************************************/ +extern pmlan_operations mlan_ops[]; +/******************************************************* + Local Functions +********************************************************/ + +/** + * @brief This function adds a BSS priority table + * + * @param priv A pointer to mlan_private structure + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +static mlan_status wlan_add_bsspriotbl(pmlan_private priv) +{ + pmlan_adapter pmadapter = priv->adapter; + mlan_bssprio_node *pbssprio = MNULL; + mlan_status status = MLAN_STATUS_SUCCESS; + + ENTER(); + + status = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, + sizeof(mlan_bssprio_node), + MLAN_MEM_DEF, + (t_u8 **)&pbssprio); + if (status) { + PRINTM(MERROR, "Failed to allocate bsspriotbl\n"); + LEAVE(); + return status; + } + + pbssprio->priv = priv; + + util_init_list((pmlan_linked_list)pbssprio); + + if (!pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur) + pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur = + pbssprio; + + util_enqueue_list_tail( + pmadapter->pmoal_handle, + &pmadapter->bssprio_tbl[priv->bss_priority].bssprio_head, + (pmlan_linked_list)pbssprio, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks.moal_spin_unlock); + + LEAVE(); + return status; +} + +/** + * @brief This function deletes the BSS priority table + * + * @param priv A pointer to mlan_private structure + * + * @return N/A + */ +static t_void wlan_delete_bsspriotbl(pmlan_private priv) +{ + int i; + pmlan_adapter pmadapter = priv->adapter; + mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL, + **ppcur = MNULL; + pmlan_list_head phead; + + ENTER(); + + for (i = 0; i < pmadapter->priv_num; ++i) { + phead = &pmadapter->bssprio_tbl[i].bssprio_head; + ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur; + PRINTM(MINFO, + "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n", + priv->bss_index, i, phead, *ppcur); + if (*ppcur) { + pbssprio_node = (mlan_bssprio_node *)util_peek_list( + pmadapter->pmoal_handle, phead, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks.moal_spin_unlock); + while (pbssprio_node && + ((pmlan_list_head)pbssprio_node != phead)) { + ptmp_node = pbssprio_node->pnext; + if (pbssprio_node->priv == priv) { + PRINTM(MINFO, + "Delete node, pnode = %p, pnext = %p\n", + pbssprio_node, ptmp_node); + util_unlink_list( + pmadapter->pmoal_handle, phead, + (pmlan_linked_list)pbssprio_node, + pmadapter->callbacks + .moal_spin_lock, + pmadapter->callbacks + .moal_spin_unlock); + pmadapter->callbacks.moal_mfree( + pmadapter->pmoal_handle, + (t_u8 *)pbssprio_node); + } + pbssprio_node = ptmp_node; + } + *ppcur = (mlan_bssprio_node *)phead; + } + } + + LEAVE(); +} + +/** + * @brief The function handles VDLL init + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS + * + */ +static mlan_status vdll_init(pmlan_adapter pmadapter) +{ + mlan_status status = MLAN_STATUS_SUCCESS; + vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl; + + ENTER(); + memset(pmadapter, ctrl, 0, sizeof(vdll_dnld_ctrl)); +#if defined(SDIO) || defined(PCIE) + if (!IS_USB(pmadapter->card_type)) { + ctrl->cmd_buf = + wlan_alloc_mlan_buffer(pmadapter, + MRVDRV_SIZE_OF_CMD_BUFFER, 0, + MOAL_MALLOC_BUFFER); + if (!ctrl->cmd_buf) { + PRINTM(MERROR, + "vdll init: fail to alloc command buffer"); + status = MLAN_STATUS_FAILURE; + } + } +#endif + LEAVE(); + return status; +} +/** + * @brief The function handles VDLL deinit + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS + * + */ +static t_void vdll_deinit(pmlan_adapter pmadapter) +{ + pmlan_callbacks pcb = &pmadapter->callbacks; + ENTER(); + if (pmadapter->vdll_ctrl.vdll_mem != MNULL) { + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->vdll_ctrl.vdll_mem); + else + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->vdll_ctrl.vdll_mem); + pmadapter->vdll_ctrl.vdll_mem = MNULL; + pmadapter->vdll_ctrl.vdll_len = 0; + } +#if defined(SDIO) || defined(PCIE) + if (!IS_USB(pmadapter->card_type) && + pmadapter->vdll_ctrl.cmd_buf != MNULL) { + wlan_free_mlan_buffer(pmadapter, pmadapter->vdll_ctrl.cmd_buf); + pmadapter->vdll_ctrl.cmd_buf = MNULL; + } +#endif + LEAVE(); +} + +/******************************************************** + Global Functions +********************************************************/ + +/** + * @brief This function allocates buffer for the members of adapter + * structure like command buffer and BSSID list. + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; +#ifdef STA_SUPPORT + t_u32 beacon_buffer_size; + t_u32 buf_size; + BSSDescriptor_t *ptemp_scan_table = MNULL; + t_u8 chan_2g[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + t_u8 chan_5g[] = {12, 16, 34, 38, 42, 46, 36, 40, 44, 48, 52, + 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, + 132, 136, 140, 144, 149, 153, 157, 161, 165}; +#endif +#ifdef SDIO + t_u32 max_mp_regs = 0; + t_u32 mp_tx_aggr_buf_size = 0; + t_u32 mp_rx_aggr_buf_size = 0; +#endif + + ENTER(); + +#ifdef SDIO + if (IS_SD(pmadapter->card_type)) { + max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs; + mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX; + mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX; + } +#endif + +#ifdef STA_SUPPORT + /* Allocate buffer to store the BSSID list */ + buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; + if (pmadapter->callbacks.moal_vmalloc && + pmadapter->callbacks.moal_vfree) + ret = pmadapter->callbacks.moal_vmalloc( + pmadapter->pmoal_handle, buf_size, + (t_u8 **)&ptemp_scan_table); + else + ret = pmadapter->callbacks.moal_malloc( + pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, + (t_u8 **)&ptemp_scan_table); + if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) { + PRINTM(MERROR, "Failed to allocate scan table\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + pmadapter->pscan_table = ptemp_scan_table; + + if (pmadapter->fixed_beacon_buffer) + beacon_buffer_size = MAX_SCAN_BEACON_BUFFER; + else + beacon_buffer_size = DEFAULT_SCAN_BEACON_BUFFER; + ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, + beacon_buffer_size, MLAN_MEM_DEF, + (t_u8 **)&pmadapter->bcn_buf); + if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) { + PRINTM(MERROR, "Failed to allocate bcn buf\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + pmadapter->bcn_buf_size = beacon_buffer_size; + + pmadapter->num_in_chan_stats = sizeof(chan_2g); + pmadapter->num_in_chan_stats += sizeof(chan_5g); + buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats; + if (pmadapter->callbacks.moal_vmalloc && + pmadapter->callbacks.moal_vfree) + ret = pmadapter->callbacks.moal_vmalloc( + pmadapter->pmoal_handle, buf_size, + (t_u8 **)&pmadapter->pchan_stats); + else + ret = pmadapter->callbacks.moal_malloc( + pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, + (t_u8 **)&pmadapter->pchan_stats); + if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) { + PRINTM(MERROR, "Failed to allocate channel statistics\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } +#endif + + /* Allocate command buffer */ + ret = wlan_alloc_cmd_buffer(pmadapter); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MERROR, "Failed to allocate command buffer\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + +#ifdef SDIO + if (IS_SD(pmadapter->card_type)) { + ret = pmadapter->callbacks.moal_malloc( + pmadapter->pmoal_handle, max_mp_regs + DMA_ALIGNMENT, + MLAN_MEM_DEF | MLAN_MEM_DMA, + (t_u8 **)&pmadapter->pcard_sd->mp_regs_buf); + if (ret != MLAN_STATUS_SUCCESS || + !pmadapter->pcard_sd->mp_regs_buf) { + PRINTM(MERROR, "Failed to allocate mp_regs_buf\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + pmadapter->pcard_sd->mp_regs = (t_u8 *)ALIGN_ADDR( + pmadapter->pcard_sd->mp_regs_buf, DMA_ALIGNMENT); + + ret = pmadapter->callbacks.moal_malloc( + pmadapter->pmoal_handle, MAX_SUPPORT_AMSDU_SIZE, + MLAN_MEM_DEF | MLAN_MEM_DMA, + (t_u8 **)&pmadapter->pcard_sd->rx_buffer); + + if (ret != MLAN_STATUS_SUCCESS || + !pmadapter->pcard_sd->rx_buffer) { + PRINTM(MERROR, "Failed to allocate receive buffer\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + pmadapter->pcard_sd->rx_buf = (t_u8 *)ALIGN_ADDR( + pmadapter->pcard_sd->rx_buffer, DMA_ALIGNMENT); + + pmadapter->pcard_sd->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE; + pmadapter->pcard_sd->max_sp_rx_size = MAX_SUPPORT_AMSDU_SIZE; + ret = wlan_alloc_sdio_mpa_buffers( + pmadapter, mp_tx_aggr_buf_size, mp_rx_aggr_buf_size); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MERROR, + "Failed to allocate sdio mp-a buffers\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } +#ifdef DEBUG_LEVEL1 + if (mlan_drvdbg & MMPA_D) { + pmadapter->pcard_sd->mpa_buf_size = + SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT * + MLAN_SDIO_BLOCK_SIZE; + if (pmadapter->callbacks.moal_vmalloc && + pmadapter->callbacks.moal_vfree) + ret = pmadapter->callbacks.moal_vmalloc( + pmadapter->pmoal_handle, + pmadapter->pcard_sd->mpa_buf_size, + (t_u8 **)&pmadapter->pcard_sd->mpa_buf); + else + ret = pmadapter->callbacks.moal_malloc( + pmadapter->pmoal_handle, + pmadapter->pcard_sd->mpa_buf_size, + MLAN_MEM_DEF, + (t_u8 **)&pmadapter->pcard_sd->mpa_buf); + if (ret != MLAN_STATUS_SUCCESS || + !pmadapter->pcard_sd->mpa_buf) { + PRINTM(MERROR, "Failed to allocate mpa buf\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + } +#endif + } +#endif + + pmadapter->psleep_cfm = + wlan_alloc_mlan_buffer(pmadapter, + sizeof(opt_sleep_confirm_buffer), 0, + MOAL_MALLOC_BUFFER); + +#ifdef PCIE + /* Initialize PCIE ring buffer */ + if (IS_PCIE(pmadapter->card_type)) { + ret = wlan_alloc_pcie_ring_buf(pmadapter); + if (MLAN_STATUS_SUCCESS != ret) { + PRINTM(MERROR, + "Failed to allocate PCIE host buffers\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + } +#endif /* PCIE */ + + vdll_init(pmadapter); + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief This function initializes the private structure + * and sets default values to the members of mlan_private. + * + * @param priv A pointer to mlan_private structure + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status wlan_init_priv(pmlan_private priv) +{ + t_u32 i; + pmlan_adapter pmadapter = priv->adapter; + mlan_status ret = MLAN_STATUS_SUCCESS; +#ifdef USB + pusb_tx_aggr_params pusb_tx_aggr = MNULL; +#endif + + ENTER(); + + priv->media_connected = MFALSE; + memset(pmadapter, priv->curr_addr, 0xff, MLAN_MAC_ADDR_LENGTH); + +#ifdef STA_SUPPORT + priv->pkt_tx_ctrl = 0; + priv->bss_mode = MLAN_BSS_MODE_INFRA; + priv->data_rate = 0; /* Initially indicate the rate as auto */ + priv->is_data_rate_auto = MTRUE; + priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; + priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; + + priv->sec_info.wep_status = Wlan802_11WEPDisabled; + priv->sec_info.authentication_mode = MLAN_AUTH_MODE_AUTO; + priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE; + for (i = 0; i < MRVL_NUM_WEP_KEY; i++) + memset(pmadapter, &priv->wep_key[i], 0, sizeof(mrvl_wep_key_t)); + priv->wep_key_curr_index = 0; + priv->ewpa_query = MFALSE; + priv->curr_pkt_filter = HostCmd_ACT_MAC_STATIC_DYNAMIC_BW_ENABLE | + HostCmd_ACT_MAC_RTS_CTS_ENABLE | + HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON | + HostCmd_ACT_MAC_ETHERNETII_ENABLE; + + priv->beacon_period = MLAN_BEACON_INTERVAL; + priv->pattempted_bss_desc = MNULL; + memset(pmadapter, &priv->gtk_rekey, 0, + sizeof(mlan_ds_misc_gtk_rekey_data)); + memset(pmadapter, &priv->curr_bss_params, 0, + sizeof(priv->curr_bss_params)); + priv->listen_interval = MLAN_DEFAULT_LISTEN_INTERVAL; + + memset(pmadapter, &priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); + priv->assoc_rsp_size = 0; + + wlan_11d_priv_init(priv); + wlan_11h_priv_init(priv); + +#ifdef UAP_SUPPORT + priv->uap_bss_started = MFALSE; + priv->uap_host_based = MFALSE; + memset(pmadapter, &priv->uap_state_chan_cb, 0, + sizeof(priv->uap_state_chan_cb)); +#endif +#ifdef UAP_SUPPORT + priv->num_drop_pkts = 0; +#endif +#if defined(STA_SUPPORT) + priv->adhoc_state_prev = ADHOC_IDLE; + memset(pmadapter, &priv->adhoc_last_start_ssid, 0, + sizeof(priv->adhoc_last_start_ssid)); +#endif + priv->atim_window = 0; + priv->adhoc_state = ADHOC_IDLE; + priv->tx_power_level = 0; + priv->max_tx_power_level = 0; + priv->min_tx_power_level = 0; + priv->tx_rate = 0; + priv->rxpd_rate_info = 0; + priv->rx_pkt_info = MFALSE; + /* refer to V15 CMD_TX_RATE_QUERY */ + priv->rxpd_vhtinfo = 0; + priv->rxpd_rate = 0; + priv->data_rssi_last = 0; + priv->data_rssi_avg = 0; + priv->data_nf_avg = 0; + priv->data_nf_last = 0; + priv->bcn_rssi_last = 0; + priv->bcn_rssi_avg = 0; + priv->bcn_nf_avg = 0; + priv->bcn_nf_last = 0; + priv->sec_info.ewpa_enabled = MFALSE; + priv->sec_info.wpa_enabled = MFALSE; + priv->sec_info.wpa2_enabled = MFALSE; + memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie)); + memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key)); + priv->wpa_ie_len = 0; + priv->wpa_is_gtk_set = MFALSE; +#if defined(STA_SUPPORT) + priv->pmfcfg.mfpc = 0; + priv->pmfcfg.mfpr = 0; +#endif + priv->sec_info.wapi_enabled = MFALSE; + priv->wapi_ie_len = 0; + priv->sec_info.wapi_key_on = MFALSE; + + memset(pmadapter, &priv->wps, 0, sizeof(priv->wps)); + memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); + priv->gen_ie_buf_len = 0; +#endif /* STA_SUPPORT */ + priv->wmm_required = MTRUE; + priv->wmm_enabled = MFALSE; + priv->wmm_qosinfo = 0; +#ifdef STA_SUPPORT + priv->pcurr_bcn_buf = MNULL; + priv->curr_bcn_size = 0; + memset(pmadapter, &priv->ext_cap, 0, sizeof(priv->ext_cap)); + + SET_EXTCAP_OPERMODENTF(priv->ext_cap); + SET_EXTCAP_QOS_MAP(priv->ext_cap); + /* Save default Extended Capability */ + memcpy_ext(priv->adapter, &priv->def_ext_cap, &priv->ext_cap, + sizeof(priv->ext_cap), sizeof(priv->def_ext_cap)); +#endif /* STA_SUPPORT */ + + for (i = 0; i < MAX_NUM_TID; i++) + priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT; + priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT; + priv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT; + memcpy_ext(priv->adapter, priv->ibss_addba_reject, priv->addba_reject, + sizeof(priv->addba_reject), sizeof(priv->ibss_addba_reject)); + priv->max_amsdu = 0; +#ifdef STA_SUPPORT + if (priv->bss_type == MLAN_BSS_TYPE_STA) { + priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE; + } +#endif +#ifdef WIFI_DIRECT_SUPPORT + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { + priv->add_ba_param.tx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE; + priv->add_ba_param.rx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE; + } +#endif +#ifdef UAP_SUPPORT + if (priv->bss_type == MLAN_BSS_TYPE_UAP) { + priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE; + priv->aggr_prio_tbl[6].ampdu_user = + priv->aggr_prio_tbl[7].ampdu_user = + BA_STREAM_NOT_ALLOWED; + } +#endif + priv->user_rxwinsize = priv->add_ba_param.rx_win_size; + + priv->port_ctrl_mode = MTRUE; + priv->port_open = MFALSE; + + priv->intf_hr_len = pmadapter->ops.intf_header_len; +#ifdef USB + if (IS_USB(pmadapter->card_type)) { + pusb_tx_aggr = + wlan_get_usb_tx_aggr_params(pmadapter, priv->port); + if (pusb_tx_aggr && pusb_tx_aggr->aggr_ctrl.aggr_mode == + MLAN_USB_AGGR_MODE_LEN_V2) { + priv->intf_hr_len = MLAN_USB_TX_AGGR_HEADER; + } + priv->port = pmadapter->tx_data_ep; + } +#endif + ret = wlan_add_bsspriotbl(priv); +#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT) + hostsa_init(priv); +#endif + + LEAVE(); + return ret; +} + +/** + * @brief This function initializes the adapter structure + * and sets default values to the members of adapter. + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return N/A + */ +t_void wlan_init_adapter(pmlan_adapter pmadapter) +{ + opt_sleep_confirm_buffer *sleep_cfm_buf = MNULL; +#ifdef USB + t_s32 i = 0; +#endif + ENTER(); + + if (pmadapter->psleep_cfm) { + sleep_cfm_buf = (opt_sleep_confirm_buffer + *)(pmadapter->psleep_cfm->pbuf + + pmadapter->psleep_cfm->data_offset); + } +#ifdef MFG_CMD_SUPPORT + if (pmadapter->init_para.mfg_mode == MLAN_INIT_PARA_DISABLED) + pmadapter->mfg_mode = MFALSE; + else + pmadapter->mfg_mode = pmadapter->init_para.mfg_mode; +#endif + +#ifdef STA_SUPPORT + pmadapter->pwarm_reset_ioctl_req = MNULL; +#endif + pmadapter->cmd_sent = MFALSE; +#ifdef SDIO + if (IS_SD(pmadapter->card_type)) { + pmadapter->pcard_sd->int_mode = pmadapter->init_para.int_mode; + pmadapter->pcard_sd->gpio_pin = pmadapter->init_para.gpio_pin; + pmadapter->data_sent = MTRUE; + pmadapter->pcard_sd->mp_rd_bitmap = 0; + pmadapter->pcard_sd->mp_wr_bitmap = 0; + pmadapter->pcard_sd->curr_rd_port = 0; + pmadapter->pcard_sd->curr_wr_port = 0; + pmadapter->pcard_sd->mp_data_port_mask = + pmadapter->pcard_sd->reg->data_port_mask; + pmadapter->pcard_sd->mp_invalid_update = 0; + memset(pmadapter, pmadapter->pcard_sd->mp_update, 0, + sizeof(pmadapter->pcard_sd->mp_update)); + pmadapter->pcard_sd->mpa_tx.buf_len = 0; + pmadapter->pcard_sd->mpa_tx.pkt_cnt = 0; + pmadapter->pcard_sd->mpa_tx.start_port = 0; + + if (!pmadapter->init_para.mpa_tx_cfg) + pmadapter->pcard_sd->mpa_tx.enabled = MFALSE; + else if (pmadapter->init_para.mpa_tx_cfg == + MLAN_INIT_PARA_DISABLED) + pmadapter->pcard_sd->mpa_tx.enabled = MFALSE; + else + pmadapter->pcard_sd->mpa_tx.enabled = MTRUE; + pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit = + SDIO_MP_AGGR_DEF_PKT_LIMIT; + + pmadapter->pcard_sd->mpa_rx.buf_len = 0; + pmadapter->pcard_sd->mpa_rx.pkt_cnt = 0; + pmadapter->pcard_sd->mpa_rx.start_port = 0; + + if (!pmadapter->init_para.mpa_rx_cfg) + pmadapter->pcard_sd->mpa_rx.enabled = MFALSE; + else if (pmadapter->init_para.mpa_rx_cfg == + MLAN_INIT_PARA_DISABLED) + pmadapter->pcard_sd->mpa_rx.enabled = MFALSE; + else + pmadapter->pcard_sd->mpa_rx.enabled = MTRUE; + pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit = + SDIO_MP_AGGR_DEF_PKT_LIMIT; + } +#endif + + pmadapter->rx_pkts_queued = 0; + pmadapter->cmd_resp_received = MFALSE; + pmadapter->event_received = MFALSE; + pmadapter->data_received = MFALSE; + + pmadapter->cmd_timer_is_set = MFALSE; + + /* PnP and power profile */ + pmadapter->surprise_removed = MFALSE; + /* FW hang report */ + pmadapter->fw_hang_report = MFALSE; + + if (!pmadapter->init_para.ps_mode) { + pmadapter->ps_mode = DEFAULT_PS_MODE; + } else if (pmadapter->init_para.ps_mode == MLAN_INIT_PARA_DISABLED) + pmadapter->ps_mode = Wlan802_11PowerModeCAM; + else + pmadapter->ps_mode = Wlan802_11PowerModePSP; + pmadapter->ps_state = PS_STATE_AWAKE; + pmadapter->need_to_wakeup = MFALSE; + +#ifdef STA_SUPPORT + pmadapter->scan_block = MFALSE; + /* Scan type */ + pmadapter->scan_type = MLAN_SCAN_TYPE_ACTIVE; + /* Scan mode */ + pmadapter->scan_mode = HostCmd_BSS_MODE_ANY; + /* Scan time */ + pmadapter->specific_scan_time = MRVDRV_SPECIFIC_SCAN_CHAN_TIME; + pmadapter->active_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME; + pmadapter->passive_scan_time = MRVDRV_PASSIVE_SCAN_CHAN_TIME; + if (!pmadapter->init_para.passive_to_active_scan) + pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN; + else if (pmadapter->init_para.passive_to_active_scan == + MLAN_INIT_PARA_DISABLED) + pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_DIS; + else + pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN; + + pmadapter->scan_chan_gap = 0; + pmadapter->num_in_scan_table = 0; + memset(pmadapter, pmadapter->pscan_table, 0, + (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST)); + pmadapter->active_scan_triggered = MFALSE; + pmadapter->ext_scan = MTRUE; + pmadapter->scan_probes = DEFAULT_PROBES; + + memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size); + pmadapter->pbcn_buf_end = pmadapter->bcn_buf; + + pmadapter->radio_on = RADIO_ON; + if (!pmadapter->multiple_dtim) + pmadapter->multiple_dtim = MRVDRV_DEFAULT_MULTIPLE_DTIM; + + pmadapter->local_listen_interval = 0; /* default value in firmware will + be used */ +#endif /* STA_SUPPORT */ + + pmadapter->is_deep_sleep = MFALSE; + pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME; + if (!pmadapter->init_para.auto_ds) + pmadapter->init_auto_ds = DEFAULT_AUTO_DS_MODE; + else if (pmadapter->init_para.auto_ds == MLAN_INIT_PARA_DISABLED) + pmadapter->init_auto_ds = MFALSE; + else + pmadapter->init_auto_ds = MTRUE; + + pmadapter->delay_null_pkt = MFALSE; + pmadapter->delay_to_ps = DELAY_TO_PS_DEFAULT; + pmadapter->enhanced_ps_mode = PS_MODE_AUTO; + + pmadapter->gen_null_pkt = MFALSE; /* Disable NULL Pkt generation-default + */ + pmadapter->pps_uapsd_mode = MFALSE; /* Disable pps/uapsd mode -default + */ + + pmadapter->pm_wakeup_card_req = MFALSE; + + pmadapter->pm_wakeup_fw_try = MFALSE; + + if (!pmadapter->init_para.max_tx_buf) + pmadapter->max_tx_buf_size = + pmadapter->pcard_info->max_tx_buf_size; + else + pmadapter->max_tx_buf_size = + (t_u16)pmadapter->init_para.max_tx_buf; + pmadapter->tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K; + pmadapter->curr_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K; + +#ifdef USB + if (IS_USB(pmadapter->card_type)) { + for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) { + pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable = + MFALSE; + pmadapter->pcard_usb->usb_tx_aggr[i] + .aggr_ctrl.aggr_mode = + MLAN_USB_AGGR_MODE_LEN_V2; + pmadapter->pcard_usb->usb_tx_aggr[i] + .aggr_ctrl.aggr_align = + MLAN_USB_TX_AGGR_V2_ALIGN; + pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.aggr_max = + MLAN_USB_TX_AGGR_MAX_LEN; + pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.aggr_tmo = + MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000; + + pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr = MNULL; + pmadapter->pcard_usb->usb_tx_aggr[i].aggr_len = 0; + pmadapter->pcard_usb->usb_tx_aggr[i].hold_timeout_msec = + MLAN_USB_TX_AGGR_TIMEOUT_MSEC; + pmadapter->pcard_usb->usb_tx_aggr[i].port = + pmadapter->tx_data_ep; + pmadapter->pcard_usb->usb_tx_aggr[i].phandle = + (t_void *)pmadapter; + } + + pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable = MFALSE; + pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_mode = + MLAN_USB_AGGR_MODE_NUM; + pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align = + MLAN_USB_RX_ALIGN_SIZE; + pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_max = + MLAN_USB_RX_MAX_AGGR_NUM; + pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_tmo = + MLAN_USB_RX_DEAGGR_TIMEOUT_USEC; + + pmadapter->pcard_usb->fw_usb_aggr = MTRUE; + } +#endif + + pmadapter->is_hs_configured = MFALSE; + pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND; + pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO; + pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP; + pmadapter->hs_activated = MFALSE; + pmadapter->min_wake_holdoff = HOST_SLEEP_DEF_WAKE_HOLDOFF; + pmadapter->hs_inactivity_timeout = HOST_SLEEP_DEF_INACTIVITY_TIMEOUT; + + memset(pmadapter, pmadapter->event_body, 0, + sizeof(pmadapter->event_body)); + pmadapter->hw_dot_11n_dev_cap = 0; + pmadapter->hw_dev_mcs_support = 0; + pmadapter->coex_rx_winsize = 1; +#ifdef STA_SUPPORT + pmadapter->chan_bandwidth = 0; +#endif /* STA_SUPPORT */ + + pmadapter->min_ba_threshold = MIN_BA_THRESHOLD; + pmadapter->hw_dot_11ac_dev_cap = 0; + pmadapter->hw_dot_11ac_mcs_support = 0; + pmadapter->max_sta_conn = 0; + /* Initialize 802.11d */ + wlan_11d_init(pmadapter); + + wlan_11h_init(pmadapter); + + wlan_wmm_init(pmadapter); + wlan_init_wmm_param(pmadapter); + pmadapter->bypass_pkt_count = 0; + if (pmadapter->psleep_cfm) { + pmadapter->psleep_cfm->buf_type = MLAN_BUF_TYPE_CMD; + pmadapter->psleep_cfm->data_len = sizeof(OPT_Confirm_Sleep); + memset(pmadapter, &sleep_cfm_buf->ps_cfm_sleep, 0, + sizeof(OPT_Confirm_Sleep)); + sleep_cfm_buf->ps_cfm_sleep.command = + wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); + sleep_cfm_buf->ps_cfm_sleep.size = + wlan_cpu_to_le16(sizeof(OPT_Confirm_Sleep)); + sleep_cfm_buf->ps_cfm_sleep.result = 0; + sleep_cfm_buf->ps_cfm_sleep.action = + wlan_cpu_to_le16(SLEEP_CONFIRM); + sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl = + wlan_cpu_to_le16(RESP_NEEDED); +#ifdef USB + if (IS_USB(pmadapter->card_type)) { + sleep_cfm_buf->hdr = + wlan_cpu_to_le32(MLAN_USB_TYPE_CMD); + pmadapter->psleep_cfm->data_len += MLAN_TYPE_LEN; + } +#endif + } + memset(pmadapter, &pmadapter->sleep_params, 0, + sizeof(pmadapter->sleep_params)); + memset(pmadapter, &pmadapter->sleep_period, 0, + sizeof(pmadapter->sleep_period)); + pmadapter->tx_lock_flag = MFALSE; + pmadapter->null_pkt_interval = 0; + pmadapter->fw_bands = 0; + pmadapter->config_bands = 0; + pmadapter->adhoc_start_band = 0; + pmadapter->pscan_channels = MNULL; + pmadapter->fw_release_number = 0; + pmadapter->fw_cap_info = 0; + memset(pmadapter, &pmadapter->upld_buf, 0, sizeof(pmadapter->upld_buf)); + pmadapter->upld_len = 0; + pmadapter->event_cause = 0; + pmadapter->pmlan_buffer_event = MNULL; + memset(pmadapter, &pmadapter->region_channel, 0, + sizeof(pmadapter->region_channel)); + pmadapter->region_code = 0; + memcpy_ext(pmadapter, pmadapter->country_code, + MRVDRV_DEFAULT_COUNTRY_CODE, COUNTRY_CODE_LEN, + COUNTRY_CODE_LEN); + pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; + +#ifdef PCIE + if (IS_PCIE(pmadapter->card_type)) { + pmadapter->pcard_pcie->txbd_wrptr = 0; + pmadapter->pcard_pcie->txbd_rdptr = 0; + pmadapter->pcard_pcie->rxbd_rdptr = 0; + pmadapter->pcard_pcie->evtbd_rdptr = 0; +#if defined(PCIE8997) || defined(PCIE8897) + if (!pmadapter->pcard_pcie->reg->use_adma) { + pmadapter->pcard_pcie->rxbd_wrptr = + pmadapter->pcard_pcie->reg + ->txrx_rw_ptr_rollover_ind; + pmadapter->pcard_pcie->evtbd_wrptr = + EVT_RW_PTR_ROLLOVER_IND; + } +#endif +#if defined(PCIE9098) || defined(PCIE9097) + if (pmadapter->pcard_pcie->reg->use_adma) { + pmadapter->pcard_pcie->rxbd_wrptr = MLAN_MAX_TXRX_BD; + pmadapter->pcard_pcie->evtbd_wrptr = MLAN_MAX_EVT_BD; + } +#endif + } +#endif + LEAVE(); + return; +} + +/** + * @brief This function intializes the lock variables and + * the list heads for interface + * + * @param pmadapter A pointer to a mlan_adapter structure + * @param start_index start index of mlan private + * + * @return MLAN_STATUS_SUCCESS -- on success, + * otherwise MLAN_STATUS_FAILURE + * + */ +mlan_status wlan_init_priv_lock_list(pmlan_adapter pmadapter, t_u8 start_index) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private priv = MNULL; + pmlan_callbacks pcb = &pmadapter->callbacks; + t_s32 i = 0; + t_u32 j = 0; + for (i = start_index; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + priv = pmadapter->priv[i]; + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &priv->rx_pkt_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &priv->wmm.ra_list_spinlock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } +#ifdef STA_SUPPORT + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &priv->curr_bcn_buf_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } +#endif + } + } + for (i = start_index; i < pmadapter->priv_num; ++i) { + util_init_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->bssprio_tbl[i].bssprio_head, + MTRUE, pmadapter->callbacks.moal_init_lock); + pmadapter->bssprio_tbl[i].bssprio_cur = MNULL; + } + + for (i = start_index; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + priv = pmadapter->priv[i]; + for (j = 0; j < MAX_NUM_TID; ++j) { + util_init_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->wmm.tid_tbl_ptr[j].ra_list, + MTRUE, + priv->adapter->callbacks.moal_init_lock); + } + util_init_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->tx_ba_stream_tbl_ptr, MTRUE, + pmadapter->callbacks.moal_init_lock); + util_init_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->rx_reorder_tbl_ptr, MTRUE, + pmadapter->callbacks.moal_init_lock); + util_scalar_init((t_void *)pmadapter->pmoal_handle, + &priv->wmm.tx_pkts_queued, 0, + priv->wmm.ra_list_spinlock, + pmadapter->callbacks.moal_init_lock); + util_scalar_init((t_void *)pmadapter->pmoal_handle, + &priv->wmm.highest_queued_prio, + HIGH_PRIO_TID, + priv->wmm.ra_list_spinlock, + pmadapter->callbacks.moal_init_lock); + util_init_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->sta_list, MTRUE, + pmadapter->callbacks.moal_init_lock); + /* Initialize bypass_txq */ + util_init_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->bypass_txq, MTRUE, + pmadapter->callbacks.moal_init_lock); + } + } +error: + LEAVE(); + return ret; +} + +/** + * @brief This function intializes the lock variables and + * the list heads. + * + * @param pmadapter A pointer to a mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS -- on success, + * otherwise MLAN_STATUS_FAILURE + * + */ +mlan_status wlan_init_lock_list(pmlan_adapter pmadapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_callbacks pcb = &pmadapter->callbacks; +#if defined(USB) + t_s32 i = 0; +#endif + ENTER(); + + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &pmadapter->pmlan_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } +#if defined(SDIO) || defined(PCIE) + if (!IS_USB(pmadapter->card_type)) { + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &pmadapter->pint_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + } +#endif + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &pmadapter->pmain_proc_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &pmadapter->prx_proc_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &pmadapter->pmlan_cmd_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } +#if defined(USB) + if (IS_USB(pmadapter->card_type)) { + for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) { + if (pcb->moal_init_lock(pmadapter->pmoal_handle, + &pmadapter->pcard_usb + ->usb_tx_aggr[i] + .paggr_lock) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + } + } +#endif + + util_init_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->rx_data_queue, MTRUE, + pmadapter->callbacks.moal_init_lock); + util_scalar_init((t_void *)pmadapter->pmoal_handle, + &pmadapter->pending_bridge_pkts, 0, MNULL, + pmadapter->callbacks.moal_init_lock); + /* Initialize cmd_free_q */ + util_init_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->cmd_free_q, MTRUE, + pmadapter->callbacks.moal_init_lock); + /* Initialize cmd_pending_q */ + util_init_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->cmd_pending_q, MTRUE, + pmadapter->callbacks.moal_init_lock); + /* Initialize scan_pending_q */ + util_init_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->scan_pending_q, MTRUE, + pmadapter->callbacks.moal_init_lock); + + /* Initialize ioctl_pending_q */ + util_init_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->ioctl_pending_q, MTRUE, + pmadapter->callbacks.moal_init_lock); + +error: + LEAVE(); + return ret; +} + +/** + * @brief This function releases the lock variables + * + * @param pmadapter A pointer to a mlan_adapter structure + * + * @return None + * + */ +t_void wlan_free_lock_list(pmlan_adapter pmadapter) +{ + pmlan_private priv = MNULL; + pmlan_callbacks pcb = &pmadapter->callbacks; + t_s32 i = 0; + t_s32 j = 0; + + ENTER(); + + if (pmadapter->pmlan_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + pmadapter->pmlan_lock); +#if defined(SDIO) || defined(PCIE) + if (!IS_USB(pmadapter->card_type) && pmadapter->pint_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + pmadapter->pint_lock); +#endif + if (pmadapter->prx_proc_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + pmadapter->prx_proc_lock); + if (pmadapter->pmain_proc_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + pmadapter->pmain_proc_lock); + if (pmadapter->pmlan_cmd_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + pmadapter->pmlan_cmd_lock); +#if defined(USB) + if (IS_USB(pmadapter->card_type)) { + for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) { + if (pmadapter->pcard_usb->usb_tx_aggr[i].paggr_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + pmadapter->pcard_usb + ->usb_tx_aggr[i] + .paggr_lock); + } + } +#endif + + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + priv = pmadapter->priv[i]; + if (priv->rx_pkt_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + priv->rx_pkt_lock); + if (priv->wmm.ra_list_spinlock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + priv->wmm.ra_list_spinlock); +#ifdef STA_SUPPORT + if (priv->curr_bcn_buf_lock) + pcb->moal_free_lock(pmadapter->pmoal_handle, + priv->curr_bcn_buf_lock); +#endif + } + } + + /* Free lists */ + util_free_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->rx_data_queue, pcb->moal_free_lock); + + util_scalar_free((t_void *)pmadapter->pmoal_handle, + &pmadapter->pending_bridge_pkts, pcb->moal_free_lock); + util_free_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->cmd_free_q, + pmadapter->callbacks.moal_free_lock); + + util_free_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->cmd_pending_q, + pmadapter->callbacks.moal_free_lock); + + util_free_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->scan_pending_q, + pmadapter->callbacks.moal_free_lock); + + util_free_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->ioctl_pending_q, + pmadapter->callbacks.moal_free_lock); + + for (i = 0; i < pmadapter->priv_num; i++) + util_free_list_head((t_void *)pmadapter->pmoal_handle, + &pmadapter->bssprio_tbl[i].bssprio_head, + pcb->moal_free_lock); + + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + priv = pmadapter->priv[i]; + util_free_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->sta_list, + priv->adapter->callbacks.moal_free_lock); + util_free_list_head( + (t_void *)pmadapter->pmoal_handle, + &priv->bypass_txq, + pmadapter->callbacks.moal_free_lock); + for (j = 0; j < MAX_NUM_TID; ++j) + util_free_list_head( + (t_void *)priv->adapter->pmoal_handle, + &priv->wmm.tid_tbl_ptr[j].ra_list, + priv->adapter->callbacks.moal_free_lock); + util_free_list_head( + (t_void *)priv->adapter->pmoal_handle, + &priv->tx_ba_stream_tbl_ptr, + priv->adapter->callbacks.moal_free_lock); + util_free_list_head( + (t_void *)priv->adapter->pmoal_handle, + &priv->rx_reorder_tbl_ptr, + priv->adapter->callbacks.moal_free_lock); + util_scalar_free( + (t_void *)priv->adapter->pmoal_handle, + &priv->wmm.tx_pkts_queued, + priv->adapter->callbacks.moal_free_lock); + util_scalar_free( + (t_void *)priv->adapter->pmoal_handle, + &priv->wmm.highest_queued_prio, + priv->adapter->callbacks.moal_free_lock); + } + } + + LEAVE(); + return; +} + +/** + * @brief This function intializes the timers + * + * @param pmadapter A pointer to a mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS -- on success, + * otherwise MLAN_STATUS_FAILURE + * + */ +mlan_status wlan_init_timer(pmlan_adapter pmadapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_callbacks pcb = &pmadapter->callbacks; +#if defined(USB) + t_s32 i = 0; +#endif + ENTER(); + + if (pcb->moal_init_timer( + pmadapter->pmoal_handle, &pmadapter->pmlan_cmd_timer, + wlan_cmd_timeout_func, pmadapter) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } +#if defined(USB) + if (IS_USB(pmadapter->card_type)) { + for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) { + if (pcb->moal_init_timer( + pmadapter->pmoal_handle, + &pmadapter->pcard_usb->usb_tx_aggr[i] + .paggr_hold_timer, + wlan_usb_tx_aggr_timeout_func, + &pmadapter->pcard_usb->usb_tx_aggr[i]) != + MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + } + } +#endif + if (pcb->moal_init_timer(pmadapter->pmoal_handle, + &pmadapter->pwakeup_fw_timer, + wlan_wakeup_card_timeout_func, + pmadapter) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + pmadapter->wakeup_fw_timer_is_set = MFALSE; +error: + LEAVE(); + return ret; +} + +/** + * @brief This function releases the timers + * + * @param pmadapter A pointer to a mlan_adapter structure + * + * @return None + * + */ +t_void wlan_free_timer(pmlan_adapter pmadapter) +{ + pmlan_callbacks pcb = &pmadapter->callbacks; +#if defined(USB) + t_s32 i = 0; +#endif + ENTER(); + + if (pmadapter->pmlan_cmd_timer) + pcb->moal_free_timer(pmadapter->pmoal_handle, + pmadapter->pmlan_cmd_timer); +#if defined(USB) + if (IS_USB(pmadapter->card_type)) { + for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) { + if (pmadapter->pcard_usb->usb_tx_aggr[i] + .paggr_hold_timer) + pcb->moal_free_timer(pmadapter->pmoal_handle, + pmadapter->pcard_usb + ->usb_tx_aggr[i] + .paggr_hold_timer); + } + } +#endif + + if (pmadapter->pwakeup_fw_timer) + pcb->moal_free_timer(pmadapter->pmoal_handle, + pmadapter->pwakeup_fw_timer); + + LEAVE(); + return; +} + +/** + * @brief This function initializes firmware + * + * @param pmadapter A pointer to mlan_adapter + * + * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or + * MLAN_STATUS_FAILURE + */ +mlan_status wlan_init_fw(pmlan_adapter pmadapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; +#ifdef PCIE + pmlan_private priv = pmadapter->priv[0]; +#endif + ENTER(); + /* Initialize adapter structure */ + wlan_init_adapter(pmadapter); +#ifdef MFG_CMD_SUPPORT + if (pmadapter->mfg_mode != MTRUE) { +#endif + wlan_adapter_get_hw_spec(pmadapter); +#ifdef MFG_CMD_SUPPORT + } +#ifdef PCIE + else if (IS_PCIE(pmadapter->card_type)) { + if (MLAN_STATUS_SUCCESS != wlan_set_pcie_buf_config(priv)) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + } +#endif /* PCIE */ +#endif /* MFG_CMD_SUPPORT */ + if (wlan_is_cmd_pending(pmadapter)) { + /* Send the first command in queue and return */ + if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE) + ret = MLAN_STATUS_FAILURE; + else + ret = MLAN_STATUS_PENDING; +#if defined(MFG_CMD_SUPPORT) && defined(PCIE) + if (IS_PCIE(pmadapter->card_type) && pmadapter->mfg_mode) { + ret = MLAN_STATUS_SUCCESS; + } +#endif + } +#ifdef PCIE +done: +#endif +#ifdef MFG_CMD_SUPPORT + if (pmadapter->mfg_mode == MTRUE) { + pmadapter->hw_status = WlanHardwareStatusInitializing; + ret = wlan_get_hw_spec_complete(pmadapter); + } +#endif + LEAVE(); + return ret; +} + +/** + * @brief This function udpate hw spec info to each interface + * + * @param pmadapter A pointer to mlan_adapter + * + * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or + * MLAN_STATUS_FAILURE + */ +void wlan_update_hw_spec(pmlan_adapter pmadapter) +{ + t_u32 i; + + ENTER(); + +#ifdef STA_SUPPORT + if (IS_SUPPORT_MULTI_BANDS(pmadapter)) + pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter); + else + pmadapter->fw_bands = BAND_B; + + if ((pmadapter->fw_bands & BAND_A) && (pmadapter->fw_bands & BAND_GN)) + pmadapter->fw_bands |= BAND_AN; + if (!(pmadapter->fw_bands & BAND_G) && (pmadapter->fw_bands & BAND_GN)) + pmadapter->fw_bands &= ~BAND_GN; + + pmadapter->config_bands = pmadapter->fw_bands; + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + pmadapter->priv[i]->config_bands = pmadapter->fw_bands; + } + } + + if (pmadapter->fw_bands & BAND_A) { + if (pmadapter->fw_bands & BAND_AN) { + pmadapter->config_bands |= BAND_AN; + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + pmadapter->priv[i]->config_bands |= + BAND_AN; + } + } + if (pmadapter->fw_bands & BAND_AAC) { + pmadapter->config_bands |= BAND_AAC; + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + pmadapter->priv[i]->config_bands |= + BAND_AAC; + } + } + pmadapter->adhoc_start_band = BAND_A; + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + pmadapter->priv[i]->adhoc_channel = + DEFAULT_AD_HOC_CHANNEL_A; + } + } else if (pmadapter->fw_bands & BAND_G) { + pmadapter->adhoc_start_band = BAND_G | BAND_B; + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + pmadapter->priv[i]->adhoc_channel = + DEFAULT_AD_HOC_CHANNEL; + } + } else if (pmadapter->fw_bands & BAND_B) { + pmadapter->adhoc_start_band = BAND_B; + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + pmadapter->priv[i]->adhoc_channel = + DEFAULT_AD_HOC_CHANNEL; + } + } +#endif /* STA_SUPPORT */ + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]->curr_addr[0] == 0xff) + memmove(pmadapter, pmadapter->priv[i]->curr_addr, + pmadapter->permanent_addr, + MLAN_MAC_ADDR_LENGTH); + } + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + wlan_update_11n_cap(pmadapter->priv[i]); + } + if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) { + PRINTM(MCMND, "Enable Beamforming\n"); + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + pmadapter->priv[i]->tx_bf_cap = + pmadapter->pcard_info + ->default_11n_tx_bf_cap; + } + } + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) + wlan_update_11ac_cap(pmadapter->priv[i]); + } + if (IS_FW_SUPPORT_11AX(pmadapter)) { + if (pmadapter->hw_2g_hecap_len) { + pmadapter->fw_bands |= BAND_GAX; + pmadapter->config_bands |= BAND_GAX; + } + if (pmadapter->hw_hecap_len) { + pmadapter->fw_bands |= BAND_AAX; + pmadapter->config_bands |= BAND_AAX; + } + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + pmadapter->priv[i]->config_bands = + pmadapter->config_bands; + pmadapter->priv[i]->user_2g_hecap_len = + pmadapter->hw_2g_hecap_len; + memcpy_ext(pmadapter, + pmadapter->priv[i]->user_2g_he_cap, + pmadapter->hw_2g_he_cap, + pmadapter->hw_2g_hecap_len, + sizeof(pmadapter->priv[i] + ->user_2g_he_cap)); + pmadapter->priv[i]->user_hecap_len = + pmadapter->hw_hecap_len; + memcpy_ext( + pmadapter, + pmadapter->priv[i]->user_he_cap, + pmadapter->hw_he_cap, + pmadapter->hw_hecap_len, + sizeof(pmadapter->priv[i]->user_he_cap)); + } + } + } + LEAVE(); + return; +} + +/** + * @brief This function initializes firmware for interface + * + * @param pmadapter A pointer to mlan_adapter + * + * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or + * MLAN_STATUS_FAILURE + */ +mlan_status wlan_init_priv_fw(pmlan_adapter pmadapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private priv = MNULL; + t_u8 i = 0; + + ENTER(); + + wlan_init_priv_lock_list(pmadapter, 1); + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + priv = pmadapter->priv[i]; + + /* Initialize private structure */ + ret = wlan_init_priv(priv); + if (ret) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + } + } +#ifdef MFG_CMD_SUPPORT + if (pmadapter->mfg_mode != MTRUE) { +#endif + wlan_update_hw_spec(pmadapter); + /* Issue firmware initialize commands for first BSS, + * for other interfaces it will be called after getting + * the last init command response of previous interface + */ + priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); + if (!priv) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + ret = priv->ops.init_cmd(priv, MTRUE); + if (ret == MLAN_STATUS_FAILURE) + goto done; +#ifdef MFG_CMD_SUPPORT + } +#endif /* MFG_CMD_SUPPORT */ + + if (wlan_is_cmd_pending(pmadapter)) { + /* Send the first command in queue and return */ + if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE) + ret = MLAN_STATUS_FAILURE; + else + ret = MLAN_STATUS_PENDING; +#if defined(MFG_CMD_SUPPORT) && defined(PCIE) + if (IS_PCIE(pmadapter->card_type) && pmadapter->mfg_mode) { + ret = MLAN_STATUS_SUCCESS; + pmadapter->hw_status = WlanHardwareStatusReady; + } +#endif + } else { + pmadapter->hw_status = WlanHardwareStatusReady; + } +done: + LEAVE(); + return ret; +} + +/** + * @brief This function frees the structure of adapter + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return N/A + */ +t_void wlan_free_adapter(pmlan_adapter pmadapter) +{ + mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks; +#if defined(USB) + t_s32 i = 0; +#endif + ENTER(); + + if (!pmadapter) { + PRINTM(MERROR, "The adapter is NULL\n"); + LEAVE(); + return; + } + + wlan_cancel_all_pending_cmd(pmadapter, MTRUE); + /* Free command buffer */ + PRINTM(MINFO, "Free Command buffer\n"); + wlan_free_cmd_buffer(pmadapter); + + if (pmadapter->cmd_timer_is_set) { + /* Cancel command timeout timer */ + pcb->moal_stop_timer(pmadapter->pmoal_handle, + pmadapter->pmlan_cmd_timer); + pmadapter->cmd_timer_is_set = MFALSE; + } +#if defined(USB) + if (IS_USB(pmadapter->card_type)) { + for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) { + if (pmadapter->pcard_usb->usb_tx_aggr[i] + .aggr_hold_timer_is_set) { + /* Cancel usb_tx_aggregation timeout timer */ + pcb->moal_stop_timer(pmadapter->pmoal_handle, + pmadapter->pcard_usb + ->usb_tx_aggr[i] + .paggr_hold_timer); + pmadapter->pcard_usb->usb_tx_aggr[i] + .aggr_hold_timer_is_set = MFALSE; + } + } + } +#endif + if (pmadapter->wakeup_fw_timer_is_set) { + /* Cancel wakeup card timer */ + pcb->moal_stop_timer(pmadapter->pmoal_handle, + pmadapter->pwakeup_fw_timer); + pmadapter->wakeup_fw_timer_is_set = MFALSE; + } + wlan_free_fw_cfp_tables(pmadapter); +#ifdef STA_SUPPORT + PRINTM(MINFO, "Free ScanTable\n"); + if (pmadapter->pscan_table) { + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pscan_table); + else + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pscan_table); + pmadapter->pscan_table = MNULL; + } + if (pmadapter->pchan_stats) { + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pchan_stats); + else + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pchan_stats); + pmadapter->pchan_stats = MNULL; + } + if (pmadapter->bcn_buf) { + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->bcn_buf); + pmadapter->bcn_buf = MNULL; + } +#endif + + wlan_11h_cleanup(pmadapter); + +#ifdef SDIO + if (IS_SD(pmadapter->card_type)) { + if (pmadapter->pcard_sd->mp_regs_buf) { + pcb->moal_mfree( + pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_sd->mp_regs_buf); + pmadapter->pcard_sd->mp_regs_buf = MNULL; + pmadapter->pcard_sd->mp_regs = MNULL; + } + if (pmadapter->pcard_sd->rx_buffer) { + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_sd->rx_buffer); + pmadapter->pcard_sd->rx_buffer = MNULL; + pmadapter->pcard_sd->rx_buf = MNULL; + } + wlan_free_sdio_mpa_buffers(pmadapter); +#ifdef DEBUG_LEVEL1 + if (pmadapter->pcard_sd->mpa_buf) { + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree( + pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_sd->mpa_buf); + else + pcb->moal_mfree( + pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_sd->mpa_buf); + pmadapter->pcard_sd->mpa_buf = MNULL; + pmadapter->pcard_sd->mpa_buf_size = 0; + } +#endif + } +#endif + + wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm); + pmadapter->psleep_cfm = MNULL; + +#ifdef PCIE + if (IS_PCIE(pmadapter->card_type)) { + /* Free ssu dma buffer just in case */ + wlan_free_ssu_pcie_buf(pmadapter); + /* Free PCIE ring buffers */ + wlan_free_pcie_ring_buf(pmadapter); + } +#endif + + /* Free timers */ + wlan_free_timer(pmadapter); + + /* Free lock variables */ + wlan_free_lock_list(pmadapter); + +#ifdef SDIO + if (pmadapter->pcard_sd) { + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_sd); + pmadapter->pcard_sd = MNULL; + } +#endif +#ifdef PCIE + if (pmadapter->pcard_pcie) { + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_pcie); + pmadapter->pcard_pcie = MNULL; + } +#endif +#ifdef USB + if (pmadapter->pcard_usb) { + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *)pmadapter->pcard_usb); + pmadapter->pcard_usb = MNULL; + } +#endif + vdll_deinit(pmadapter); + + LEAVE(); + return; +} + +/** + * @brief This function frees the structure of priv + * + * @param pmpriv A pointer to mlan_private structure + * + * @return N/A + */ +t_void wlan_free_priv(mlan_private *pmpriv) +{ + ENTER(); + wlan_clean_txrx(pmpriv); + wlan_delete_bsspriotbl(pmpriv); + +#ifdef STA_SUPPORT + wlan_free_curr_bcn(pmpriv); +#endif /* STA_SUPPORT */ + +#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT) + hostsa_cleanup(pmpriv); +#endif /*EMBEDDED AUTHENTICATOR*/ + + wlan_delete_station_list(pmpriv); + LEAVE(); +} + +/** + * @brief This function init interface based on pmadapter's bss_attr table + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return N/A + */ +mlan_status wlan_init_interface(pmlan_adapter pmadapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_callbacks pcb = MNULL; + t_u8 i = 0; + t_u32 j = 0; + + ENTER(); + + pcb = &pmadapter->callbacks; + for (i = 0; i < MLAN_MAX_BSS_NUM; i++) { + if (pmadapter->bss_attr[i].active == MTRUE) { + if (!pmadapter->priv[i]) { + /* For valid bss_attr, allocate memory for + * private structure */ + if (pcb->moal_vmalloc && pcb->moal_vfree) + ret = pcb->moal_vmalloc( + pmadapter->pmoal_handle, + sizeof(mlan_private), + (t_u8 **)&pmadapter->priv[i]); + else + ret = pcb->moal_malloc( + pmadapter->pmoal_handle, + sizeof(mlan_private), + MLAN_MEM_DEF, + (t_u8 **)&pmadapter->priv[i]); + if (ret != MLAN_STATUS_SUCCESS || + !pmadapter->priv[i]) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + + pmadapter->priv_num++; + memset(pmadapter, pmadapter->priv[i], 0, + sizeof(mlan_private)); + } + pmadapter->priv[i]->adapter = pmadapter; + + /* Save bss_type, frame_type & bss_priority */ + pmadapter->priv[i]->bss_type = + (t_u8)pmadapter->bss_attr[i].bss_type; + pmadapter->priv[i]->frame_type = + (t_u8)pmadapter->bss_attr[i].frame_type; + pmadapter->priv[i]->bss_priority = + (t_u8)pmadapter->bss_attr[i].bss_priority; + if (pmadapter->bss_attr[i].bss_type == + MLAN_BSS_TYPE_STA) + pmadapter->priv[i]->bss_role = + MLAN_BSS_ROLE_STA; + else if (pmadapter->bss_attr[i].bss_type == + MLAN_BSS_TYPE_UAP) + pmadapter->priv[i]->bss_role = + MLAN_BSS_ROLE_UAP; +#ifdef WIFI_DIRECT_SUPPORT + else if (pmadapter->bss_attr[i].bss_type == + MLAN_BSS_TYPE_WIFIDIRECT) { + pmadapter->priv[i]->bss_role = + MLAN_BSS_ROLE_STA; + if (pmadapter->bss_attr[i].bss_virtual) + pmadapter->priv[i]->bss_virtual = MTRUE; + } +#endif + /* Save bss_index and bss_num */ + pmadapter->priv[i]->bss_index = i; + pmadapter->priv[i]->bss_num = + (t_u8)pmadapter->bss_attr[i].bss_num; + + /* init function table */ + for (j = 0; mlan_ops[j]; j++) { + if (mlan_ops[j]->bss_role == + GET_BSS_ROLE(pmadapter->priv[i])) { + memcpy_ext(pmadapter, + &pmadapter->priv[i]->ops, + mlan_ops[j], + sizeof(mlan_operations), + sizeof(mlan_operations)); + break; + } + } + } + } + /*wmm init*/ + wlan_wmm_init(pmadapter); + /* Initialize firmware, may return PENDING */ + ret = wlan_init_priv_fw(pmadapter); + PRINTM(MINFO, "wlan_init_priv_fw returned ret=0x%x\n", ret); +error: + LEAVE(); + return ret; +} + +/** + * @brief The cmdresp handler calls this function for init_fw_complete callback + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS + * The firmware initialization callback succeeded. + */ +mlan_status wlan_get_hw_spec_complete(pmlan_adapter pmadapter) +{ + mlan_status status = MLAN_STATUS_SUCCESS; + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_callbacks pcb = &pmadapter->callbacks; + mlan_hw_info info; + mlan_bss_tbl bss_tbl; + + ENTER(); +#ifdef MFG_CMD_SUPPORT + if (pmadapter->mfg_mode != MTRUE) { +#endif + /* Check if hardware is ready */ + if (pmadapter->hw_status != WlanHardwareStatusInitializing) + status = MLAN_STATUS_FAILURE; + else { + memset(pmadapter, &info, 0, sizeof(info)); + info.fw_cap = pmadapter->fw_cap_info; + memset(pmadapter, &bss_tbl, 0, sizeof(bss_tbl)); + memcpy_ext(pmadapter, bss_tbl.bss_attr, + pmadapter->bss_attr, sizeof(mlan_bss_tbl), + sizeof(mlan_bss_tbl)); + } + /* Invoke callback */ + ret = pcb->moal_get_hw_spec_complete(pmadapter->pmoal_handle, + status, &info, &bss_tbl); + if (ret == MLAN_STATUS_SUCCESS && status == MLAN_STATUS_SUCCESS) + memcpy_ext(pmadapter, pmadapter->bss_attr, + bss_tbl.bss_attr, sizeof(mlan_bss_tbl), + sizeof(mlan_bss_tbl)); + else { + pmadapter->hw_status = WlanHardwareStatusNotReady; + wlan_init_fw_complete(pmadapter); + } +#ifdef MFG_CMD_SUPPORT + } +#endif + if (pmadapter->hw_status == WlanHardwareStatusInitializing) + ret = wlan_init_interface(pmadapter); + LEAVE(); + return ret; +} + +/** + * @brief The cmdresp handler calls this function for init_fw_complete callback + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS + * The firmware initialization callback succeeded. + */ +mlan_status wlan_init_fw_complete(pmlan_adapter pmadapter) +{ + mlan_status status = MLAN_STATUS_SUCCESS; + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_callbacks pcb = &pmadapter->callbacks; + mlan_private *pmpriv = MNULL; + + ENTER(); + + /* Check if hardware is ready */ + if (pmadapter->hw_status != WlanHardwareStatusReady) + status = MLAN_STATUS_FAILURE; + + /* Reconfigure wmm parameter*/ + if (status == MLAN_STATUS_SUCCESS) { + pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA); + if (pmpriv) + status = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_WMM_PARAM_CONFIG, + HostCmd_ACT_GEN_SET, 0, MNULL, + &pmadapter->ac_params); + } + /* Invoke callback */ + ret = pcb->moal_init_fw_complete(pmadapter->pmoal_handle, status); + LEAVE(); + return ret; +} + +/** + * @brief The cmdresp handler calls this function + * for shutdown_fw_complete callback + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS + * The firmware shutdown callback succeeded. + */ +mlan_status wlan_shutdown_fw_complete(pmlan_adapter pmadapter) +{ + pmlan_callbacks pcb = &pmadapter->callbacks; + mlan_status status = MLAN_STATUS_SUCCESS; + mlan_status ret = MLAN_STATUS_SUCCESS; + + ENTER(); + pmadapter->hw_status = WlanHardwareStatusNotReady; + /* Invoke callback */ + ret = pcb->moal_shutdown_fw_complete(pmadapter->pmoal_handle, status); + LEAVE(); + return ret; +} |