xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_sta_event.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_sta_event.c
2  *
3  *  @brief This file contains MLAN event handling.
4  *
5  *
6  *  Copyright 2008-2022 NXP
7  *
8  *  This software file (the File) is distributed by NXP
9  *  under the terms of the GNU General Public License Version 2, June 1991
10  *  (the License).  You may use, redistribute and/or modify the File in
11  *  accordance with the terms and conditions of the License, a copy of which
12  *  is available by writing to the Free Software Foundation, Inc.,
13  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15  *
16  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19  *  this warranty disclaimer.
20  *
21  */
22 
23 /********************************************************
24 Change log:
25     10/13/2008: initial version
26 ********************************************************/
27 
28 #include "mlan.h"
29 #include "mlan_join.h"
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_11n.h"
35 #include "mlan_11h.h"
36 #ifdef DRV_EMBEDDED_SUPPLICANT
37 #include "authenticator_api.h"
38 #endif
39 #ifdef PCIE
40 #include "mlan_pcie.h"
41 #endif /* PCIE */
42 
43 /********************************************************
44 			Global Variables
45 ********************************************************/
46 
47 /********************************************************
48 			Local Functions
49 ********************************************************/
50 
51 /**
52  *  @brief This function handles link lost, deauth and
53  *          disassoc events.
54  *
55  *  @param pmpriv   A pointer to mlan_private structure
56  *  @return         N/A
57  */
wlan_handle_disconnect_event(pmlan_private pmpriv)58 static t_void wlan_handle_disconnect_event(pmlan_private pmpriv)
59 {
60 	ENTER();
61 
62 	if (pmpriv->media_connected == MTRUE)
63 		wlan_reset_connect_state(pmpriv, MTRUE);
64 
65 	LEAVE();
66 }
67 
68 /**
69  *  @brief This function will parse the TDLS event for further wlan action
70  *
71  *  @param priv     A pointer to mlan_private
72  *  @param pevent   A pointer to event buf
73  *
74  *  @return         N/A
75  */
wlan_parse_tdls_event(pmlan_private priv,pmlan_buffer pevent)76 static void wlan_parse_tdls_event(pmlan_private priv, pmlan_buffer pevent)
77 {
78 	Event_tdls_generic *tdls_event =
79 		(Event_tdls_generic *)(pevent->pbuf + pevent->data_offset +
80 				       sizeof(mlan_event_id));
81 	sta_node *sta_ptr = MNULL;
82 	pmlan_adapter pmadapter = priv->adapter;
83 	t_u8 i = 0;
84 	IEEEtypes_HTCap_t *pht_cap = MNULL;
85 	t_u16 ie_len = 0;
86 	mlan_ds_misc_tdls_oper tdls_oper;
87 	t_u8 event_buf[100];
88 	mlan_event *ptdls_event = (mlan_event *)event_buf;
89 	tdls_tear_down_event *tdls_evt =
90 		(tdls_tear_down_event *)ptdls_event->event_buf;
91 	ENTER();
92 
93 	/* reason code is not mandatory, hence less by sizeof(t_u16) */
94 	if (pevent->data_len < (sizeof(Event_tdls_generic) - sizeof(t_u16) -
95 				sizeof(mlan_event_id))) {
96 		PRINTM(MERROR, "Invalid length %d for TDLS event\n",
97 		       pevent->data_len);
98 		LEAVE();
99 		return;
100 	}
101 	sta_ptr = wlan_get_station_entry(priv, tdls_event->peer_mac_addr);
102 	PRINTM(MEVENT, "TDLS_EVENT: %d " MACSTR "\n",
103 	       wlan_le16_to_cpu(tdls_event->event_type),
104 	       MAC2STR(tdls_event->peer_mac_addr));
105 	switch (wlan_le16_to_cpu(tdls_event->event_type)) {
106 	case TDLS_EVENT_TYPE_SETUP_REQ:
107 		if (sta_ptr == MNULL) {
108 			sta_ptr = wlan_add_station_entry(
109 				priv, tdls_event->peer_mac_addr);
110 			if (sta_ptr) {
111 				sta_ptr->status = TDLS_SETUP_INPROGRESS;
112 				wlan_hold_tdls_packets(
113 					priv, tdls_event->peer_mac_addr);
114 			}
115 		}
116 		break;
117 
118 	case TDLS_EVENT_TYPE_LINK_ESTABLISHED:
119 		if (sta_ptr) {
120 			sta_ptr->status = TDLS_SETUP_COMPLETE;
121 			/* parse the TLV for station's capability */
122 			ie_len = wlan_le16_to_cpu(
123 				tdls_event->u.ie_data.ie_length);
124 			if (ie_len) {
125 				pht_cap = (IEEEtypes_HTCap_t *)
126 					wlan_get_specific_ie(
127 						priv,
128 						tdls_event->u.ie_data.ie_ptr,
129 						ie_len, HT_CAPABILITY, 0);
130 				if (pht_cap) {
131 					sta_ptr->is_11n_enabled = MTRUE;
132 					if (GETHT_MAXAMSDU(
133 						    pht_cap->ht_cap.ht_cap_info))
134 						sta_ptr->max_amsdu =
135 							MLAN_TX_DATA_BUF_SIZE_8K;
136 					else
137 						sta_ptr->max_amsdu =
138 							MLAN_TX_DATA_BUF_SIZE_4K;
139 				}
140 			}
141 			for (i = 0; i < MAX_NUM_TID; i++) {
142 				if (sta_ptr->is_11n_enabled ||
143 				    sta_ptr->is_11ax_enabled)
144 					sta_ptr->ampdu_sta[i] =
145 						priv->aggr_prio_tbl[i]
146 							.ampdu_user;
147 				else
148 					sta_ptr->ampdu_sta[i] =
149 						BA_STREAM_NOT_ALLOWED;
150 			}
151 			memset(priv->adapter, sta_ptr->rx_seq, 0xff,
152 			       sizeof(sta_ptr->rx_seq));
153 			wlan_restore_tdls_packets(priv,
154 						  tdls_event->peer_mac_addr,
155 						  TDLS_SETUP_COMPLETE);
156 			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
157 		}
158 		break;
159 
160 	case TDLS_EVENT_TYPE_SETUP_FAILURE:
161 		wlan_restore_tdls_packets(priv, tdls_event->peer_mac_addr,
162 					  TDLS_SETUP_FAILURE);
163 		if (sta_ptr)
164 			wlan_delete_station_entry(priv,
165 						  tdls_event->peer_mac_addr);
166 		if (MTRUE == wlan_is_station_list_empty(priv))
167 			pmadapter->tdls_status = TDLS_NOT_SETUP;
168 		else
169 			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
170 		break;
171 	case TDLS_EVENT_TYPE_LINK_TORN_DOWN:
172 		if (sta_ptr) {
173 			if (sta_ptr->external_tdls) {
174 				PRINTM(MMSG,
175 				       "Receive TDLS TEAR DOWN event, Disable TDLS LINK\n");
176 				pmadapter->tdls_status = TDLS_TEAR_DOWN;
177 				memset(pmadapter, &tdls_oper, 0,
178 				       sizeof(tdls_oper));
179 				tdls_oper.tdls_action = WLAN_TDLS_DISABLE_LINK;
180 				memcpy_ext(priv->adapter, tdls_oper.peer_mac,
181 					   tdls_event->peer_mac_addr,
182 					   MLAN_MAC_ADDR_LENGTH,
183 					   MLAN_MAC_ADDR_LENGTH);
184 				/* Send command to firmware to delete tdls
185 				 * link*/
186 				wlan_prepare_cmd(priv,
187 						 HostCmd_CMD_TDLS_OPERATION,
188 						 HostCmd_ACT_GEN_SET, 0,
189 						 (t_void *)MNULL, &tdls_oper);
190 				ptdls_event->bss_index = priv->bss_index;
191 				ptdls_event->event_id =
192 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
193 				ptdls_event->event_len =
194 					sizeof(tdls_tear_down_event);
195 				memcpy_ext(priv->adapter,
196 					   (t_u8 *)tdls_evt->peer_mac_addr,
197 					   tdls_event->peer_mac_addr,
198 					   MLAN_MAC_ADDR_LENGTH,
199 					   MLAN_MAC_ADDR_LENGTH);
200 				tdls_evt->reason_code = wlan_le16_to_cpu(
201 					tdls_event->u.reason_code);
202 				wlan_recv_event(
203 					priv,
204 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
205 					ptdls_event);
206 				/* Signal MOAL to trigger mlan_main_process */
207 				wlan_recv_event(
208 					priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
209 					MNULL);
210 				LEAVE();
211 				return;
212 			}
213 			wlan_restore_tdls_packets(priv,
214 						  tdls_event->peer_mac_addr,
215 						  TDLS_TEAR_DOWN);
216 			if (sta_ptr->is_11n_enabled ||
217 			    sta_ptr->is_11ax_enabled) {
218 				wlan_cleanup_reorder_tbl(
219 					priv, tdls_event->peer_mac_addr);
220 				wlan_11n_cleanup_txbastream_tbl(
221 					priv, tdls_event->peer_mac_addr);
222 			}
223 			wlan_delete_station_entry(priv,
224 						  tdls_event->peer_mac_addr);
225 			if (MTRUE == wlan_is_station_list_empty(priv))
226 				pmadapter->tdls_status = TDLS_NOT_SETUP;
227 			else
228 				pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
229 		}
230 		break;
231 	case TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT:
232 		PRINTM(MEVENT,
233 		       "TDLS_CHAN_SWITCH_RESULT: status=0x%x, reason=0x%x current_channel=%d\n",
234 		       tdls_event->u.switch_result.status,
235 		       tdls_event->u.switch_result.reason,
236 		       (int)tdls_event->u.switch_result.current_channel);
237 		if (tdls_event->u.switch_result.status == MLAN_STATUS_SUCCESS) {
238 			if (tdls_event->u.switch_result.current_channel ==
239 			    TDLS_BASE_CHANNEL) {
240 				/* enable traffic to AP */
241 				if (pmadapter->tdls_status !=
242 				    TDLS_IN_BASE_CHANNEL) {
243 					wlan_update_non_tdls_ralist(
244 						priv, tdls_event->peer_mac_addr,
245 						MFALSE);
246 					pmadapter->tdls_status =
247 						TDLS_IN_BASE_CHANNEL;
248 				}
249 			} else if (tdls_event->u.switch_result.current_channel ==
250 				   TDLS_OFF_CHANNEL) {
251 				/* pause traffic to AP */
252 				if (pmadapter->tdls_status !=
253 				    TDLS_IN_OFF_CHANNEL) {
254 					wlan_update_non_tdls_ralist(
255 						priv, tdls_event->peer_mac_addr,
256 						MTRUE);
257 					pmadapter->tdls_status =
258 						TDLS_IN_OFF_CHANNEL;
259 				}
260 			}
261 		} else {
262 			if (tdls_event->u.switch_result.current_channel ==
263 			    TDLS_BASE_CHANNEL)
264 				pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
265 			else if (tdls_event->u.switch_result.current_channel ==
266 				 TDLS_OFF_CHANNEL)
267 				pmadapter->tdls_status = TDLS_IN_OFF_CHANNEL;
268 		}
269 		break;
270 	case TDLS_EVENT_TYPE_START_CHAN_SWITCH:
271 		PRINTM(MEVENT, "TDLS start channel switch....\n");
272 		pmadapter->tdls_status = TDLS_SWITCHING_CHANNEL;
273 		break;
274 	case TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED:
275 		PRINTM(MEVENT, "TDLS channel switch stopped, reason=%d\n",
276 		       tdls_event->u.cs_stop_reason);
277 		break;
278 	case TDLS_EVENT_TYPE_DEBUG:
279 	case TDLS_EVENT_TYPE_PACKET:
280 		break;
281 	default:
282 		PRINTM(MERROR, "unknown event type %d\n",
283 		       wlan_le16_to_cpu(tdls_event->event_type));
284 		break;
285 	}
286 	LEAVE();
287 }
288 
289 /**
290  *  @brief This function send the tdls teardown request event.
291  *
292  *  @param priv    A pointer to mlan_private
293  *
294  *  @return        N/A
295  */
wlan_send_tdls_tear_down_request(pmlan_private priv)296 static void wlan_send_tdls_tear_down_request(pmlan_private priv)
297 {
298 	t_u8 event_buf[100];
299 	mlan_event *ptdls_event = (mlan_event *)event_buf;
300 	tdls_tear_down_event *tdls_evt =
301 		(tdls_tear_down_event *)ptdls_event->event_buf;
302 	sta_node *sta_ptr = MNULL;
303 
304 	ENTER();
305 
306 	sta_ptr = (sta_node *)util_peek_list(
307 		priv->adapter->pmoal_handle, &priv->sta_list,
308 		priv->adapter->callbacks.moal_spin_lock,
309 		priv->adapter->callbacks.moal_spin_unlock);
310 	if (!sta_ptr) {
311 		LEAVE();
312 		return;
313 	}
314 	while (sta_ptr != (sta_node *)&priv->sta_list) {
315 		if (sta_ptr->external_tdls) {
316 			ptdls_event->bss_index = priv->bss_index;
317 			ptdls_event->event_id =
318 				MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
319 			ptdls_event->event_len = sizeof(tdls_tear_down_event);
320 			memcpy_ext(priv->adapter,
321 				   (t_u8 *)tdls_evt->peer_mac_addr,
322 				   sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH,
323 				   MLAN_MAC_ADDR_LENGTH);
324 			tdls_evt->reason_code =
325 				MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
326 			wlan_recv_event(priv,
327 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
328 					ptdls_event);
329 		}
330 		sta_ptr = sta_ptr->pnext;
331 	}
332 	LEAVE();
333 	return;
334 }
335 
336 /********************************************************
337 			Global Functions
338 ********************************************************/
339 /**
340  *  @brief This function handles disconnect event, reports disconnect
341  *          to upper layer, cleans tx/rx packets,
342  *          resets link state etc.
343  *
344  *  @param priv             A pointer to mlan_private structure
345  *  @param drv_disconnect   Flag indicating the driver should disconnect
346  *                          and flush pending packets.
347  *
348  *  @return                 N/A
349  */
wlan_reset_connect_state(pmlan_private priv,t_u8 drv_disconnect)350 t_void wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect)
351 {
352 	mlan_adapter *pmadapter = priv->adapter;
353 	mlan_status ret = MLAN_STATUS_SUCCESS;
354 	state_11d_t enable;
355 	t_u8 event_buf[100];
356 	mlan_event *pevent = (mlan_event *)event_buf;
357 
358 	ENTER();
359 
360 	PRINTM(MINFO, "Handles disconnect event.\n");
361 
362 #ifdef UAP_SUPPORT
363 	/* If DFS repeater mode is enabled and station interface disconnects
364 	 * then make sure that all uAPs are stopped.
365 	 */
366 	if (pmadapter->dfs_repeater)
367 		wlan_dfs_rep_disconnect(pmadapter);
368 #endif
369 
370 	if (drv_disconnect) {
371 		priv->media_connected = MFALSE;
372 		pmadapter->state_rdh.tx_block = MFALSE;
373 #ifdef UAP_SUPPORT
374 		if (pmadapter->dfs_mode)
375 			wlan_11h_update_dfs_master_state_on_disconect(priv);
376 		else
377 #endif
378 			wlan_11h_check_update_radar_det_state(priv);
379 	}
380 
381 	if (priv->port_ctrl_mode == MTRUE) {
382 		/* Close the port on Disconnect */
383 		PRINTM(MINFO, "DISC: port_status = CLOSED\n");
384 		priv->port_open = MFALSE;
385 	}
386 	memset(pmadapter, &priv->gtk_rekey, 0,
387 	       sizeof(mlan_ds_misc_gtk_rekey_data));
388 	priv->tx_pause = MFALSE;
389 	pmadapter->scan_block = MFALSE;
390 
391 	/* Reset SNR/NF/RSSI values */
392 	priv->data_rssi_last = 0;
393 	priv->data_nf_last = 0;
394 	priv->data_rssi_avg = 0;
395 	priv->data_nf_avg = 0;
396 	priv->bcn_rssi_last = 0;
397 	priv->bcn_nf_last = 0;
398 	priv->bcn_rssi_avg = 0;
399 	priv->bcn_nf_avg = 0;
400 	priv->rxpd_rate = 0;
401 	priv->rxpd_rate_info = 0;
402 	priv->max_amsdu = 0;
403 	priv->amsdu_disable = MFALSE;
404 	wlan_coex_ampdu_rxwinsize(pmadapter);
405 
406 	priv->sec_info.ewpa_enabled = MFALSE;
407 	priv->sec_info.wpa_enabled = MFALSE;
408 	priv->sec_info.wpa2_enabled = MFALSE;
409 	priv->wpa_ie_len = 0;
410 #ifdef DRV_EMBEDDED_SUPPLICANT
411 	supplicantStopSessionTimer(priv->psapriv);
412 	supplicantClrEncryptKey(priv->psapriv);
413 	supplicantDisable(priv->psapriv);
414 #endif
415 
416 	priv->sec_info.wapi_enabled = MFALSE;
417 	priv->wapi_ie_len = 0;
418 	priv->sec_info.wapi_key_on = MFALSE;
419 
420 	priv->wps.session_enable = MFALSE;
421 	memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie, 0x00,
422 	       sizeof(priv->wps.wps_ie));
423 	priv->sec_info.osen_enabled = MFALSE;
424 	priv->osen_ie_len = 0;
425 
426 	priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;
427 
428 	/*Enable auto data rate */
429 	priv->is_data_rate_auto = MTRUE;
430 	priv->data_rate = 0;
431 
432 	if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
433 		priv->adhoc_state = ADHOC_IDLE;
434 		priv->adhoc_is_link_sensed = MFALSE;
435 		priv->intf_state_11h.adhoc_auto_sel_chan = MTRUE;
436 	}
437 
438 	if (drv_disconnect) {
439 		/* Free Tx and Rx packets, report disconnect to upper layer */
440 		wlan_clean_txrx(priv);
441 
442 		/* Need to erase the current SSID and BSSID info */
443 		memset(pmadapter, &priv->curr_bss_params, 0x00,
444 		       sizeof(priv->curr_bss_params));
445 	}
446 	wlan_send_tdls_tear_down_request(priv);
447 	wlan_delete_station_list(priv);
448 	pmadapter->tdls_status = TDLS_NOT_SETUP;
449 	priv->wmm_qosinfo = priv->saved_wmm_qosinfo;
450 	pmadapter->sleep_period.period = pmadapter->saved_sleep_period.period;
451 	pmadapter->tx_lock_flag = MFALSE;
452 	pmadapter->pps_uapsd_mode = MFALSE;
453 	pmadapter->delay_null_pkt = MFALSE;
454 
455 	if ((wlan_fw_11d_is_enabled(priv)) &&
456 	    (priv->state_11d.user_enable_11d == DISABLE_11D)) {
457 		priv->state_11d.enable_11d = DISABLE_11D;
458 		enable = DISABLE_11D;
459 
460 		/* Send cmd to FW to enable/disable 11D function */
461 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
462 				       HostCmd_ACT_GEN_SET, Dot11D_i, MNULL,
463 				       &enable);
464 		if (ret)
465 			PRINTM(MERROR, "11D: Failed to enable 11D\n");
466 	}
467 	if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
468 	    (pmadapter->cmd_timer_is_set == MFALSE)) {
469 		LEAVE();
470 		return;
471 	}
472 
473 	if (pmadapter->pending_disconnect_priv) {
474 		LEAVE();
475 		return;
476 	}
477 
478 	pevent->bss_index = priv->bss_index;
479 	pevent->event_id = MLAN_EVENT_ID_FW_DISCONNECTED;
480 	pevent->event_len = sizeof(priv->disconnect_reason_code);
481 	memcpy_ext(priv->adapter, pevent->event_buf,
482 		   &priv->disconnect_reason_code, pevent->event_len,
483 		   pevent->event_len);
484 	wlan_recv_event(priv, MLAN_EVENT_ID_FW_DISCONNECTED, pevent);
485 	priv->disconnect_reason_code = 0;
486 
487 	LEAVE();
488 }
489 
490 /**
491  *  @brief This function sends the OBSS scan parameters to the application
492  *
493  *  @param pmpriv     A pointer to mlan_private structure
494  *
495  *  @return           N/A
496  */
wlan_2040_coex_event(pmlan_private pmpriv)497 t_void wlan_2040_coex_event(pmlan_private pmpriv)
498 {
499 	t_u8 event_buf[100];
500 	mlan_event *pevent = (mlan_event *)event_buf;
501 	t_u8 ele_len;
502 
503 	ENTER();
504 
505 	if (pmpriv->curr_bss_params.bss_descriptor.poverlap_bss_scan_param &&
506 	    pmpriv->curr_bss_params.bss_descriptor.poverlap_bss_scan_param
507 			    ->ieee_hdr.element_id == OVERLAPBSSSCANPARAM) {
508 		ele_len = pmpriv->curr_bss_params.bss_descriptor
509 				  .poverlap_bss_scan_param->ieee_hdr.len;
510 		pevent->bss_index = pmpriv->bss_index;
511 		pevent->event_id = MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM;
512 		pevent->event_len = ele_len;
513 		/* Copy OBSS scan parameters */
514 		memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
515 			   (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor
516 				   .poverlap_bss_scan_param->obss_scan_param,
517 			   ele_len, pevent->event_len);
518 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM,
519 				pevent);
520 	}
521 
522 	LEAVE();
523 }
524 
525 /**
526  *  @brief This function will process tx pause event
527  *
528  *  @param priv    A pointer to mlan_private
529  *  @param pevent  A pointer to event buf
530  *
531  *  @return        N/A
532  */
wlan_process_sta_tx_pause_event(pmlan_private priv,pmlan_buffer pevent)533 static void wlan_process_sta_tx_pause_event(pmlan_private priv,
534 					    pmlan_buffer pevent)
535 {
536 	t_u16 tlv_type, tlv_len;
537 	int tlv_buf_left = pevent->data_len - sizeof(t_u32);
538 	MrvlIEtypesHeader_t *tlv =
539 		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
540 					sizeof(t_u32));
541 	MrvlIEtypes_tx_pause_t *tx_pause_tlv;
542 	sta_node *sta_ptr = MNULL;
543 	tdlsStatus_e status;
544 	t_u8 *bssid = MNULL;
545 	ENTER();
546 	if (priv->media_connected)
547 		bssid = priv->curr_bss_params.bss_descriptor.mac_address;
548 	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
549 		tlv_type = wlan_le16_to_cpu(tlv->type);
550 		tlv_len = wlan_le16_to_cpu(tlv->len);
551 		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
552 		    (unsigned int)tlv_buf_left) {
553 			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
554 			       tlv_len, tlv_buf_left);
555 			break;
556 		}
557 		if (tlv_type == TLV_TYPE_TX_PAUSE) {
558 			tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv;
559 			PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d\n",
560 			       MAC2STR(tx_pause_tlv->peermac),
561 			       tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt);
562 
563 			if (bssid &&
564 			    !memcmp(priv->adapter, bssid, tx_pause_tlv->peermac,
565 				    MLAN_MAC_ADDR_LENGTH)) {
566 				if (tx_pause_tlv->tx_pause)
567 					priv->tx_pause = MTRUE;
568 				else
569 					priv->tx_pause = MFALSE;
570 			} else {
571 				status = wlan_get_tdls_link_status(
572 					priv, tx_pause_tlv->peermac);
573 				if (MTRUE == wlan_is_tdls_link_setup(status)) {
574 					sta_ptr = wlan_get_station_entry(
575 						priv, tx_pause_tlv->peermac);
576 					if (sta_ptr) {
577 						if (sta_ptr->tx_pause !=
578 						    tx_pause_tlv->tx_pause) {
579 							sta_ptr->tx_pause =
580 								tx_pause_tlv
581 									->tx_pause;
582 							wlan_update_ralist_tx_pause(
583 								priv,
584 								tx_pause_tlv
585 									->peermac,
586 								tx_pause_tlv
587 									->tx_pause);
588 						}
589 					}
590 				}
591 			}
592 		}
593 		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
594 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
595 					      sizeof(MrvlIEtypesHeader_t));
596 	}
597 
598 	LEAVE();
599 	return;
600 }
601 
602 /**
603  *  @brief This function will print diconnect reason code according
604  *  to IEEE 802.11 spec
605  *
606  *  @param reason_code    reason code for the deauth/disaccoc
607  *                        received from firmware
608  *  @return        N/A
609  */
wlan_print_disconnect_reason(t_u16 reason_code)610 static void wlan_print_disconnect_reason(t_u16 reason_code)
611 {
612 	ENTER();
613 
614 	switch (reason_code) {
615 	case MLAN_REASON_UNSPECIFIED:
616 		PRINTM(MMSG, "wlan: REASON: Unspecified reason\n");
617 		break;
618 	case MLAN_REASON_PREV_AUTH_NOT_VALID:
619 		PRINTM(MMSG,
620 		       "wlan: REASON: Previous authentication no longer valid\n");
621 		break;
622 	case MLAN_REASON_DEAUTH_LEAVING:
623 		PRINTM(MMSG,
624 		       "wlan: REASON: (Deauth) Sending STA is leaving (or has left) IBSS or ESS\n");
625 		break;
626 	case MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
627 		PRINTM(MMSG,
628 		       "wlan: REASON: Disassociated due to inactivity \n");
629 		break;
630 	case MLAN_REASON_DISASSOC_AP_BUSY:
631 		PRINTM(MMSG,
632 		       "wlan: REASON: (Disassociated) AP unable to handle all connected STAs\n");
633 		break;
634 	case MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA:
635 		PRINTM(MMSG,
636 		       "wlan: REASON: Class 2 frame was received from nonauthenticated STA\n");
637 		break;
638 	case MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA:
639 		PRINTM(MMSG,
640 		       "wlan: REASON: Class 3 frame was received from nonassociated STA\n");
641 		break;
642 	case MLAN_REASON_DISASSOC_STA_HAS_LEFT:
643 		PRINTM(MMSG,
644 		       "wlan: REASON: (Disassocated) Sending STA is leaving (or has left) BSS\n");
645 		break;
646 	case MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
647 		PRINTM(MMSG,
648 		       "wlan: REASON: STA requesting (re)assoc is not authenticated with responding STA\n");
649 		break;
650 	default:
651 		break;
652 	}
653 
654 	LEAVE();
655 	return;
656 }
657 
658 /**
659  *  @brief This function handles events generated by firmware
660  *
661  *  @param priv A pointer to mlan_private structure
662  *
663  *  @return     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
664  */
wlan_ops_sta_process_event(t_void * priv)665 mlan_status wlan_ops_sta_process_event(t_void *priv)
666 {
667 	pmlan_private pmpriv = (pmlan_private)priv;
668 	pmlan_adapter pmadapter = pmpriv->adapter;
669 	mlan_status ret = MLAN_STATUS_SUCCESS;
670 	t_u32 eventcause = pmadapter->event_cause;
671 	t_u8 *event_buf = MNULL;
672 	t_u8 *evt_buf = MNULL;
673 	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
674 	t_u16 reason_code;
675 	pmlan_callbacks pcb = &pmadapter->callbacks;
676 	mlan_event *pevent = MNULL;
677 	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
678 	chan_band_info *pchan_band_info = MNULL;
679 	t_u8 radar_chan;
680 	t_u16 enable = 0;
681 
682 	ENTER();
683 
684 	if (!pmbuf) {
685 		LEAVE();
686 		return MLAN_STATUS_FAILURE;
687 	}
688 
689 	/* Event length check */
690 	if ((pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) {
691 		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
692 		LEAVE();
693 		return MLAN_STATUS_FAILURE;
694 	}
695 
696 	/* Allocate memory for event buffer */
697 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
698 			       MAX_EVENT_SIZE + sizeof(mlan_event),
699 			       MLAN_MEM_DEF, &event_buf);
700 	if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
701 		PRINTM(MERROR, "Could not allocate buffer for event buf\n");
702 		if (pmbuf)
703 			pmbuf->status_code = MLAN_ERROR_NO_MEM;
704 		goto done;
705 	}
706 	pevent = (pmlan_event)event_buf;
707 	memset(pmadapter, event_buf, 0, MAX_EVENT_SIZE);
708 
709 	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
710 	    pmbuf->data_len > sizeof(eventcause))
711 		DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset,
712 			    pmbuf->data_len);
713 
714 	switch (eventcause) {
715 	case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
716 		PRINTM(MERROR,
717 		       "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n");
718 		break;
719 	case EVENT_LINK_SENSED:
720 		PRINTM(MEVENT, "EVENT: LINK_SENSED\n");
721 		pmpriv->adhoc_is_link_sensed = MTRUE;
722 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED,
723 				MNULL);
724 		break;
725 
726 	case EVENT_DEAUTHENTICATED:
727 		if (pmpriv->wps.session_enable) {
728 			PRINTM(MMSG,
729 			       "wlan: Receive deauth event in wps session\n");
730 			break;
731 		}
732 		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
733 							  pmbuf->data_offset +
734 							  sizeof(eventcause)));
735 		PRINTM(MMSG, "wlan: EVENT: Deauthenticated (reason 0x%x)\n",
736 		       reason_code);
737 		wlan_print_disconnect_reason(reason_code);
738 		pmpriv->disconnect_reason_code = reason_code;
739 		pmadapter->dbg.num_event_deauth++;
740 		wlan_handle_disconnect_event(pmpriv);
741 
742 		break;
743 
744 	case EVENT_DISASSOCIATED:
745 		if (pmpriv->wps.session_enable) {
746 			PRINTM(MMSG,
747 			       "wlan: Receive disassociate event in wps session\n");
748 			break;
749 		}
750 		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
751 							  pmbuf->data_offset +
752 							  sizeof(eventcause)));
753 		PRINTM(MMSG, "wlan: EVENT: Disassociated (reason 0x%x)\n",
754 		       reason_code);
755 		wlan_print_disconnect_reason(reason_code);
756 		pmpriv->disconnect_reason_code = reason_code;
757 		pmadapter->dbg.num_event_disassoc++;
758 		wlan_handle_disconnect_event(pmpriv);
759 		break;
760 
761 	case EVENT_LINK_LOST:
762 		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
763 							  pmbuf->data_offset +
764 							  sizeof(eventcause)));
765 		PRINTM(MMSG, "wlan: EVENT: Link lost (reason 0x%x)\n",
766 		       reason_code);
767 		pmpriv->disconnect_reason_code = reason_code;
768 		pmadapter->dbg.num_event_link_lost++;
769 		wlan_handle_disconnect_event(pmpriv);
770 		break;
771 
772 	case EVENT_PS_SLEEP:
773 		PRINTM(MINFO, "EVENT: SLEEP\n");
774 		PRINTM_NETINTF(MEVENT, pmpriv);
775 		PRINTM(MEVENT, "_");
776 
777 		/* Handle unexpected PS SLEEP event */
778 		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
779 			break;
780 		pmadapter->ps_state = PS_STATE_PRE_SLEEP;
781 
782 		wlan_check_ps_cond(pmadapter);
783 		break;
784 
785 	case EVENT_PS_AWAKE:
786 		PRINTM(MINFO, "EVENT: AWAKE\n");
787 		PRINTM_NETINTF(MEVENT, pmpriv);
788 		PRINTM(MEVENT, "|");
789 		if (!pmadapter->pps_uapsd_mode && pmpriv->media_connected &&
790 		    (pmpriv->port_open || !pmpriv->port_ctrl_mode) &&
791 		    pmadapter->sleep_period.period) {
792 			pmadapter->pps_uapsd_mode = MTRUE;
793 			PRINTM(MEVENT, "PPS/UAPSD mode activated\n");
794 		}
795 		/* Handle unexpected PS AWAKE event */
796 		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
797 			break;
798 		pmadapter->tx_lock_flag = MFALSE;
799 		if (pmadapter->pps_uapsd_mode && pmadapter->gen_null_pkt) {
800 			if (MTRUE ==
801 			    wlan_check_last_packet_indication(pmpriv)) {
802 				if (!pmadapter->data_sent) {
803 					if (wlan_send_null_packet(
804 						    pmpriv,
805 						    MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
806 							    MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) ==
807 					    MLAN_STATUS_SUCCESS) {
808 						ret = MLAN_STATUS_SUCCESS;
809 						goto done;
810 					}
811 				}
812 			}
813 		}
814 		pmadapter->ps_state = PS_STATE_AWAKE;
815 		pmadapter->pm_wakeup_card_req = MFALSE;
816 		pmadapter->pm_wakeup_fw_try = MFALSE;
817 		break;
818 
819 	case EVENT_HS_ACT_REQ:
820 		PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
821 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, 0,
822 				       0, MNULL, MNULL);
823 		break;
824 	case EVENT_MIC_ERR_UNICAST:
825 		PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n");
826 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL);
827 		break;
828 
829 	case EVENT_MIC_ERR_MULTICAST:
830 		PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n");
831 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL);
832 		break;
833 	case EVENT_MIB_CHANGED:
834 	case EVENT_INIT_DONE:
835 		break;
836 
837 	case EVENT_ADHOC_BCN_LOST:
838 		PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n");
839 		pmpriv->adhoc_is_link_sensed = MFALSE;
840 		wlan_clean_txrx(pmpriv);
841 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST,
842 				MNULL);
843 		break;
844 	case EVENT_ASSOC_REQ_IE:
845 		pmpriv->assoc_req_size = pmbuf->data_len - sizeof(eventcause);
846 		evt_buf =
847 			(pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause));
848 		memcpy_ext(pmpriv->adapter, pmpriv->assoc_req_buf, evt_buf,
849 			   pmbuf->data_len - sizeof(eventcause),
850 			   MRVDRV_ASSOC_RSP_BUF_SIZE);
851 		break;
852 
853 	case EVENT_FW_DEBUG_INFO:
854 		pevent->bss_index = pmpriv->bss_index;
855 		pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
856 		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
857 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
858 			   pmbuf->pbuf + pmbuf->data_offset +
859 				   sizeof(eventcause),
860 			   pevent->event_len, pevent->event_len);
861 		PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
862 		       (t_u8 *)pevent->event_buf);
863 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
864 		break;
865 
866 	case EVENT_BG_SCAN_REPORT:
867 		PRINTM(MEVENT, "EVENT: BGS_REPORT\n");
868 		pmadapter->bgscan_reported = MTRUE;
869 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL);
870 		break;
871 	case EVENT_BG_SCAN_STOPPED:
872 		PRINTM(MEVENT, "EVENT: BGS_STOPPED\n");
873 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN_STOPPED,
874 				MNULL);
875 		break;
876 
877 	case EVENT_PORT_RELEASE:
878 		PRINTM(MEVENT, "EVENT: PORT RELEASE\n");
879 		/* Open the port for e-supp mode */
880 		if (pmpriv->port_ctrl_mode == MTRUE) {
881 			PRINTM(MINFO, "PORT_REL: port_status = OPEN\n");
882 			pmpriv->port_open = MTRUE;
883 		}
884 		pmadapter->scan_block = MFALSE;
885 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL);
886 		/* Send OBSS scan param to the application */
887 		wlan_2040_coex_event(pmpriv);
888 		break;
889 
890 	case EVENT_STOP_TX:
891 		PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause);
892 		wlan_11h_tx_disable(pmpriv); /* this fn will send event up to
893 						MOAL */
894 		break;
895 	case EVENT_START_TX:
896 		PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause);
897 		wlan_11h_tx_enable(pmpriv); /* this fn will send event up to
898 					       MOAL */
899 		break;
900 	case EVENT_CHANNEL_SWITCH:
901 		PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause);
902 		if (pmadapter->ecsa_enable) {
903 			MrvlIEtypes_channel_band_t *pchan_info =
904 				(MrvlIEtypes_channel_band_t
905 					 *)(pmadapter->event_body);
906 			t_u8 channel = pchan_info->channel;
907 			chan_freq_power_t *cfp = MNULL;
908 			DBG_HEXDUMP(MCMD_D, "chan band config",
909 				    (t_u8 *)pchan_info,
910 				    sizeof(MrvlIEtypes_channel_band_t));
911 			PRINTM(MEVENT, "Switch to channel %d success!\n",
912 			       channel);
913 #define MAX_CHANNEL_BAND_B 14
914 			if (channel <= MAX_CHANNEL_BAND_B)
915 				cfp = wlan_find_cfp_by_band_and_channel(
916 					pmadapter, BAND_B, channel);
917 			else
918 				cfp = wlan_find_cfp_by_band_and_channel(
919 					pmadapter, BAND_A, channel);
920 			pmpriv->curr_bss_params.bss_descriptor.channel =
921 				channel;
922 			if (cfp)
923 				pmpriv->curr_bss_params.bss_descriptor.freq =
924 					cfp->freq;
925 			else
926 				pmpriv->curr_bss_params.bss_descriptor.freq = 0;
927 #ifdef UAP_SUPPORT
928 			if (pmpriv->adapter->dfs_mode)
929 				wlan_11h_update_dfs_master_state_by_sta(pmpriv);
930 #endif
931 			if (pmpriv->adapter->state_rdh.stage ==
932 			    RDH_SET_CUSTOM_IE) {
933 				pmadapter->state_rdh.stage =
934 					RDH_RESTART_TRAFFIC;
935 				wlan_11h_radar_detected_handling(pmadapter,
936 								 pmpriv);
937 			}
938 			pmadapter->state_rdh.tx_block = MFALSE;
939 			/* Setup event buffer */
940 			pevent->bss_index = pmpriv->bss_index;
941 			pevent->event_id =
942 				MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE;
943 			pevent->event_len = sizeof(chan_band_info);
944 			pchan_band_info = (chan_band_info *)pevent->event_buf;
945 			/* Copy event data */
946 			memcpy_ext(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
947 				   (t_u8 *)&pchan_info->bandcfg,
948 				   sizeof(pchan_info->bandcfg),
949 				   sizeof(pchan_band_info->bandcfg));
950 			pchan_band_info->channel = pchan_info->channel;
951 			if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
952 				pchan_band_info->center_chan =
953 					wlan_get_center_freq_idx(
954 						priv, BAND_AAC,
955 						pchan_info->channel,
956 						CHANNEL_BW_80MHZ);
957 			wlan_recv_event(pmpriv,
958 					MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE,
959 					pevent);
960 		}
961 		break;
962 	case EVENT_CHANNEL_SWITCH_ANN:
963 		PRINTM_NETINTF(MEVENT, pmpriv);
964 		PRINTM(MEVENT, "EVENT: Channel Switch Announcement\n");
965 		/* Here, pass up event first, as handling will send deauth */
966 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN,
967 				MNULL);
968 		wlan_11h_handle_event_chanswann(pmpriv);
969 		break;
970 	case EVENT_RADAR_DETECTED:
971 		PRINTM_NETINTF(MEVENT, pmpriv);
972 		PRINTM(MEVENT, "EVENT: Radar Detected\n");
973 
974 		/* Send as passthru first, this event can cause other events */
975 		pevent->bss_index = pmpriv->bss_index;
976 		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
977 		pevent->event_len = pmbuf->data_len;
978 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
979 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
980 			   pevent->event_len);
981 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
982 
983 		if (pmadapter->state_rdh.stage == RDH_OFF) {
984 			pmadapter->state_rdh.stage = RDH_CHK_INTFS;
985 			wlan_11h_radar_detected_handling(pmadapter, pmpriv);
986 		} else {
987 			PRINTM(MEVENT, "Ignore Event Radar Detected - handling"
988 				       " already in progress.\n");
989 		}
990 
991 		break;
992 
993 	case EVENT_CHANNEL_REPORT_RDY:
994 		PRINTM_NETINTF(MEVENT, pmpriv);
995 		PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
996 		pevent->bss_index = pmpriv->bss_index;
997 		pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY;
998 		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
999 		/* Copy event data */
1000 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1001 			   pmbuf->pbuf + pmbuf->data_offset +
1002 				   sizeof(eventcause),
1003 			   pevent->event_len, pevent->event_len);
1004 		/* Handle / pass event data */
1005 		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent,
1006 							  &radar_chan, 0);
1007 		/* Also send this event as passthru */
1008 		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
1009 		pevent->event_len = pmbuf->data_len;
1010 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1011 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
1012 			   pevent->event_len);
1013 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1014 		/* Send up this Event to unblock MOAL waitqueue */
1015 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
1016 		break;
1017 	case EVENT_EXT_SCAN_REPORT:
1018 		PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%d)\n",
1019 		       pmbuf->data_len);
1020 		if (pmadapter->pscan_ioctl_req && pmadapter->ext_scan)
1021 			ret = wlan_handle_event_ext_scan_report(priv, pmbuf);
1022 		break;
1023 	case EVENT_EXT_SCAN_STATUS_REPORT:
1024 		PRINTM(MEVENT, "EVENT: EXT_SCAN status report (%d)\n",
1025 		       pmbuf->data_len);
1026 		pmadapter->ext_scan_timeout = MFALSE;
1027 		ret = wlan_handle_event_ext_scan_status(priv, pmbuf);
1028 		break;
1029 	case EVENT_MEAS_REPORT_RDY:
1030 		PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n",
1031 		       eventcause);
1032 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
1033 				       HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
1034 		break;
1035 	case EVENT_WMM_STATUS_CHANGE:
1036 		if (pmbuf &&
1037 		    pmbuf->data_len >
1038 			    sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
1039 			PRINTM(MEVENT, "EVENT: WMM status changed: %d\n",
1040 			       pmbuf->data_len);
1041 
1042 			evt_buf = (pmbuf->pbuf + pmbuf->data_offset +
1043 				   sizeof(eventcause));
1044 
1045 			wlan_ret_wmm_get_status(pmpriv, evt_buf,
1046 						pmbuf->data_len -
1047 							sizeof(eventcause));
1048 		} else {
1049 			PRINTM(MEVENT, "EVENT: WMM status changed\n");
1050 			ret = wlan_cmd_wmm_status_change(pmpriv);
1051 		}
1052 		break;
1053 
1054 	case EVENT_RSSI_LOW:
1055 		PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
1056 		pevent->bss_index = pmpriv->bss_index;
1057 		pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_LOW;
1058 		pevent->event_len = sizeof(t_u16);
1059 		/** Fw send bcnRssi low value in event reason field*/
1060 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1061 			   (t_u8 *)&pmadapter->event_body, pevent->event_len,
1062 			   pevent->event_len);
1063 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1064 		break;
1065 	case EVENT_SNR_LOW:
1066 		PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n");
1067 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL);
1068 		break;
1069 	case EVENT_MAX_FAIL:
1070 		PRINTM(MEVENT, "EVENT: MAX_FAIL\n");
1071 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL);
1072 		break;
1073 	case EVENT_RSSI_HIGH:
1074 		PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n");
1075 		pevent->bss_index = pmpriv->bss_index;
1076 		pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_HIGH;
1077 		pevent->event_len = sizeof(t_u16);
1078 		/** Fw send bcnRssi high value in event reason field*/
1079 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1080 			   (t_u8 *)&pmadapter->event_body, pevent->event_len,
1081 			   pevent->event_len);
1082 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1083 		break;
1084 	case EVENT_SNR_HIGH:
1085 		PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n");
1086 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL);
1087 		break;
1088 	case EVENT_DATA_RSSI_LOW:
1089 		PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n");
1090 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL);
1091 		break;
1092 	case EVENT_DATA_SNR_LOW:
1093 		PRINTM(MEVENT, "EVENT: Data SNR_LOW\n");
1094 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL);
1095 		break;
1096 	case EVENT_DATA_RSSI_HIGH:
1097 		PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n");
1098 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL);
1099 		break;
1100 	case EVENT_DATA_SNR_HIGH:
1101 		PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n");
1102 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL);
1103 		break;
1104 	case EVENT_LINK_QUALITY:
1105 		PRINTM(MEVENT, "EVENT: Link Quality\n");
1106 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL);
1107 		break;
1108 	case EVENT_PRE_BEACON_LOST:
1109 		PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n");
1110 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL);
1111 		break;
1112 	case EVENT_IBSS_COALESCED:
1113 		PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n");
1114 		ret = wlan_prepare_cmd(
1115 			pmpriv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
1116 			HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
1117 		break;
1118 	case EVENT_ADDBA:
1119 		PRINTM(MEVENT, "EVENT: ADDBA Request\n");
1120 		if (pmpriv->media_connected == MTRUE)
1121 			ret = wlan_prepare_cmd(pmpriv,
1122 					       HostCmd_CMD_11N_ADDBA_RSP,
1123 					       HostCmd_ACT_GEN_SET, 0, MNULL,
1124 					       pmadapter->event_body);
1125 		else
1126 			PRINTM(MERROR,
1127 			       "Ignore ADDBA Request event in disconnected state\n");
1128 		break;
1129 	case EVENT_DELBA:
1130 		PRINTM(MEVENT, "EVENT: DELBA Request\n");
1131 		if (pmpriv->media_connected == MTRUE)
1132 			wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
1133 		else
1134 			PRINTM(MERROR,
1135 			       "Ignore DELBA Request event in disconnected state\n");
1136 		break;
1137 	case EVENT_BA_STREAM_TIMEOUT:
1138 		PRINTM(MEVENT, "EVENT:  BA Stream timeout\n");
1139 		if (pmpriv->media_connected == MTRUE)
1140 			wlan_11n_ba_stream_timeout(
1141 				pmpriv, (HostCmd_DS_11N_BATIMEOUT *)
1142 						pmadapter->event_body);
1143 		else
1144 			PRINTM(MERROR,
1145 			       "Ignore BA Stream timeout event in disconnected state\n");
1146 		break;
1147 	case EVENT_RXBA_SYNC:
1148 		PRINTM(MEVENT, "EVENT:  RXBA_SYNC\n");
1149 		wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body,
1150 					 pmbuf->data_len - sizeof(eventcause));
1151 		break;
1152 	case EVENT_AMSDU_AGGR_CTRL:
1153 		PRINTM(MEVENT, "EVENT:  AMSDU_AGGR_CTRL %d\n",
1154 		       *(t_u16 *)pmadapter->event_body);
1155 		pmadapter->tx_buf_size =
1156 			MIN(pmadapter->curr_tx_buf_size,
1157 			    wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body));
1158 		if (pmbuf->data_len == sizeof(eventcause) + sizeof(t_u32)) {
1159 			enable = wlan_le16_to_cpu(
1160 				*(t_u16 *)(pmadapter->event_body +
1161 					   sizeof(t_u16)));
1162 			if (enable)
1163 				pmpriv->amsdu_disable = MFALSE;
1164 			else
1165 				pmpriv->amsdu_disable = MTRUE;
1166 			PRINTM(MEVENT, "amsdu_disable=%d\n",
1167 			       pmpriv->amsdu_disable);
1168 		}
1169 		PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size);
1170 		break;
1171 
1172 	case EVENT_WEP_ICV_ERR:
1173 		PRINTM(MEVENT, "EVENT: WEP ICV error\n");
1174 		pevent->bss_index = pmpriv->bss_index;
1175 		pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR;
1176 		pevent->event_len = sizeof(Event_WEP_ICV_ERR);
1177 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1178 			   pmadapter->event_body, pevent->event_len,
1179 			   pevent->event_len);
1180 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent);
1181 		break;
1182 
1183 	case EVENT_BW_CHANGE:
1184 		PRINTM(MEVENT, "EVENT: BW Change\n");
1185 		pevent->bss_index = pmpriv->bss_index;
1186 		pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED;
1187 		pevent->event_len = sizeof(t_u8);
1188 		/* Copy event body from the event buffer */
1189 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1190 			   pmadapter->event_body, pevent->event_len,
1191 			   pevent->event_len);
1192 #ifdef UAP_SUPPORT
1193 		if (pmadapter->dfs_repeater)
1194 			wlan_dfs_rep_bw_change(pmadapter);
1195 #endif
1196 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent);
1197 		break;
1198 
1199 #ifdef WIFI_DIRECT_SUPPORT
1200 	case EVENT_WIFIDIRECT_GENERIC_EVENT:
1201 		PRINTM(MEVENT, "EVENT: WIFIDIRECT event %d\n", eventcause);
1202 		pevent->bss_index = pmpriv->bss_index;
1203 		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
1204 		pevent->event_len = pmbuf->data_len;
1205 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1206 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
1207 			   pevent->event_len);
1208 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1209 		break;
1210 	case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
1211 		PRINTM(MEVENT, "EVENT: WIFIDIRECT service discovery event %d\n",
1212 		       eventcause);
1213 		pevent->bss_index = pmpriv->bss_index;
1214 		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
1215 		pevent->event_len = pmbuf->data_len;
1216 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1217 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
1218 			   pevent->event_len);
1219 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1220 		break;
1221 #endif /* WIFI_DIRECT_SUPPORT */
1222 	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
1223 		PRINTM_NETINTF(MEVENT, pmpriv);
1224 		PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
1225 		       *(t_u16 *)pmadapter->event_body);
1226 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
1227 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED,
1228 				MNULL);
1229 		break;
1230 	case EVENT_TDLS_GENERIC_EVENT:
1231 		PRINTM(MEVENT, "EVENT: TDLS event %d\n", eventcause);
1232 		wlan_parse_tdls_event(pmpriv, pmbuf);
1233 		pevent->bss_index = pmpriv->bss_index;
1234 		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
1235 		pevent->event_len = pmbuf->data_len;
1236 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1237 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
1238 			   pevent->event_len);
1239 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1240 		break;
1241 
1242 	case EVENT_TX_DATA_PAUSE:
1243 		PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n");
1244 		wlan_process_sta_tx_pause_event(priv, pmbuf);
1245 		break;
1246 
1247 	case EVENT_IBSS_STATION_CONNECT:
1248 		break;
1249 	case EVENT_IBSS_STATION_DISCONNECT:
1250 		break;
1251 	case EVENT_SAD_REPORT: {
1252 #ifdef DEBUG_LEVEL1
1253 		t_u8 *pevt_dat =
1254 			pmbuf->pbuf + pmbuf->data_offset + sizeof(t_u32);
1255 #endif
1256 		PRINTM(MEVENT,
1257 		       "EVENT: Antenna Diversity %d  (%d, %d, %d, %d)\n",
1258 		       eventcause, pevt_dat[0] + 1, pevt_dat[1] + 1,
1259 		       pevt_dat[2], pevt_dat[3]);
1260 	} break;
1261 
1262 	case EVENT_FW_DUMP_INFO:
1263 		PRINTM(MINFO, "EVENT: Dump FW info\n");
1264 		pevent->bss_index = pmpriv->bss_index;
1265 		pevent->event_id = MLAN_EVENT_ID_FW_DUMP_INFO;
1266 		pevent->event_len = pmbuf->data_len;
1267 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1268 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
1269 			   pevent->event_len);
1270 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1271 		break;
1272 	case EVENT_TX_STATUS_REPORT:
1273 		PRINTM(MINFO, "EVENT: TX_STATUS\n");
1274 		pevent->bss_index = pmpriv->bss_index;
1275 		pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS;
1276 		pevent->event_len = pmbuf->data_len;
1277 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1278 			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
1279 			   pevent->event_len);
1280 
1281 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1282 		break;
1283 	case EVENT_BT_COEX_WLAN_PARA_CHANGE:
1284 		PRINTM(MEVENT, "EVENT: BT coex wlan param update\n");
1285 		wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf);
1286 		break;
1287 
1288 #if defined(PCIE)
1289 	case EVENT_SSU_DUMP_DMA:
1290 		PRINTM(MEVENT, "EVENT: EVENT_SSU_DUMP_DMA\n");
1291 		if (!pmadapter->ssu_buf || !pmadapter->ssu_buf->pbuf)
1292 			break;
1293 
1294 		/* If ADMA is supported, SSU header could not be received with
1295 		 * SSU data. Instead, SSU header is received through this event.
1296 		 * So, copy the header into the buffer before passing the buffer
1297 		 * to upper layer for file writting
1298 		 */
1299 		memcpy_ext(pmadapter,
1300 			   (t_u8 *)pmadapter->ssu_buf->pbuf +
1301 				   pmadapter->ssu_buf->data_offset,
1302 			   pmbuf->pbuf + pmbuf->data_offset +
1303 				   sizeof(eventcause),
1304 			   (pmbuf->data_len - sizeof(eventcause)),
1305 			   (pmbuf->data_len - sizeof(eventcause)));
1306 
1307 		DBG_HEXDUMP(MEVT_D, "SSU data",
1308 			    (t_u8 *)pmadapter->ssu_buf->pbuf +
1309 				    pmadapter->ssu_buf->data_offset,
1310 			    512);
1311 		pevent->bss_index = pmpriv->bss_index;
1312 		pevent->event_id = MLAN_EVENT_ID_SSU_DUMP_FILE;
1313 		pevent->event_len = MLAN_SSU_BUF_SIZE;
1314 		*(t_ptr *)pevent->event_buf = (t_ptr)pmadapter->ssu_buf->pbuf +
1315 					      pmadapter->ssu_buf->data_offset;
1316 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1317 		wlan_free_ssu_pcie_buf(pmadapter);
1318 		break;
1319 #endif
1320 	case EVENT_CSI:
1321 		PRINTM(MEVENT, "EVENT: EVENT_CSI on STA\n");
1322 		wlan_process_csi_event(pmpriv);
1323 		break;
1324 	case EVENT_MEF_HOST_WAKEUP:
1325 		PRINTM(MEVENT, "EVENT: EVENT_MEF_HOST_WAKEUP len=%d\n",
1326 		       pmbuf->data_len);
1327 		break;
1328 	case EVENT_MANAGEMENT_FRAME_WAKEUP:
1329 		PRINTM(MEVENT, "EVENT: EVENT_MANAGEMENT_FRAME_WAKEUP HOST\n");
1330 		break;
1331 	case EVENT_ROAM_OFFLOAD:
1332 		memcpy_ext(pmadapter, addr,
1333 			   pmpriv->curr_bss_params.bss_descriptor.mac_address,
1334 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1335 		memcpy_ext(pmadapter,
1336 			   pmpriv->curr_bss_params.bss_descriptor.mac_address,
1337 			   (t_u8 *)(pmadapter->event_body + 2),
1338 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1339 		/** replace ralist's mac address with new mac address */
1340 		if (0 ==
1341 		    wlan_ralist_update(
1342 			    pmpriv, addr,
1343 			    pmpriv->curr_bss_params.bss_descriptor.mac_address))
1344 			wlan_ralist_add(pmpriv,
1345 					pmpriv->curr_bss_params.bss_descriptor
1346 						.mac_address);
1347 		wlan_11n_cleanup_reorder_tbl(pmpriv);
1348 		wlan_11n_deleteall_txbastream_tbl(pmpriv);
1349 		/*Update the BSS for inform kernel, otherwise kernel will give
1350 		 * warning for not find BSS*/
1351 		memcpy_ext(pmadapter, (t_u8 *)&pmadapter->pscan_table[0],
1352 			   (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor,
1353 			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
1354 		if (!pmadapter->num_in_scan_table)
1355 			pmadapter->num_in_scan_table = 1;
1356 		PRINTM(MEVENT, "EVENT: ROAM OFFLOAD IN FW SUCCESS\n");
1357 		pevent->bss_index = pmpriv->bss_index;
1358 		pevent->event_id = MLAN_EVENT_ID_FW_ROAM_OFFLOAD_RESULT;
1359 		/** Drop event id length and 2 bytes reverved length*/
1360 		pevent->event_len = pmbuf->data_len - sizeof(eventcause) - 2;
1361 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
1362 			   pmadapter->event_body + 2, pevent->event_len,
1363 			   pevent->event_len);
1364 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
1365 		break;
1366 	case EVENT_CLOUD_KEEP_ALIVE_RETRY_FAIL:
1367 		break;
1368 	case EVENT_VDLL_IND:
1369 		wlan_process_vdll_event(pmpriv, pmbuf);
1370 		break;
1371 	case EVENT_FW_HANG_REPORT:
1372 		if (pmbuf->data_len < (sizeof(eventcause) + sizeof(t_u16))) {
1373 			PRINTM(MEVENT,
1374 			       "EVENT: EVENT_FW_HANG_REPORT skip for len too short: %d\n",
1375 			       pmbuf->data_len);
1376 			break;
1377 		}
1378 		PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT reasoncode=%d\n",
1379 		       wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
1380 						   pmbuf->data_offset +
1381 						   sizeof(eventcause))));
1382 		pmadapter->fw_hang_report = MTRUE;
1383 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
1384 		break;
1385 	case CHAN_LOAD_EVENT: {
1386 		t_u8 *ptr = MNULL;
1387 		HostCmd_DS_GET_CH_LOAD *cfg_cmd = MNULL;
1388 		ptr = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
1389 		ptr += 4; /* data start */
1390 		cfg_cmd = (HostCmd_DS_GET_CH_LOAD *)ptr;
1391 		pmpriv->ch_load_param = wlan_le16_to_cpu(cfg_cmd->ch_load);
1392 		pmpriv->noise = wlan_le16_to_cpu(cfg_cmd->noise);
1393 		pmpriv->rx_quality = wlan_le16_to_cpu(cfg_cmd->rx_quality);
1394 		break;
1395 	}
1396 	default:
1397 		PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
1398 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
1399 		break;
1400 	}
1401 done:
1402 	if (event_buf)
1403 		pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
1404 	LEAVE();
1405 	return ret;
1406 }
1407