summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/sd8797/mlan/mlan_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/sd8797/mlan/mlan_init.c')
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_init.c1038
1 files changed, 1038 insertions, 0 deletions
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_init.c b/drivers/net/wireless/sd8797/mlan/mlan_init.c
new file mode 100644
index 000000000000..e949502e7d69
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_init.c
@@ -0,0 +1,1038 @@
+/** @file mlan_init.c
+ *
+ * @brief This file contains the initialization for FW
+ * and HW.
+ *
+ * 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_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#include "mlan_meas.h"
+#include "mlan_sdio.h"
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ 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();
+
+ if ((status =
+ pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(mlan_bssprio_node),
+ MLAN_MEM_DEF,
+ (t_u8 **) & pbssprio))) {
+ 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();
+}
+
+/********************************************************
+ 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 buf_size;
+ BSSDescriptor_t *ptemp_scan_table = MNULL;
+#endif
+
+ ENTER();
+
+#ifdef STA_SUPPORT
+ /* Allocate buffer to store the BSSID list */
+ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
+ 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;
+ ret =
+ pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ DEFAULT_SCAN_BEACON_BUFFER,
+ 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 = DEFAULT_SCAN_BEACON_BUFFER;
+#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;
+ }
+
+ ret =
+ pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ MAX_MP_REGS + DMA_ALIGNMENT,
+ MLAN_MEM_DEF | MLAN_MEM_DMA,
+ (t_u8 **) & pmadapter->mp_regs_buf);
+ if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) {
+ PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ pmadapter->mp_regs =
+ (t_u8 *) ALIGN_ADDR(pmadapter->mp_regs_buf, DMA_ALIGNMENT);
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+ ret = wlan_alloc_sdio_mpa_buffers(pmadapter, SDIO_MP_TX_AGGR_DEF_BUF_SIZE,
+ SDIO_MP_RX_AGGR_DEF_BUF_SIZE);
+ if (ret != MLAN_STATUS_SUCCESS) {
+ PRINTM(MERROR, "Failed to allocate sdio mp-a buffers\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+#endif
+
+ pmadapter->psleep_cfm =
+ wlan_alloc_mlan_buffer(pmadapter, sizeof(opt_sleep_confirm_buffer), 0,
+ MTRUE);
+
+ 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;
+
+ 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 < sizeof(priv->wep_key) / sizeof(priv->wep_key[0]); i++)
+ memset(pmadapter, &priv->wep_key[i], 0, sizeof(mrvl_wep_key_t));
+ priv->wep_key_curr_index = 0;
+ priv->ewpa_query = MFALSE;
+ priv->adhoc_aes_enabled = MFALSE;
+ priv->curr_pkt_filter =
+ 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->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);
+#if defined(UAP_SUPPORT)
+ priv->uap_bss_started = MFALSE;
+ memset(pmadapter, &priv->uap_state_chan_cb, 0,
+ sizeof(priv->uap_state_chan_cb));
+#endif
+#if defined(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->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+ 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_htinfo = 0;
+ priv->rxpd_rate = 0;
+ priv->rate_bitmap = 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;
+ 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;
+
+ 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->tx_bf_cap = 0;
+ 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;
+#endif /* STA_SUPPORT */
+
+ for (i = 0; i < MAX_NUM_TID; i++)
+ priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+ priv->max_amsdu = 0;
+
+ priv->scan_block = MFALSE;
+
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+ priv->port_ctrl_mode = MTRUE;
+ } else {
+ priv->port_ctrl_mode = MFALSE;
+ }
+ priv->port_open = MFALSE;
+
+ if (!ret)
+ ret = wlan_add_bsspriotbl(priv);
+
+ 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)
+{
+ int i;
+ opt_sleep_confirm_buffer *sleep_cfm_buf = MNULL;
+
+ ENTER();
+
+ 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
+
+ pmadapter->int_mode = pmadapter->init_para.int_mode;
+ pmadapter->gpio_pin = pmadapter->init_para.gpio_pin;
+
+#if defined(STA_SUPPORT)
+ pmadapter->pwarm_reset_ioctl_req = MNULL;
+#endif
+ pmadapter->cmd_sent = MFALSE;
+ pmadapter->data_sent = MTRUE;
+ pmadapter->mp_rd_bitmap = 0;
+ pmadapter->mp_wr_bitmap = 0;
+ pmadapter->curr_rd_port = 1;
+ pmadapter->curr_wr_port = 1;
+ for (i = 0; i < MAX_NUM_TID; i++) {
+ pmadapter->tx_eligibility[i] = 1;
+ }
+ pmadapter->mp_data_port_mask = DATA_PORT_MASK;
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+ pmadapter->mpa_tx.buf_len = 0;
+ pmadapter->mpa_tx.pkt_cnt = 0;
+ pmadapter->mpa_tx.start_port = 0;
+
+ if (!pmadapter->init_para.mpa_tx_cfg) {
+ pmadapter->mpa_tx.enabled = MFALSE;
+ } else if (pmadapter->init_para.mpa_tx_cfg == MLAN_INIT_PARA_DISABLED) {
+ pmadapter->mpa_tx.enabled = MFALSE;
+ } else {
+ pmadapter->mpa_tx.enabled = MTRUE;
+ }
+ pmadapter->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+ pmadapter->mpa_rx.buf_len = 0;
+ pmadapter->mpa_rx.pkt_cnt = 0;
+ pmadapter->mpa_rx.start_port = 0;
+
+ if (!pmadapter->init_para.mpa_rx_cfg) {
+ pmadapter->mpa_rx.enabled = MFALSE;
+ } else if (pmadapter->init_para.mpa_rx_cfg == MLAN_INIT_PARA_DISABLED) {
+ pmadapter->mpa_rx.enabled = MFALSE;
+ } else {
+ pmadapter->mpa_rx.enabled = MTRUE;
+ }
+ pmadapter->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+ 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;
+
+ /* Status variables */
+ pmadapter->hw_status = WlanHardwareStatusInitializing;
+
+ 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
+ /* 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;
+
+ pmadapter->num_in_scan_table = 0;
+ memset(pmadapter, pmadapter->pscan_table, 0,
+ (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+ pmadapter->ext_scan = 0;
+ 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;
+ 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 = MLAN_TX_DATA_BUF_SIZE_2K;
+ 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;
+
+ 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;
+
+ memset(pmadapter, pmadapter->event_body, 0, sizeof(pmadapter->event_body));
+ pmadapter->hw_dot_11n_dev_cap = 0;
+ pmadapter->hw_dev_mcs_support = 0;
+ pmadapter->usr_dot_11n_dev_cap_bg = 0;
+ pmadapter->usr_dot_11n_dev_cap_a = 0;
+ pmadapter->usr_dev_mcs_support = 0;
+#ifdef STA_SUPPORT
+ pmadapter->chan_bandwidth = 0;
+ pmadapter->adhoc_11n_enabled = MFALSE;
+#endif /* STA_SUPPORT */
+
+ /* Initialize 802.11d */
+ wlan_11d_init(pmadapter);
+
+ wlan_11h_init(pmadapter);
+
+ wlan_wmm_init(pmadapter);
+
+ 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);
+ }
+ 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;
+ pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
+ pmadapter->adhoc_awake_period = 0;
+#ifdef STA_SUPPORT
+ memset(pmadapter, &pmadapter->arp_filter, 0, sizeof(pmadapter->arp_filter));
+ pmadapter->arp_filter_size = 0;
+#endif /* STA_SUPPORT */
+
+ LEAVE();
+ return;
+}
+
+/**
+ * @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(IN pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = MNULL;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+ t_s32 i = 0;
+ t_u32 j = 0;
+
+ ENTER();
+
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmlan_lock)
+ != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pint_lock)
+ != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ 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->pmlan_cmd_lock)
+ != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto error;
+ }
+ for (i = 0; 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
+ }
+ }
+
+ /* Initialize bypass_txq */
+ util_init_list_head((t_void *) pmadapter->pmoal_handle,
+ &pmadapter->bypass_txq, MTRUE,
+ 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);
+
+ for (i = 0; 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 = 0; 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);
+ }
+ }
+
+ 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(IN 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 (pmadapter->pint_lock)
+ pcb->moal_free_lock(pmadapter->pmoal_handle, pmadapter->pint_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);
+
+ 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->bypass_txq,
+ pmadapter->callbacks.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);
+
+ 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);
+
+ 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(IN pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ 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;
+ }
+ 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(IN pmlan_adapter pmadapter)
+{
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ if (pmadapter->pmlan_cmd_timer)
+ pcb->moal_free_timer(pmadapter->pmoal_handle,
+ pmadapter->pmlan_cmd_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(IN pmlan_adapter pmadapter)
+{
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_private priv = MNULL;
+ t_u8 i = 0;
+
+ ENTER();
+
+ /* Initialize adapter structure */
+ wlan_init_adapter(pmadapter);
+
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i]) {
+ priv = pmadapter->priv[i];
+
+ /* Initialize private structure */
+ if ((ret = wlan_init_priv(priv))) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ }
+#ifdef MFG_CMD_SUPPORT
+ if (pmadapter->mfg_mode != MTRUE) {
+#endif
+ /* 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);
+ ret = priv->ops.init_cmd(priv, MTRUE);
+ if (ret == MLAN_STATUS_FAILURE)
+ goto done;
+#ifdef MFG_CMD_SUPPORT
+ }
+#endif
+
+ if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock)) {
+ /* 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;
+ } 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;
+
+ ENTER();
+
+ if (!pmadapter) {
+ PRINTM(MERROR, "The adapter is NULL\n");
+ LEAVE();
+ return;
+ }
+
+ wlan_cancel_all_pending_cmd(pmadapter);
+ /* 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;
+ }
+#ifdef STA_SUPPORT
+ PRINTM(MINFO, "Free ScanTable\n");
+ if (pmadapter->pscan_table) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *) pmadapter->pscan_table);
+ pmadapter->pscan_table = 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);
+
+ if (pmadapter->mp_regs_buf) {
+ pcb->moal_mfree(pmadapter->pmoal_handle,
+ (t_u8 *) pmadapter->mp_regs_buf);
+ pmadapter->mp_regs_buf = MNULL;
+ pmadapter->mp_regs = MNULL;
+ }
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+ wlan_free_sdio_mpa_buffers(pmadapter);
+#endif
+ wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
+ pmadapter->psleep_cfm = MNULL;
+
+ 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 */
+
+ wlan_delete_station_list(pmpriv);
+ LEAVE();
+}
+
+/**
+ * @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(IN pmlan_adapter pmadapter)
+{
+ mlan_status status = MLAN_STATUS_SUCCESS;
+ mlan_status ret = MLAN_STATUS_SUCCESS;
+ pmlan_callbacks pcb = &pmadapter->callbacks;
+
+ ENTER();
+
+ /* Check if hardware is ready */
+ if (pmadapter->hw_status != WlanHardwareStatusReady)
+ status = MLAN_STATUS_FAILURE;
+
+ /* 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(IN 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;
+}