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