File Index
Files and directories
Sign in
FILE

init.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/marvell/mwifiex/init.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * NXP Wireless LAN device driver: HW/FW Initialization
  4 *
  5 * Copyright 2011-2020 NXP
  6 */
  7
  8#include "decl.h"
  9#include "ioctl.h"
 10#include "util.h"
 11#include "fw.h"
 12#include "main.h"
 13#include "wmm.h"
 14#include "11n.h"
 15
 16/*
 17 * This function adds a BSS priority table to the table list.
 18 *
 19 * The function allocates a new BSS priority table node and adds it to
 20 * the end of BSS priority table list, kept in driver memory.
 21 */
 22static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
 23{
 24	struct mwifiex_adapter *adapter = priv->adapter;
 25	struct mwifiex_bss_prio_node *bss_prio;
 26	struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
 27
 28	bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
 29	if (!bss_prio)
 30		return -ENOMEM;
 31
 32	bss_prio->priv = priv;
 33	INIT_LIST_HEAD(&bss_prio->list);
 34
 35	spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock);
 36	list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
 37	spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock);
 38
 39	return 0;
 40}
 41
 42static void wakeup_timer_fn(struct timer_list *t)
 43{
 44	struct mwifiex_adapter *adapter = timer_container_of(adapter, t,
 45						             wakeup_timer);
 46
 47	mwifiex_dbg(adapter, ERROR, "Firmware wakeup failed\n");
 48	adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
 49	mwifiex_cancel_all_pending_cmd(adapter);
 50
 51	if (adapter->if_ops.card_reset)
 52		adapter->if_ops.card_reset(adapter);
 53}
 54
 55static void fw_dump_work(struct work_struct *work)
 56{
 57	struct mwifiex_adapter *adapter =
 58		container_of(work, struct mwifiex_adapter, devdump_work.work);
 59
 60	mwifiex_upload_device_dump(adapter);
 61}
 62
 63/*
 64 * This function initializes the private structure and sets default
 65 * values to the members.
 66 *
 67 * Additionally, it also initializes all the locks and sets up all the
 68 * lists.
 69 */
 70int mwifiex_init_priv(struct mwifiex_private *priv)
 71{
 72	u32 i;
 73
 74	priv->media_connected = false;
 75	eth_broadcast_addr(priv->curr_addr);
 76	priv->port_open = false;
 77	priv->usb_port = MWIFIEX_USB_EP_DATA;
 78	priv->pkt_tx_ctrl = 0;
 79	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
 80	priv->data_rate = 0;	/* Initially indicate the rate as auto */
 81	priv->is_data_rate_auto = true;
 82	priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
 83	priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
 84
 85	priv->auth_flag = 0;
 86	priv->auth_alg = WLAN_AUTH_NONE;
 87
 88	priv->sec_info.wep_enabled = 0;
 89	priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
 90	priv->sec_info.encryption_mode = 0;
 91	for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++)
 92		memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key));
 93	priv->wep_key_curr_index = 0;
 94	priv->curr_pkt_filter = HostCmd_ACT_MAC_DYNAMIC_BW_ENABLE |
 95				HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
 96				HostCmd_ACT_MAC_ETHERNETII_ENABLE;
 97
 98	priv->beacon_period = 100; /* beacon interval */
 99	priv->attempted_bss_desc = NULL;
