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 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 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 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 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. */ 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 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 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. */ 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. */ 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 * 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 * 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 * 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 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 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. */ 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. */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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