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