15e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
25e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Marvell Wireless LAN device driver: HW/FW Initialization
35e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
45e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Copyright (C) 2011, Marvell International Ltd.
55e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
65e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This software file (the "File") is distributed by Marvell International
75e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Ltd. under the terms of the GNU General Public License Version 2, June 1991
85e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * (the "License").  You may use, redistribute and/or modify this File in
95e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * accordance with the terms and conditions of the License, a copy of which
105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is available by writing to the Free Software Foundation, Inc.,
115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * this warranty disclaimer.
185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "decl.h"
215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "ioctl.h"
225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "util.h"
235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "fw.h"
245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "main.h"
255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "wmm.h"
265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "11n.h"
275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function adds a BSS priority table to the table list.
305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The function allocates a new BSS priority table node and adds it to
325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * the end of BSS priority table list, kept in driver memory.
335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	struct mwifiex_adapter *adapter = priv->adapter;
375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	struct mwifiex_bss_prio_node *bss_prio;
38931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar	struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	unsigned long flags;
405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (!bss_prio) {
435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_err(adapter->dev, "%s: failed to alloc bss_prio\n",
44931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar			__func__);
45b53575ecf939a4f752de87eabf1adbcfa4478a6cChristoph Fritz		return -ENOMEM;
465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	bss_prio->priv = priv;
495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	INIT_LIST_HEAD(&bss_prio->list);
50931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar	if (!tbl[priv->bss_priority].bss_prio_cur)
51931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar		tbl[priv->bss_priority].bss_prio_cur = bss_prio;
52931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar
53931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar	spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
54931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar	list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
55931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar	spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
57600f5d909a54a8dccf8c8c23898fc2e91bc0953eAmitkumar Karwar	return 0;
585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes the private structure and sets default
625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * values to the members.
635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Additionally, it also initializes all the locks and sets up all the
655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * lists.
665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int mwifiex_init_priv(struct mwifiex_private *priv)
685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	u32 i;
705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->media_connected = false;
725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(priv->curr_addr, 0xff, ETH_ALEN);
735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->pkt_tx_ctrl = 0;
7593a1df48d224296fb527d32fbec4d5162828feb4Yogesh Ashok Powar	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->data_rate = 0;	/* Initially indicate the rate as auto */
775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->is_data_rate_auto = true;
785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
815eb02e44adc92a71bae3ff60acb1eea5ada14e93Amitkumar Karwar	priv->sec_info.wep_enabled = 0;
82f986b6d538c9351c99108b51be9f77ac1b300b16Marc Yang	priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
832be50b8df53f2f329b7ddcc8be286ef6a7469fd2Yogesh Ashok Powar	priv->sec_info.encryption_mode = 0;
845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++)
855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key));
865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->wep_key_curr_index = 0;
875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				HostCmd_ACT_MAC_ETHERNETII_ENABLE;
895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->beacon_period = 100; /* beacon interval */ ;
915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->attempted_bss_desc = NULL;
925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params));
935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL;
945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid));
965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid));
975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->assoc_rsp_size = 0;
995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
1005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->atim_window = 0;
1015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->adhoc_state = ADHOC_IDLE;
1025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->tx_power_level = 0;
1035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->max_tx_power_level = 0;
1045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->min_tx_power_level = 0;
1055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->tx_rate = 0;
1065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->rxpd_htinfo = 0;
1075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->rxpd_rate = 0;
1085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->rate_bitmap = 0;
1095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->data_rssi_last = 0;
1105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->data_rssi_avg = 0;
1115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->data_nf_avg = 0;
1125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->data_nf_last = 0;
1135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->bcn_rssi_last = 0;
1145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->bcn_rssi_avg = 0;
1155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->bcn_nf_avg = 0;
1165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->bcn_nf_last = 0;
1175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie));
1185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->aes_key, 0, sizeof(priv->aes_key));
1195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->wpa_ie_len = 0;
1205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->wpa_is_gtk_set = false;
1215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf));
1235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->assoc_tlv_buf_len = 0;
1245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->wps, 0, sizeof(priv->wps));
1255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
1265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->gen_ie_buf_len = 0;
1275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(priv->vs_ie, 0, sizeof(priv->vs_ie));
1285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->wmm_required = true;
1305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->wmm_enabled = false;
1315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->wmm_qosinfo = 0;
1325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->curr_bcn_buf = NULL;
1335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->curr_bcn_size = 0;
1345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	priv->scan_block = false;
1365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
137636c4598499eeacce0893dc8d91113b904bd531eYogesh Ashok Powar	return mwifiex_add_bss_prio_tbl(priv);
1385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
1395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
1415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function allocates buffers for members of the adapter
1425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * structure.
1435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
1445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The memory allocated includes scan table, command buffers, and
1455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * sleep confirm command buffer. In addition, the queues are
1465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * also initialized.
1475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
1485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
1495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
150270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	int ret;
1515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Allocate command buffer */
1535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	ret = mwifiex_alloc_cmd_buffer(adapter);
1545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (ret) {
1555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n",
156931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar			__func__);
1575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return -1;
1585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
1595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->sleep_cfm =
1617cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
162931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar			      + INTF_HEADER_LEN);
1635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (!adapter->sleep_cfm) {
1655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_err(adapter->dev, "%s: failed to alloc sleep cfm"
1665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			" cmd buffer\n", __func__);
1675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return -1;
1685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
1695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN);
1705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	return 0;
1725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
1735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
1755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes the adapter structure and sets default
1765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * values to the members of adapter.
1775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
1785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This also initializes the WMM related parameters in the driver private
1795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * structures.
1805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
1815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
1825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
1837cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar	struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL;
1845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1857cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar	skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm));
1865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->cmd_sent = false;
188d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar
189d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	if (adapter->iface_type == MWIFIEX_PCIE)
190d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar		adapter->data_sent = false;
191d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	else
192d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar		adapter->data_sent = true;
193d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar
1945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->cmd_resp_received = false;
1955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->event_received = false;
1965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->data_received = false;
1975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
1985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->surprise_removed = false;
1995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
2015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
2035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->ps_state = PS_STATE_AWAKE;
2045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->need_to_wakeup = false;
2055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->scan_mode = HostCmd_BSS_MODE_ANY;
2075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME;
2085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
2095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
2105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->scan_probes = 1;
2125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->multiple_dtim = 1;
2145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->local_listen_interval = 0;	/* default value in firmware
2165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao						   will be used */
2175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->is_deep_sleep = false;
2195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->delay_null_pkt = false;
2215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->delay_to_ps = 1000;
2225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->enhanced_ps_mode = PS_MODE_AUTO;
2235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->gen_null_pkt = false;	/* Disable NULL Pkg generation by
2255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					   default */
2265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by
2275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					   default */
2285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->pm_wakeup_card_req = false;
2295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->pm_wakeup_fw_try = false;
2315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
2335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
2345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
2355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->is_hs_configured = false;
2375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF);
2385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF;
2395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF;
2405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hs_activated = false;
2415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(adapter->event_body, 0, sizeof(adapter->event_body));
2435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hw_dot_11n_dev_cap = 0;
2445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hw_dev_mcs_support = 0;
24521c3ba346486c3df39d23a2a085fcdfc7a59a853Amitkumar Karwar	adapter->sec_chan_offset = 0;
2465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->adhoc_11n_enabled = false;
2475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	mwifiex_wmm_init(adapter);
2495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (adapter->sleep_cfm) {
2518ed1303321914a70ad580c1d034898e43c39b065Yogesh Ashok Powar		sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
2528ed1303321914a70ad580c1d034898e43c39b065Yogesh Ashok Powar						adapter->sleep_cfm->data;
2537cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len);
2547cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		sleep_cfm_buf->command =
2557cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar				cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
2567cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		sleep_cfm_buf->size =
2577cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar				cpu_to_le16(adapter->sleep_cfm->len);
2587cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		sleep_cfm_buf->result = 0;
2597cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM);
2607cc5eb629cefa9a40295ff5ee4b1ec41ad855e8dAmitkumar Karwar		sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED);
2615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
2625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params));
2635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period));
2645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->tx_lock_flag = false;
2655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->null_pkt_interval = 0;
2665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->fw_bands = 0;
2675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->config_bands = 0;
2685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->adhoc_start_band = 0;
2695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->scan_channels = NULL;
2705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->fw_release_number = 0;
2715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->fw_cap_info = 0;
2725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf));
2735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->event_cause = 0;
2745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->region_code = 0;
2755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
2765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->adhoc_awake_period = 0;
2775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
2785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->arp_filter_size = 0;
2793dc5e1751803e812806d7aa46150af92f91ef489Amitkumar Karwar	adapter->channel_type = NL80211_CHAN_HT20;
2805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
2815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
2825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
283bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil * This function sets trans_start per tx_queue
284bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil */
285bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patilvoid mwifiex_set_trans_start(struct net_device *dev)
286bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil{
287bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	int i;
288bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
289bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	for (i = 0; i < dev->num_tx_queues; i++)
290bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil		netdev_get_tx_queue(dev, i)->trans_start = jiffies;
291bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
292bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	dev->trans_start = jiffies;
293bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil}
294bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
295bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil/*
296bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil * This function wakes up all queues in net_device
297bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil */
298bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patilvoid mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
299bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil					struct mwifiex_adapter *adapter)
300bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil{
301bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	unsigned long dev_queue_flags;
302bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
303bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
304bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	netif_tx_wake_all_queues(netdev);
305bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
306bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil}
307bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
308bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil/*
309bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil * This function stops all queues in net_device
310bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil */
311bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patilvoid mwifiex_stop_net_dev_queue(struct net_device *netdev,
312bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil					struct mwifiex_adapter *adapter)
313bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil{
314bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	unsigned long dev_queue_flags;
315bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
316bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
317bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	netif_tx_stop_all_queues(netdev);
318bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
319bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil}
320bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil
321bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil/*
322711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar *  This function releases the lock variables and frees the locks and
323711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar *  associated locks.
324711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar */
325711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwarstatic void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
326711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar{
327711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	struct mwifiex_private *priv;
328711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	s32 i, j;
329711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar
330711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	/* Free lists */
331711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	list_del(&adapter->cmd_free_q);
332711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	list_del(&adapter->cmd_pending_q);
333711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	list_del(&adapter->scan_pending_q);
334711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar
335711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	for (i = 0; i < adapter->priv_num; i++)
336711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar		list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
337711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar
338711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	for (i = 0; i < adapter->priv_num; i++) {
339711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar		if (adapter->priv[i]) {
340711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar			priv = adapter->priv[i];
341711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar			for (j = 0; j < MAX_NUM_TID; ++j)
342711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar				list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
343711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar			list_del(&priv->tx_ba_stream_tbl_ptr);
344711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar			list_del(&priv->rx_reorder_tbl_ptr);
345711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar		}
346711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar	}
347711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar}
348711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar
349711825a06bb288e04f8236d77c4e12eba9a1c478Amitkumar Karwar/*
3505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function frees the adapter structure.
3515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
3525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The freeing operation is done recursively, by canceling all
3535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * pending commands, freeing the member buffers previously
3545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * allocated (command buffers, scan table buffer, sleep confirm
3555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * command buffer), stopping the timers and calling the cleanup
3565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * routines for every interface, before the actual adapter
3575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * structure is freed.
3585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
3595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void
3605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_free_adapter(struct mwifiex_adapter *adapter)
3615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
3625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (!adapter) {
3635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		pr_err("%s: adapter is NULL\n", __func__);
3645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return;
3655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
3665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	mwifiex_cancel_all_pending_cmd(adapter);
3685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Free lock variables */
3705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	mwifiex_free_lock_list(adapter);
3715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Free command buffer */
3735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	dev_dbg(adapter->dev, "info: free cmd buffer\n");
3745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	mwifiex_free_cmd_buffer(adapter);
3755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	del_timer(&adapter->cmd_timer);
3775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	dev_dbg(adapter->dev, "info: free scan table\n");
3795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->if_ops.cleanup_if(adapter);
3815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3822da8cbf8a6b454296c9db7b57cac72d5a39e3aa7Amitkumar Karwar	if (adapter->sleep_cfm)
3832da8cbf8a6b454296c9db7b57cac72d5a39e3aa7Amitkumar Karwar		dev_kfree_skb_any(adapter->sleep_cfm);
3845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
3855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
3875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *  This function intializes the lock variables and
3885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *  the list heads.
3895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
3905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
3915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
392270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	struct mwifiex_private *priv;
393270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	s32 i, j;
3945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
3955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->mwifiex_lock);
3965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->int_lock);
3975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->main_proc_lock);
3985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->mwifiex_cmd_lock);
399bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil	spin_lock_init(&adapter->queue_lock);
4005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; i++) {
4015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (adapter->priv[i]) {
4025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			priv = adapter->priv[i];
4035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			spin_lock_init(&priv->rx_pkt_lock);
4045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			spin_lock_init(&priv->wmm.ra_list_spinlock);
4055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			spin_lock_init(&priv->curr_bcn_buf_lock);
4065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
4075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
4085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Initialize cmd_free_q */
4105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	INIT_LIST_HEAD(&adapter->cmd_free_q);
4115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Initialize cmd_pending_q */
4125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	INIT_LIST_HEAD(&adapter->cmd_pending_q);
4135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Initialize scan_pending_q */
4145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	INIT_LIST_HEAD(&adapter->scan_pending_q);
4155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->cmd_free_q_lock);
4175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->cmd_pending_q_lock);
4185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_init(&adapter->scan_pending_q_lock);
4195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; ++i) {
4215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
4225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		adapter->bss_prio_tbl[i].bss_prio_cur = NULL;
4235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
4245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
4255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; i++) {
4275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (!adapter->priv[i])
4285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			continue;
4295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		priv = adapter->priv[i];
4305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		for (j = 0; j < MAX_NUM_TID; ++j) {
4315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list);
4325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock);
4335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
4345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
4355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
4365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
4385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		spin_lock_init(&priv->rx_reorder_tbl_lock);
4395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
4405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	return 0;
4425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
4435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
4455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes the firmware.
4465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
4475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The following operations are performed sequentially -
4485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Allocate adapter structure
4495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Initialize the adapter structure
4505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Initialize the private structure
4515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Add BSS priority tables to the adapter structure
4525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - For each interface, send the init commands to firmware
4535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Send the first command in command pending queue, if available
4545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
4555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_init_fw(struct mwifiex_adapter *adapter)
4565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
457270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	int ret;
458270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	struct mwifiex_private *priv;
459270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	u8 i, first_sta = true;
4605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	int is_cmd_pend_q_empty;
4615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	unsigned long flags;
4625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
4645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Allocate memory for member of adapter structure */
4665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	ret = mwifiex_allocate_adapter(adapter);
4675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (ret)
4685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return -1;
4695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Initialize adapter structure */
4715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	mwifiex_init_adapter(adapter);
4725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; i++) {
4745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (adapter->priv[i]) {
4755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			priv = adapter->priv[i];
4765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			/* Initialize private structure */
4785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			ret = mwifiex_init_priv(priv);
4795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			if (ret)
4805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				return -1;
4815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
4825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
4835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; i++) {
4845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (adapter->priv[i]) {
4855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta);
4865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			if (ret == -1)
4875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				return -1;
4885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			first_sta = false;
4905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
4915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
4925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
4935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
4945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
4955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
4965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (!is_cmd_pend_q_empty) {
4975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		/* Send the first command in queue and return */
4985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (mwifiex_main_process(adapter) != -1)
4995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			ret = -EINPROGRESS;
5005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	} else {
5015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
5025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
5035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	return ret;
5055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
5065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
5085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes the BSS priority tables.
5095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
5105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The function traverses through all the allocated BSS priority nodes
5115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * in every BSS priority table and frees them.
5125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
5135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
5145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
5155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	int i;
5165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	struct mwifiex_adapter *adapter = priv->adapter;
517270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur;
5185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	struct list_head *head;
519931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar	spinlock_t *lock; /* bss priority lock */
5205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	unsigned long flags;
5215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; ++i) {
5235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		head = &adapter->bss_prio_tbl[i].bss_prio_head;
5245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		cur = &adapter->bss_prio_tbl[i].bss_prio_cur;
5255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
5265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_dbg(adapter->dev, "info: delete BSS priority table,"
5279da9a3b29ba6a9a98e437f24576f13cbe259997bYogesh Ashok Powar				" bss_type = %d, bss_num = %d, i = %d,"
5289da9a3b29ba6a9a98e437f24576f13cbe259997bYogesh Ashok Powar				" head = %p, cur = %p\n",
5299da9a3b29ba6a9a98e437f24576f13cbe259997bYogesh Ashok Powar			      priv->bss_type, priv->bss_num, i, head, *cur);
5305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (*cur) {
5315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			spin_lock_irqsave(lock, flags);
5325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			if (list_empty(head)) {
5335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				spin_unlock_irqrestore(lock, flags);
5345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				continue;
5355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			}
5365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			bssprio_node = list_first_entry(head,
5375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					struct mwifiex_bss_prio_node, list);
5385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			spin_unlock_irqrestore(lock, flags);
5395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			list_for_each_entry_safe(bssprio_node, tmp_node, head,
5415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao						 list) {
5425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				if (bssprio_node->priv == priv) {
5435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					dev_dbg(adapter->dev, "info: Delete "
5445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao						"node %p, next = %p\n",
5455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao						bssprio_node, tmp_node);
5465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					spin_lock_irqsave(lock, flags);
5475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					list_del(&bssprio_node->list);
5485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					spin_unlock_irqrestore(lock, flags);
5495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao					kfree(bssprio_node);
5505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao				}
5515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			}
5525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			*cur = (struct mwifiex_bss_prio_node *)head;
5535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
5545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
5555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
5565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
5585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function is used to shutdown the driver.
5595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
5605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The following operations are performed sequentially -
5615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Check if already shut down
5625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Make sure the main process has stopped
5635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Clean up the Tx and Rx queues
5645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Delete BSS priority tables
5655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Free the adapter
5665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Notify completion
5675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
5685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint
5695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
5705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
5715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	int ret = -EINPROGRESS;
572270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	struct mwifiex_private *priv;
573270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar	s32 i;
5745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	unsigned long flags;
5755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* mwifiex already shutdown */
5775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)
5785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return 0;
5795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
5815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* wait for mwifiex_process to complete */
5825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (adapter->mwifiex_processing) {
5835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_warn(adapter->dev, "main process is still running\n");
5845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return ret;
5855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
5865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* shut down mwifiex */
5885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
5895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Clean up Tx/Rx queues and delete BSS priority table */
5915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	for (i = 0; i < adapter->priv_num; i++) {
5925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (adapter->priv[i]) {
5935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			priv = adapter->priv[i];
5945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
5955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			mwifiex_clean_txrx(priv);
5965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			mwifiex_delete_bss_prio_tbl(priv);
5975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
5985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
5995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_lock_irqsave(&adapter->mwifiex_lock, flags);
6015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Free adapter structure */
6035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	mwifiex_free_adapter(adapter);
6045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	spin_unlock_irqrestore(&adapter->mwifiex_lock, flags);
6065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Notify completion */
6085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	ret = mwifiex_shutdown_fw_complete(adapter);
6095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	return ret;
6115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
6125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/*
6145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function downloads the firmware to the card.
6155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
6165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The actual download is preceded by two sanity checks -
6175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Check if firmware is already running
6185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Check if the interface is the winner to download the firmware
6195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
6205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * ...and followed by another -
6215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *      - Check if the firmware is downloaded successfully
6225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *
6235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * After download is successfully completed, the host interrupts are enabled.
6245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */
6255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
6265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		    struct mwifiex_fw_image *pmfw)
6275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{
628d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	int ret;
6295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	u32 poll_num = 1;
6305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
631d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	adapter->winner = 0;
632d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar
6335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Check if firmware is already running */
634d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	ret = adapter->if_ops.check_fw_status(adapter, poll_num);
6355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (!ret) {
6365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_notice(adapter->dev,
637931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar			   "WLAN FW already running! Skip FW download\n");
6385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		goto done;
6395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
6405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	poll_num = MAX_FIRMWARE_POLL_TRIES;
6415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Check if we are the winner for downloading FW */
643d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	if (!adapter->winner) {
6445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_notice(adapter->dev,
645931f15842a9e1251d46a681bd10d2033f6fb1ffdYogesh Ashok Powar			   "Other intf already running! Skip FW download\n");
6465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
6475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		goto poll_fw;
6485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
6495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (pmfw) {
6505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		/* Download firmware with helper */
6515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		ret = adapter->if_ops.prog_fw(adapter, pmfw);
6525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		if (ret) {
6535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			dev_err(adapter->dev, "prog_fw failed ret=%#x\n", ret);
6545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao			return ret;
6555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		}
6565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
6575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao
6585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaopoll_fw:
6595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* Check if the firmware is downloaded successfully or not */
660d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar	ret = adapter->if_ops.check_fw_status(adapter, poll_num);
6615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	if (ret) {
6625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		dev_err(adapter->dev, "FW failed to be active in time\n");
6635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao		return -1;
6645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	}
6655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaodone:
6665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	/* re-enable host interrupt for mwifiex after fw dnld is successful */
6675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	adapter->if_ops.enable_int(adapter);
6685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao	return ret;
6695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}
670