100	memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params));
101	priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL;
102
103	memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid));
104	memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid));
105	memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
106	priv->assoc_rsp_size = 0;
107	priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
108	priv->atim_window = 0;
109	priv->adhoc_state = ADHOC_IDLE;
110	priv->tx_power_level = 0;
111	priv->max_tx_power_level = 0;
112	priv->min_tx_power_level = 0;
113	priv->tx_ant = 0;
114	priv->rx_ant = 0;
115	priv->tx_rate = 0;
116	priv->rxpd_htinfo = 0;
117	priv->rxpd_rate = 0;
118	priv->rate_bitmap = 0;
119	priv->data_rssi_last = 0;
120	priv->data_rssi_avg = 0;
121	priv->data_nf_avg = 0;
122	priv->data_nf_last = 0;
123	priv->bcn_rssi_last = 0;
124	priv->bcn_rssi_avg = 0;
125	priv->bcn_nf_avg = 0;
126	priv->bcn_nf_last = 0;
127	memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie));
128	memset(&priv->aes_key, 0, sizeof(priv->aes_key));
129	priv->wpa_ie_len = 0;
130	priv->wpa_is_gtk_set = false;
131
132	memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf));
133	priv->assoc_tlv_buf_len = 0;
134	memset(&priv->wps, 0, sizeof(priv->wps));
135	memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
136	priv->gen_ie_buf_len = 0;
137	memset(priv->vs_ie, 0, sizeof(priv->vs_ie));
138
139	priv->wmm_required = true;
140	priv->wmm_enabled = false;
141	priv->wmm_qosinfo = 0;
142	priv->curr_bcn_buf = NULL;
143	priv->curr_bcn_size = 0;
144	priv->wps_ie = NULL;
145	priv->wps_ie_len = 0;
146	priv->ap_11n_enabled = 0;
147	memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg));
148
149	priv->scan_block = false;
150
151	priv->csa_chan = 0;
152	priv->csa_expire_time = 0;
153	priv->del_list_idx = 0;
154	priv->hs2_enabled = false;
155	priv->check_tdls_tx = false;
156	memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
157
158	mwifiex_init_11h_params(priv);
159
160	return mwifiex_add_bss_prio_tbl(priv);
161}
162
163/*
164 * This function allocates buffers for members of the adapter
165 * structure.
166 *
167 * The memory allocated includes scan table, command buffers, and
168 * sleep confirm command buffer. In addition, the queues are
169 * also initialized.
170 */
171static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
172{
173	int ret;
174
175	/* Allocate command buffer */
176	ret = mwifiex_alloc_cmd_buffer(adapter);
177	if (ret) {
178		mwifiex_dbg(adapter, ERROR,
179			    "%s: failed to alloc cmd buffer\n",
180			    __func__);
181		return -1;
182	}
183
184	adapter->sleep_cfm =
185		dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
186			      + INTF_HEADER_LEN);
187
188	if (!adapter->sleep_cfm) {
189		mwifiex_dbg(adapter, ERROR,
190			    "%s: failed to alloc sleep cfm\t"
191			    " cmd buffer\n", __func__);
192		return -1;
193	}
194	skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN);
195
196	return 0;
197}
198
199/*
200 * This function initializes the adapter structure and sets default
201 * values to the members of adapter.
202 *
203 * This also initializes the WMM related parameters in the driver private
204 * structures.
205 */
206static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
207{
208	struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL;
209
210	skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm));
211
212	adapter->cmd_sent = false;
213
214	if (adapter->iface_type == MWIFIEX_SDIO)
215		adapter->data_sent = true;
216	else
217		adapter->data_sent = false;
218
219	if (adapter->iface_type == MWIFIEX_USB)
220		adapter->intf_hdr_len = 0;
221	else
222		adapter->intf_hdr_len = INTF_HEADER_LEN;
223
224	adapter->cmd_resp_received = false;
225	adapter->event_received = false;
226	adapter->data_received = false;
227	adapter->assoc_resp_received = false;
228	adapter->priv_link_lost = NULL;
229	adapter->host_mlme_link_lost = false;
230
231	clear_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags);
232
233	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
234
235	adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
236	adapter->ps_state = PS_STATE_AWAKE;
237	adapter->need_to_wakeup = false;
238
239	adapter->scan_mode = HostCmd_BSS_MODE_ANY;
240	adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME;
241	adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
242	adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
243	adapter->scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME;
244
245	adapter->scan_probes = 1;
246
247	adapter->multiple_dtim = 1;
248
249	adapter->local_listen_interval = 0;	/* default value in firmware
250						   will be used */
251
252	adapter->is_deep_sleep = false;
253
254	adapter->delay_null_pkt = false;
255	adapter->delay_to_ps = 1000;
256	adapter->enhanced_ps_mode = PS_MODE_AUTO;
257
258	adapter->gen_null_pkt = false;	/* Disable NULL Pkg generation by
259					   default */
260	adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by
261					   default */
262	adapter->pm_wakeup_card_req = false;
263
264	adapter->pm_wakeup_fw_try = false;
265
266	adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
267
268	clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
269	adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF);
270	adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF;
271	adapter->hs_cfg.gap = HS_CFG_GAP_DEF;
272	adapter->hs_activated = false;
273
274	memset(adapter->event_body, 0, sizeof(adapter->event_body));
275	adapter->hw_dot_11n_dev_cap = 0;
276	adapter->hw_dev_mcs_support = 0;
277	adapter->sec_chan_offset = 0;
278	adapter->adhoc_11n_enabled = false;
279
280	mwifiex_wmm_init(adapter);
281	atomic_set(&adapter->tx_hw_pending, 0);
282
283	sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
284					adapter->sleep_cfm->data;
285	memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len);
286	sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
287	sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len);
288	sleep_cfm_buf->result = 0;
289	sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM);
290	sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED);
291
292	memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period));
293	adapter->tx_lock_flag = false;
294	adapter->null_pkt_interval = 0;
295	adapter->fw_bands = 0;
296	adapter->config_bands = 0;
297	adapter->adhoc_start_band = 0;
298	adapter->fw_release_number = 0;
299	adapter->fw_cap_info = 0;
300	memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf));
301	adapter->event_cause = 0;
302	adapter->region_code = 0;
303	adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
304	adapter->adhoc_awake_period = 0;
305	memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
306	adapter->arp_filter_size = 0;
307	adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
308	adapter->mfg_mode = mfg_mode;
309	adapter->key_api_major_ver = 0;
310	adapter->key_api_minor_ver = 0;
311	eth_broadcast_addr(adapter->perm_addr);
312	adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
313	adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
314	adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
315	adapter->active_scan_triggered = false;
316	timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
317	adapter->devdump_len = 0;
318	INIT_DELAYED_WORK(&adapter->devdump_work, fw_dump_work);
319}
320
321/*
322 * This function sets trans_start per tx_queue
323 */
324void mwifiex_set_trans_start(struct net_device *dev)
325{
326	int i;
327
328	for (i = 0; i < dev->num_tx_queues; i++)
329		txq_trans_cond_update(netdev_get_tx_queue(dev, i));
330
331	netif_trans_update(dev);
332}
333
334/*
335 * This function wakes up all queues in net_device
336 */
337void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
338					struct mwifiex_adapter *adapter)
339{
340	spin_lock_bh(&adapter->queue_lock);
341	netif_tx_wake_all_queues(netdev);
342	spin_unlock_bh(&adapter->queue_lock);
343}
344
345/*
346 * This function stops all queues in net_device
347 */
348void mwifiex_stop_net_dev_queue(struct net_device *netdev,
349					struct mwifiex_adapter *adapter)
350{
351	spin_lock_bh(&adapter->queue_lock);
352	netif_tx_stop_all_queues(netdev);
353	spin_unlock_bh(&adapter->queue_lock);
354}
355
356/*
357 * This function invalidates the list heads.
358 */
359static void mwifiex_invalidate_lists(struct mwifiex_adapter *adapter)
360{
361	struct mwifiex_private *priv;
362	s32 i, j;
363
364	list_del(&adapter->cmd_free_q);
365	list_del(&adapter->cmd_pending_q);
366	list_del(&adapter->scan_pending_q);
367
368	for (i = 0; i < adapter->priv_num; i++)
369		list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
370
371	for (i = 0; i < adapter->priv_num; i++) {
372		priv = adapter->priv[i];
373		for (j = 0; j < MAX_NUM_TID; ++j)
374			list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
375		list_del(&priv->tx_ba_stream_tbl_ptr);
376		list_del(&priv->rx_reorder_tbl_ptr);
377		list_del(&priv->sta_list);
378		list_del(&priv->auto_tdls_list);
379	}
380}
381
382/*
383 * This function performs cleanup for adapter structure.
384 *
385 * The cleanup is done recursively, by canceling all pending
386 * commands, freeing the member buffers previously allocated
387 * (command buffers, scan table buffer, sleep confirm command
388 * buffer), stopping the timers and calling the cleanup routines
389 * for every interface.
390 */
391static void
392mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
393{
394	timer_delete(&adapter->wakeup_timer);
395	cancel_delayed_work_sync(&adapter->devdump_work);
396	mwifiex_cancel_all_pending_cmd(adapter);
397	wake_up_interruptible(&adapter->cmd_wait_q.wait);
398	wake_up_interruptible(&adapter->hs_activate_wait_q);
399}
400
401void mwifiex_free_cmd_buffers(struct mwifiex_adapter *adapter)
402{
403	mwifiex_invalidate_lists(adapter);
404
405	/* Free command buffer */
406	mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
407	mwifiex_free_cmd_buffer(adapter);
408
409	if (adapter->sleep_cfm)
410		dev_kfree_skb_any(adapter->sleep_cfm);
411}
412
413/*
414 *  This function intializes the lock variables and
415 *  the list heads.
416 */
417int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
418{
419	struct mwifiex_private *priv;
420	s32 i, j;
421
422	spin_lock_init(&adapter->int_lock);
423	spin_lock_init(&adapter->main_proc_lock);
424	spin_lock_init(&adapter->mwifiex_cmd_lock);
425	spin_lock_init(&adapter->queue_lock);
426	for (i = 0; i < adapter->priv_num; i++) {
427		priv = adapter->priv[i];
428		spin_lock_init(&priv->wmm.ra_list_spinlock);
429		spin_lock_init(&priv->curr_bcn_buf_lock);
430		spin_lock_init(&priv->sta_list_spinlock);
431		spin_lock_init(&priv->auto_tdls_lock);
432	}
433
434	/* Initialize cmd_free_q */
435	INIT_LIST_HEAD(&adapter->cmd_free_q);
436	/* Initialize cmd_pending_q */
437	INIT_LIST_HEAD(&adapter->cmd_pending_q);
438	/* Initialize scan_pending_q */
439	INIT_LIST_HEAD(&adapter->scan_pending_q);
440
441	spin_lock_init(&adapter->cmd_free_q_lock);
442	spin_lock_init(&adapter->cmd_pending_q_lock);
443	spin_lock_init(&adapter->scan_pending_q_lock);
444	spin_lock_init(&adapter->rx_proc_lock);
445
446	skb_queue_head_init(&adapter->rx_data_q);
447	skb_queue_head_init(&adapter->tx_data_q);
448
449	for (i = 0; i < adapter->priv_num; ++i) {
450		INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
451		spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
452	}
453
454	for (i = 0; i < adapter->priv_num; i++) {
455		priv = adapter->priv[i];
456		for (j = 0; j < MAX_NUM_TID; ++j)
457			INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list);
458		INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
459		INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
460		INIT_LIST_HEAD(&priv->sta_list);
461		INIT_LIST_HEAD(&priv->auto_tdls_list);
462		skb_queue_head_init(&priv->tdls_txq);
463		skb_queue_head_init(&priv->bypass_txq);
464
465		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
466		spin_lock_init(&priv->rx_reorder_tbl_lock);
467
468		spin_lock_init(&priv->ack_status_lock);
469		idr_init(&priv->ack_status_frames);
470	}
471
472	return 0;
473}
474
475/*
476 * This function initializes the firmware.
477 *
478 * The following operations are performed sequentially -
479 *      - Allocate adapter structure
480 *      - Initialize the adapter structure
481 *      - Initialize the private structure
482 *      - Add BSS priority tables to the adapter structure
483 *      - For each interface, send the init commands to firmware
484 */
485int mwifiex_init_fw(struct mwifiex_adapter *adapter)
486{
487	int ret;
488	struct mwifiex_private *priv;
489	u8 i, first_sta = true;
490
491	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
492
493	/* Allocate memory for member of adapter structure */
494	ret = mwifiex_allocate_adapter(adapter);
495	if (ret)
496		return -1;
497
498	/* Initialize adapter structure */
499	mwifiex_init_adapter(adapter);
500
501	for (i = 0; i < adapter->priv_num; i++) {
502		priv = adapter->priv[i];
503
504		/* Initialize private structure */
505		ret = mwifiex_init_priv(priv);
506		if (ret)
507			return -1;
508	}
509	if (adapter->mfg_mode) {
510		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
511	} else {
512		for (i = 0; i < adapter->priv_num; i++) {
513			ret = mwifiex_sta_init_cmd(adapter->priv[i],
514						   first_sta);
515			if (ret == -1)
516				return -1;
517
518			first_sta = false;
519		}
520	}
521
522	spin_lock_bh(&adapter->cmd_pending_q_lock);
523	WARN_ON(!list_empty(&adapter->cmd_pending_q));
524	spin_unlock_bh(&adapter->cmd_pending_q_lock);
525
526	adapter->hw_status = MWIFIEX_HW_STATUS_READY;
527
528	if (adapter->if_ops.init_fw_port)
529		adapter->if_ops.init_fw_port(adapter);
530
531	return 0;
532}
533
534/*
535 * This function deletes the BSS priority tables.
536 *
537 * The function traverses through all the allocated BSS priority nodes
538 * in every BSS priority table and frees them.
539 */
540static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
541{
542	int i;
543	struct mwifiex_adapter *adapter = priv->adapter;
544	struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
545	struct list_head *head;
546	spinlock_t *lock; /* bss priority lock */
547
548	for (i = 0; i < adapter->priv_num; ++i) {
549		head = &adapter->bss_prio_tbl[i].bss_prio_head;
550		lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
551		mwifiex_dbg(adapter, INFO,
552			    "info: delete BSS priority table,\t"
553			    "bss_type = %d, bss_num = %d, i = %d,\t"
554			    "head = %p\n",
555			    priv->bss_type, priv->bss_num, i, head);
556
557		{
558			spin_lock_bh(lock);
559			list_for_each_entry_safe(bssprio_node, tmp_node, head,
560						 list) {
561				if (bssprio_node->priv == priv) {
562					mwifiex_dbg(adapter, INFO,
563						    "info: Delete\t"
564						    "node %p, next = %p\n",
565						    bssprio_node, tmp_node);
566					list_del(&bssprio_node->list);
567					kfree(bssprio_node);
568				}
569			}
570			spin_unlock_bh(lock);
571		}
572	}
573}
574
575/*
576 * This function frees the private structure, including cleans
577 * up the TX and RX queues and frees the BSS priority tables.
578 */
579void mwifiex_free_priv(struct mwifiex_private *priv)
580{
581	mwifiex_clean_txrx(priv);
582	mwifiex_delete_bss_prio_tbl(priv);
583	mwifiex_free_curr_bcn(priv);
584}
585
586/*
587 * This function is used to shutdown the driver.
588 *
589 * The following operations are performed sequentially -
590 *      - Check if already shut down
591 *      - Make sure the main process has stopped
592 *      - Clean up the Tx and Rx queues
593 *      - Delete BSS priority tables
594 *      - Free the adapter
595 *      - Notify completion
596 */
597void
598mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
599{
600	struct mwifiex_private *priv;
601	s32 i;
602	struct sk_buff *skb;
603
604	/* mwifiex already shutdown */
605	if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)
606		return;
607
608	/* cancel current command */
609	if (adapter->curr_cmd) {
610		mwifiex_dbg(adapter, WARN,
611			    "curr_cmd is still in processing\n");
612		timer_delete_sync(&adapter->cmd_timer);
613		mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
614		adapter->curr_cmd = NULL;
615	}
616
617	/* shut down mwifiex */
618	mwifiex_dbg(adapter, MSG,
619		    "info: shutdown mwifiex...\n");
620
621	/* Clean up Tx/Rx queues and delete BSS priority table */
622	for (i = 0; i < adapter->priv_num; i++) {
623		priv = adapter->priv[i];
624
625		mwifiex_clean_auto_tdls(priv);
626		mwifiex_abort_cac(priv);
627		mwifiex_free_priv(priv);
628	}
629
630	atomic_set(&adapter->tx_queued, 0);
631	while ((skb = skb_dequeue(&adapter->tx_data_q)))
632		mwifiex_write_data_complete(adapter, skb, 0, 0);
633
634	spin_lock_bh(&adapter->rx_proc_lock);
635
636	while ((skb = skb_dequeue(&adapter->rx_data_q))) {
637		struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
638
639		atomic_dec(&adapter->rx_pending);
640		priv = adapter->priv[rx_info->bss_num];
641		if (priv)
642			priv->stats.rx_dropped++;
643
644		dev_kfree_skb_any(skb);
645	}
646
647	spin_unlock_bh(&adapter->rx_proc_lock);
648
649	mwifiex_adapter_cleanup(adapter);
650
651	adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
652}
653
654/*
655 * This function downloads the firmware to the card.
656 *
657 * The actual download is preceded by two sanity checks -
658 *      - Check if firmware is already running
659 *      - Check if the interface is the winner to download the firmware
660 *
661 * ...and followed by another -
662 *      - Check if the firmware is downloaded successfully
663 *
664 * After download is successfully completed, the host interrupts are enabled.
665 */
666int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
667		    struct mwifiex_fw_image *pmfw)
668{
669	int ret;
670	u32 poll_num = 1;
671
672	/* check if firmware is already running */
673	ret = adapter->if_ops.check_fw_status(adapter, poll_num);
674	if (!ret) {
675		mwifiex_dbg(adapter, MSG,
676			    "WLAN FW already running! Skip FW dnld\n");
677		return 0;
678	}
679
680	/* check if we are the winner for downloading FW */
681	if (adapter->if_ops.check_winner_status) {
682		adapter->winner = 0;
683		ret = adapter->if_ops.check_winner_status(adapter);
684
685		poll_num = MAX_FIRMWARE_POLL_TRIES;
686		if (ret) {
687			mwifiex_dbg(adapter, MSG,
688				    "WLAN read winner status failed!\n");
689			return ret;
690		}
691
692		if (!adapter->winner) {
693			mwifiex_dbg(adapter, MSG,
694				    "WLAN is not the winner! Skip FW dnld\n");
695			goto poll_fw;
696		}
697	}
698
699	if (pmfw) {
700		/* Download firmware with helper */
701		ret = adapter->if_ops.prog_fw(adapter, pmfw);
702		if (ret) {
703			mwifiex_dbg(adapter, ERROR,
704				    "prog_fw failed ret=%#x\n", ret);
705			return ret;
706		}
707	}
708
709poll_fw:
710	/* Check if the firmware is downloaded successfully or not */
711	ret = adapter->if_ops.check_fw_status(adapter, poll_num);
712	if (ret)
713		mwifiex_dbg(adapter, ERROR,
714			    "FW failed to be active in time\n");
715
716	return ret;
717}
718EXPORT_SYMBOL_GPL(mwifiex_dnld_fw);
~/ Read-only file preview.