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