xref: /linux/drivers/net/wireless/nxp/nxpwifi/util.c (revision d8674294aefef02266c4d47ad10131f1bffbe534)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * NXP Wireless LAN device driver: utility functions
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 #include <net/netlink.h>
16 #include <linux/mmc/sdio_ids.h>
17 #include <linux/mmc/sdio_func.h>
18 #include <linux/bitfield.h>
19 #include <net/ieee80211_radiotap.h>
20 
21 #define RX_RATE_FORMAT_MASK   GENMASK(1, 0)
22 #define RX_RATE_BW_MASK       GENMASK(3, 2)
23 #define RX_RATE_GI_MASK       BIT(4)
24 #define RX_RATE_STBC_MASK     BIT(5)
25 #define RX_RATE_LDPC_MASK     BIT(6)
26 
27 static struct nxpwifi_debug_data items[] = {
28 	{"debug_mask", item_size(debug_mask),
29 	 item_addr(debug_mask), 1},
30 	{"int_counter", item_size(int_counter),
31 	 item_addr(int_counter), 1},
32 	{"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]),
33 	 item_addr(packets_out[WMM_AC_VO]), 1},
34 	{"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]),
35 	 item_addr(packets_out[WMM_AC_VI]), 1},
36 	{"wmm_ac_be", item_size(packets_out[WMM_AC_BE]),
37 	 item_addr(packets_out[WMM_AC_BE]), 1},
38 	{"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]),
39 	 item_addr(packets_out[WMM_AC_BK]), 1},
40 	{"tx_buf_size", item_size(tx_buf_size),
41 	 item_addr(tx_buf_size), 1},
42 	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
43 	 item_addr(curr_tx_buf_size), 1},
44 	{"ps_mode", item_size(ps_mode),
45 	 item_addr(ps_mode), 1},
46 	{"ps_state", item_size(ps_state),
47 	 item_addr(ps_state), 1},
48 	{"is_deep_sleep", item_size(is_deep_sleep),
49 	 item_addr(is_deep_sleep), 1},
50 	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
51 	 item_addr(pm_wakeup_card_req), 1},
52 	{"wakeup_tries", item_size(pm_wakeup_fw_try),
53 	 item_addr(pm_wakeup_fw_try), 1},
54 	{"hs_configured", item_size(is_hs_configured),
55 	 item_addr(is_hs_configured), 1},
56 	{"hs_activated", item_size(hs_activated),
57 	 item_addr(hs_activated), 1},
58 	{"num_tx_timeout", item_size(num_tx_timeout),
59 	 item_addr(num_tx_timeout), 1},
60 	{"is_cmd_timedout", item_size(is_cmd_timedout),
61 	 item_addr(is_cmd_timedout), 1},
62 	{"timeout_cmd_id", item_size(timeout_cmd_id),
63 	 item_addr(timeout_cmd_id), 1},
64 	{"timeout_cmd_act", item_size(timeout_cmd_act),
65 	 item_addr(timeout_cmd_act), 1},
66 	{"last_cmd_id", item_size(last_cmd_id),
67 	 item_addr(last_cmd_id), DBG_CMD_NUM},
68 	{"last_cmd_act", item_size(last_cmd_act),
69 	 item_addr(last_cmd_act), DBG_CMD_NUM},
70 	{"last_cmd_index", item_size(last_cmd_index),
71 	 item_addr(last_cmd_index), 1},
72 	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
73 	 item_addr(last_cmd_resp_id), DBG_CMD_NUM},
74 	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
75 	 item_addr(last_cmd_resp_index), 1},
76 	{"last_event", item_size(last_event),
77 	 item_addr(last_event), DBG_CMD_NUM},
78 	{"last_event_index", item_size(last_event_index),
79 	 item_addr(last_event_index), 1},
80 	{"last_mp_wr_bitmap", item_size(last_mp_wr_bitmap),
81 	 item_addr(last_mp_wr_bitmap), NXPWIFI_DBG_SDIO_MP_NUM},
82 	{"last_mp_wr_ports", item_size(last_mp_wr_ports),
83 	 item_addr(last_mp_wr_ports), NXPWIFI_DBG_SDIO_MP_NUM},
84 	{"last_mp_wr_len", item_size(last_mp_wr_len),
85 	 item_addr(last_mp_wr_len), NXPWIFI_DBG_SDIO_MP_NUM},
86 	{"last_mp_curr_wr_port", item_size(last_mp_curr_wr_port),
87 	 item_addr(last_mp_curr_wr_port), NXPWIFI_DBG_SDIO_MP_NUM},
88 	{"last_sdio_mp_index", item_size(last_sdio_mp_index),
89 	 item_addr(last_sdio_mp_index), 1},
90 	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
91 	 item_addr(num_cmd_host_to_card_failure), 1},
92 	{"num_cmd_sleep_cfm_fail",
93 	 item_size(num_cmd_sleep_cfm_host_to_card_failure),
94 	 item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1},
95 	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
96 	 item_addr(num_tx_host_to_card_failure), 1},
97 	{"num_evt_deauth", item_size(num_event_deauth),
98 	 item_addr(num_event_deauth), 1},
99 	{"num_evt_disassoc", item_size(num_event_disassoc),
100 	 item_addr(num_event_disassoc), 1},
101 	{"num_evt_link_lost", item_size(num_event_link_lost),
102 	 item_addr(num_event_link_lost), 1},
103 	{"num_cmd_deauth", item_size(num_cmd_deauth),
104 	 item_addr(num_cmd_deauth), 1},
105 	{"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
106 	 item_addr(num_cmd_assoc_success), 1},
107 	{"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
108 	 item_addr(num_cmd_assoc_failure), 1},
109 	{"cmd_sent", item_size(cmd_sent),
110 	 item_addr(cmd_sent), 1},
111 	{"data_sent", item_size(data_sent),
112 	 item_addr(data_sent), 1},
113 	{"cmd_resp_received", item_size(cmd_resp_received),
114 	 item_addr(cmd_resp_received), 1},
115 	{"event_received", item_size(event_received),
116 	 item_addr(event_received), 1},
117 
118 	/* variables defined in struct nxpwifi_adapter */
119 	{"cmd_pending", adapter_item_size(cmd_pending),
120 	 adapter_item_addr(cmd_pending), 1},
121 	{"tx_pending", adapter_item_size(tx_pending),
122 	 adapter_item_addr(tx_pending), 1},
123 	{"rx_pending", adapter_item_size(rx_pending),
124 	 adapter_item_addr(rx_pending), 1},
125 };
126 
127 static int num_of_items = ARRAY_SIZE(items);
128 
129 /* Send init or shutdown command to firmware. */
130 int nxpwifi_init_shutdown_fw(struct nxpwifi_private *priv,
131 			     u32 func_init_shutdown)
132 {
133 	u16 cmd;
134 
135 	if (func_init_shutdown == NXPWIFI_FUNC_INIT) {
136 		cmd = HOST_CMD_FUNC_INIT;
137 	} else if (func_init_shutdown == NXPWIFI_FUNC_SHUTDOWN) {
138 		cmd = HOST_CMD_FUNC_SHUTDOWN;
139 	} else {
140 		nxpwifi_dbg(priv->adapter, ERROR,
141 			    "unsupported parameter\n");
142 		return -EINVAL;
143 	}
144 
145 	return nxpwifi_send_cmd(priv, cmd, HOST_ACT_GEN_SET, 0, NULL, true);
146 }
147 EXPORT_SYMBOL_GPL(nxpwifi_init_shutdown_fw);
148 
149 /* Handle IOCTL get/set of debug info across driver structures. */
150 int nxpwifi_get_debug_info(struct nxpwifi_private *priv,
151 			   struct nxpwifi_debug_info *info)
152 {
153 	struct nxpwifi_adapter *adapter = priv->adapter;
154 
155 	if (info) {
156 		info->debug_mask = adapter->debug_mask;
157 		memcpy(info->packets_out,
158 		       priv->wmm.packets_out,
159 		       sizeof(priv->wmm.packets_out));
160 		info->curr_tx_buf_size = (u32)adapter->curr_tx_buf_size;
161 		info->tx_buf_size = (u32)adapter->tx_buf_size;
162 		info->rx_tbl_num = nxpwifi_get_rx_reorder_tbl(priv,
163 							      info->rx_tbl);
164 		info->tx_tbl_num = nxpwifi_get_tx_ba_stream_tbl(priv,
165 								info->tx_tbl);
166 		info->ps_mode = adapter->ps_mode;
167 		info->ps_state = adapter->ps_state;
168 		info->is_deep_sleep = adapter->is_deep_sleep;
169 		info->pm_wakeup_card_req = adapter->pm_wakeup_card_req;
170 		info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try;
171 		info->is_hs_configured = test_bit(NXPWIFI_IS_HS_CONFIGURED,
172 						  &adapter->work_flags);
173 		info->hs_activated = adapter->hs_activated;
174 		info->is_cmd_timedout = test_bit(NXPWIFI_IS_CMD_TIMEDOUT,
175 						 &adapter->work_flags);
176 		info->num_cmd_host_to_card_failure =
177 			adapter->dbg.num_cmd_host_to_card_failure;
178 		info->num_cmd_sleep_cfm_host_to_card_failure =
179 			adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
180 		info->num_tx_host_to_card_failure =
181 			adapter->dbg.num_tx_host_to_card_failure;
182 		info->num_event_deauth = adapter->dbg.num_event_deauth;
183 		info->num_event_disassoc = adapter->dbg.num_event_disassoc;
184 		info->num_event_link_lost = adapter->dbg.num_event_link_lost;
185 		info->num_cmd_deauth = adapter->dbg.num_cmd_deauth;
186 		info->num_cmd_assoc_success =
187 			adapter->dbg.num_cmd_assoc_success;
188 		info->num_cmd_assoc_failure =
189 			adapter->dbg.num_cmd_assoc_failure;
190 		info->num_tx_timeout = adapter->dbg.num_tx_timeout;
191 		info->timeout_cmd_id = adapter->dbg.timeout_cmd_id;
192 		info->timeout_cmd_act = adapter->dbg.timeout_cmd_act;
193 		memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id,
194 		       sizeof(adapter->dbg.last_cmd_id));
195 		memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act,
196 		       sizeof(adapter->dbg.last_cmd_act));
197 		info->last_cmd_index = adapter->dbg.last_cmd_index;
198 		memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id,
199 		       sizeof(adapter->dbg.last_cmd_resp_id));
200 		info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index;
201 		memcpy(info->last_event, adapter->dbg.last_event,
202 		       sizeof(adapter->dbg.last_event));
203 		info->last_event_index = adapter->dbg.last_event_index;
204 		memcpy(info->last_mp_wr_bitmap, adapter->dbg.last_mp_wr_bitmap,
205 		       sizeof(adapter->dbg.last_mp_wr_bitmap));
206 		memcpy(info->last_mp_wr_ports, adapter->dbg.last_mp_wr_ports,
207 		       sizeof(adapter->dbg.last_mp_wr_ports));
208 		memcpy(info->last_mp_curr_wr_port,
209 		       adapter->dbg.last_mp_curr_wr_port,
210 		       sizeof(adapter->dbg.last_mp_curr_wr_port));
211 		memcpy(info->last_mp_wr_len, adapter->dbg.last_mp_wr_len,
212 		       sizeof(adapter->dbg.last_mp_wr_len));
213 		info->last_sdio_mp_index = adapter->dbg.last_sdio_mp_index;
214 		info->data_sent = adapter->data_sent;
215 		info->cmd_sent = adapter->cmd_sent;
216 		info->cmd_resp_received = adapter->cmd_resp_received;
217 	}
218 
219 	return 0;
220 }
221 
222 int nxpwifi_debug_info_to_buffer(struct nxpwifi_private *priv, char *buf,
223 				 size_t buf_size,
224 				 struct nxpwifi_debug_info *info)
225 {
226 	size_t used = 0;
227 	struct nxpwifi_debug_data *d = &items[0];
228 	size_t size, addr;
229 	long val;
230 	u32 tx_tbl_num, rx_tbl_num, win_size;
231 	int i, j;
232 
233 	if (!info)
234 		return 0;
235 
236 	tx_tbl_num = min_t(u32, info->tx_tbl_num, ARRAY_SIZE(info->tx_tbl));
237 	rx_tbl_num = min_t(u32, info->rx_tbl_num, ARRAY_SIZE(info->rx_tbl));
238 
239 	for (i = 0; i < num_of_items; i++) {
240 		used += scnprintf(buf + used, buf_size - used, "%s=", d[i].name);
241 
242 		size = d[i].size / d[i].num;
243 
244 		if (i < (num_of_items - 3))
245 			addr = d[i].addr + (size_t)info;
246 		else /* The last 3 items are struct nxpwifi_adapter variables */
247 			addr = d[i].addr + (size_t)priv->adapter;
248 
249 		for (j = 0; j < d[i].num; j++) {
250 			switch (size) {
251 			case 1:
252 				val = *((u8 *)addr);
253 				break;
254 			case 2:
255 				val = get_unaligned((u16 *)addr);
256 				break;
257 			case 4:
258 				val = get_unaligned((u32 *)addr);
259 				break;
260 			case 8:
261 				val = get_unaligned((long long *)addr);
262 				break;
263 			default:
264 				val = -1;
265 				break;
266 			}
267 
268 			used += scnprintf(buf + used, buf_size - used, "%#lx ", val);
269 			addr += size;
270 		}
271 
272 		used += scnprintf(buf + used, buf_size - used, "\n");
273 	}
274 
275 	if (tx_tbl_num) {
276 		used += scnprintf(buf + used, buf_size - used, "Tx BA stream table:\n");
277 		for (i = 0; i < tx_tbl_num; i++)
278 			used += scnprintf(buf + used, buf_size - used, "tid = %d, ra = %pM\n",
279 				     info->tx_tbl[i].tid, info->tx_tbl[i].ra);
280 	}
281 
282 	if (rx_tbl_num) {
283 		used += scnprintf(buf + used, buf_size - used, "Rx reorder table:\n");
284 		for (i = 0; i < rx_tbl_num; i++) {
285 			used += scnprintf(buf + used, buf_size - used, "tid = %d, ta = %pM, ",
286 				     info->rx_tbl[i].tid,
287 				     info->rx_tbl[i].ta);
288 			used += scnprintf(buf + used, buf_size - used, "start_win = %d, ",
289 				     info->rx_tbl[i].start_win);
290 			used += scnprintf(buf + used, buf_size - used, "win_size = %d, buffer: ",
291 				     info->rx_tbl[i].win_size);
292 
293 			win_size = min_t(u32, info->rx_tbl[i].win_size,
294 					 ARRAY_SIZE(info->rx_tbl[i].buffer));
295 			for (j = 0; j < win_size; j++)
296 				used += scnprintf(buf + used, buf_size - used, "%c ",
297 					     info->rx_tbl[i].buffer[j] ?
298 					     '1' : '0');
299 
300 			used += scnprintf(buf + used, buf_size - used, "\n");
301 		}
302 	}
303 
304 	return used;
305 }
306 
307 bool nxpwifi_is_channel_setting_allowable(struct nxpwifi_private *priv,
308 					  struct ieee80211_channel *check_chan)
309 {
310 	struct nxpwifi_adapter *adapter = priv->adapter;
311 	int i;
312 	struct nxpwifi_private *tmp_priv;
313 	u8 bss_role = GET_BSS_ROLE(priv);
314 	struct ieee80211_channel *set_chan;
315 
316 	for (i = 0; i < adapter->priv_num; i++) {
317 		tmp_priv = adapter->priv[i];
318 		if (tmp_priv == priv)
319 			continue;
320 
321 		set_chan = NULL;
322 		if (bss_role == NXPWIFI_BSS_ROLE_STA) {
323 			if (GET_BSS_ROLE(tmp_priv) == NXPWIFI_BSS_ROLE_UAP &&
324 			    netif_carrier_ok(tmp_priv->netdev) &&
325 			    cfg80211_chandef_valid(&tmp_priv->bss_chandef))
326 				set_chan = tmp_priv->bss_chandef.chan;
327 		} else if (bss_role == NXPWIFI_BSS_ROLE_UAP) {
328 			struct nxpwifi_current_bss_params *bss_params =
329 				&tmp_priv->curr_bss_params;
330 			int channel = bss_params->bss_descriptor.channel;
331 			enum nl80211_band band =
332 				nxpwifi_band_to_radio_type(bss_params->band);
333 			int freq =
334 				ieee80211_channel_to_frequency(channel, band);
335 
336 			if (GET_BSS_ROLE(tmp_priv) == NXPWIFI_BSS_ROLE_STA &&
337 			    tmp_priv->media_connected)
338 				set_chan = ieee80211_get_channel(adapter->wiphy, freq);
339 		}
340 
341 		if (set_chan && !ieee80211_channel_equal(check_chan, set_chan)) {
342 			nxpwifi_dbg(adapter, ERROR,
343 				    "AP/STA must run on the same channel\n");
344 			return false;
345 		}
346 	}
347 
348 	return true;
349 }
350 
351 void nxpwifi_convert_chan_to_band_cfg(struct nxpwifi_private *priv,
352 				      u8 *band_cfg,
353 				      struct cfg80211_chan_def *chan_def)
354 {
355 	u8 chan_band = 0, chan_width = 0, chan2_offset = 0;
356 
357 	switch (chan_def->chan->band) {
358 	case NL80211_BAND_2GHZ:
359 		chan_band = BAND_2GHZ;
360 		break;
361 	case NL80211_BAND_5GHZ:
362 		chan_band = BAND_5GHZ;
363 		break;
364 	default:
365 		break;
366 	}
367 
368 	switch (chan_def->width) {
369 	case NL80211_CHAN_WIDTH_20_NOHT:
370 	case NL80211_CHAN_WIDTH_20:
371 		chan_width = CHAN_BW_20MHZ;
372 		break;
373 	case NL80211_CHAN_WIDTH_40:
374 		chan_width = CHAN_BW_40MHZ;
375 		if (chan_def->center_freq1 > chan_def->chan->center_freq)
376 			chan2_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
377 		else
378 			chan2_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
379 		break;
380 	case NL80211_CHAN_WIDTH_80:
381 		chan2_offset =
382 			nxpwifi_get_sec_chan_offset(chan_def->chan->hw_value);
383 		chan_width = CHAN_BW_80MHZ;
384 		break;
385 	case NL80211_CHAN_WIDTH_80P80:
386 	case NL80211_CHAN_WIDTH_160:
387 	default:
388 		nxpwifi_dbg(priv->adapter,
389 			    WARN, "Unknown channel width: %d\n",
390 			    chan_def->width);
391 		break;
392 	}
393 
394 	*band_cfg = ((chan2_offset << BAND_CFG_CHAN2_SHIFT_BIT) &
395 		     BAND_CFG_CHAN2_OFFSET_MASK) |
396 		    ((chan_width << BAND_CFG_CHAN_WIDTH_SHIFT_BIT) &
397 		     BAND_CFG_CHAN_WIDTH_MASK) |
398 		    ((chan_band << BAND_CFG_CHAN_BAND_SHIFT_BIT) &
399 		     BAND_CFG_CHAN_BAND_MASK);
400 }
401 
402 static int
403 nxpwifi_parse_mgmt_packet(struct nxpwifi_private *priv, u8 *payload, u16 len,
404 			  struct rxpd *rx_pd)
405 {
406 	u16 stype;
407 	u8 category;
408 	struct ieee80211_hdr *ieee_hdr = (void *)payload;
409 
410 	stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
411 
412 	switch (stype) {
413 	case IEEE80211_STYPE_ACTION:
414 		category = *(payload + sizeof(struct ieee80211_hdr));
415 		switch (category) {
416 		case WLAN_CATEGORY_BACK:
417 			/*we dont indicate BACK action frames to cfg80211*/
418 			nxpwifi_dbg(priv->adapter, INFO,
419 				    "drop BACK action frames");
420 			return -EINVAL;
421 		default:
422 			nxpwifi_dbg(priv->adapter, INFO,
423 				    "unknown public action frame category %d\n",
424 				    category);
425 		}
426 		break;
427 	default:
428 		nxpwifi_dbg(priv->adapter, INFO,
429 			    "unknown mgmt frame subtype %#x\n", stype);
430 		return 0;
431 	}
432 
433 	return 0;
434 }
435 
436 /* Send deauth frame to cfg80211. */
437 void nxpwifi_host_mlme_disconnect(struct nxpwifi_private *priv,
438 				  u16 reason_code, u8 *sa)
439 {
440 	u8 frame_buf[100];
441 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)frame_buf;
442 
443 	memset(frame_buf, 0, sizeof(frame_buf));
444 	mgmt->frame_control = cpu_to_le16(IEEE80211_STYPE_DEAUTH);
445 	mgmt->duration = 0;
446 	mgmt->seq_ctrl = 0;
447 	mgmt->u.deauth.reason_code = cpu_to_le16(reason_code);
448 
449 	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA) {
450 		eth_broadcast_addr(mgmt->da);
451 		memcpy(mgmt->sa,
452 		       priv->curr_bss_params.bss_descriptor.mac_address,
453 		       ETH_ALEN);
454 		memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
455 		priv->auth_flag = 0;
456 		priv->auth_alg = WLAN_AUTH_NONE;
457 	} else {
458 		memcpy(mgmt->da, priv->curr_addr, ETH_ALEN);
459 		memcpy(mgmt->sa, sa, ETH_ALEN);
460 		memcpy(mgmt->bssid, priv->curr_addr, ETH_ALEN);
461 	}
462 
463 	if (GET_BSS_ROLE(priv) != NXPWIFI_BSS_ROLE_UAP) {
464 		cfg80211_rx_mlme_mgmt(priv->netdev, frame_buf, 26);
465 	} else {
466 		cfg80211_rx_mgmt(&priv->wdev,
467 				 priv->bss_chandef.chan->center_freq,
468 				 0, frame_buf, 26, 0);
469 	}
470 }
471 
472 /* Parse and forward received management packet to cfg80211. */
473 int
474 nxpwifi_process_mgmt_packet(struct nxpwifi_private *priv,
475 			    struct sk_buff *skb)
476 {
477 	struct nxpwifi_adapter *adapter = priv->adapter;
478 	struct rxpd *rx_pd;
479 	u16 pkt_len;
480 	struct ieee80211_hdr *ieee_hdr;
481 	int ret;
482 
483 	if (!skb)
484 		return -ENOMEM;
485 
486 	if (!priv->mgmt_frame_mask ||
487 	    priv->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
488 		nxpwifi_dbg(adapter, ERROR,
489 			    "do not receive mgmt frames on uninitialized intf");
490 		return -EINVAL;
491 	}
492 
493 	rx_pd = (struct rxpd *)skb->data;
494 	pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
495 	if (pkt_len < sizeof(struct ieee80211_hdr) + sizeof(pkt_len)) {
496 		nxpwifi_dbg(adapter, ERROR, "invalid rx_pkt_length");
497 		return -EINVAL;
498 	}
499 
500 	skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
501 	skb_pull(skb, sizeof(pkt_len));
502 	pkt_len -= sizeof(pkt_len);
503 
504 	ieee_hdr = (void *)skb->data;
505 	if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
506 		ret = nxpwifi_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
507 						pkt_len, rx_pd);
508 		if (ret)
509 			return ret;
510 	}
511 	/* Remove address4 */
512 	memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
513 		skb->data + sizeof(struct ieee80211_hdr),
514 		pkt_len - sizeof(struct ieee80211_hdr));
515 
516 	pkt_len -= ETH_ALEN;
517 	rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
518 
519 	if (priv->host_mlme_reg &&
520 	    (GET_BSS_ROLE(priv) != NXPWIFI_BSS_ROLE_UAP) &&
521 	    (ieee80211_is_auth(ieee_hdr->frame_control) ||
522 	     ieee80211_is_deauth(ieee_hdr->frame_control) ||
523 	     ieee80211_is_disassoc(ieee_hdr->frame_control))) {
524 		struct nxpwifi_rxinfo *rx_info;
525 
526 		if (ieee80211_is_auth(ieee_hdr->frame_control)) {
527 			if (priv->auth_flag & HOST_MLME_AUTH_PENDING) {
528 				if (priv->auth_alg != WLAN_AUTH_SAE) {
529 					priv->auth_flag &=
530 						~HOST_MLME_AUTH_PENDING;
531 					priv->auth_flag |=
532 						HOST_MLME_AUTH_DONE;
533 				}
534 			} else {
535 				return 0;
536 			}
537 
538 			nxpwifi_dbg(adapter, MSG,
539 				    "auth: receive authentication from %pM\n",
540 				    ieee_hdr->addr3);
541 		} else {
542 			if (!priv->wdev.connected)
543 				return 0;
544 
545 			if (ieee80211_is_deauth(ieee_hdr->frame_control)) {
546 				nxpwifi_dbg(adapter, MSG,
547 					    "auth: receive deauth from %pM\n",
548 					    ieee_hdr->addr3);
549 				priv->auth_flag = 0;
550 				priv->auth_alg = WLAN_AUTH_NONE;
551 			} else {
552 				nxpwifi_dbg(adapter, MSG,
553 					    "assoc: receive disassoc from %pM\n",
554 					    ieee_hdr->addr3);
555 			}
556 		}
557 
558 		rx_info = NXPWIFI_SKB_RXCB(skb);
559 		rx_info->pkt_len = pkt_len;
560 		skb_queue_tail(&adapter->rx_mlme_q, skb);
561 		nxpwifi_queue_wiphy_work(adapter, &adapter->host_mlme_work);
562 		return -EINPROGRESS;
563 	}
564 
565 	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) {
566 		if (ieee80211_is_auth(ieee_hdr->frame_control))
567 			nxpwifi_dbg(adapter, MSG,
568 				    "auth: receive auth from %pM\n",
569 				    ieee_hdr->addr2);
570 		if (ieee80211_is_deauth(ieee_hdr->frame_control))
571 			nxpwifi_dbg(adapter, MSG,
572 				    "auth: receive deauth from %pM\n",
573 				    ieee_hdr->addr2);
574 		if (ieee80211_is_disassoc(ieee_hdr->frame_control))
575 			nxpwifi_dbg(adapter, MSG,
576 				    "assoc: receive disassoc from %pM\n",
577 				    ieee_hdr->addr2);
578 		if (ieee80211_is_assoc_req(ieee_hdr->frame_control))
579 			nxpwifi_dbg(adapter, MSG,
580 				    "assoc: receive assoc req from %pM\n",
581 				    ieee_hdr->addr2);
582 		if (ieee80211_is_reassoc_req(ieee_hdr->frame_control))
583 			nxpwifi_dbg(adapter, MSG,
584 				    "assoc: receive reassoc req from %pM\n",
585 				    ieee_hdr->addr2);
586 	}
587 
588 	cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
589 			 CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len,
590 			 0);
591 
592 	return 0;
593 }
594 
595 #define RTAP_MAX_LEN 128
596 
597 int nxpwifi_recv_packet_to_monif(struct nxpwifi_private *priv,
598 				 struct sk_buff *skb)
599 {
600 	struct rxpd *rxpd;
601 	struct rxpd_extra_info ext;
602 	struct ieee80211_hdr *dot11;
603 	struct ieee80211_radiotap_header *hdr;
604 	int freq, band;
605 	bool has_ext = false, has_ts = false, use_tsft = false;
606 	u16 rx_flags = 0, off, chan_flags, rx_pkt_offset;
607 	__le16 freq_le, flags_le;
608 	u8 rthdr[RTAP_MAX_LEN] = {0};
609 	s8 signal, noise;
610 	u8 flags = 0, chan, ant, format, bw, gi, ldpc, mcs, nss, stbc;
611 
612 	if (!skb)
613 		return -EINVAL;
614 
615 	rxpd = (struct rxpd *)skb->data;
616 	rx_pkt_offset = le16_to_cpu(rxpd->rx_pkt_offset);
617 
618 	if (rx_pkt_offset > skb->len || rx_pkt_offset < sizeof(struct rxpd))
619 		return -EINVAL;
620 
621 	if (skb->len - rx_pkt_offset < sizeof(struct ieee80211_hdr))
622 		return -EINVAL;
623 
624 	has_ext = rxpd->flags & RXPD_FLAG_EXTRA_HEADER;
625 
626 	if (has_ext)
627 		memcpy((void *)&ext, (void *)(rxpd + 1), sizeof(ext));
628 
629 	dot11 = (void *)skb->data + rx_pkt_offset;
630 	memset(rthdr, 0, sizeof(rthdr));
631 	hdr = (void *)rthdr;
632 	hdr->it_version = 0;
633 	hdr->it_pad = 0;
634 	hdr->it_present = 0;
635 	off = sizeof(*hdr);
636 	hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_FLAGS));
637 
638 	if (has_ext) {
639 		has_ts = true;
640 		use_tsft = (ext.timestamp.position == 0);
641 
642 		if (has_ts) {
643 			if (use_tsft)
644 				hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_TSFT));
645 			else
646 				hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_TIMESTAMP));
647 		}
648 
649 		flags = ext.flags & ~IEEE80211_RADIOTAP_F_BADFCS;
650 		/* reverse fail fcs, 1 means pass FCS in FW,
651 		 * but means fail FCS in radiotap
652 		 */
653 		flags &= ~((~ext.flags) & IEEE80211_RADIOTAP_F_BADFCS);
654 
655 		if (ext.plcp_crc_failed)
656 			rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
657 	}
658 
659 	if (has_ts && use_tsft) {
660 		off = ALIGN(off, 8);
661 		memcpy(rthdr + off, &ext.timestamp.device_timestamp, 8);
662 		off += 8;
663 	}
664 
665 	if (ieee80211_has_morefrags(dot11->frame_control))
666 		flags |= IEEE80211_RADIOTAP_F_FRAG;
667 
668 	if (ieee80211_has_protected(dot11->frame_control))
669 		flags |= IEEE80211_RADIOTAP_F_WEP;
670 
671 	rthdr[off++] = flags;
672 	off = ALIGN(off, 2);
673 	hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_CHANNEL));
674 	chan = (le32_to_cpu(rxpd->rx_info) >> 5) & 0xff;
675 	band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
676 	freq = ieee80211_channel_to_frequency(chan, band);
677 
678 	if (has_ext)
679 		chan_flags = ext.channel_flags;
680 	else if (band == NL80211_BAND_2GHZ)
681 		chan_flags = IEEE80211_CHAN_2GHZ;
682 	else
683 		chan_flags = IEEE80211_CHAN_5GHZ;
684 
685 	freq_le  = cpu_to_le16(freq);
686 	flags_le = cpu_to_le16(chan_flags);
687 	memcpy(rthdr + off, &freq_le, 2);
688 	off += 2;
689 	memcpy(rthdr + off, &flags_le, 2);
690 	off += 2;
691 	hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL));
692 	signal = -(rxpd->nf - rxpd->snr);
693 	rthdr[off++] = signal;
694 	hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_DBM_ANTNOISE));
695 	noise = -rxpd->nf;
696 	rthdr[off++] = noise;
697 	hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_ANTENNA));
698 	ant = rxpd->antenna >> 1;
699 	rthdr[off++] = ant;
700 
701 	if (rx_flags) {
702 		hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_RX_FLAGS));
703 		off = ALIGN(off, 2);
704 		memcpy(rthdr + off, &rx_flags, 2);
705 		off += 2;
706 	}
707 
708 	format = FIELD_GET(RX_RATE_FORMAT_MASK, rxpd->rate_info);
709 	bw = FIELD_GET(RX_RATE_BW_MASK, rxpd->rate_info);
710 	ldpc = FIELD_GET(RX_RATE_LDPC_MASK, rxpd->rate_info) ? 1 : 0;
711 	stbc = FIELD_GET(RX_RATE_STBC_MASK, rxpd->rate_info) ? 1 : 0;
712 
713 	if (format == NXPWIFI_RATE_FORMAT_HE) {
714 		gi = ((rxpd->rate_info >> 7) & 0x1) << 1 |
715 			((rxpd->rate_info >> 4) & 0x1);
716 	} else {
717 		gi = FIELD_GET(RX_RATE_GI_MASK, rxpd->rate_info);
718 	}
719 
720 	mcs = rxpd->rx_rate & 0xf;
721 	nss = ((rxpd->rx_rate >> 4) & 0xf) + 1;
722 
723 	if (format == NXPWIFI_RATE_FORMAT_HT) {
724 		u8 mcs_flags = 0;
725 
726 		hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_MCS));
727 		rthdr[off++] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
728 					IEEE80211_RADIOTAP_MCS_HAVE_BW |
729 					IEEE80211_RADIOTAP_MCS_HAVE_GI;
730 
731 		if (bw == 1)
732 			mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_40;
733 
734 		if (gi)
735 			mcs_flags |= IEEE80211_RADIOTAP_MCS_SGI;
736 
737 		if (ldpc)
738 			mcs_flags |= IEEE80211_RADIOTAP_MCS_FEC_LDPC;
739 
740 		if (stbc)
741 			mcs_flags |= (1 << IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
742 
743 		rthdr[off++] = mcs_flags;
744 		rthdr[off++] = mcs;
745 	}
746 
747 	if (format == NXPWIFI_RATE_FORMAT_VHT && has_ext) {
748 		struct ieee80211_radiotap_vht vht = {0};
749 		u32 vht_sig1 = 0, vht_sig2 = 0;
750 		__le16 partial_aid = 0;
751 		u8 bw_field = 0;
752 
753 		vht_sig1 = ext.vht_he_sig1;
754 		vht_sig2 = ext.vht_he_sig2;
755 		hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_VHT));
756 		vht.known = cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
757 					IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH |
758 					IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
759 					IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED |
760 					IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID);
761 
762 		if (stbc)
763 			vht.flags |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
764 
765 		if (gi)
766 			vht.flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
767 
768 		if (vht_sig2 & BIT(1))
769 			vht.flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9;
770 
771 		if (vht_sig2 & BIT(8))
772 			vht.flags |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
773 
774 		switch (bw) {
775 		case 1:
776 			bw_field = 1; /* 40 MHz */
777 			break;
778 		case 2:
779 			bw_field = 4; /* 80 MHz */
780 			break;
781 		case 3:
782 			bw_field = 11; /* 160 MHz */
783 			break;
784 		default:
785 			bw_field = 0; /* 20 MHz */
786 		}
787 
788 		vht.bandwidth = bw_field;
789 		vht.mcs_nss[0] = (nss & 0xf) | (mcs << 4);
790 
791 		if (vht_sig2 & BIT(2))
792 			vht.coding |= IEEE80211_RADIOTAP_CODING_LDPC_USER0;
793 
794 		vht.group_id = (vht_sig1 >> 4) & 0x3f;
795 		memcpy(&vht.partial_aid, &partial_aid, 2);
796 		off = ALIGN(off, 2);
797 		memcpy(rthdr + off, &vht, sizeof(vht));
798 		off += sizeof(vht);
799 	}
800 
801 	/* TIMESTAMP */
802 	if (has_ts && !use_tsft) {
803 		u64 ts;
804 		__le64 ts_le;
805 		u16 accuracy = 0;
806 		__le16 acc_le;
807 		u8 flags = 0;
808 
809 		hdr->it_present |=
810 			cpu_to_le32(BIT(IEEE80211_RADIOTAP_TIMESTAMP));
811 		off = ALIGN(off, 8);
812 
813 		if (ext.timestamp.flags & 0x01) {
814 			flags |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT;
815 			ts = (u32)ext.timestamp.device_timestamp;
816 		} else {
817 			flags |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT;
818 			ts = ext.timestamp.device_timestamp;
819 		}
820 
821 		ts_le = cpu_to_le64(ts);
822 		memcpy(rthdr + off, &ts_le, sizeof(ts_le));
823 		off += sizeof(ts_le);
824 
825 		if (ext.timestamp.flags & 0x02) {
826 			accuracy = ext.timestamp.accuracy;
827 			flags |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY;
828 		}
829 
830 		acc_le = cpu_to_le16(accuracy);
831 		memcpy(rthdr + off, &acc_le, sizeof(acc_le));
832 		off += sizeof(acc_le);
833 		rthdr[off++] = (ext.timestamp.unit & 0x0f) |
834 				((ext.timestamp.position & 0x0f) << 4);
835 		rthdr[off++] = flags;
836 	}
837 
838 	if (format == NXPWIFI_RATE_FORMAT_HE && has_ext) {
839 		struct ieee80211_radiotap_he he = {0};
840 		u16 data1 = 0, data2 = 0, data3 = 0, data5 = 0, data6 = 0;
841 		u8 bw_val = 0;
842 
843 		memcpy((void *)&ext, (void *)(rxpd + 1), sizeof(ext));
844 
845 		off = ALIGN(off, 2);
846 		hdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE));
847 		data1 |= IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN;
848 		data1 |= IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN;
849 		data1 |= IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN;
850 		data1 |= IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN;
851 		data2 |= IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN;
852 		data3 = mcs << 8;
853 		data3 |= FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS, mcs);
854 
855 		if (stbc)
856 			data3 |= IEEE80211_RADIOTAP_HE_DATA3_STBC;
857 
858 		switch (bw) {
859 		case 0:
860 			bw_val |= IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ;
861 			break;
862 		case 1:
863 			bw_val |= IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ;
864 			break;
865 		case 2:
866 			bw_val |= IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ;
867 			break;
868 		case 3:
869 			bw_val |= IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ;
870 			break;
871 		}
872 
873 		data5 |= FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC,
874 						    bw_val);
875 
876 		switch (gi) {
877 		case 0:
878 			data5 |= IEEE80211_RADIOTAP_HE_DATA5_GI_0_8;
879 			break;
880 		case 1:
881 			data5 |= IEEE80211_RADIOTAP_HE_DATA5_GI_1_6;
882 			break;
883 		case 2:
884 			data5 |= IEEE80211_RADIOTAP_HE_DATA5_GI_3_2;
885 			break;
886 		}
887 
888 		data6 |= FIELD_PREP(IEEE80211_RADIOTAP_HE_DATA6_NSTS, nss);
889 		he.data1 = cpu_to_le16(data1);
890 		he.data2 = cpu_to_le16(data2);
891 		he.data3 = cpu_to_le16(data3);
892 		he.data5 = cpu_to_le16(data5);
893 		he.data6 = cpu_to_le16(data6);
894 		memcpy(rthdr + off, &he, sizeof(he));
895 		off += sizeof(he);
896 	}
897 
898 	hdr->it_len = cpu_to_le16(off);
899 
900 	if (off > sizeof(rthdr))
901 		return -EINVAL;
902 
903 	/* Remove RXPD */
904 	skb_pull(skb, rx_pkt_offset);
905 
906 	/* Ensure enough headroom */
907 	if (skb_cow_head(skb, off))
908 		return -ENOMEM;
909 
910 	/* Push radiotap header */
911 	skb_push(skb, off);
912 	memcpy(skb->data, rthdr, off);
913 	skb_reset_mac_header(skb);
914 	skb->ip_summed = CHECKSUM_NONE;
915 	skb->pkt_type  = PACKET_OTHERHOST;
916 	skb->dev       = priv->netdev;
917 	skb->protocol  = htons(ETH_P_802_2);
918 	netif_rx(skb);
919 	return 0;
920 }
921 
922 /* Process received packet and pass to net stack; reuse or build skb as needed. */
923 int nxpwifi_recv_packet(struct nxpwifi_private *priv, struct sk_buff *skb)
924 {
925 	struct nxpwifi_sta_node *src_node;
926 	struct ethhdr *p_ethhdr;
927 
928 	if (!skb)
929 		return -ENOMEM;
930 
931 	priv->stats.rx_bytes += skb->len;
932 	priv->stats.rx_packets++;
933 
934 	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) {
935 		p_ethhdr = (void *)skb->data;
936 		rcu_read_lock();
937 		src_node = nxpwifi_get_sta_entry(priv, p_ethhdr->h_source);
938 		if (src_node) {
939 			src_node->stats.last_rx = jiffies;
940 			src_node->stats.rx_bytes += skb->len;
941 			src_node->stats.rx_packets++;
942 		}
943 		rcu_read_unlock();
944 	}
945 
946 	skb->dev = priv->netdev;
947 	skb->protocol = eth_type_trans(skb, priv->netdev);
948 	skb->ip_summed = CHECKSUM_NONE;
949 
950 	netif_rx(skb);
951 	return 0;
952 }
953 
954 /* IOCTL completion callback: wake waiters or process response as needed. */
955 int nxpwifi_complete_cmd(struct nxpwifi_adapter *adapter,
956 			 struct cmd_ctrl_node *cmd_node)
957 {
958 	WARN_ON(!cmd_node->wait_q_enabled);
959 	nxpwifi_dbg(adapter, CMD, "cmd completed: status=%d\n",
960 		    adapter->cmd_wait_q.status);
961 
962 	*cmd_node->condition = true;
963 	wake_up_interruptible(&adapter->cmd_wait_q.wait);
964 
965 	return 0;
966 }
967 
968 /* Find STA entry by MAC under rcu_read_lock(); return NULL if not found. */
969 struct nxpwifi_sta_node *
970 nxpwifi_get_sta_entry(struct nxpwifi_private *priv, const u8 *mac)
971 {
972 	struct nxpwifi_sta_node *node;
973 	struct nxpwifi_sta_node *found = NULL;
974 
975 	if (!mac)
976 		return NULL;
977 	list_for_each_entry_rcu(node, &priv->sta_list, list) {
978 		if (!memcmp(node->mac_addr, mac, ETH_ALEN)) {
979 			found = node;
980 			break;
981 		}
982 	}
983 
984 	return found;
985 }
986 
987 struct nxpwifi_sta_node *
988 nxpwifi_get_sta_entry_rcu(struct nxpwifi_private *priv, const u8 *mac)
989 {
990 	struct nxpwifi_sta_node *node;
991 
992 	rcu_read_lock();
993 	node = nxpwifi_get_sta_entry(priv, mac);
994 	rcu_read_unlock();
995 
996 	return node;
997 }
998 
999 /* Add STA entry by MAC; return existing entry or NULL on invalid MAC. */
1000 struct nxpwifi_sta_node *
1001 nxpwifi_add_sta_entry(struct nxpwifi_private *priv, const u8 *mac)
1002 {
1003 	struct nxpwifi_sta_node *node;
1004 
1005 	if (!mac)
1006 		return NULL;
1007 
1008 	spin_lock_bh(&priv->sta_list_spinlock);
1009 	node = nxpwifi_get_sta_entry_rcu(priv, mac);
1010 
1011 	if (node)
1012 		goto done;
1013 
1014 	node = kzalloc_obj(*node, GFP_ATOMIC);
1015 	if (!node)
1016 		goto done;
1017 
1018 	memcpy(node->mac_addr, mac, ETH_ALEN);
1019 	list_add_tail_rcu(&node->list, &priv->sta_list);
1020 
1021 done:
1022 	spin_unlock_bh(&priv->sta_list_spinlock);
1023 	return node;
1024 }
1025 
1026 /* Parse HT cap IE from association IEs and set STA HT parameters. */
1027 void
1028 nxpwifi_set_sta_ht_cap(struct nxpwifi_private *priv, const u8 *ies,
1029 		       int ies_len, struct nxpwifi_sta_node *node)
1030 {
1031 	struct element *ht_cap_ie;
1032 	const struct ieee80211_ht_cap *ht_cap;
1033 
1034 	if (!ies)
1035 		return;
1036 
1037 	ht_cap_ie = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies,
1038 					     ies_len);
1039 	if (ht_cap_ie) {
1040 		ht_cap = (void *)(ht_cap_ie + 1);
1041 		node->is_11n_enabled = 1;
1042 		node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
1043 				  IEEE80211_HT_CAP_MAX_AMSDU ?
1044 				  NXPWIFI_TX_DATA_BUF_SIZE_8K :
1045 				  NXPWIFI_TX_DATA_BUF_SIZE_4K;
1046 	} else {
1047 		node->is_11n_enabled = 0;
1048 	}
1049 }
1050 
1051 /* Delete a station from list. */
1052 
1053 void nxpwifi_del_sta_entry(struct nxpwifi_private *priv, const u8 *mac)
1054 {
1055 	struct nxpwifi_sta_node *node;
1056 
1057 	spin_lock_bh(&priv->sta_list_spinlock);
1058 
1059 	list_for_each_entry(node, &priv->sta_list, list) {
1060 		if (!memcmp(node->mac_addr, mac, ETH_ALEN)) {
1061 			list_del_rcu(&node->list);
1062 			kfree_rcu(node, rcu);
1063 			break;
1064 		}
1065 	}
1066 
1067 	spin_unlock_bh(&priv->sta_list_spinlock);
1068 }
1069 
1070 /* Delete all stations from list. */
1071 void nxpwifi_del_all_sta_list(struct nxpwifi_private *priv)
1072 {
1073 	struct nxpwifi_sta_node *node, *tmp;
1074 
1075 	spin_lock_bh(&priv->sta_list_spinlock);
1076 
1077 	list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
1078 		list_del_rcu(&node->list);
1079 		kfree_rcu(node, rcu);
1080 	}
1081 
1082 	INIT_LIST_HEAD(&priv->sta_list);
1083 	spin_unlock_bh(&priv->sta_list_spinlock);
1084 }
1085 
1086 /* Add one histogram sample. */
1087 void nxpwifi_hist_data_add(struct nxpwifi_private *priv,
1088 			   u8 rx_rate, s8 snr, s8 nflr)
1089 {
1090 	struct nxpwifi_histogram_data *phist_data = priv->hist_data;
1091 
1092 	if (atomic_read(&phist_data->num_samples) > NXPWIFI_HIST_MAX_SAMPLES)
1093 		nxpwifi_hist_data_reset(priv);
1094 	nxpwifi_hist_data_set(priv, rx_rate, snr, nflr);
1095 }
1096 
1097 /* function to add histogram record */
1098 void nxpwifi_hist_data_set(struct nxpwifi_private *priv, u8 rx_rate, s8 snr,
1099 			   s8 nflr)
1100 {
1101 	struct nxpwifi_histogram_data *phist_data = priv->hist_data;
1102 	s8 nf   = -nflr;
1103 	s8 rssi = snr - nflr;
1104 
1105 	atomic_inc(&phist_data->num_samples);
1106 	atomic_inc(&phist_data->rx_rate[rx_rate]);
1107 	atomic_inc(&phist_data->snr[snr + 128]);
1108 	atomic_inc(&phist_data->noise_flr[nf + 128]);
1109 	atomic_inc(&phist_data->sig_str[rssi + 128]);
1110 }
1111 
1112 /* function to reset histogram data during init/reset */
1113 void nxpwifi_hist_data_reset(struct nxpwifi_private *priv)
1114 {
1115 	int ix;
1116 	struct nxpwifi_histogram_data *phist_data = priv->hist_data;
1117 
1118 	atomic_set(&phist_data->num_samples, 0);
1119 	for (ix = 0; ix < NXPWIFI_MAX_AC_RX_RATES; ix++)
1120 		atomic_set(&phist_data->rx_rate[ix], 0);
1121 	for (ix = 0; ix < NXPWIFI_MAX_SNR; ix++)
1122 		atomic_set(&phist_data->snr[ix], 0);
1123 	for (ix = 0; ix < NXPWIFI_MAX_NOISE_FLR; ix++)
1124 		atomic_set(&phist_data->noise_flr[ix], 0);
1125 	for (ix = 0; ix < NXPWIFI_MAX_SIG_STRENGTH; ix++)
1126 		atomic_set(&phist_data->sig_str[ix], 0);
1127 }
1128 
1129 void *nxpwifi_alloc_dma_align_buf(int rx_len, gfp_t flags)
1130 {
1131 	struct sk_buff *skb;
1132 	int buf_len, pad;
1133 
1134 	buf_len = rx_len + NXPWIFI_RX_HEADROOM + NXPWIFI_DMA_ALIGN_SZ;
1135 
1136 	skb = __dev_alloc_skb(buf_len, flags);
1137 
1138 	if (!skb)
1139 		return NULL;
1140 
1141 	skb_reserve(skb, NXPWIFI_RX_HEADROOM);
1142 
1143 	pad = NXPWIFI_ALIGN_ADDR(skb->data, NXPWIFI_DMA_ALIGN_SZ) -
1144 	      (long)skb->data;
1145 
1146 	skb_reserve(skb, pad);
1147 
1148 	return skb;
1149 }
1150 EXPORT_SYMBOL_GPL(nxpwifi_alloc_dma_align_buf);
1151 
1152 void nxpwifi_fw_dump_event(struct nxpwifi_private *priv)
1153 {
1154 	nxpwifi_send_cmd(priv, HOST_CMD_FW_DUMP_EVENT, HOST_ACT_GEN_SET,
1155 			 0, NULL, true);
1156 }
1157 EXPORT_SYMBOL_GPL(nxpwifi_fw_dump_event);
1158 
1159 int nxpwifi_append_data_tlv(u16 id, u8 *data, int len, u8 *pos, u8 *cmd_end)
1160 {
1161 	struct nxpwifi_ie_types_data *tlv;
1162 	u16 header_len = sizeof(struct nxpwifi_ie_types_header);
1163 
1164 	tlv = (struct nxpwifi_ie_types_data *)pos;
1165 	tlv->header.len = cpu_to_le16(len);
1166 
1167 	if (id == WLAN_EID_EXT_HE_CAPABILITY) {
1168 		if ((pos + header_len + len + 1) > cmd_end)
1169 			return 0;
1170 
1171 		tlv->header.type = cpu_to_le16(WLAN_EID_EXTENSION);
1172 		tlv->data[0] = WLAN_EID_EXT_HE_CAPABILITY;
1173 		memcpy(tlv->data + 1, data, len);
1174 	} else {
1175 		if ((pos + header_len + len) > cmd_end)
1176 			return 0;
1177 
1178 		tlv->header.type = cpu_to_le16(id);
1179 		memcpy(tlv->data, data, len);
1180 	}
1181 
1182 	return (header_len + len);
1183 }
1184 
1185 static int nxpwifi_get_vdll_image(struct nxpwifi_adapter *adapter, u32 vdll_len)
1186 {
1187 	struct vdll_dnld_ctrl *ctrl = &adapter->vdll_ctrl;
1188 	bool req_fw = false;
1189 	u32 offset;
1190 
1191 	if (ctrl->vdll_mem) {
1192 		nxpwifi_dbg(adapter, EVENT,
1193 			    "VDLL mem is not empty: %p old_len=%d new_len=%d\n",
1194 			    ctrl->vdll_mem, ctrl->vdll_len, vdll_len);
1195 		vfree(ctrl->vdll_mem);
1196 		ctrl->vdll_mem = NULL;
1197 		ctrl->vdll_len = 0;
1198 	}
1199 
1200 	ctrl->vdll_mem = vmalloc(vdll_len);
1201 	if (!ctrl->vdll_mem)
1202 		return -ENOMEM;
1203 
1204 	if (!adapter->firmware) {
1205 		req_fw = true;
1206 		if (request_firmware(&adapter->firmware, adapter->fw_name,
1207 				     adapter->dev))
1208 			return -ENOENT;
1209 	}
1210 
1211 	if (adapter->firmware) {
1212 		if (vdll_len < adapter->firmware->size) {
1213 			offset = adapter->firmware->size - vdll_len;
1214 			memcpy(ctrl->vdll_mem, adapter->firmware->data + offset,
1215 			       vdll_len);
1216 		} else {
1217 			nxpwifi_dbg(adapter, ERROR,
1218 				    "Invalid VDLL length = %d, fw_len=%d\n",
1219 				    vdll_len, (int)adapter->firmware->size);
1220 			return -EINVAL;
1221 		}
1222 		if (req_fw) {
1223 			release_firmware(adapter->firmware);
1224 			adapter->firmware = NULL;
1225 		}
1226 	}
1227 
1228 	ctrl->vdll_len = vdll_len;
1229 	nxpwifi_dbg(adapter, MSG, "VDLL image: len=%d\n", ctrl->vdll_len);
1230 
1231 	return 0;
1232 }
1233 
1234 int nxpwifi_download_vdll_block(struct nxpwifi_adapter *adapter,
1235 				u8 *block, u16 block_len)
1236 {
1237 	struct vdll_dnld_ctrl *ctrl = &adapter->vdll_ctrl;
1238 	struct host_cmd_ds_command *host_cmd;
1239 	u16 msg_len = block_len + S_DS_GEN;
1240 	int ret = 0;
1241 
1242 	skb_trim(ctrl->skb, 0);
1243 	skb_put_zero(ctrl->skb, msg_len);
1244 
1245 	host_cmd = (struct host_cmd_ds_command *)(ctrl->skb->data);
1246 
1247 	host_cmd->command = cpu_to_le16(HOST_CMD_VDLL);
1248 	host_cmd->seq_num = cpu_to_le16(0xFF00);
1249 	host_cmd->size = cpu_to_le16(msg_len);
1250 	memcpy(ctrl->skb->data + S_DS_GEN, block, block_len);
1251 
1252 	skb_push(ctrl->skb, adapter->intf_hdr_len);
1253 	ret = adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_VDLL,
1254 					   ctrl->skb, NULL);
1255 	skb_pull(ctrl->skb, adapter->intf_hdr_len);
1256 
1257 	if (ret)
1258 		nxpwifi_dbg(adapter, ERROR,
1259 			    "Fail to download VDLL: block: %p, len: %d\n",
1260 			    block, block_len);
1261 
1262 	return ret;
1263 }
1264 
1265 int nxpwifi_process_vdll_event(struct nxpwifi_private *priv,
1266 			       struct sk_buff *skb)
1267 {
1268 	struct nxpwifi_adapter *adapter = priv->adapter;
1269 	struct vdll_ind_event *vdll_evt =
1270 		(struct vdll_ind_event *)(skb->data + sizeof(u32));
1271 	u16 type = le16_to_cpu(vdll_evt->type);
1272 	u16 vdll_id = le16_to_cpu(vdll_evt->vdll_id);
1273 	u32 offset = le32_to_cpu(vdll_evt->offset);
1274 	u16 block_len = le16_to_cpu(vdll_evt->block_len);
1275 	struct vdll_dnld_ctrl *ctrl = &adapter->vdll_ctrl;
1276 	int ret = 0;
1277 
1278 	switch (type) {
1279 	case VDLL_IND_TYPE_REQ:
1280 		nxpwifi_dbg(adapter, EVENT,
1281 			    "VDLL IND (REG): ID: %d, offset: %#x, len: %d\n",
1282 			    vdll_id, offset, block_len);
1283 		if (offset <= ctrl->vdll_len) {
1284 			block_len =
1285 				min((u32)block_len, ctrl->vdll_len - offset);
1286 			if (!adapter->cmd_sent) {
1287 				ret = nxpwifi_download_vdll_block(adapter,
1288 								  ctrl->vdll_mem
1289 								  + offset,
1290 								  block_len);
1291 				if (ret)
1292 					nxpwifi_dbg(adapter, ERROR,
1293 						    "Download VDLL failed\n");
1294 			} else {
1295 				nxpwifi_dbg(adapter, EVENT,
1296 					    "Delay download VDLL block\n");
1297 				ctrl->pending_block_len = block_len;
1298 				ctrl->pending_block = ctrl->vdll_mem + offset;
1299 			}
1300 		} else {
1301 			nxpwifi_dbg(adapter, ERROR,
1302 				    "Err Req: offset=%#x, len=%d, vdll_len=%d\n",
1303 				    offset, block_len, ctrl->vdll_len);
1304 			ret = -EINVAL;
1305 		}
1306 		break;
1307 	case VDLL_IND_TYPE_OFFSET:
1308 		nxpwifi_dbg(adapter, EVENT,
1309 			    "VDLL IND (OFFSET): offset: %#x\n", offset);
1310 		ret = nxpwifi_get_vdll_image(adapter, offset);
1311 		break;
1312 	case VDLL_IND_TYPE_ERR_SIG:
1313 	case VDLL_IND_TYPE_ERR_ID:
1314 	case VDLL_IND_TYPE_SEC_ERR_ID:
1315 		nxpwifi_dbg(adapter, ERROR, "VDLL IND: error: %d\n", type);
1316 		break;
1317 	case VDLL_IND_TYPE_INTF_RESET:
1318 		nxpwifi_dbg(adapter, EVENT, "VDLL IND: interface reset\n");
1319 		break;
1320 	default:
1321 		nxpwifi_dbg(adapter, ERROR, "VDLL IND: unknown type: %d", type);
1322 		ret = -EINVAL;
1323 		break;
1324 	}
1325 
1326 	return ret;
1327 }
1328 
1329 u64 nxpwifi_roc_cookie(struct nxpwifi_adapter *adapter)
1330 {
1331 	adapter->roc_cookie_counter++;
1332 
1333 	/* wow, you wrapped 64 bits ... more likely a bug */
1334 	if (WARN_ON(adapter->roc_cookie_counter == 0))
1335 		adapter->roc_cookie_counter++;
1336 
1337 	return adapter->roc_cookie_counter;
1338 }
1339 
1340 static bool nxpwifi_can_queue_work(struct nxpwifi_adapter *adapter)
1341 {
1342 	if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags) ||
1343 	    test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags) ||
1344 	    test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) {
1345 		nxpwifi_dbg(adapter, WARN,
1346 			    "queueing nxpwifi work while going to suspend\n");
1347 		return false;
1348 	}
1349 
1350 	return true;
1351 }
1352 
1353 void nxpwifi_queue_work(struct nxpwifi_adapter *adapter,
1354 			struct work_struct *work)
1355 {
1356 	if (!nxpwifi_can_queue_work(adapter))
1357 		return;
1358 
1359 	queue_work(adapter->workqueue, work);
1360 }
1361 EXPORT_SYMBOL(nxpwifi_queue_work);
1362 
1363 void nxpwifi_queue_delayed_work(struct nxpwifi_adapter *adapter,
1364 				struct delayed_work *dwork,
1365 				unsigned long delay)
1366 {
1367 	if (!nxpwifi_can_queue_work(adapter))
1368 		return;
1369 
1370 	queue_delayed_work(adapter->workqueue, dwork, delay);
1371 }
1372 EXPORT_SYMBOL(nxpwifi_queue_delayed_work);
1373 
1374 void nxpwifi_queue_wiphy_work(struct nxpwifi_adapter *adapter,
1375 			      struct wiphy_work *work)
1376 {
1377 	if (!nxpwifi_can_queue_work(adapter))
1378 		return;
1379 
1380 	wiphy_work_queue(adapter->wiphy, work);
1381 }
1382 
1383 void nxpwifi_queue_delayed_wiphy_work(struct nxpwifi_adapter *adapter,
1384 				      struct wiphy_delayed_work *dwork,
1385 				      unsigned long delay)
1386 {
1387 	if (!nxpwifi_can_queue_work(adapter))
1388 		return;
1389 
1390 	wiphy_delayed_work_queue(adapter->wiphy, dwork, delay);
1391 }
1392