1/*
2 * NXP Wireless LAN device driver: station event handling
3 *
4 * Copyright 2011-2020 NXP
5 *
6 * This software file (the "File") is distributed by NXP
7 * under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License").  You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "decl.h"
21#include "ioctl.h"
22#include "util.h"
23#include "fw.h"
24#include "main.h"
25#include "wmm.h"
26#include "11n.h"
27
28#define MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE    12
29
30static int mwifiex_check_ibss_peer_capabilities(struct mwifiex_private *priv,
31					        struct mwifiex_sta_node *sta_ptr,
32					        struct sk_buff *event)
33{
34	int evt_len, ele_len;
35	u8 *curr;
36	struct ieee_types_header *ele_hdr;
37	struct mwifiex_ie_types_mgmt_frame *tlv_mgmt_frame;
38	const struct ieee80211_ht_cap *ht_cap;
39	const struct ieee80211_vht_cap *vht_cap;
40
41	skb_pull(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE);
42	evt_len = event->len;
43	curr = event->data;
44
45	mwifiex_dbg_dump(priv->adapter, EVT_D, "ibss peer capabilities:",
46			 event->data, event->len);
47
48	skb_push(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE);
49
50	tlv_mgmt_frame = (void *)curr;
51	if (evt_len >= sizeof(*tlv_mgmt_frame) &&
52	    le16_to_cpu(tlv_mgmt_frame->header.type) ==
53	    TLV_TYPE_UAP_MGMT_FRAME) {
54		/* Locate curr pointer to the start of beacon tlv,
55		 * timestamp 8 bytes, beacon intervel 2 bytes,
56		 * capability info 2 bytes, totally 12 byte beacon header
57		 */
58		evt_len = le16_to_cpu(tlv_mgmt_frame->header.len);
59		curr += (sizeof(*tlv_mgmt_frame) + 12);
60	} else {
61		mwifiex_dbg(priv->adapter, MSG,
62			    "management frame tlv not found!\n");
63		return 0;
64	}
65
66	while (evt_len >= sizeof(*ele_hdr)) {
67		ele_hdr = (struct ieee_types_header *)curr;
68		ele_len = ele_hdr->len;
69
70		if (evt_len < ele_len + sizeof(*ele_hdr))
71			break;
72
73		switch (ele_hdr->element_id) {
74		case WLAN_EID_HT_CAPABILITY:
75			sta_ptr->is_11n_enabled = true;
76			ht_cap = (void *)(ele_hdr + 2);
77			sta_ptr->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
78				IEEE80211_HT_CAP_MAX_AMSDU ?
79				MWIFIEX_TX_DATA_BUF_SIZE_8K :
80				MWIFIEX_TX_DATA_BUF_SIZE_4K;
81			mwifiex_dbg(priv->adapter, INFO,
82				    "11n enabled!, max_amsdu : %d\n",
83				    sta_ptr->max_amsdu);
84			break;
85
86		case WLAN_EID_VHT_CAPABILITY:
87			sta_ptr->is_11ac_enabled = true;
88			vht_cap = (void *)(ele_hdr + 2);
89			/* check VHT MAXMPDU capability */
90			switch (le32_to_cpu(vht_cap->vht_cap_info) & 0x3) {
91			case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
92				sta_ptr->max_amsdu =
93					MWIFIEX_TX_DATA_BUF_SIZE_12K;
94				break;
95			case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
96				sta_ptr->max_amsdu =
97					MWIFIEX_TX_DATA_BUF_SIZE_8K;
98				break;
99			case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
100				sta_ptr->max_amsdu =
101					MWIFIEX_TX_DATA_BUF_SIZE_4K;
102			default:
103				break;
104			}
105
106			mwifiex_dbg(priv->adapter, INFO,
107				    "11ac enabled!, max_amsdu : %d\n",
108				    sta_ptr->max_amsdu);
109			break;
110		default:
111			break;
112		}
113
114		curr += (ele_len + sizeof(*ele_hdr));
115		evt_len -= (ele_len + sizeof(*ele_hdr));
116	}
117
118	return 0;
119}
120
121/*
122 * This function resets the connection state.
123 *
124 * The function is invoked after receiving a disconnect event from firmware,
125 * and performs the following actions -
126 *      - Set media status to disconnected
127 *      - Clean up Tx and Rx packets
128 *      - Resets SNR/NF/RSSI value in driver
129 *      - Resets security configurations in driver
130 *      - Enables auto data rate
131 *      - Saves the previous SSID and BSSID so that they can
132 *        be used for re-association, if required
133 *      - Erases current SSID and BSSID information
134 *      - Sends a disconnect event to upper layers/applications.
135 */
136void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code,
137				 bool from_ap)
138{
139	struct mwifiex_adapter *adapter = priv->adapter;
140
141	if (!priv->media_connected)
142		return;
143
144	mwifiex_dbg(adapter, INFO,
145		    "info: handles disconnect event\n");
146
147	priv->media_connected = false;
148
149	priv->scan_block = false;
150	priv->port_open = false;
151
152	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
153	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) {
154		mwifiex_disable_all_tdls_links(priv);
155
156		if (priv->adapter->auto_tdls)
157			mwifiex_clean_auto_tdls(priv);
158	}
159
160	/* Free Tx and Rx packets, report disconnect to upper layer */
161	mwifiex_clean_txrx(priv);
162
163	/* Reset SNR/NF/RSSI values */
164	priv->data_rssi_last = 0;
165	priv->data_nf_last = 0;
166	priv->data_rssi_avg = 0;
167	priv->data_nf_avg = 0;
168	priv->bcn_rssi_last = 0;
169	priv->bcn_nf_last = 0;
170	priv->bcn_rssi_avg = 0;
171	priv->bcn_nf_avg = 0;
172	priv->rxpd_rate = 0;
173	priv->rxpd_htinfo = 0;
174	priv->sec_info.wpa_enabled = false;
175	priv->sec_info.wpa2_enabled = false;
176	priv->wpa_ie_len = 0;
177
178	priv->sec_info.wapi_enabled = false;
179	priv->wapi_ie_len = 0;
180	priv->sec_info.wapi_key_on = false;
181
182	priv->sec_info.encryption_mode = 0;
183
184	/* Enable auto data rate */
185	priv->is_data_rate_auto = true;
186	priv->data_rate = 0;
187
188	priv->assoc_resp_ht_param = 0;
189	priv->ht_param_present = false;
190
191	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
192	     GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data)
193		mwifiex_hist_data_reset(priv);
194
195	if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
196		priv->adhoc_state = ADHOC_IDLE;
197		priv->adhoc_is_link_sensed = false;
198	}
199
200	/*
201	 * Memorize the previous SSID and BSSID so
202	 * it could be used for re-assoc
203	 */
204
205	mwifiex_dbg(adapter, INFO,
206		    "info: previous SSID=%s, SSID len=%u\n",
207		    priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
208
209	mwifiex_dbg(adapter, INFO,
210		    "info: current SSID=%s, SSID len=%u\n",
211		    priv->curr_bss_params.bss_descriptor.ssid.ssid,
212		    priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
213
214	memcpy(&priv->prev_ssid,
215	       &priv->curr_bss_params.bss_descriptor.ssid,
216	       sizeof(struct cfg80211_ssid));
217
218	memcpy(priv->prev_bssid,
219	       priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
220
221	/* Need to erase the current SSID and BSSID info */
222	memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));
223
224	adapter->tx_lock_flag = false;
225	adapter->pps_uapsd_mode = false;
226
227	if (test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags) &&
228	    adapter->curr_cmd)
229		return;
230	priv->media_connected = false;
231	mwifiex_dbg(adapter, MSG,
232		    "info: successfully disconnected from %pM: reason code %d\n",
233		    priv->cfg_bssid, reason_code);
234	if (priv->bss_mode == NL80211_IFTYPE_STATION ||
235	    priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
236		cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
237				      !from_ap, GFP_KERNEL);
238	}
239	eth_zero_addr(priv->cfg_bssid);
240
241	mwifiex_stop_net_dev_queue(priv->netdev, adapter);
242	if (netif_carrier_ok(priv->netdev))
243		netif_carrier_off(priv->netdev);
244
245	if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))
246		return;
247
248	mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
249			 HostCmd_ACT_GEN_REMOVE, 0, NULL, false);
250}
251
252static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
253				    struct sk_buff *event_skb)
254{
255	int ret = 0;
256	struct mwifiex_adapter *adapter = priv->adapter;
257	struct mwifiex_sta_node *sta_ptr;
258	struct mwifiex_tdls_generic_event *tdls_evt =
259			(void *)event_skb->data + sizeof(adapter->event_cause);
260	u8 *mac = tdls_evt->peer_mac;
261
262	/* reserved 2 bytes are not mandatory in tdls event */
263	if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -
264			      sizeof(u16) - sizeof(adapter->event_cause))) {
265		mwifiex_dbg(adapter, ERROR, "Invalid event length!\n");
266		return -1;
267	}
268
269	sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);
270	if (!sta_ptr) {
271		mwifiex_dbg(adapter, ERROR, "cannot get sta entry!\n");
272		return -1;
273	}
274
275	switch (le16_to_cpu(tdls_evt->type)) {
276	case TDLS_EVENT_LINK_TEAR_DOWN:
277		cfg80211_tdls_oper_request(priv->netdev,
278					   tdls_evt->peer_mac,
279					   NL80211_TDLS_TEARDOWN,
280					   le16_to_cpu(tdls_evt->u.reason_code),
281					   GFP_KERNEL);
282		break;
283	case TDLS_EVENT_CHAN_SWITCH_RESULT:
284		mwifiex_dbg(adapter, EVENT, "tdls channel switch result :\n");
285		mwifiex_dbg(adapter, EVENT,
286			    "status=0x%x, reason=0x%x cur_chan=%d\n",
287			    tdls_evt->u.switch_result.status,
288			    tdls_evt->u.switch_result.reason,
289			    tdls_evt->u.switch_result.cur_chan);
290
291		/* tdls channel switch failed */
292		if (tdls_evt->u.switch_result.status != 0) {
293			switch (tdls_evt->u.switch_result.cur_chan) {
294			case TDLS_BASE_CHANNEL:
295				sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
296				break;
297			case TDLS_OFF_CHANNEL:
298				sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
299				break;
300			default:
301				break;
302			}
303			return ret;
304		}
305
306		/* tdls channel switch success */
307		switch (tdls_evt->u.switch_result.cur_chan) {
308		case TDLS_BASE_CHANNEL:
309			if (sta_ptr->tdls_status == TDLS_IN_BASE_CHAN)
310				break;
311			mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
312								  false);
313			sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
314			break;
315		case TDLS_OFF_CHANNEL:
316			if (sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)
317				break;
318			mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
319								  true);
320			sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
321			break;
322		default:
323			break;
324		}
325
326		break;
327	case TDLS_EVENT_START_CHAN_SWITCH:
328		mwifiex_dbg(adapter, EVENT, "tdls start channel switch...\n");
329		sta_ptr->tdls_status = TDLS_CHAN_SWITCHING;
330		break;
331	case TDLS_EVENT_CHAN_SWITCH_STOPPED:
332		mwifiex_dbg(adapter, EVENT,
333			    "tdls chan switch stopped, reason=%d\n",
334			    tdls_evt->u.cs_stop_reason);
335		break;
336	default:
337		break;
338	}
339
340	return ret;
341}
342
343static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
344					 struct mwifiex_ie_types_header *tlv)
345{
346	struct mwifiex_tx_pause_tlv *tp;
347	struct mwifiex_sta_node *sta_ptr;
348
349	tp = (void *)tlv;
350	mwifiex_dbg(priv->adapter, EVENT,
351		    "uap tx_pause: %pM pause=%d, pkts=%d\n",
352		    tp->peermac, tp->tx_pause,
353		    tp->pkt_cnt);
354
355	if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) {
356		if (tp->tx_pause)
357			priv->port_open = false;
358		else
359			priv->port_open = true;
360	} else if (is_multicast_ether_addr(tp->peermac)) {
361		mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
362	} else {
363		spin_lock_bh(&priv->sta_list_spinlock);
364		sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
365		if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
366			sta_ptr->tx_pause = tp->tx_pause;
367			spin_unlock_bh(&priv->sta_list_spinlock);
368			mwifiex_update_ralist_tx_pause(priv, tp->peermac,
369						       tp->tx_pause);
370		} else {
371			spin_unlock_bh(&priv->sta_list_spinlock);
372		}
373	}
374}
375
376static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
377					 struct mwifiex_ie_types_header *tlv)
378{
379	struct mwifiex_tx_pause_tlv *tp;
380	struct mwifiex_sta_node *sta_ptr;
381	int status;
382
383	tp = (void *)tlv;
384	mwifiex_dbg(priv->adapter, EVENT,
385		    "sta tx_pause: %pM pause=%d, pkts=%d\n",
386		    tp->peermac, tp->tx_pause,
387		    tp->pkt_cnt);
388
389	if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) {
390		if (tp->tx_pause)
391			priv->port_open = false;
392		else
393			priv->port_open = true;
394	} else {
395		if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
396			return;
397
398		status = mwifiex_get_tdls_link_status(priv, tp->peermac);
399		if (mwifiex_is_tdls_link_setup(status)) {
400			spin_lock_bh(&priv->sta_list_spinlock);
401			sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
402			if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
403				sta_ptr->tx_pause = tp->tx_pause;
404				spin_unlock_bh(&priv->sta_list_spinlock);
405				mwifiex_update_ralist_tx_pause(priv,
406							       tp->peermac,
407							       tp->tx_pause);
408			} else {
409				spin_unlock_bh(&priv->sta_list_spinlock);
410			}
411		}
412	}
413}
414
415void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
416				      struct sk_buff *event_skb)
417{
418	struct mwifiex_ie_types_multi_chan_info *chan_info;
419	struct mwifiex_ie_types_mc_group_info *grp_info;
420	struct mwifiex_adapter *adapter = priv->adapter;
421	struct mwifiex_ie_types_header *tlv;
422	u16 tlv_buf_left, tlv_type, tlv_len;
423	int intf_num, bss_type, bss_num, i;
424	struct mwifiex_private *intf_priv;
425
426	tlv_buf_left = event_skb->len - sizeof(u32);
427	chan_info = (void *)event_skb->data + sizeof(u32);
428
429	if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO ||
430	    tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) {
431		mwifiex_dbg(adapter, ERROR,
432			    "unknown TLV in chan_info event\n");
433		return;
434	}
435
436	adapter->usb_mc_status = le16_to_cpu(chan_info->status);
437	mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n",
438		    adapter->usb_mc_status ? "started" : "over");
439
440	tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info);
441	tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer;
442
443	while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
444		tlv_type = le16_to_cpu(tlv->type);
445		tlv_len  = le16_to_cpu(tlv->len);
446		if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
447		    tlv_buf_left) {
448			mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t"
449				    "tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
450			break;
451		}
452		if (tlv_type != TLV_TYPE_MC_GROUP_INFO) {
453			mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n",
454				    tlv_type);
455			break;
456		}
457
458		grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv;
459		intf_num = grp_info->intf_num;
460		for (i = 0; i < intf_num; i++) {
461			bss_type = grp_info->bss_type_numlist[i] >> 4;
462			bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK;
463			intf_priv = mwifiex_get_priv_by_id(adapter, bss_num,
464							   bss_type);
465			if (!intf_priv) {
466				mwifiex_dbg(adapter, ERROR,
467					    "Invalid bss_type bss_num\t"
468					    "in multi channel event\n");
469				continue;
470			}
471			if (adapter->iface_type == MWIFIEX_USB) {
472				u8 ep;
473
474				ep = grp_info->hid_num.usb_ep_num;
475				if (ep == MWIFIEX_USB_EP_DATA ||
476				    ep == MWIFIEX_USB_EP_DATA_CH2)
477					intf_priv->usb_port = ep;
478			}
479		}
480
481		tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
482				tlv_len;
483		tlv = (void *)((u8 *)tlv + tlv_len +
484			       sizeof(struct mwifiex_ie_types_header));
485	}
486
487	if (adapter->iface_type == MWIFIEX_USB) {
488		adapter->tx_lock_flag = true;
489		adapter->usb_mc_setup = true;
490		mwifiex_multi_chan_resync(adapter);
491	}
492}
493
494void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
495				    struct sk_buff *event_skb)
496{
497	struct mwifiex_ie_types_header *tlv;
498	u16 tlv_type, tlv_len;
499	int tlv_buf_left;
500
501	if (!priv->media_connected) {
502		mwifiex_dbg(priv->adapter, ERROR,
503			    "tx_pause event while disconnected; bss_role=%d\n",
504			    priv->bss_role);
505		return;
506	}
507
508	tlv_buf_left = event_skb->len - sizeof(u32);
509	tlv = (void *)event_skb->data + sizeof(u32);
510
511	while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
512		tlv_type = le16_to_cpu(tlv->type);
513		tlv_len  = le16_to_cpu(tlv->len);
514		if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
515		    tlv_buf_left) {
516			mwifiex_dbg(priv->adapter, ERROR,
517				    "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
518				    tlv_len, tlv_buf_left);
519			break;
520		}
521		if (tlv_type == TLV_TYPE_TX_PAUSE) {
522			if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
523				mwifiex_process_sta_tx_pause(priv, tlv);
524			else
525				mwifiex_process_uap_tx_pause(priv, tlv);
526		}
527
528		tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
529				tlv_len;
530		tlv = (void *)((u8 *)tlv + tlv_len +
531			       sizeof(struct mwifiex_ie_types_header));
532	}
533
534}
535
536/*
537* This function handles coex events generated by firmware
538*/
539void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
540					     struct sk_buff *event_skb)
541{
542	struct mwifiex_adapter *adapter = priv->adapter;
543	struct mwifiex_ie_types_header *tlv;
544	struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv;
545	struct mwifiex_ie_types_btcoex_scan_time *scantlv;
546	s32 len = event_skb->len - sizeof(u32);
547	u8 *cur_ptr = event_skb->data + sizeof(u32);
548	u16 tlv_type, tlv_len;
549
550	while (len >= sizeof(struct mwifiex_ie_types_header)) {
551		tlv = (struct mwifiex_ie_types_header *)cur_ptr;
552		tlv_len = le16_to_cpu(tlv->len);
553		tlv_type = le16_to_cpu(tlv->type);
554
555		if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len)
556			break;
557		switch (tlv_type) {
558		case TLV_BTCOEX_WL_AGGR_WINSIZE:
559			winsizetlv =
560			    (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv;
561			adapter->coex_win_size = winsizetlv->coex_win_size;
562			adapter->coex_tx_win_size =
563				winsizetlv->tx_win_size;
564			adapter->coex_rx_win_size =
565				winsizetlv->rx_win_size;
566			mwifiex_coex_ampdu_rxwinsize(adapter);
567			mwifiex_update_ampdu_txwinsize(adapter);
568			break;
569
570		case TLV_BTCOEX_WL_SCANTIME:
571			scantlv =
572			    (struct mwifiex_ie_types_btcoex_scan_time *)tlv;
573			adapter->coex_scan = scantlv->coex_scan;
574			adapter->coex_min_scan_time = le16_to_cpu(scantlv->min_scan_time);
575			adapter->coex_max_scan_time = le16_to_cpu(scantlv->max_scan_time);
576			break;
577
578		default:
579			break;
580		}
581
582		len -= tlv_len + sizeof(struct mwifiex_ie_types_header);
583		cur_ptr += tlv_len +
584			sizeof(struct mwifiex_ie_types_header);
585	}
586
587	dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
588		adapter->coex_scan, adapter->coex_min_scan_time,
589		adapter->coex_win_size, adapter->coex_tx_win_size,
590		adapter->coex_rx_win_size);
591}
592
593static void
594mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
595			   struct sk_buff *event_skb)
596{
597	struct mwifiex_adapter *adapter = priv->adapter;
598	struct mwifiex_fw_dump_header *fw_dump_hdr =
599				(void *)adapter->event_body;
600
601	if (adapter->iface_type != MWIFIEX_USB) {
602		mwifiex_dbg(adapter, MSG,
603			    "event is not on usb interface, ignore it\n");
604		return;
605	}
606
607	if (!adapter->devdump_data) {
608		/* When receive the first event, allocate device dump
609		 * buffer, dump driver info.
610		 */
611		adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
612		if (!adapter->devdump_data) {
613			mwifiex_dbg(adapter, ERROR,
614				    "vzalloc devdump data failure!\n");
615			return;
616		}
617
618		mwifiex_drv_info_dump(adapter);
619
620		/* If no proceeded event arrive in 10s, upload device
621		 * dump data, this will be useful if the end of
622		 * transmission event get lost, in this cornel case,
623		 * user would still get partial of the dump.
624		 */
625		mod_timer(&adapter->devdump_timer,
626			  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
627	}
628
629	/* Overflow check */
630	if (adapter->devdump_len + event_skb->len >= MWIFIEX_FW_DUMP_SIZE)
631		goto upload_dump;
632
633	memmove(adapter->devdump_data + adapter->devdump_len,
634		adapter->event_skb->data, event_skb->len);
635	adapter->devdump_len += event_skb->len;
636
637	if (le16_to_cpu(fw_dump_hdr->type == FW_DUMP_INFO_ENDED)) {
638		mwifiex_dbg(adapter, MSG,
639			    "receive end of transmission flag event!\n");
640		goto upload_dump;
641	}
642	return;
643
644upload_dump:
645	del_timer_sync(&adapter->devdump_timer);
646	mwifiex_upload_device_dump(adapter);
647}
648
649/*
650 * This function handles events generated by firmware.
651 *
652 * This is a generic function and handles all events.
653 *
654 * Event specific routines are called by this function based
655 * upon the generated event cause.
656 *
657 * For the following events, the function just forwards them to upper
658 * layers, optionally recording the change -
659 *      - EVENT_LINK_SENSED
660 *      - EVENT_MIC_ERR_UNICAST
661 *      - EVENT_MIC_ERR_MULTICAST
662 *      - EVENT_PORT_RELEASE
663 *      - EVENT_RSSI_LOW
664 *      - EVENT_SNR_LOW
665 *      - EVENT_MAX_FAIL
666 *      - EVENT_RSSI_HIGH
667 *      - EVENT_SNR_HIGH
668 *      - EVENT_DATA_RSSI_LOW
669 *      - EVENT_DATA_SNR_LOW
670 *      - EVENT_DATA_RSSI_HIGH
671 *      - EVENT_DATA_SNR_HIGH
672 *      - EVENT_LINK_QUALITY
673 *      - EVENT_PRE_BEACON_LOST
674 *      - EVENT_IBSS_COALESCED
675 *      - EVENT_IBSS_STA_CONNECT
676 *      - EVENT_IBSS_STA_DISCONNECT
677 *      - EVENT_WEP_ICV_ERR
678 *      - EVENT_BW_CHANGE
679 *      - EVENT_HOSTWAKE_STAIE
680  *
681 * For the following events, no action is taken -
682 *      - EVENT_MIB_CHANGED
683 *      - EVENT_INIT_DONE
684 *      - EVENT_DUMMY_HOST_WAKEUP_SIGNAL
685 *
686 * Rest of the supported events requires driver handling -
687 *      - EVENT_DEAUTHENTICATED
688 *      - EVENT_DISASSOCIATED
689 *      - EVENT_LINK_LOST
690 *      - EVENT_PS_SLEEP
691 *      - EVENT_PS_AWAKE
692 *      - EVENT_DEEP_SLEEP_AWAKE
693 *      - EVENT_HS_ACT_REQ
694 *      - EVENT_ADHOC_BCN_LOST
695 *      - EVENT_BG_SCAN_REPORT
696 *      - EVENT_WMM_STATUS_CHANGE
697 *      - EVENT_ADDBA
698 *      - EVENT_DELBA
699 *      - EVENT_BA_STREAM_TIEMOUT
700 *      - EVENT_AMSDU_AGGR_CTRL
701 *      - EVENT_FW_DUMP_INFO
702 */
703int mwifiex_process_sta_event(struct mwifiex_private *priv)
704{
705	struct mwifiex_adapter *adapter = priv->adapter;
706	int ret = 0, i;
707	u32 eventcause = adapter->event_cause;
708	u16 ctrl, reason_code;
709	u8 ibss_sta_addr[ETH_ALEN];
710	struct mwifiex_sta_node *sta_ptr;
711
712	switch (eventcause) {
713	case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
714		mwifiex_dbg(adapter, ERROR,
715			    "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
716		break;
717	case EVENT_LINK_SENSED:
718		mwifiex_dbg(adapter, EVENT, "event: LINK_SENSED\n");
719		if (!netif_carrier_ok(priv->netdev))
720			netif_carrier_on(priv->netdev);
721		mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
722		break;
723
724	case EVENT_DEAUTHENTICATED:
725		mwifiex_dbg(adapter, EVENT, "event: Deauthenticated\n");
726		if (priv->wps.session_enable) {
727			mwifiex_dbg(adapter, INFO,
728				    "info: receive deauth event in wps session\n");
729			break;
730		}
731		adapter->dbg.num_event_deauth++;
732		if (priv->media_connected) {
733			reason_code =
734				get_unaligned_le16(adapter->event_body);
735			mwifiex_reset_connect_state(priv, reason_code, true);
736		}
737		break;
738
739	case EVENT_DISASSOCIATED:
740		mwifiex_dbg(adapter, EVENT, "event: Disassociated\n");
741		if (priv->wps.session_enable) {
742			mwifiex_dbg(adapter, INFO,
743				    "info: receive disassoc event in wps session\n");
744			break;
745		}
746		adapter->dbg.num_event_disassoc++;
747		if (priv->media_connected) {
748			reason_code =
749				get_unaligned_le16(adapter->event_body);
750			mwifiex_reset_connect_state(priv, reason_code, true);
751		}
752		break;
753
754	case EVENT_LINK_LOST:
755		mwifiex_dbg(adapter, EVENT, "event: Link lost\n");
756		adapter->dbg.num_event_link_lost++;
757		if (priv->media_connected) {
758			reason_code =
759				get_unaligned_le16(adapter->event_body);
760			mwifiex_reset_connect_state(priv, reason_code, true);
761		}
762		break;
763
764	case EVENT_PS_SLEEP:
765		mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
766
767		adapter->ps_state = PS_STATE_PRE_SLEEP;
768
769		mwifiex_check_ps_cond(adapter);
770		break;
771
772	case EVENT_PS_AWAKE:
773		mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
774		if (!adapter->pps_uapsd_mode &&
775		    (priv->port_open ||
776		     (priv->bss_mode == NL80211_IFTYPE_ADHOC)) &&
777		    priv->media_connected && adapter->sleep_period.period) {
778			adapter->pps_uapsd_mode = true;
779			mwifiex_dbg(adapter, EVENT,
780				    "event: PPS/UAPSD mode activated\n");
781		}
782		adapter->tx_lock_flag = false;
783		if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
784			if (mwifiex_check_last_packet_indication(priv)) {
785				if (adapter->data_sent ||
786				    (adapter->if_ops.is_port_ready &&
787				     !adapter->if_ops.is_port_ready(priv))) {
788					adapter->ps_state = PS_STATE_AWAKE;
789					adapter->pm_wakeup_card_req = false;
790					adapter->pm_wakeup_fw_try = false;
791					del_timer(&adapter->wakeup_timer);
792					break;
793				}
794				if (!mwifiex_send_null_packet
795					(priv,
796					 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
797					 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
798						adapter->ps_state =
799							PS_STATE_SLEEP;
800					return 0;
801			}
802		}
803		adapter->ps_state = PS_STATE_AWAKE;
804		adapter->pm_wakeup_card_req = false;
805		adapter->pm_wakeup_fw_try = false;
806		del_timer(&adapter->wakeup_timer);
807
808		break;
809
810	case EVENT_DEEP_SLEEP_AWAKE:
811		adapter->if_ops.wakeup_complete(adapter);
812		mwifiex_dbg(adapter, EVENT, "event: DS_AWAKE\n");
813		if (adapter->is_deep_sleep)
814			adapter->is_deep_sleep = false;
815		break;
816
817	case EVENT_HS_ACT_REQ:
818		mwifiex_dbg(adapter, EVENT, "event: HS_ACT_REQ\n");
819		ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH,
820				       0, 0, NULL, false);
821		break;
822
823	case EVENT_MIC_ERR_UNICAST:
824		mwifiex_dbg(adapter, EVENT, "event: UNICAST MIC ERROR\n");
825		cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
826					     NL80211_KEYTYPE_PAIRWISE,
827					     -1, NULL, GFP_KERNEL);
828		break;
829
830	case EVENT_MIC_ERR_MULTICAST:
831		mwifiex_dbg(adapter, EVENT, "event: MULTICAST MIC ERROR\n");
832		cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
833					     NL80211_KEYTYPE_GROUP,
834					     -1, NULL, GFP_KERNEL);
835		break;
836	case EVENT_MIB_CHANGED:
837	case EVENT_INIT_DONE:
838		break;
839
840	case EVENT_ADHOC_BCN_LOST:
841		mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n");
842		priv->adhoc_is_link_sensed = false;
843		mwifiex_clean_txrx(priv);
844		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
845		if (netif_carrier_ok(priv->netdev))
846			netif_carrier_off(priv->netdev);
847		break;
848
849	case EVENT_BG_SCAN_REPORT:
850		mwifiex_dbg(adapter, EVENT, "event: BGS_REPORT\n");
851		ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY,
852				       HostCmd_ACT_GEN_GET, 0, NULL, false);
853		break;
854
855	case EVENT_BG_SCAN_STOPPED:
856		dev_dbg(adapter->dev, "event: BGS_STOPPED\n");
857		cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0);
858		if (priv->sched_scanning)
859			priv->sched_scanning = false;
860		break;
861
862	case EVENT_PORT_RELEASE:
863		mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n");
864		priv->port_open = true;
865		break;
866
867	case EVENT_EXT_SCAN_REPORT:
868		mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
869		/* We intend to skip this event during suspend, but handle
870		 * it in interface disabled case
871		 */
872		if (adapter->ext_scan && (!priv->scan_aborting ||
873					  !netif_running(priv->netdev)))
874			ret = mwifiex_handle_event_ext_scan_report(priv,
875						adapter->event_skb->data);
876
877		break;
878
879	case EVENT_WMM_STATUS_CHANGE:
880		mwifiex_dbg(adapter, EVENT, "event: WMM status changed\n");
881		ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS,
882				       0, 0, NULL, false);
883		break;
884
885	case EVENT_RSSI_LOW:
886		cfg80211_cqm_rssi_notify(priv->netdev,
887					 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
888					 0, GFP_KERNEL);
889		mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
890				 HostCmd_ACT_GEN_GET, 0, NULL, false);
891		priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
892		mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_LOW\n");
893		break;
894	case EVENT_SNR_LOW:
895		mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_LOW\n");
896		break;
897	case EVENT_MAX_FAIL:
898		mwifiex_dbg(adapter, EVENT, "event: MAX_FAIL\n");
899		break;
900	case EVENT_RSSI_HIGH:
901		cfg80211_cqm_rssi_notify(priv->netdev,
902					 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
903					 0, GFP_KERNEL);
904		mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
905				 HostCmd_ACT_GEN_GET, 0, NULL, false);
906		priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
907		mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_HIGH\n");
908		break;
909	case EVENT_SNR_HIGH:
910		mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_HIGH\n");
911		break;
912	case EVENT_DATA_RSSI_LOW:
913		mwifiex_dbg(adapter, EVENT, "event: Data RSSI_LOW\n");
914		break;
915	case EVENT_DATA_SNR_LOW:
916		mwifiex_dbg(adapter, EVENT, "event: Data SNR_LOW\n");
917		break;
918	case EVENT_DATA_RSSI_HIGH:
919		mwifiex_dbg(adapter, EVENT, "event: Data RSSI_HIGH\n");
920		break;
921	case EVENT_DATA_SNR_HIGH:
922		mwifiex_dbg(adapter, EVENT, "event: Data SNR_HIGH\n");
923		break;
924	case EVENT_LINK_QUALITY:
925		mwifiex_dbg(adapter, EVENT, "event: Link Quality\n");
926		break;
927	case EVENT_PRE_BEACON_LOST:
928		mwifiex_dbg(adapter, EVENT, "event: Pre-Beacon Lost\n");
929		break;
930	case EVENT_IBSS_COALESCED:
931		mwifiex_dbg(adapter, EVENT, "event: IBSS_COALESCED\n");
932		ret = mwifiex_send_cmd(priv,
933				HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
934				HostCmd_ACT_GEN_GET, 0, NULL, false);
935		break;
936	case EVENT_IBSS_STA_CONNECT:
937		ether_addr_copy(ibss_sta_addr, adapter->event_body + 2);
938		mwifiex_dbg(adapter, EVENT, "event: IBSS_STA_CONNECT %pM\n",
939			    ibss_sta_addr);
940		sta_ptr = mwifiex_add_sta_entry(priv, ibss_sta_addr);
941		if (sta_ptr && adapter->adhoc_11n_enabled) {
942			mwifiex_check_ibss_peer_capabilities(priv, sta_ptr,
943							     adapter->event_skb);
944			if (sta_ptr->is_11n_enabled)
945				for (i = 0; i < MAX_NUM_TID; i++)
946					sta_ptr->ampdu_sta[i] =
947					priv->aggr_prio_tbl[i].ampdu_user;
948			else
949				for (i = 0; i < MAX_NUM_TID; i++)
950					sta_ptr->ampdu_sta[i] =
951						BA_STREAM_NOT_ALLOWED;
952			memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
953		}
954
955		break;
956	case EVENT_IBSS_STA_DISCONNECT:
957		ether_addr_copy(ibss_sta_addr, adapter->event_body + 2);
958		mwifiex_dbg(adapter, EVENT, "event: IBSS_STA_DISCONNECT %pM\n",
959			    ibss_sta_addr);
960		sta_ptr = mwifiex_get_sta_entry(priv, ibss_sta_addr);
961		if (sta_ptr && sta_ptr->is_11n_enabled) {
962			mwifiex_11n_del_rx_reorder_tbl_by_ta(priv,
963							     ibss_sta_addr);
964			mwifiex_del_tx_ba_stream_tbl_by_ra(priv, ibss_sta_addr);
965		}
966		mwifiex_wmm_del_peer_ra_list(priv, ibss_sta_addr);
967		mwifiex_del_sta_entry(priv, ibss_sta_addr);
968		break;
969	case EVENT_ADDBA:
970		mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
971		mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
972				 HostCmd_ACT_GEN_SET, 0,
973				 adapter->event_body, false);
974		break;
975	case EVENT_DELBA:
976		mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
977		mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
978		break;
979	case EVENT_BA_STREAM_TIEMOUT:
980		mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
981		mwifiex_11n_ba_stream_timeout(priv,
982					      (struct host_cmd_ds_11n_batimeout
983					       *)
984					      adapter->event_body);
985		break;
986	case EVENT_AMSDU_AGGR_CTRL:
987		ctrl = get_unaligned_le16(adapter->event_body);
988		mwifiex_dbg(adapter, EVENT,
989			    "event: AMSDU_AGGR_CTRL %d\n", ctrl);
990
991		adapter->tx_buf_size =
992				min_t(u16, adapter->curr_tx_buf_size, ctrl);
993		mwifiex_dbg(adapter, EVENT, "event: tx_buf_size %d\n",
994			    adapter->tx_buf_size);
995		break;
996
997	case EVENT_WEP_ICV_ERR:
998		mwifiex_dbg(adapter, EVENT, "event: WEP ICV error\n");
999		break;
1000
1001	case EVENT_BW_CHANGE:
1002		mwifiex_dbg(adapter, EVENT, "event: BW Change\n");
1003		break;
1004
1005	case EVENT_HOSTWAKE_STAIE:
1006		mwifiex_dbg(adapter, EVENT,
1007			    "event: HOSTWAKE_STAIE %d\n", eventcause);
1008		break;
1009
1010	case EVENT_REMAIN_ON_CHAN_EXPIRED:
1011		mwifiex_dbg(adapter, EVENT,
1012			    "event: Remain on channel expired\n");
1013		cfg80211_remain_on_channel_expired(&priv->wdev,
1014						   priv->roc_cfg.cookie,
1015						   &priv->roc_cfg.chan,
1016						   GFP_ATOMIC);
1017
1018		memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
1019
1020		break;
1021
1022	case EVENT_CHANNEL_SWITCH_ANN:
1023		mwifiex_dbg(adapter, EVENT, "event: Channel Switch Announcement\n");
1024		priv->csa_expire_time =
1025				jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
1026		priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
1027		ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
1028			HostCmd_ACT_GEN_SET, 0,
1029			priv->curr_bss_params.bss_descriptor.mac_address,
1030			false);
1031		break;
1032
1033	case EVENT_TDLS_GENERIC_EVENT:
1034		ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
1035		break;
1036
1037	case EVENT_TX_DATA_PAUSE:
1038		mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
1039		mwifiex_process_tx_pause_event(priv, adapter->event_skb);
1040		break;
1041
1042	case EVENT_MULTI_CHAN_INFO:
1043		mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
1044		mwifiex_process_multi_chan_event(priv, adapter->event_skb);
1045		break;
1046
1047	case EVENT_TX_STATUS_REPORT:
1048		mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
1049		mwifiex_parse_tx_status_event(priv, adapter->event_body);
1050		break;
1051
1052	case EVENT_CHANNEL_REPORT_RDY:
1053		mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
1054		ret = mwifiex_11h_handle_chanrpt_ready(priv,
1055						       adapter->event_skb);
1056		break;
1057	case EVENT_RADAR_DETECTED:
1058		mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
1059		ret = mwifiex_11h_handle_radar_detected(priv,
1060							adapter->event_skb);
1061		break;
1062	case EVENT_BT_COEX_WLAN_PARA_CHANGE:
1063		dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n");
1064		if (adapter->ignore_btcoex_events)
1065			break;
1066
1067		mwifiex_bt_coex_wlan_param_update_event(priv,
1068							adapter->event_skb);
1069		break;
1070	case EVENT_RXBA_SYNC:
1071		dev_dbg(adapter->dev, "EVENT: RXBA_SYNC\n");
1072		mwifiex_11n_rxba_sync_event(priv, adapter->event_body,
1073					    adapter->event_skb->len -
1074					    sizeof(eventcause));
1075		break;
1076	case EVENT_FW_DUMP_INFO:
1077		mwifiex_dbg(adapter, EVENT, "event: firmware debug info\n");
1078		mwifiex_fw_dump_info_event(priv, adapter->event_skb);
1079		break;
1080	/* Debugging event; not used, but let's not print an ERROR for it. */
1081	case EVENT_UNKNOWN_DEBUG:
1082		mwifiex_dbg(adapter, EVENT, "event: debug\n");
1083		break;
1084	default:
1085		mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
1086			    eventcause);
1087		break;
1088	}
1089
1090	return ret;
1091}
1092