diff options
Diffstat (limited to 'drivers/net/wireless/sd8797/mlan/mlan_shim.c')
-rw-r--r-- | drivers/net/wireless/sd8797/mlan/mlan_shim.c | 939 |
1 files changed, 939 insertions, 0 deletions
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_shim.c b/drivers/net/wireless/sd8797/mlan/mlan_shim.c new file mode 100644 index 000000000000..c17b8e21c482 --- /dev/null +++ b/drivers/net/wireless/sd8797/mlan/mlan_shim.c @@ -0,0 +1,939 @@ +/** @file mlan_shim.c + * + * @brief This file contains APIs to MOAL module. + * + * Copyright (C) 2008-2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this 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_wmm.h" +#include "mlan_sdio.h" +#ifdef UAP_SUPPORT +#include "mlan_uap.h" +#endif +#include "mlan_11h.h" + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ +#ifdef STA_SUPPORT +mlan_operations mlan_sta_ops = { + /* init cmd handler */ + wlan_ops_sta_init_cmd, + /* ioctl handler */ + wlan_ops_sta_ioctl, + /* cmd handler */ + wlan_ops_sta_prepare_cmd, + /* cmdresp handler */ + wlan_ops_sta_process_cmdresp, + /* rx handler */ + wlan_ops_sta_process_rx_packet, + /* Event handler */ + wlan_ops_sta_process_event, + /* txpd handler */ + wlan_ops_sta_process_txpd, + /* BSS role: STA */ + MLAN_BSS_ROLE_STA, +}; +#endif +#ifdef UAP_SUPPORT +mlan_operations mlan_uap_ops = { + /* init cmd handler */ + wlan_ops_uap_init_cmd, + /* ioctl handler */ + wlan_ops_uap_ioctl, + /* cmd handler */ + wlan_ops_uap_prepare_cmd, + /* cmdresp handler */ + wlan_ops_uap_process_cmdresp, + /* rx handler */ + wlan_ops_uap_process_rx_packet, + /* Event handler */ + wlan_ops_uap_process_event, + /* txpd handler */ + wlan_ops_uap_process_txpd, + /* BSS role: uAP */ + MLAN_BSS_ROLE_UAP, +}; +#endif + +/** mlan function table */ +mlan_operations *mlan_ops[] = { +#ifdef STA_SUPPORT + &mlan_sta_ops, +#endif +#ifdef UAP_SUPPORT + &mlan_uap_ops, +#endif + MNULL, +}; + +/** Global moal_assert callback */ +t_void(*assert_callback) (IN t_void * pmoal_handle, IN t_u32 cond) = MNULL; +#ifdef DEBUG_LEVEL1 +#ifdef DEBUG_LEVEL2 +#define DEFAULT_DEBUG_MASK (0xffffffff) +#else +#define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR) +#endif + +/** Global moal_print callback */ +t_void(*print_callback) (IN t_void * pmoal_handle, + IN t_u32 level, IN t_s8 * pformat, IN ...) = MNULL; +/** Global driver debug mit masks */ +t_u32 drvdbg = DEFAULT_DEBUG_MASK; +#endif + +/******************************************************** + Local Functions +*******************************************************/ + +/******************************************************** + Global Functions +********************************************************/ + +/** + * @brief This function registers MOAL to MLAN module. + * + * @param pmdevice A pointer to a mlan_device structure + * allocated in MOAL + * @param ppmlan_adapter A pointer to a t_void pointer to store + * mlan_adapter structure pointer as the context + * + * @return MLAN_STATUS_SUCCESS + * The registration succeeded. + * MLAN_STATUS_FAILURE + * The registration failed. + * + * mlan_status mlan_register ( + * IN pmlan_device pmdevice, + * OUT t_void **ppmlan_adapter + * ); + * + * Comments + * MOAL constructs mlan_device data structure to pass moal_handle and + * mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to + * the ppmlan_adapter buffer provided by MOAL. + * Headers: + * declared in mlan_decl.h + * See Also + * mlan_unregister + */ +mlan_status +mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_adapter pmadapter = MNULL; + pmlan_callbacks pcb = MNULL; + t_u8 i = 0; + t_u32 j = 0; + + MASSERT(pmdevice); + MASSERT(ppmlan_adapter); + MASSERT(pmdevice->callbacks.moal_print); +#ifdef DEBUG_LEVEL1 + print_callback = pmdevice->callbacks.moal_print; +#endif + assert_callback = pmdevice->callbacks.moal_assert; + + ENTER(); + + MASSERT(pmdevice->callbacks.moal_malloc); + MASSERT(pmdevice->callbacks.moal_memset); + MASSERT(pmdevice->callbacks.moal_memmove); + + /* Allocate memory for adapter structure */ + if ((pmdevice->callbacks. + moal_malloc(pmdevice->pmoal_handle, sizeof(mlan_adapter), MLAN_MEM_DEF, + (t_u8 **) & pmadapter) != MLAN_STATUS_SUCCESS) + || !pmadapter) { + ret = MLAN_STATUS_FAILURE; + goto exit_register; + } + + pmdevice->callbacks.moal_memset(pmadapter, pmadapter, + 0, sizeof(mlan_adapter)); + + pcb = &pmadapter->callbacks; + + /* Save callback functions */ + pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb, + &pmdevice->callbacks, + sizeof(mlan_callbacks)); + + /* Assertion for all callback functions */ + MASSERT(pcb->moal_init_fw_complete); + MASSERT(pcb->moal_shutdown_fw_complete); + MASSERT(pcb->moal_send_packet_complete); + MASSERT(pcb->moal_recv_packet); + MASSERT(pcb->moal_recv_event); + MASSERT(pcb->moal_ioctl_complete); + MASSERT(pcb->moal_write_reg); + MASSERT(pcb->moal_read_reg); + MASSERT(pcb->moal_alloc_mlan_buffer); + MASSERT(pcb->moal_free_mlan_buffer); + MASSERT(pcb->moal_write_data_sync); + MASSERT(pcb->moal_read_data_sync); + MASSERT(pcb->moal_mfree); + MASSERT(pcb->moal_memcpy); + MASSERT(pcb->moal_memcmp); + MASSERT(pcb->moal_get_system_time); + MASSERT(pcb->moal_init_timer); + MASSERT(pcb->moal_free_timer); + MASSERT(pcb->moal_start_timer); + MASSERT(pcb->moal_stop_timer); + MASSERT(pcb->moal_init_lock); + MASSERT(pcb->moal_free_lock); + MASSERT(pcb->moal_spin_lock); + MASSERT(pcb->moal_spin_unlock); + + /* Save pmoal_handle */ + pmadapter->pmoal_handle = pmdevice->pmoal_handle; + + if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) { + PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n"); + ret = MLAN_STATUS_FAILURE; + goto error; + } + pmadapter->init_para.int_mode = pmdevice->int_mode; + pmadapter->init_para.gpio_pin = pmdevice->gpio_pin; + /* card specific probing has been deferred until now .. */ + if (MLAN_STATUS_SUCCESS != (ret = wlan_sdio_probe(pmadapter))) { + ret = MLAN_STATUS_FAILURE; + goto error; + } +#ifdef DEBUG_LEVEL1 + drvdbg = pmdevice->drvdbg; +#endif + +#ifdef MFG_CMD_SUPPORT + pmadapter->init_para.mfg_mode = pmdevice->mfg_mode; +#endif +#ifdef SDIO_MULTI_PORT_TX_AGGR + pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg; +#endif +#ifdef SDIO_MULTI_PORT_RX_AGGR + pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg; +#endif + pmadapter->init_para.auto_ds = pmdevice->auto_ds; + pmadapter->init_para.ps_mode = pmdevice->ps_mode; + if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K || + pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K || + pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K) + pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf; +#ifdef STA_SUPPORT + pmadapter->init_para.cfg_11d = pmdevice->cfg_11d; +#else + pmadapter->init_para.cfg_11d = 0; +#endif + pmadapter->init_para.dfs_master_radar_det_en = DFS_MASTER_RADAR_DETECT_EN; + pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN; + + pmadapter->priv_num = 0; + for (i = 0; i < MLAN_MAX_BSS_NUM; i++) { + pmadapter->priv[i] = MNULL; + if (pmdevice->bss_attr[i].active == MTRUE) { + /* For valid bss_attr, allocate memory for private structure */ + if ((pcb-> + moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_private), + MLAN_MEM_DEF, + (t_u8 **) & pmadapter->priv[i]) != + 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) pmdevice->bss_attr[i].bss_type; + pmadapter->priv[i]->frame_type = + (t_u8) pmdevice->bss_attr[i].frame_type; + pmadapter->priv[i]->bss_priority = + (t_u8) pmdevice->bss_attr[i].bss_priority; + if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_STA) + pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_STA; + else if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_UAP) + pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_UAP; +#ifdef WIFI_DIRECT_SUPPORT + else if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_WIFIDIRECT) + pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_STA; +#endif + /* Save bss_index and bss_num */ + pmadapter->priv[i]->bss_index = i; + pmadapter->priv[i]->bss_num = (t_u8) pmdevice->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(pmadapter, &pmadapter->priv[i]->ops, mlan_ops[j], + sizeof(mlan_operations)); + } + } + } + } + + /* Initialize lock variables */ + if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + + /* Allocate memory for member of adapter structure */ + if (wlan_allocate_adapter(pmadapter)) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + + /* Initialize timers */ + if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto error; + } + /* Return pointer of mlan_adapter to MOAL */ + *ppmlan_adapter = pmadapter; + + goto exit_register; + + error: + PRINTM(MINFO, "Leave mlan_register with error\n"); + /* Free timers */ + wlan_free_timer(pmadapter); + /* Free adapter structure */ + wlan_free_adapter(pmadapter); + /* Free lock variables */ + wlan_free_lock_list(pmadapter); + for (i = 0; i < MLAN_MAX_BSS_NUM; i++) { + if (pmadapter->priv[i]) + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->priv[i]); + } + pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); + + exit_register: + LEAVE(); + return ret; +} + +/** + * @brief This function unregisters MOAL from MLAN module. + * + * @param pmlan_adapter A pointer to a mlan_device structure + * allocated in MOAL + * + * @return MLAN_STATUS_SUCCESS + * The deregistration succeeded. + */ +mlan_status +mlan_unregister(IN t_void * pmlan_adapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + pmlan_callbacks pcb; + t_s32 i = 0; + + MASSERT(pmlan_adapter); + + ENTER(); + + pcb = &pmadapter->callbacks; + + /* Free adapter structure */ + wlan_free_adapter(pmadapter); + + /* Free timers */ + wlan_free_timer(pmadapter); + + /* Free lock variables */ + wlan_free_lock_list(pmadapter); + + /* Free private structures */ + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->priv[i]); + } + } + + /* Free mlan_adapter */ + pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); + + LEAVE(); + return ret; +} + +/** + * @brief This function downloads the firmware + * + * @param pmlan_adapter A pointer to a t_void pointer to store + * mlan_adapter structure pointer + * @param pmfw A pointer to firmware image + * + * @return MLAN_STATUS_SUCCESS + * The firmware download succeeded. + * MLAN_STATUS_FAILURE + * The firmware download failed. + */ +mlan_status +mlan_dnld_fw(IN t_void * pmlan_adapter, IN pmlan_fw_image pmfw) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + t_u32 poll_num = 1; + t_u32 winner = 0; + + ENTER(); + MASSERT(pmlan_adapter); + + /* Card specific probing */ + ret = wlan_sdio_probe(pmadapter); + if (ret == MLAN_STATUS_FAILURE) { + PRINTM(MERROR, "WLAN SDIO probe failed\n", ret); + LEAVE(); + return ret; + } + + /* Check if firmware is already running */ + ret = wlan_check_fw_status(pmadapter, poll_num); + if (ret == MLAN_STATUS_SUCCESS) { + PRINTM(MMSG, "WLAN FW already running! Skip FW download\n"); + goto done; + } + poll_num = MAX_FIRMWARE_POLL_TRIES; + + /* Check if other interface is downloading */ + ret = wlan_check_winner_status(pmadapter, &winner); + if (ret == MLAN_STATUS_FAILURE) { + PRINTM(MFATAL, "WLAN read winner status failed!\n"); + goto done; + } + if (winner) { + PRINTM(MMSG, "WLAN is not the winner (0x%x). Skip FW download\n", + winner); + poll_num = MAX_MULTI_INTERFACE_POLL_TRIES; + goto poll_fw; + } + + if (pmfw) { + /* Download helper/firmware */ + ret = wlan_dnld_fw(pmadapter, pmfw); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret); + LEAVE(); + return ret; + } + } + + poll_fw: + /* Check if the firmware is downloaded successfully or not */ + ret = wlan_check_fw_status(pmadapter, poll_num); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MFATAL, "FW failed to be active in time!\n"); + ret = MLAN_STATUS_FAILURE; + LEAVE(); + return ret; + } + done: + + /* re-enable host interrupt for mlan after fw dnld is successful */ + wlan_enable_host_int(pmadapter); + + LEAVE(); + return ret; +} + +/** + * @brief This function pass init param to MLAN + * + * @param pmlan_adapter A pointer to a t_void pointer to store + * mlan_adapter structure pointer + * @param pparam A pointer to mlan_init_param structure + * + * @return MLAN_STATUS_SUCCESS + * + */ +mlan_status +mlan_set_init_param(IN t_void * pmlan_adapter, IN pmlan_init_param pparam) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + + ENTER(); + MASSERT(pmlan_adapter); + + /** Save cal data in MLAN */ + if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) { + pmadapter->pcal_data = pparam->pcal_data_buf; + pmadapter->cal_data_len = pparam->cal_data_len; + } + + LEAVE(); + return ret; +} + +/** + * @brief This function initializes the firmware + * + * @param pmlan_adapter A pointer to a t_void pointer to store + * mlan_adapter structure pointer + * + * @return MLAN_STATUS_SUCCESS + * The firmware initialization succeeded. + * MLAN_STATUS_PENDING + * The firmware initialization is pending. + * MLAN_STATUS_FAILURE + * The firmware initialization failed. + */ +mlan_status +mlan_init_fw(IN t_void * pmlan_adapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + + ENTER(); + MASSERT(pmlan_adapter); + + pmadapter->hw_status = WlanHardwareStatusInitializing; + + /* Initialize firmware, may return PENDING */ + ret = wlan_init_fw(pmadapter); + PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret); + + LEAVE(); + return ret; +} + +/** + * @brief Shutdown firmware + * + * @param pmlan_adapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS + * The firmware shutdown call succeeded. + * MLAN_STATUS_PENDING + * The firmware shutdown call is pending. + * MLAN_STATUS_FAILURE + * The firmware shutdown call failed. + */ +mlan_status +mlan_shutdown_fw(IN t_void * pmlan_adapter) +{ + mlan_status ret = MLAN_STATUS_PENDING; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + pmlan_callbacks pcb; + t_s32 i = 0; + + ENTER(); + MASSERT(pmlan_adapter); + /* mlan already shutdown */ + if (pmadapter->hw_status == WlanHardwareStatusNotReady) { + LEAVE(); + return MLAN_STATUS_SUCCESS; + } + + pmadapter->hw_status = WlanHardwareStatusClosing; + /* wait for mlan_process to complete */ + if (pmadapter->mlan_processing) { + PRINTM(MWARN, "mlan main processing is still running\n"); + LEAVE(); + return ret; + } + + /* shut down mlan */ + PRINTM(MINFO, "Shutdown mlan...\n"); + + /* Clean up priv structures */ + for (i = 0; i < pmadapter->priv_num; i++) { + if (pmadapter->priv[i]) { + wlan_free_priv(pmadapter->priv[i]); + } + } + + pcb = &pmadapter->callbacks; + + if (pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_lock) + != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto exit_shutdown_fw; + } + + if (pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmlan_lock) + != MLAN_STATUS_SUCCESS) { + ret = MLAN_STATUS_FAILURE; + goto exit_shutdown_fw; + } + + /* Notify completion */ + ret = wlan_shutdown_fw_complete(pmadapter); + + exit_shutdown_fw: + LEAVE(); + return ret; +} + +/** + * @brief The main process + * + * @param pmlan_adapter A pointer to mlan_adapter structure + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +mlan_main_process(IN t_void * pmlan_adapter) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + pmlan_callbacks pcb; + + ENTER(); + + MASSERT(pmlan_adapter); + + pcb = &pmadapter->callbacks; + + pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); + + /* Check if already processing */ + if (pmadapter->mlan_processing) { + pcb->moal_spin_unlock(pmadapter->pmoal_handle, + pmadapter->pmain_proc_lock); + goto exit_main_proc; + } else { + pmadapter->mlan_processing = MTRUE; + pcb->moal_spin_unlock(pmadapter->pmoal_handle, + pmadapter->pmain_proc_lock); + } + process_start: + do { + /* Is MLAN shutting down or not ready? */ + if ((pmadapter->hw_status == WlanHardwareStatusClosing) || + (pmadapter->hw_status == WlanHardwareStatusNotReady)) + break; + + /* Handle pending SDIO interrupts if any */ + if (pmadapter->sdio_ireg) { + if (pmadapter->hs_activated == MTRUE) + wlan_process_hs_config(pmadapter); + wlan_process_int_status(pmadapter); + } + + /* Need to wake up the card ? */ + if ((pmadapter->ps_state == PS_STATE_SLEEP) && + (pmadapter->pm_wakeup_card_req && + !pmadapter->pm_wakeup_fw_try) && + (util_peek_list + (pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, + pcb->moal_spin_lock, pcb->moal_spin_unlock) + || !wlan_bypass_tx_list_empty(pmadapter) + || !wlan_wmm_lists_empty(pmadapter) + )) { + pmadapter->pm_wakeup_fw_try = MTRUE; + wlan_pm_wakeup_card(pmadapter); + continue; + } + if (IS_CARD_RX_RCVD(pmadapter)) { + pmadapter->data_received = MFALSE; + if (pmadapter->hs_activated == MTRUE) { + pmadapter->is_hs_configured = MFALSE; + wlan_host_sleep_activated_event(wlan_get_priv + (pmadapter, MLAN_BSS_ROLE_ANY), + MFALSE); + } + pmadapter->pm_wakeup_fw_try = MFALSE; + if (pmadapter->ps_state == PS_STATE_SLEEP) + pmadapter->ps_state = PS_STATE_AWAKE; + } else { + /* We have tried to wakeup the card already */ + if (pmadapter->pm_wakeup_fw_try) + break; + if (pmadapter->ps_state != PS_STATE_AWAKE || + (pmadapter->tx_lock_flag == MTRUE)) + break; + + if (pmadapter->scan_processing || pmadapter->data_sent + || (wlan_bypass_tx_list_empty(pmadapter) && + wlan_wmm_lists_empty(pmadapter)) + || wlan_11h_radar_detected_tx_blocked(pmadapter) + ) { + if (pmadapter->cmd_sent || pmadapter->curr_cmd || + (!util_peek_list + (pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, + pcb->moal_spin_lock, pcb->moal_spin_unlock))) { + break; + } + } + } + + /* Check for Cmd Resp */ + if (pmadapter->cmd_resp_received) { + pmadapter->cmd_resp_received = MFALSE; + wlan_process_cmdresp(pmadapter); + + /* call moal back when init_fw is done */ + if (pmadapter->hw_status == WlanHardwareStatusInitdone) { + pmadapter->hw_status = WlanHardwareStatusReady; + wlan_init_fw_complete(pmadapter); + } + } + + /* Check for event */ + if (pmadapter->event_received) { + pmadapter->event_received = MFALSE; + wlan_process_event(pmadapter); + } + + /* Check if we need to confirm Sleep Request received previously */ + if (pmadapter->ps_state == PS_STATE_PRE_SLEEP) { + if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) { + wlan_check_ps_cond(pmadapter); + } + } + + /* + * The ps_state may have been changed during processing of + * Sleep Request event. + */ + if ((pmadapter->ps_state == PS_STATE_SLEEP) + || (pmadapter->ps_state == PS_STATE_PRE_SLEEP) + || (pmadapter->ps_state == PS_STATE_SLEEP_CFM) + || (pmadapter->tx_lock_flag == MTRUE) + ) + continue; + + if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) { + if (wlan_exec_next_cmd(pmadapter) == MLAN_STATUS_FAILURE) { + ret = MLAN_STATUS_FAILURE; + break; + } + } + + if (!pmadapter->scan_processing && !pmadapter->data_sent && + !wlan_11h_radar_detected_tx_blocked(pmadapter) && + !wlan_bypass_tx_list_empty(pmadapter)) { + PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n"); + wlan_process_bypass_tx(pmadapter); + if (pmadapter->hs_activated == MTRUE) { + pmadapter->is_hs_configured = MFALSE; + wlan_host_sleep_activated_event(wlan_get_priv + (pmadapter, MLAN_BSS_ROLE_ANY), + MFALSE); + } + } + + if (!pmadapter->scan_processing && !pmadapter->data_sent && + !wlan_wmm_lists_empty(pmadapter) + && !wlan_11h_radar_detected_tx_blocked(pmadapter) + ) { + wlan_wmm_process_tx(pmadapter); + if (pmadapter->hs_activated == MTRUE) { + pmadapter->is_hs_configured = MFALSE; + wlan_host_sleep_activated_event(wlan_get_priv + (pmadapter, MLAN_BSS_ROLE_ANY), + MFALSE); + } + } + +#ifdef STA_SUPPORT + if (pmadapter->delay_null_pkt && !pmadapter->cmd_sent && + !pmadapter->curr_cmd && !IS_COMMAND_PENDING(pmadapter) && + wlan_bypass_tx_list_empty(pmadapter) && + wlan_wmm_lists_empty(pmadapter)) { + if (wlan_send_null_packet + (wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA), + MRVDRV_TxPD_POWER_MGMT_NULL_PACKET | + MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) + == MLAN_STATUS_SUCCESS) { + pmadapter->delay_null_pkt = MFALSE; + } + break; + } +#endif + + } while (MTRUE); + + if ((pmadapter->sdio_ireg) || IS_CARD_RX_RCVD(pmadapter)) { + goto process_start; + } + pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); + pmadapter->mlan_processing = MFALSE; + pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); + + exit_main_proc: + if (pmadapter->hw_status == WlanHardwareStatusClosing) + mlan_shutdown_fw(pmadapter); + LEAVE(); + return ret; +} + +/** + * @brief Function to send packet + * + * @param pmlan_adapter A pointer to mlan_adapter structure + * @param pmbuf A pointer to mlan_buffer structure + * + * @return MLAN_STATUS_PENDING + */ +mlan_status +mlan_send_packet(IN t_void * pmlan_adapter, IN pmlan_buffer pmbuf) +{ + mlan_status ret = MLAN_STATUS_PENDING; + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + + ENTER(); + MASSERT(pmlan_adapter && pmbuf); + + MASSERT(pmbuf->bss_index < pmadapter->priv_num); + pmbuf->flags = MLAN_BUF_FLAG_MOAL_TX_BUF; + + if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) && + ((mlan_ntohs(*(t_u16 *) & pmbuf->pbuf[pmbuf->data_offset + + MLAN_ETHER_PKT_TYPE_OFFSET]) == + MLAN_ETHER_PKT_TYPE_EAPOL) + || + (mlan_ntohs + (*(t_u16 *) & pmbuf-> + pbuf[pmbuf->data_offset + MLAN_ETHER_PKT_TYPE_OFFSET]) == + MLAN_ETHER_PKT_TYPE_WAPI) + )) + || (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) + + ) { + PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n"); + wlan_add_buf_bypass_txqueue(pmadapter, pmbuf); + } else { + /* Transmit the packet */ + wlan_wmm_add_buf_txqueue(pmadapter, pmbuf); + } + + LEAVE(); + return ret; +} + +/** + * @brief MLAN ioctl handler + * + * @param adapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail + */ +mlan_status +mlan_ioctl(IN t_void * adapter, IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_adapter pmadapter = (pmlan_adapter) adapter; + pmlan_private pmpriv = MNULL; + + ENTER(); + + if (pioctl_req == MNULL) { + PRINTM(MERROR, "MLAN IOCTL information buffer is NULL\n"); + ret = MLAN_STATUS_FAILURE; + goto exit; + } + if (pioctl_req->action == MLAN_ACT_CANCEL) { + wlan_cancel_pending_ioctl(pmadapter, pioctl_req); + ret = MLAN_STATUS_SUCCESS; + goto exit; + } + pmpriv = pmadapter->priv[pioctl_req->bss_index]; + ret = pmpriv->ops.ioctl(adapter, pioctl_req); + exit: + LEAVE(); + return ret; +} + +/** + * @brief Packet receive completion callback handler + * + * @param pmlan_adapter A pointer to mlan_adapter structure + * @param pmbuf A pointer to mlan_buffer structure + * @param status Callback status + * + * @return MLAN_STATUS_SUCCESS + */ +mlan_status +mlan_recv_packet_complete(IN t_void * pmlan_adapter, + IN pmlan_buffer pmbuf, IN mlan_status status) +{ + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + + ENTER(); + wlan_recv_packet_complete(pmadapter, pmbuf, status); + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief select wmm queue + * + * @param pmlan_adapter A pointer to mlan_adapter structure + * @param bss_num BSS number + * @param tid TID + * + * @return wmm queue priority (0 - 3) + */ +t_u8 +mlan_select_wmm_queue(IN t_void * pmlan_adapter, IN t_u8 bss_num, IN t_u8 tid) +{ + mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; + pmlan_private pmpriv = pmadapter->priv[bss_num]; + t_u8 ret; + ENTER(); + ret = wlan_wmm_select_queue(pmpriv, tid); + LEAVE(); + return ret; +} + +/** + * @brief This function gets interrupt status. + * + * @param adapter A pointer to mlan_adapter structure + * @return N/A + */ +t_void +mlan_interrupt(IN t_void * adapter) +{ + mlan_adapter *pmadapter = (mlan_adapter *) adapter; + + ENTER(); + if (!pmadapter->pps_uapsd_mode && pmadapter->ps_state == PS_STATE_SLEEP) { + pmadapter->pm_wakeup_fw_try = MFALSE; + pmadapter->ps_state = PS_STATE_AWAKE; + } + wlan_interrupt(pmadapter); + LEAVE(); +} |