xref: /linux/drivers/net/wireless/nxp/nxpwifi/sta_event.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * NXP Wireless LAN device driver: station event handling
4  *
5  * Copyright 2011-2024 NXP
6  */
7 
8 #include "cfg.h"
9 #include "util.h"
10 #include "fw.h"
11 #include "main.h"
12 #include "cmdevt.h"
13 #include "wmm.h"
14 #include "11n.h"
15 
16 static int
nxpwifi_sta_event_link_lost(struct nxpwifi_private * priv)17 nxpwifi_sta_event_link_lost(struct nxpwifi_private *priv)
18 {
19 	struct nxpwifi_adapter *adapter = priv->adapter;
20 
21 	adapter->dbg.num_event_link_lost++;
22 	if (priv->media_connected) {
23 		adapter->priv_link_lost = priv;
24 		adapter->host_mlme_link_lost = true;
25 		nxpwifi_queue_wiphy_work(adapter,
26 					 &adapter->host_mlme_work);
27 	}
28 
29 	return 0;
30 }
31 
32 static int
nxpwifi_sta_event_link_sensed(struct nxpwifi_private * priv)33 nxpwifi_sta_event_link_sensed(struct nxpwifi_private *priv)
34 {
35 	struct nxpwifi_adapter *adapter = priv->adapter;
36 
37 	netif_carrier_on(priv->netdev);
38 	nxpwifi_wake_up_net_dev_queue(priv->netdev, adapter);
39 
40 	return 0;
41 }
42 
43 static int
nxpwifi_sta_event_deauthenticated(struct nxpwifi_private * priv)44 nxpwifi_sta_event_deauthenticated(struct nxpwifi_private *priv)
45 {
46 	struct nxpwifi_adapter *adapter = priv->adapter;
47 
48 	if (priv->wps.session_enable) {
49 		nxpwifi_dbg(adapter, INFO,
50 			    "info: receive deauth event in wps session\n");
51 	} else {
52 		adapter->dbg.num_event_deauth++;
53 		if (priv->media_connected) {
54 			priv->last_deauth_reason =
55 				get_unaligned_le16(priv->adapter->event_body);
56 			nxpwifi_queue_wiphy_work(priv->adapter,
57 						 &priv->reset_conn_state_work);
58 		}
59 	}
60 
61 	return 0;
62 }
63 
64 static int
nxpwifi_sta_event_disassociated(struct nxpwifi_private * priv)65 nxpwifi_sta_event_disassociated(struct nxpwifi_private *priv)
66 {
67 	struct nxpwifi_adapter *adapter = priv->adapter;
68 
69 	if (priv->wps.session_enable) {
70 		nxpwifi_dbg(adapter, INFO,
71 			    "info: receive disassoc event in wps session\n");
72 	} else {
73 		adapter->dbg.num_event_disassoc++;
74 		if (priv->media_connected) {
75 			priv->last_deauth_reason =
76 				get_unaligned_le16(priv->adapter->event_body);
77 			nxpwifi_queue_wiphy_work(priv->adapter,
78 						 &priv->reset_conn_state_work);
79 		}
80 	}
81 
82 	return 0;
83 }
84 
85 static int
nxpwifi_sta_event_ps_awake(struct nxpwifi_private * priv)86 nxpwifi_sta_event_ps_awake(struct nxpwifi_private *priv)
87 {
88 	struct nxpwifi_adapter *adapter = priv->adapter;
89 
90 	if (!adapter->pps_uapsd_mode &&
91 	    priv->port_open &&
92 	    priv->media_connected && adapter->sleep_period.period) {
93 		adapter->pps_uapsd_mode = true;
94 		nxpwifi_dbg(adapter, EVENT,
95 			    "event: PPS/UAPSD mode activated\n");
96 	}
97 	adapter->tx_lock_flag = false;
98 	if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
99 		if (nxpwifi_check_last_packet_indication(priv)) {
100 			if (adapter->data_sent) {
101 				adapter->ps_state = PS_STATE_AWAKE;
102 				adapter->pm_wakeup_card_req = false;
103 				adapter->pm_wakeup_fw_try = false;
104 				timer_delete(&adapter->wakeup_timer);
105 			} else {
106 				if (!nxpwifi_send_null_packet
107 				    (priv,
108 				     NXPWIFI_TxPD_POWER_MGMT_NULL_PACKET |
109 				     NXPWIFI_TxPD_POWER_MGMT_LAST_PACKET))
110 					adapter->ps_state = PS_STATE_SLEEP;
111 			}
112 
113 			return 0;
114 		}
115 	}
116 
117 	adapter->ps_state = PS_STATE_AWAKE;
118 	adapter->pm_wakeup_card_req = false;
119 	adapter->pm_wakeup_fw_try = false;
120 	timer_delete(&adapter->wakeup_timer);
121 
122 	return 0;
123 }
124 
125 static int
nxpwifi_sta_event_ps_sleep(struct nxpwifi_private * priv)126 nxpwifi_sta_event_ps_sleep(struct nxpwifi_private *priv)
127 {
128 	struct nxpwifi_adapter *adapter = priv->adapter;
129 
130 	adapter->ps_state = PS_STATE_PRE_SLEEP;
131 	nxpwifi_check_ps_cond(adapter);
132 
133 	return 0;
134 }
135 
136 static int
nxpwifi_sta_event_mic_err_multicast(struct nxpwifi_private * priv)137 nxpwifi_sta_event_mic_err_multicast(struct nxpwifi_private *priv)
138 {
139 	cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
140 				     NL80211_KEYTYPE_GROUP,
141 				     -1, NULL, GFP_KERNEL);
142 
143 	return 0;
144 }
145 
146 static int
nxpwifi_sta_event_mic_err_unicast(struct nxpwifi_private * priv)147 nxpwifi_sta_event_mic_err_unicast(struct nxpwifi_private *priv)
148 {
149 	cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
150 				     NL80211_KEYTYPE_PAIRWISE,
151 				     -1, NULL, GFP_KERNEL);
152 
153 	return 0;
154 }
155 
156 static int
nxpwifi_sta_event_deep_sleep_awake(struct nxpwifi_private * priv)157 nxpwifi_sta_event_deep_sleep_awake(struct nxpwifi_private *priv)
158 {
159 	struct nxpwifi_adapter *adapter = priv->adapter;
160 
161 	adapter->if_ops.wakeup_complete(adapter);
162 	if (adapter->is_deep_sleep)
163 		adapter->is_deep_sleep = false;
164 
165 	return 0;
166 }
167 
168 static int
nxpwifi_sta_event_wmm_status_change(struct nxpwifi_private * priv)169 nxpwifi_sta_event_wmm_status_change(struct nxpwifi_private *priv)
170 {
171 	return nxpwifi_send_cmd(priv, HOST_CMD_WMM_GET_STATUS,
172 				0, 0, NULL, false);
173 }
174 
175 static int
nxpwifi_sta_event_bs_scan_report(struct nxpwifi_private * priv)176 nxpwifi_sta_event_bs_scan_report(struct nxpwifi_private *priv)
177 {
178 	return nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_QUERY,
179 				HOST_ACT_GEN_GET, 0, NULL, false);
180 }
181 
182 static int
nxpwifi_sta_event_rssi_low(struct nxpwifi_private * priv)183 nxpwifi_sta_event_rssi_low(struct nxpwifi_private *priv)
184 {
185 	cfg80211_cqm_rssi_notify(priv->netdev,
186 				 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
187 				 0, GFP_KERNEL);
188 	priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
189 
190 	return nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO,
191 				HOST_ACT_GEN_GET, 0, NULL, false);
192 }
193 
194 static int
nxpwifi_sta_event_rssi_high(struct nxpwifi_private * priv)195 nxpwifi_sta_event_rssi_high(struct nxpwifi_private *priv)
196 {
197 	cfg80211_cqm_rssi_notify(priv->netdev,
198 				 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
199 				 0, GFP_KERNEL);
200 	priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
201 
202 	return nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO,
203 				HOST_ACT_GEN_GET, 0, NULL, false);
204 }
205 
206 static int
nxpwifi_sta_event_port_release(struct nxpwifi_private * priv)207 nxpwifi_sta_event_port_release(struct nxpwifi_private *priv)
208 {
209 	priv->port_open = true;
210 
211 	return 0;
212 }
213 
214 static int
nxpwifi_sta_event_addba(struct nxpwifi_private * priv)215 nxpwifi_sta_event_addba(struct nxpwifi_private *priv)
216 {
217 	struct nxpwifi_adapter *adapter = priv->adapter;
218 
219 	return nxpwifi_send_cmd(priv, HOST_CMD_11N_ADDBA_RSP,
220 				HOST_ACT_GEN_SET, 0,
221 				adapter->event_body, false);
222 }
223 
224 static int
nxpwifi_sta_event_delba(struct nxpwifi_private * priv)225 nxpwifi_sta_event_delba(struct nxpwifi_private *priv)
226 {
227 	struct nxpwifi_adapter *adapter = priv->adapter;
228 
229 	nxpwifi_11n_delete_ba_stream(priv, adapter->event_body);
230 
231 	return 0;
232 }
233 
234 static int
nxpwifi_sta_event_bs_stream_timeout(struct nxpwifi_private * priv)235 nxpwifi_sta_event_bs_stream_timeout(struct nxpwifi_private *priv)
236 {
237 	struct nxpwifi_adapter *adapter = priv->adapter;
238 	struct host_cmd_ds_11n_batimeout *event =
239 		(struct host_cmd_ds_11n_batimeout *)adapter->event_body;
240 
241 	nxpwifi_11n_ba_stream_timeout(priv, event);
242 
243 	return 0;
244 }
245 
246 static int
nxpwifi_sta_event_amsdu_aggr_ctrl(struct nxpwifi_private * priv)247 nxpwifi_sta_event_amsdu_aggr_ctrl(struct nxpwifi_private *priv)
248 {
249 	struct nxpwifi_adapter *adapter = priv->adapter;
250 	u16 ctrl;
251 
252 	ctrl = get_unaligned_le16(adapter->event_body);
253 	adapter->tx_buf_size = min_t(u16, adapter->curr_tx_buf_size, ctrl);
254 
255 	return 0;
256 }
257 
258 static int
nxpwifi_sta_event_hs_act_req(struct nxpwifi_private * priv)259 nxpwifi_sta_event_hs_act_req(struct nxpwifi_private *priv)
260 {
261 	return nxpwifi_send_cmd(priv, HOST_CMD_802_11_HS_CFG_ENH,
262 				0, 0, NULL, false);
263 }
264 
265 static int
nxpwifi_sta_event_channel_switch_ann(struct nxpwifi_private * priv)266 nxpwifi_sta_event_channel_switch_ann(struct nxpwifi_private *priv)
267 {
268 	struct nxpwifi_bssdescriptor *bss_desc;
269 
270 	bss_desc = &priv->curr_bss_params.bss_descriptor;
271 	priv->csa_expire_time = jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
272 	priv->csa_chan = bss_desc->channel;
273 	return nxpwifi_send_cmd(priv, HOST_CMD_802_11_DEAUTHENTICATE,
274 				HOST_ACT_GEN_SET, 0,
275 				bss_desc->mac_address, false);
276 }
277 
278 static int
nxpwifi_sta_event_radar_detected(struct nxpwifi_private * priv)279 nxpwifi_sta_event_radar_detected(struct nxpwifi_private *priv)
280 {
281 	struct nxpwifi_adapter *adapter = priv->adapter;
282 
283 	return nxpwifi_11h_handle_radar_detected(priv, adapter->event_skb);
284 }
285 
286 static int
nxpwifi_sta_event_channel_report_rdy(struct nxpwifi_private * priv)287 nxpwifi_sta_event_channel_report_rdy(struct nxpwifi_private *priv)
288 {
289 	struct nxpwifi_adapter *adapter = priv->adapter;
290 
291 	return nxpwifi_11h_handle_chanrpt_ready(priv, adapter->event_skb);
292 }
293 
294 static int
nxpwifi_sta_event_tx_data_pause(struct nxpwifi_private * priv)295 nxpwifi_sta_event_tx_data_pause(struct nxpwifi_private *priv)
296 {
297 	struct nxpwifi_adapter *adapter = priv->adapter;
298 
299 	nxpwifi_process_tx_pause_event(priv, adapter->event_skb);
300 
301 	return 0;
302 }
303 
304 static int
nxpwifi_sta_event_ext_scan_report(struct nxpwifi_private * priv)305 nxpwifi_sta_event_ext_scan_report(struct nxpwifi_private *priv)
306 {
307 	struct nxpwifi_adapter *adapter = priv->adapter;
308 	void *buf = adapter->event_skb->data;
309 	int ret = 0;
310 
311 	/*
312 	 * We intend to skip this event during suspend, but handle
313 	 * it in interface disabled case
314 	 */
315 	if (adapter->ext_scan && (!priv->scan_aborting ||
316 				  !netif_running(priv->netdev)))
317 		ret = nxpwifi_handle_event_ext_scan_report(priv, buf);
318 
319 	return ret;
320 }
321 
322 static int
nxpwifi_sta_event_rxba_sync(struct nxpwifi_private * priv)323 nxpwifi_sta_event_rxba_sync(struct nxpwifi_private *priv)
324 {
325 	struct nxpwifi_adapter *adapter = priv->adapter;
326 
327 	nxpwifi_11n_rxba_sync_event(priv, adapter->event_body,
328 				    adapter->event_skb->len -
329 				    sizeof(adapter->event_cause));
330 
331 	return 0;
332 }
333 
334 static int
nxpwifi_sta_event_remain_on_chan_expired(struct nxpwifi_private * priv)335 nxpwifi_sta_event_remain_on_chan_expired(struct nxpwifi_private *priv)
336 {
337 	if (priv->auth_flag & HOST_MLME_AUTH_PENDING) {
338 		priv->auth_flag = 0;
339 		priv->auth_alg = WLAN_AUTH_NONE;
340 	} else {
341 		cfg80211_remain_on_channel_expired(&priv->wdev,
342 						   priv->roc_cfg.cookie,
343 						   &priv->roc_cfg.chan,
344 						   GFP_ATOMIC);
345 	}
346 
347 	memset(&priv->roc_cfg, 0x00, sizeof(struct nxpwifi_roc_cfg));
348 
349 	return 0;
350 }
351 
352 static int
nxpwifi_sta_event_bg_scan_stopped(struct nxpwifi_private * priv)353 nxpwifi_sta_event_bg_scan_stopped(struct nxpwifi_private *priv)
354 {
355 	cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0);
356 	if (priv->sched_scanning)
357 		priv->sched_scanning = false;
358 
359 	return 0;
360 }
361 
362 static int
nxpwifi_sta_event_multi_chan_info(struct nxpwifi_private * priv)363 nxpwifi_sta_event_multi_chan_info(struct nxpwifi_private *priv)
364 {
365 	struct nxpwifi_adapter *adapter = priv->adapter;
366 
367 	nxpwifi_process_multi_chan_event(priv, adapter->event_skb);
368 
369 	return 0;
370 }
371 
372 static int
nxpwifi_sta_event_tx_status_report(struct nxpwifi_private * priv)373 nxpwifi_sta_event_tx_status_report(struct nxpwifi_private *priv)
374 {
375 	struct nxpwifi_adapter *adapter = priv->adapter;
376 
377 	nxpwifi_parse_tx_status_event(priv, adapter->event_body);
378 
379 	return 0;
380 }
381 
382 static int
nxpwifi_sta_event_bt_coex_wlan_para_change(struct nxpwifi_private * priv)383 nxpwifi_sta_event_bt_coex_wlan_para_change(struct nxpwifi_private *priv)
384 {
385 	struct nxpwifi_adapter *adapter = priv->adapter;
386 
387 	if (!adapter->ignore_btcoex_events)
388 		nxpwifi_bt_coex_wlan_param_update_event(priv,
389 							adapter->event_skb);
390 
391 	return 0;
392 }
393 
394 static int
nxpwifi_sta_event_vdll_ind(struct nxpwifi_private * priv)395 nxpwifi_sta_event_vdll_ind(struct nxpwifi_private *priv)
396 {
397 	struct nxpwifi_adapter *adapter = priv->adapter;
398 
399 	return nxpwifi_process_vdll_event(priv, adapter->event_skb);
400 }
401 
402 static const struct nxpwifi_evt_entry evt_table_sta[] = {
403 	{.event_cause = EVENT_LINK_LOST,
404 	.event_handler = nxpwifi_sta_event_link_lost},
405 	{.event_cause = EVENT_LINK_SENSED,
406 	.event_handler = nxpwifi_sta_event_link_sensed},
407 	{.event_cause = EVENT_DEAUTHENTICATED,
408 	.event_handler = nxpwifi_sta_event_deauthenticated},
409 	{.event_cause = EVENT_DISASSOCIATED,
410 	.event_handler = nxpwifi_sta_event_disassociated},
411 	{.event_cause = EVENT_PS_AWAKE,
412 	.event_handler = nxpwifi_sta_event_ps_awake},
413 	{.event_cause = EVENT_PS_SLEEP,
414 	.event_handler = nxpwifi_sta_event_ps_sleep},
415 	{.event_cause = EVENT_MIC_ERR_MULTICAST,
416 	.event_handler = nxpwifi_sta_event_mic_err_multicast},
417 	{.event_cause = EVENT_MIC_ERR_UNICAST,
418 	.event_handler = nxpwifi_sta_event_mic_err_unicast},
419 	{.event_cause = EVENT_DEEP_SLEEP_AWAKE,
420 	.event_handler = nxpwifi_sta_event_deep_sleep_awake},
421 	{.event_cause = EVENT_WMM_STATUS_CHANGE,
422 	.event_handler = nxpwifi_sta_event_wmm_status_change},
423 	{.event_cause = EVENT_BG_SCAN_REPORT,
424 	.event_handler = nxpwifi_sta_event_bs_scan_report},
425 	{.event_cause = EVENT_RSSI_LOW,
426 	.event_handler = nxpwifi_sta_event_rssi_low},
427 	{.event_cause = EVENT_RSSI_HIGH,
428 	.event_handler = nxpwifi_sta_event_rssi_high},
429 	{.event_cause = EVENT_PORT_RELEASE,
430 	.event_handler = nxpwifi_sta_event_port_release},
431 	{.event_cause = EVENT_ADDBA,
432 	.event_handler = nxpwifi_sta_event_addba},
433 	{.event_cause = EVENT_DELBA,
434 	.event_handler = nxpwifi_sta_event_delba},
435 	{.event_cause = EVENT_BA_STREAM_TIEMOUT,
436 	.event_handler = nxpwifi_sta_event_bs_stream_timeout},
437 	{.event_cause = EVENT_AMSDU_AGGR_CTRL,
438 	.event_handler = nxpwifi_sta_event_amsdu_aggr_ctrl},
439 	{.event_cause = EVENT_HS_ACT_REQ,
440 	.event_handler = nxpwifi_sta_event_hs_act_req},
441 	{.event_cause = EVENT_CHANNEL_SWITCH_ANN,
442 	.event_handler = nxpwifi_sta_event_channel_switch_ann},
443 	{.event_cause = EVENT_RADAR_DETECTED,
444 	.event_handler = nxpwifi_sta_event_radar_detected},
445 	{.event_cause = EVENT_CHANNEL_REPORT_RDY,
446 	.event_handler = nxpwifi_sta_event_channel_report_rdy},
447 	{.event_cause = EVENT_TX_DATA_PAUSE,
448 	.event_handler = nxpwifi_sta_event_tx_data_pause},
449 	{.event_cause = EVENT_EXT_SCAN_REPORT,
450 	.event_handler = nxpwifi_sta_event_ext_scan_report},
451 	{.event_cause = EVENT_RXBA_SYNC,
452 	.event_handler = nxpwifi_sta_event_rxba_sync},
453 	{.event_cause = EVENT_REMAIN_ON_CHAN_EXPIRED,
454 	.event_handler = nxpwifi_sta_event_remain_on_chan_expired},
455 	{.event_cause = EVENT_BG_SCAN_STOPPED,
456 	.event_handler = nxpwifi_sta_event_bg_scan_stopped},
457 	{.event_cause = EVENT_MULTI_CHAN_INFO,
458 	.event_handler = nxpwifi_sta_event_multi_chan_info},
459 	{.event_cause = EVENT_TX_STATUS_REPORT,
460 	.event_handler = nxpwifi_sta_event_tx_status_report},
461 	{.event_cause = EVENT_BT_COEX_WLAN_PARA_CHANGE,
462 	.event_handler = nxpwifi_sta_event_bt_coex_wlan_para_change},
463 	{.event_cause = EVENT_VDLL_IND,
464 	.event_handler = nxpwifi_sta_event_vdll_ind},
465 	{.event_cause = EVENT_DUMMY_HOST_WAKEUP_SIGNAL,
466 	.event_handler = NULL},
467 	{.event_cause = EVENT_MIB_CHANGED,
468 	.event_handler = NULL},
469 	{.event_cause = EVENT_INIT_DONE,
470 	.event_handler = NULL},
471 	{.event_cause = EVENT_SNR_LOW,
472 	.event_handler = NULL},
473 	{.event_cause = EVENT_MAX_FAIL,
474 	.event_handler = NULL},
475 	{.event_cause = EVENT_SNR_HIGH,
476 	.event_handler = NULL},
477 	{.event_cause = EVENT_DATA_RSSI_LOW,
478 	.event_handler = NULL},
479 	{.event_cause = EVENT_DATA_SNR_LOW,
480 	.event_handler = NULL},
481 	{.event_cause = EVENT_DATA_RSSI_HIGH,
482 	.event_handler = NULL},
483 	{.event_cause = EVENT_DATA_SNR_HIGH,
484 	.event_handler = NULL},
485 	{.event_cause = EVENT_LINK_QUALITY,
486 	.event_handler = NULL},
487 	{.event_cause = EVENT_PRE_BEACON_LOST,
488 	.event_handler = NULL},
489 	{.event_cause = EVENT_WEP_ICV_ERR,
490 	.event_handler = NULL},
491 	{.event_cause = EVENT_BW_CHANGE,
492 	.event_handler = NULL},
493 	{.event_cause = EVENT_HOSTWAKE_STAIE,
494 	.event_handler = NULL},
495 	{.event_cause = EVENT_UNKNOWN_DEBUG,
496 	.event_handler = NULL},
497 };
498 
nxpwifi_process_uap_tx_pause(struct nxpwifi_private * priv,struct nxpwifi_ie_types_header * tlv)499 static void nxpwifi_process_uap_tx_pause(struct nxpwifi_private *priv,
500 					 struct nxpwifi_ie_types_header *tlv)
501 {
502 	struct nxpwifi_tx_pause_tlv *tp;
503 	struct nxpwifi_sta_node *sta_ptr;
504 
505 	tp = (void *)tlv;
506 	nxpwifi_dbg(priv->adapter, EVENT,
507 		    "uap tx_pause: %pM pause=%d, pkts=%d\n",
508 		    tp->peermac, tp->tx_pause,
509 		    tp->pkt_cnt);
510 
511 	if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) {
512 		if (tp->tx_pause)
513 			priv->port_open = false;
514 		else
515 			priv->port_open = true;
516 	} else if (is_multicast_ether_addr(tp->peermac)) {
517 		nxpwifi_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
518 	} else {
519 		rcu_read_lock();
520 		sta_ptr = nxpwifi_get_sta_entry(priv, tp->peermac);
521 		if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
522 			sta_ptr->tx_pause = tp->tx_pause;
523 			nxpwifi_update_ralist_tx_pause(priv, tp->peermac,
524 						       tp->tx_pause);
525 		}
526 		rcu_read_unlock();
527 	}
528 }
529 
nxpwifi_process_sta_tx_pause(struct nxpwifi_private * priv,struct nxpwifi_ie_types_header * tlv)530 static void nxpwifi_process_sta_tx_pause(struct nxpwifi_private *priv,
531 					 struct nxpwifi_ie_types_header *tlv)
532 {
533 	struct nxpwifi_tx_pause_tlv *tp;
534 
535 	tp = (void *)tlv;
536 	nxpwifi_dbg(priv->adapter, EVENT,
537 		    "sta tx_pause: %pM pause=%d, pkts=%d\n",
538 		    tp->peermac, tp->tx_pause,
539 		    tp->pkt_cnt);
540 
541 	if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) {
542 		if (tp->tx_pause)
543 			priv->port_open = false;
544 		else
545 			priv->port_open = true;
546 	}
547 }
548 
549 /*
550  * Reset connection state after a firmware-triggered disconnect.
551  * Clears link state, queues, RSSI/SNR and security settings,
552  * saves previous SSID/BSSID for possible reassociation,
553  * and notifies cfg80211.
554  */
nxpwifi_reset_connect_state(struct nxpwifi_private * priv,u16 reason_code,bool from_ap)555 void nxpwifi_reset_connect_state(struct nxpwifi_private *priv, u16 reason_code,
556 				 bool from_ap)
557 {
558 	struct nxpwifi_adapter *adapter = priv->adapter;
559 
560 	if (!priv->media_connected)
561 		return;
562 
563 	nxpwifi_dbg(adapter, INFO,
564 		    "info: handles disconnect event\n");
565 
566 	priv->media_connected = false;
567 
568 	priv->auth_flag = 0;
569 	priv->auth_alg = WLAN_AUTH_NONE;
570 
571 	priv->scan_block = false;
572 	priv->port_open = false;
573 
574 	/* Free Tx and Rx packets, report disconnect to upper layer */
575 	nxpwifi_clean_txrx(priv);
576 
577 	/* Reset SNR/NF/RSSI values */
578 	priv->data_rssi_last = 0;
579 	priv->data_nf_last = 0;
580 	priv->data_rssi_avg = 0;
581 	priv->data_nf_avg = 0;
582 	priv->bcn_rssi_last = 0;
583 	priv->bcn_nf_last = 0;
584 	priv->bcn_rssi_avg = 0;
585 	priv->bcn_nf_avg = 0;
586 	priv->rxpd_rate = 0;
587 	priv->rxpd_htinfo = 0;
588 	priv->sec_info.wpa_enabled = false;
589 	priv->sec_info.wpa2_enabled = false;
590 	priv->wpa_ie_len = 0;
591 
592 	priv->sec_info.encryption_mode = 0;
593 
594 	/* Enable auto data rate */
595 	priv->is_data_rate_auto = true;
596 	priv->data_rate = 0;
597 
598 	priv->assoc_resp_ht_param = 0;
599 	priv->ht_param_present = false;
600 
601 	if ((GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA ||
602 	     GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) && priv->hist_data)
603 		nxpwifi_hist_data_reset(priv);
604 
605 	/*
606 	 * Memorize the previous SSID and BSSID so
607 	 * it could be used for re-assoc
608 	 */
609 
610 	nxpwifi_dbg(adapter, INFO,
611 		    "info: previous SSID=%s, SSID len=%u\n",
612 		    priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
613 
614 	nxpwifi_dbg(adapter, INFO,
615 		    "info: current SSID=%s, SSID len=%u\n",
616 		    priv->curr_bss_params.bss_descriptor.ssid.ssid,
617 		    priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
618 
619 	memcpy(&priv->prev_ssid,
620 	       &priv->curr_bss_params.bss_descriptor.ssid,
621 	       sizeof(struct cfg80211_ssid));
622 
623 	memcpy(priv->prev_bssid,
624 	       priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
625 
626 	/* Need to erase the current SSID and BSSID info */
627 	memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));
628 
629 	adapter->tx_lock_flag = false;
630 	adapter->pps_uapsd_mode = false;
631 
632 	if (test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags) &&
633 	    adapter->curr_cmd)
634 		return;
635 
636 	priv->media_connected = false;
637 	nxpwifi_dbg(adapter, MSG,
638 		    "info: successfully disconnected from %pM: reason code %d\n",
639 		    priv->cfg_bssid, reason_code);
640 
641 	if (priv->bss_mode == NL80211_IFTYPE_STATION) {
642 		if (adapter->host_mlme_link_lost)
643 			nxpwifi_host_mlme_disconnect(adapter->priv_link_lost,
644 						     reason_code, NULL);
645 		else
646 			cfg80211_disconnected(priv->netdev, reason_code, NULL,
647 					      0, !from_ap, GFP_KERNEL);
648 	}
649 	eth_zero_addr(priv->cfg_bssid);
650 
651 	nxpwifi_stop_net_dev_queue(priv->netdev, adapter);
652 	netif_carrier_off(priv->netdev);
653 
654 	if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))
655 		return;
656 
657 	nxpwifi_send_cmd(priv, HOST_CMD_GTK_REKEY_OFFLOAD_CFG,
658 			 HOST_ACT_GEN_REMOVE, 0, NULL, false);
659 }
660 
nxpwifi_reset_conn_state_work(struct wiphy * wiphy,struct wiphy_work * work)661 void nxpwifi_reset_conn_state_work(struct wiphy *wiphy, struct wiphy_work *work)
662 {
663 	struct nxpwifi_private *priv = container_of(work,
664 						    struct nxpwifi_private,
665 						    reset_conn_state_work);
666 
667 	nxpwifi_reset_connect_state(priv, priv->last_deauth_reason, true);
668 }
669 
nxpwifi_process_multi_chan_event(struct nxpwifi_private * priv,struct sk_buff * event_skb)670 void nxpwifi_process_multi_chan_event(struct nxpwifi_private *priv,
671 				      struct sk_buff *event_skb)
672 {
673 	struct nxpwifi_ie_types_multi_chan_info *chan_info;
674 	struct nxpwifi_ie_types_mc_group_info *grp_info;
675 	struct nxpwifi_adapter *adapter = priv->adapter;
676 	struct nxpwifi_ie_types_header *tlv;
677 	u16 tlv_buf_left, tlv_type, tlv_len;
678 	int intf_num, bss_type, bss_num, i;
679 	struct nxpwifi_private *intf_priv;
680 
681 	tlv_buf_left = event_skb->len - sizeof(u32);
682 	chan_info = (void *)event_skb->data + sizeof(u32);
683 
684 	if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO ||
685 	    tlv_buf_left < sizeof(struct nxpwifi_ie_types_multi_chan_info)) {
686 		nxpwifi_dbg(adapter, ERROR,
687 			    "unknown TLV in chan_info event\n");
688 		return;
689 	}
690 
691 	adapter->usb_mc_status = le16_to_cpu(chan_info->status);
692 	nxpwifi_dbg(adapter, EVENT, "multi chan operation %s\n",
693 		    adapter->usb_mc_status ? "started" : "over");
694 
695 	tlv_buf_left -= sizeof(struct nxpwifi_ie_types_multi_chan_info);
696 	tlv = (struct nxpwifi_ie_types_header *)chan_info->tlv_buffer;
697 
698 	while (tlv_buf_left >= (int)sizeof(struct nxpwifi_ie_types_header)) {
699 		tlv_type = le16_to_cpu(tlv->type);
700 		tlv_len  = le16_to_cpu(tlv->len);
701 		if ((sizeof(struct nxpwifi_ie_types_header) + tlv_len) >
702 		    tlv_buf_left) {
703 			nxpwifi_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t"
704 				    "tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
705 			break;
706 		}
707 		if (tlv_type != TLV_TYPE_MC_GROUP_INFO) {
708 			nxpwifi_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n",
709 				    tlv_type);
710 			break;
711 		}
712 
713 		grp_info = (struct nxpwifi_ie_types_mc_group_info *)tlv;
714 		intf_num = grp_info->intf_num;
715 		for (i = 0; i < intf_num; i++) {
716 			bss_type = grp_info->bss_type_numlist[i] >> 4;
717 			bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK;
718 			intf_priv = nxpwifi_get_priv_by_id(adapter, bss_num,
719 							   bss_type);
720 			if (!intf_priv) {
721 				nxpwifi_dbg(adapter, ERROR,
722 					    "Invalid bss_type bss_num\t"
723 					    "in multi channel event\n");
724 				continue;
725 			}
726 		}
727 
728 		tlv_buf_left -= sizeof(struct nxpwifi_ie_types_header) +
729 				tlv_len;
730 		tlv = (void *)((u8 *)tlv + tlv_len +
731 			       sizeof(struct nxpwifi_ie_types_header));
732 	}
733 }
734 
nxpwifi_process_tx_pause_event(struct nxpwifi_private * priv,struct sk_buff * event_skb)735 void nxpwifi_process_tx_pause_event(struct nxpwifi_private *priv,
736 				    struct sk_buff *event_skb)
737 {
738 	struct nxpwifi_ie_types_header *tlv;
739 	u16 tlv_type, tlv_len;
740 	int tlv_buf_left;
741 
742 	if (!priv->media_connected) {
743 		nxpwifi_dbg(priv->adapter, ERROR,
744 			    "tx_pause event while disconnected; bss_role=%d\n",
745 			    priv->bss_role);
746 		return;
747 	}
748 
749 	tlv_buf_left = event_skb->len - sizeof(u32);
750 	tlv = (void *)event_skb->data + sizeof(u32);
751 
752 	while (tlv_buf_left >= (int)sizeof(struct nxpwifi_ie_types_header)) {
753 		tlv_type = le16_to_cpu(tlv->type);
754 		tlv_len  = le16_to_cpu(tlv->len);
755 		if ((sizeof(struct nxpwifi_ie_types_header) + tlv_len) >
756 		    tlv_buf_left) {
757 			nxpwifi_dbg(priv->adapter, ERROR,
758 				    "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
759 				    tlv_len, tlv_buf_left);
760 			break;
761 		}
762 		if (tlv_type == TLV_TYPE_TX_PAUSE) {
763 			if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA)
764 				nxpwifi_process_sta_tx_pause(priv, tlv);
765 			else
766 				nxpwifi_process_uap_tx_pause(priv, tlv);
767 		}
768 
769 		tlv_buf_left -= sizeof(struct nxpwifi_ie_types_header) +
770 				tlv_len;
771 		tlv = (void *)((u8 *)tlv + tlv_len +
772 			       sizeof(struct nxpwifi_ie_types_header));
773 	}
774 }
775 
776 /*
777  * Handle BT coexistence event. Parse TLVs and update
778  * coexistence aggregation window and scan timing parameters.
779  */
nxpwifi_bt_coex_wlan_param_update_event(struct nxpwifi_private * priv,struct sk_buff * event_skb)780 void nxpwifi_bt_coex_wlan_param_update_event(struct nxpwifi_private *priv,
781 					     struct sk_buff *event_skb)
782 {
783 	struct nxpwifi_adapter *adapter = priv->adapter;
784 	struct nxpwifi_ie_types_header *tlv;
785 	struct nxpwifi_ie_types_btcoex_aggr_win_size *winsizetlv;
786 	struct nxpwifi_ie_types_btcoex_scan_time *scantlv;
787 	s32 len = event_skb->len - sizeof(u32);
788 	u8 *cur_ptr = event_skb->data + sizeof(u32);
789 	u16 tlv_type, tlv_len;
790 
791 	while (len >= sizeof(struct nxpwifi_ie_types_header)) {
792 		tlv = (struct nxpwifi_ie_types_header *)cur_ptr;
793 		tlv_len = le16_to_cpu(tlv->len);
794 		tlv_type = le16_to_cpu(tlv->type);
795 
796 		if ((tlv_len + sizeof(struct nxpwifi_ie_types_header)) > len)
797 			break;
798 		switch (tlv_type) {
799 		case TLV_BTCOEX_WL_AGGR_WINSIZE:
800 			winsizetlv =
801 			    (struct nxpwifi_ie_types_btcoex_aggr_win_size *)tlv;
802 			adapter->coex_win_size = winsizetlv->coex_win_size;
803 			adapter->coex_tx_win_size =
804 				winsizetlv->tx_win_size;
805 			adapter->coex_rx_win_size =
806 				winsizetlv->rx_win_size;
807 			nxpwifi_coex_ampdu_rxwinsize(adapter);
808 			nxpwifi_update_ampdu_txwinsize(adapter);
809 			break;
810 
811 		case TLV_BTCOEX_WL_SCANTIME:
812 			scantlv =
813 			    (struct nxpwifi_ie_types_btcoex_scan_time *)tlv;
814 			adapter->coex_scan = scantlv->coex_scan;
815 			adapter->coex_min_scan_time = le16_to_cpu(scantlv->min_scan_time);
816 			adapter->coex_max_scan_time = le16_to_cpu(scantlv->max_scan_time);
817 			break;
818 
819 		default:
820 			break;
821 		}
822 
823 		len -= tlv_len + sizeof(struct nxpwifi_ie_types_header);
824 		cur_ptr += tlv_len +
825 			sizeof(struct nxpwifi_ie_types_header);
826 	}
827 
828 	nxpwifi_dbg(adapter, INFO, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
829 		    adapter->coex_scan, adapter->coex_min_scan_time,
830 		    adapter->coex_win_size, adapter->coex_tx_win_size,
831 		    adapter->coex_rx_win_size);
832 }
833 
834 /*
835  * Dispatch station firmware event based on event_cause.
836  * Looks up the handler in the station event table and invokes it.
837  */
nxpwifi_process_sta_event(struct nxpwifi_private * priv)838 int nxpwifi_process_sta_event(struct nxpwifi_private *priv)
839 {
840 	struct nxpwifi_adapter *adapter = priv->adapter;
841 	u32 eventcause = adapter->event_cause;
842 	int evt, ret = 0;
843 
844 	for (evt = 0; evt < ARRAY_SIZE(evt_table_sta); evt++) {
845 		if (eventcause == evt_table_sta[evt].event_cause) {
846 			if (evt_table_sta[evt].event_handler)
847 				ret = evt_table_sta[evt].event_handler(priv);
848 			break;
849 		}
850 	}
851 
852 	if (evt == ARRAY_SIZE(evt_table_sta))
853 		nxpwifi_dbg(adapter, EVENT,
854 			    "%s: unknown event id: %#x\n",
855 			    __func__, eventcause);
856 	else
857 		nxpwifi_dbg(adapter, EVENT,
858 			    "%s: event id: %#x\n",
859 			    __func__, eventcause);
860 
861 	return ret;
862 }
863