1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * nxpwifi: station command handling 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 "11ac.h" 16 #include "11ax.h" 17 18 static bool disable_auto_ds; 19 20 static int 21 nxpwifi_cmd_sta_get_hw_spec(struct nxpwifi_private *priv, 22 struct host_cmd_ds_command *cmd, 23 u16 cmd_no, void *data_buf, 24 u16 cmd_action, u32 cmd_type) 25 { 26 struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec; 27 28 cmd->command = cpu_to_le16(HOST_CMD_GET_HW_SPEC); 29 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + 30 S_DS_GEN); 31 memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); 32 33 return 0; 34 } 35 36 static int 37 nxpwifi_ret_sta_get_hw_spec(struct nxpwifi_private *priv, 38 struct host_cmd_ds_command *resp, 39 u16 cmdresp_no, 40 void *data_buf) 41 { 42 struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; 43 struct nxpwifi_adapter *adapter = priv->adapter; 44 struct nxpwifi_ie_types_header *tlv; 45 struct hw_spec_api_rev *api_rev; 46 struct hw_spec_max_conn *max_conn; 47 struct hw_spec_extension *hw_he_cap; 48 struct hw_spec_fw_cap_info *fw_cap; 49 struct hw_spec_secure_boot_uuid *sb_uuid; 50 u16 resp_size, api_id; 51 int i, left_len, parsed_len = 0; 52 53 adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); 54 55 if (IS_SUPPORT_MULTI_BANDS(adapter)) 56 adapter->fw_bands = GET_FW_DEFAULT_BANDS(adapter); 57 else 58 adapter->fw_bands = BAND_B; 59 60 if ((adapter->fw_bands & BAND_A) && (adapter->fw_bands & BAND_GN)) 61 adapter->fw_bands |= BAND_AN; 62 if (!(adapter->fw_bands & BAND_G) && (adapter->fw_bands & BAND_GN)) 63 adapter->fw_bands &= ~BAND_GN; 64 65 adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); 66 adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; 67 adapter->number_of_antenna = 68 le16_to_cpu(hw_spec->number_of_antenna) & 0xf; 69 70 if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { 71 adapter->is_hw_11ac_capable = true; 72 73 /* Copy 11AC cap */ 74 adapter->hw_dot_11ac_dev_cap = 75 le32_to_cpu(hw_spec->dot_11ac_dev_cap); 76 adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap 77 & ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK; 78 adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap 79 & ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK; 80 81 /* Copy 11AC mcs */ 82 adapter->hw_dot_11ac_mcs_support = 83 le32_to_cpu(hw_spec->dot_11ac_mcs_support); 84 adapter->usr_dot_11ac_mcs_support = 85 adapter->hw_dot_11ac_mcs_support; 86 } else { 87 adapter->is_hw_11ac_capable = false; 88 } 89 90 resp_size = le16_to_cpu(resp->size) - S_DS_GEN; 91 if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) { 92 /* we have variable HW SPEC information */ 93 left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec); 94 while (left_len > sizeof(struct nxpwifi_ie_types_header)) { 95 tlv = (void *)&hw_spec->tlv + parsed_len; 96 switch (le16_to_cpu(tlv->type)) { 97 case TLV_TYPE_API_REV: 98 api_rev = (struct hw_spec_api_rev *)tlv; 99 api_id = le16_to_cpu(api_rev->api_id); 100 switch (api_id) { 101 case KEY_API_VER_ID: 102 adapter->key_api_major_ver = 103 api_rev->major_ver; 104 adapter->key_api_minor_ver = 105 api_rev->minor_ver; 106 nxpwifi_dbg(adapter, INFO, 107 "key_api v%d.%d\n", 108 adapter->key_api_major_ver, 109 adapter->key_api_minor_ver); 110 break; 111 case FW_API_VER_ID: 112 adapter->fw_api_ver = 113 api_rev->major_ver; 114 nxpwifi_dbg(adapter, MSG, 115 "Firmware api version %d.%d\n", 116 adapter->fw_api_ver, 117 api_rev->minor_ver); 118 break; 119 case UAP_FW_API_VER_ID: 120 nxpwifi_dbg(adapter, INFO, 121 "uAP api version %d.%d\n", 122 api_rev->major_ver, 123 api_rev->minor_ver); 124 break; 125 case CHANRPT_API_VER_ID: 126 nxpwifi_dbg(adapter, INFO, 127 "channel report api version %d.%d\n", 128 api_rev->major_ver, 129 api_rev->minor_ver); 130 break; 131 case FW_HOTFIX_VER_ID: 132 adapter->fw_hotfix_ver = 133 api_rev->major_ver; 134 nxpwifi_dbg(adapter, INFO, 135 "Firmware hotfix version %d\n", 136 api_rev->major_ver); 137 break; 138 default: 139 nxpwifi_dbg(adapter, FATAL, 140 "Unknown api_id: %d\n", 141 api_id); 142 break; 143 } 144 break; 145 case TLV_TYPE_MAX_CONN: 146 max_conn = (struct hw_spec_max_conn *)tlv; 147 adapter->max_sta_conn = max_conn->max_sta_conn; 148 nxpwifi_dbg(adapter, INFO, 149 "max sta connections: %u\n", 150 adapter->max_sta_conn); 151 break; 152 case TLV_TYPE_EXTENSION_ID: 153 hw_he_cap = (struct hw_spec_extension *)tlv; 154 if (hw_he_cap->ext_id == 155 WLAN_EID_EXT_HE_CAPABILITY) 156 nxpwifi_update_11ax_cap(adapter, hw_he_cap); 157 break; 158 case TLV_TYPE_FW_CAP_INFO: 159 fw_cap = (struct hw_spec_fw_cap_info *)tlv; 160 adapter->fw_cap_info = 161 le32_to_cpu(fw_cap->fw_cap_info); 162 adapter->fw_cap_ext = 163 le32_to_cpu(fw_cap->fw_cap_ext); 164 nxpwifi_dbg(adapter, INFO, 165 "fw_cap_info:%#x fw_cap_ext:%#x\n", 166 adapter->fw_cap_info, 167 adapter->fw_cap_ext); 168 break; 169 case TLV_TYPE_SECURE_BOOT_UUID: 170 sb_uuid = (struct hw_spec_secure_boot_uuid *)tlv; 171 adapter->uuid_lo = 172 le64_to_cpu(sb_uuid->uuid_lo); 173 adapter->uuid_hi = 174 le64_to_cpu(sb_uuid->uuid_hi); 175 nxpwifi_dbg(adapter, INFO, 176 "uuid: %#llx%#llx\n", 177 adapter->uuid_lo, adapter->uuid_hi); 178 break; 179 default: 180 nxpwifi_dbg(adapter, FATAL, 181 "Unknown GET_HW_SPEC TLV type: %#x\n", 182 le16_to_cpu(tlv->type)); 183 break; 184 } 185 parsed_len += le16_to_cpu(tlv->len) + 186 sizeof(struct nxpwifi_ie_types_header); 187 left_len -= le16_to_cpu(tlv->len) + 188 sizeof(struct nxpwifi_ie_types_header); 189 } 190 } 191 192 if (adapter->key_api_major_ver < KEY_API_VER_MAJOR_V2) 193 return -EOPNOTSUPP; 194 195 nxpwifi_dbg(adapter, INFO, 196 "info: GET_HW_SPEC: fw_release_number- %#x\n", 197 adapter->fw_release_number); 198 nxpwifi_dbg(adapter, INFO, 199 "info: GET_HW_SPEC: permanent addr: %pM\n", 200 hw_spec->permanent_addr); 201 nxpwifi_dbg(adapter, INFO, 202 "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n", 203 le16_to_cpu(hw_spec->hw_if_version), 204 le16_to_cpu(hw_spec->version)); 205 206 ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr); 207 adapter->region_code = le16_to_cpu(hw_spec->region_code); 208 209 /* If it's unidentified region code, use the default (USA/FCC) */ 210 if (!nxpwifi_is_valid_region_code(adapter->region_code)) { 211 nxpwifi_dbg(adapter, WARN, 212 "cmd: unknown region code %#x, use default (USA/%#x)\n", 213 adapter->region_code, NXPWIFI_DEFAULT_REGION_CODE); 214 adapter->region_code = NXPWIFI_DEFAULT_REGION_CODE; 215 } 216 217 adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); 218 adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; 219 adapter->hw_mpdu_density = GET_MPDU_DENSITY(le32_to_cpu(hw_spec->hw_dev_cap)); 220 adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support; 221 adapter->user_htstream = adapter->hw_dev_mcs_support; 222 if (adapter->fw_bands & BAND_A) 223 adapter->user_htstream |= (adapter->user_htstream << 8); 224 225 if (adapter->if_ops.update_mp_end_port) { 226 u16 mp_end_port; 227 228 mp_end_port = le16_to_cpu(hw_spec->mp_end_port); 229 adapter->if_ops.update_mp_end_port(adapter, mp_end_port); 230 } 231 232 if (adapter->fw_api_ver == NXPWIFI_FW_V15) 233 adapter->scan_chan_gap_enabled = true; 234 235 for (i = 0; i < adapter->priv_num; i++) 236 adapter->priv[i]->config_bands = adapter->fw_bands; 237 238 return 0; 239 } 240 241 static int 242 nxpwifi_cmd_sta_802_11_scan(struct nxpwifi_private *priv, 243 struct host_cmd_ds_command *cmd, 244 u16 cmd_no, void *data_buf, 245 u16 cmd_action, u32 cmd_type) 246 { 247 return nxpwifi_cmd_802_11_scan(cmd, data_buf); 248 } 249 250 static int 251 nxpwifi_ret_sta_802_11_scan(struct nxpwifi_private *priv, 252 struct host_cmd_ds_command *resp, 253 u16 cmdresp_no, 254 void *data_buf) 255 { 256 struct nxpwifi_adapter *adapter = priv->adapter; 257 int ret; 258 259 ret = nxpwifi_ret_802_11_scan(priv, resp); 260 adapter->curr_cmd->wait_q_enabled = false; 261 262 return ret; 263 } 264 265 static int 266 nxpwifi_cmd_sta_802_11_get_log(struct nxpwifi_private *priv, 267 struct host_cmd_ds_command *cmd, 268 u16 cmd_no, void *data_buf, 269 u16 cmd_action, u32 cmd_type) 270 { 271 cmd->command = cpu_to_le16(HOST_CMD_802_11_GET_LOG); 272 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + 273 S_DS_GEN); 274 275 return 0; 276 } 277 278 static int 279 nxpwifi_ret_sta_802_11_get_log(struct nxpwifi_private *priv, 280 struct host_cmd_ds_command *resp, 281 u16 cmdresp_no, 282 void *data_buf) 283 { 284 struct host_cmd_ds_802_11_get_log *get_log = 285 &resp->params.get_log; 286 struct nxpwifi_ds_get_stats *stats = 287 (struct nxpwifi_ds_get_stats *)data_buf; 288 289 if (stats) { 290 stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); 291 stats->failed = le32_to_cpu(get_log->failed); 292 stats->retry = le32_to_cpu(get_log->retry); 293 stats->multi_retry = le32_to_cpu(get_log->multi_retry); 294 stats->frame_dup = le32_to_cpu(get_log->frame_dup); 295 stats->rts_success = le32_to_cpu(get_log->rts_success); 296 stats->rts_failure = le32_to_cpu(get_log->rts_failure); 297 stats->ack_failure = le32_to_cpu(get_log->ack_failure); 298 stats->rx_frag = le32_to_cpu(get_log->rx_frag); 299 stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); 300 stats->fcs_error = le32_to_cpu(get_log->fcs_error); 301 stats->tx_frame = le32_to_cpu(get_log->tx_frame); 302 stats->wep_icv_error[0] = 303 le32_to_cpu(get_log->wep_icv_err_cnt[0]); 304 stats->wep_icv_error[1] = 305 le32_to_cpu(get_log->wep_icv_err_cnt[1]); 306 stats->wep_icv_error[2] = 307 le32_to_cpu(get_log->wep_icv_err_cnt[2]); 308 stats->wep_icv_error[3] = 309 le32_to_cpu(get_log->wep_icv_err_cnt[3]); 310 stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt); 311 stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt); 312 } 313 314 return 0; 315 } 316 317 static int 318 nxpwifi_cmd_sta_mac_multicast_adr(struct nxpwifi_private *priv, 319 struct host_cmd_ds_command *cmd, 320 u16 cmd_no, void *data_buf, 321 u16 cmd_action, u32 cmd_type) 322 { 323 struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr; 324 struct nxpwifi_multicast_list *mcast_list = 325 (struct nxpwifi_multicast_list *)data_buf; 326 327 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + 328 S_DS_GEN); 329 cmd->command = cpu_to_le16(HOST_CMD_MAC_MULTICAST_ADR); 330 331 mcast_addr->action = cpu_to_le16(cmd_action); 332 mcast_addr->num_of_adrs = 333 cpu_to_le16((u16)mcast_list->num_multicast_addr); 334 memcpy(mcast_addr->mac_list, mcast_list->mac_list, 335 mcast_list->num_multicast_addr * ETH_ALEN); 336 337 return 0; 338 } 339 340 static int 341 nxpwifi_cmd_sta_802_11_associate(struct nxpwifi_private *priv, 342 struct host_cmd_ds_command *cmd, 343 u16 cmd_no, void *data_buf, 344 u16 cmd_action, u32 cmd_type) 345 { 346 return nxpwifi_cmd_802_11_associate(priv, cmd, data_buf); 347 } 348 349 static int 350 nxpwifi_ret_sta_802_11_associate(struct nxpwifi_private *priv, 351 struct host_cmd_ds_command *resp, 352 u16 cmdresp_no, 353 void *data_buf) 354 { 355 return nxpwifi_ret_802_11_associate(priv, resp); 356 } 357 358 static int 359 nxpwifi_cmd_sta_802_11_snmp_mib(struct nxpwifi_private *priv, 360 struct host_cmd_ds_command *cmd, 361 u16 cmd_no, void *data_buf, 362 u16 cmd_action, u32 cmd_type) 363 { 364 struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; 365 u16 *ul_temp = (u16 *)data_buf; 366 367 nxpwifi_dbg(priv->adapter, CMD, 368 "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_type); 369 cmd->command = cpu_to_le16(HOST_CMD_802_11_SNMP_MIB); 370 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) 371 + S_DS_GEN); 372 373 snmp_mib->oid = cpu_to_le16((u16)cmd_type); 374 if (cmd_action == HOST_ACT_GEN_GET) { 375 snmp_mib->query_type = cpu_to_le16(HOST_ACT_GEN_GET); 376 snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); 377 le16_unaligned_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE); 378 } else if (cmd_action == HOST_ACT_GEN_SET) { 379 snmp_mib->query_type = cpu_to_le16(HOST_ACT_GEN_SET); 380 snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); 381 put_unaligned_le16(*ul_temp, snmp_mib->value); 382 le16_unaligned_add_cpu(&cmd->size, sizeof(u16)); 383 } 384 385 nxpwifi_dbg(priv->adapter, CMD, 386 "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t" 387 "OIDSize=0x%x, Value=0x%x\n", 388 cmd_action, cmd_type, le16_to_cpu(snmp_mib->buf_size), 389 get_unaligned_le16(snmp_mib->value)); 390 391 return 0; 392 } 393 394 static int 395 nxpwifi_ret_sta_802_11_snmp_mib(struct nxpwifi_private *priv, 396 struct host_cmd_ds_command *resp, 397 u16 cmdresp_no, 398 void *data_buf) 399 { 400 struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; 401 u16 oid = le16_to_cpu(smib->oid); 402 u16 query_type = le16_to_cpu(smib->query_type); 403 u32 ul_temp; 404 405 nxpwifi_dbg(priv->adapter, INFO, 406 "info: SNMP_RESP: oid value = %#x,\t" 407 "query_type = %#x, buf size = %#x\n", 408 oid, query_type, le16_to_cpu(smib->buf_size)); 409 if (query_type == HOST_ACT_GEN_GET) { 410 ul_temp = get_unaligned_le16(smib->value); 411 if (data_buf) 412 *(u32 *)data_buf = ul_temp; 413 switch (oid) { 414 case FRAG_THRESH_I: 415 nxpwifi_dbg(priv->adapter, INFO, 416 "info: SNMP_RESP: FragThsd =%u\n", 417 ul_temp); 418 break; 419 case RTS_THRESH_I: 420 nxpwifi_dbg(priv->adapter, INFO, 421 "info: SNMP_RESP: RTSThsd =%u\n", 422 ul_temp); 423 break; 424 case SHORT_RETRY_LIM_I: 425 nxpwifi_dbg(priv->adapter, INFO, 426 "info: SNMP_RESP: TxRetryCount=%u\n", 427 ul_temp); 428 break; 429 case DTIM_PERIOD_I: 430 nxpwifi_dbg(priv->adapter, INFO, 431 "info: SNMP_RESP: DTIM period=%u\n", 432 ul_temp); 433 break; 434 default: 435 break; 436 } 437 } 438 439 return 0; 440 } 441 442 static int nxpwifi_cmd_sta_reg_access(struct nxpwifi_private *priv, 443 struct host_cmd_ds_command *cmd, 444 u16 cmd_no, void *data_buf, 445 u16 cmd_action, u32 cmd_type) 446 { 447 struct nxpwifi_ds_reg_rw *reg_rw = data_buf; 448 449 cmd->command = cpu_to_le16(cmd_no); 450 451 switch (cmd_no) { 452 case HOST_CMD_MAC_REG_ACCESS: 453 { 454 struct host_cmd_ds_mac_reg_access *mac_reg; 455 456 cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); 457 mac_reg = &cmd->params.mac_reg; 458 mac_reg->action = cpu_to_le16(cmd_action); 459 mac_reg->offset = cpu_to_le16((u16)reg_rw->offset); 460 mac_reg->value = cpu_to_le32(reg_rw->value); 461 break; 462 } 463 case HOST_CMD_BBP_REG_ACCESS: 464 { 465 struct host_cmd_ds_bbp_reg_access *bbp_reg; 466 467 cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); 468 bbp_reg = &cmd->params.bbp_reg; 469 bbp_reg->action = cpu_to_le16(cmd_action); 470 bbp_reg->offset = cpu_to_le16((u16)reg_rw->offset); 471 bbp_reg->value = (u8)reg_rw->value; 472 break; 473 } 474 case HOST_CMD_RF_REG_ACCESS: 475 { 476 struct host_cmd_ds_rf_reg_access *rf_reg; 477 478 cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); 479 rf_reg = &cmd->params.rf_reg; 480 rf_reg->action = cpu_to_le16(cmd_action); 481 rf_reg->offset = cpu_to_le16((u16)reg_rw->offset); 482 rf_reg->value = (u8)reg_rw->value; 483 break; 484 } 485 case HOST_CMD_PMIC_REG_ACCESS: 486 { 487 struct host_cmd_ds_pmic_reg_access *pmic_reg; 488 489 cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); 490 pmic_reg = &cmd->params.pmic_reg; 491 pmic_reg->action = cpu_to_le16(cmd_action); 492 pmic_reg->offset = cpu_to_le16((u16)reg_rw->offset); 493 pmic_reg->value = (u8)reg_rw->value; 494 break; 495 } 496 case HOST_CMD_CAU_REG_ACCESS: 497 { 498 struct host_cmd_ds_rf_reg_access *cau_reg; 499 500 cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); 501 cau_reg = &cmd->params.rf_reg; 502 cau_reg->action = cpu_to_le16(cmd_action); 503 cau_reg->offset = cpu_to_le16((u16)reg_rw->offset); 504 cau_reg->value = (u8)reg_rw->value; 505 break; 506 } 507 case HOST_CMD_802_11_EEPROM_ACCESS: 508 { 509 struct nxpwifi_ds_read_eeprom *rd_eeprom = data_buf; 510 struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom = 511 &cmd->params.eeprom; 512 513 cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); 514 cmd_eeprom->action = cpu_to_le16(cmd_action); 515 cmd_eeprom->offset = cpu_to_le16(rd_eeprom->offset); 516 cmd_eeprom->byte_count = cpu_to_le16(rd_eeprom->byte_count); 517 cmd_eeprom->value = 0; 518 break; 519 } 520 default: 521 return -EINVAL; 522 } 523 524 return 0; 525 } 526 527 static int 528 nxpwifi_ret_sta_reg_access(struct nxpwifi_private *priv, 529 struct host_cmd_ds_command *resp, 530 u16 cmdresp_no, 531 void *data_buf) 532 { 533 struct nxpwifi_ds_reg_rw *reg_rw; 534 struct nxpwifi_ds_read_eeprom *eeprom; 535 union reg { 536 struct host_cmd_ds_mac_reg_access *mac; 537 struct host_cmd_ds_bbp_reg_access *bbp; 538 struct host_cmd_ds_rf_reg_access *rf; 539 struct host_cmd_ds_pmic_reg_access *pmic; 540 struct host_cmd_ds_802_11_eeprom_access *eeprom; 541 } r; 542 543 if (!data_buf) 544 return 0; 545 546 reg_rw = data_buf; 547 eeprom = data_buf; 548 switch (cmdresp_no) { 549 case HOST_CMD_MAC_REG_ACCESS: 550 r.mac = &resp->params.mac_reg; 551 reg_rw->offset = (u32)le16_to_cpu(r.mac->offset); 552 reg_rw->value = le32_to_cpu(r.mac->value); 553 break; 554 case HOST_CMD_BBP_REG_ACCESS: 555 r.bbp = &resp->params.bbp_reg; 556 reg_rw->offset = (u32)le16_to_cpu(r.bbp->offset); 557 reg_rw->value = (u32)r.bbp->value; 558 break; 559 560 case HOST_CMD_RF_REG_ACCESS: 561 r.rf = &resp->params.rf_reg; 562 reg_rw->offset = (u32)le16_to_cpu(r.rf->offset); 563 reg_rw->value = (u32)r.bbp->value; 564 break; 565 case HOST_CMD_PMIC_REG_ACCESS: 566 r.pmic = &resp->params.pmic_reg; 567 reg_rw->offset = (u32)le16_to_cpu(r.pmic->offset); 568 reg_rw->value = (u32)r.pmic->value; 569 break; 570 case HOST_CMD_CAU_REG_ACCESS: 571 r.rf = &resp->params.rf_reg; 572 reg_rw->offset = (u32)le16_to_cpu(r.rf->offset); 573 reg_rw->value = (u32)r.rf->value; 574 break; 575 case HOST_CMD_802_11_EEPROM_ACCESS: 576 r.eeprom = &resp->params.eeprom; 577 pr_debug("info: EEPROM read len=%x\n", 578 le16_to_cpu(r.eeprom->byte_count)); 579 if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) { 580 eeprom->byte_count = 0; 581 pr_debug("info: EEPROM read length is too big\n"); 582 return -ENOMEM; 583 } 584 eeprom->offset = le16_to_cpu(r.eeprom->offset); 585 eeprom->byte_count = le16_to_cpu(r.eeprom->byte_count); 586 if (eeprom->byte_count > 0) 587 memcpy(&eeprom->value, &r.eeprom->value, 588 min((u16)MAX_EEPROM_DATA, eeprom->byte_count)); 589 break; 590 default: 591 return -EINVAL; 592 } 593 return 0; 594 } 595 596 static int 597 nxpwifi_cmd_sta_rf_tx_pwr(struct nxpwifi_private *priv, 598 struct host_cmd_ds_command *cmd, 599 u16 cmd_no, void *data_buf, 600 u16 cmd_action, u32 cmd_type) 601 { 602 struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp; 603 604 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr) 605 + S_DS_GEN); 606 cmd->command = cpu_to_le16(HOST_CMD_RF_TX_PWR); 607 txp->action = cpu_to_le16(cmd_action); 608 609 return 0; 610 } 611 612 static int 613 nxpwifi_ret_sta_rf_tx_pwr(struct nxpwifi_private *priv, 614 struct host_cmd_ds_command *resp, 615 u16 cmdresp_no, 616 void *data_buf) 617 { 618 struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp; 619 u16 action = le16_to_cpu(txp->action); 620 621 priv->tx_power_level = le16_to_cpu(txp->cur_level); 622 623 if (action == HOST_ACT_GEN_GET) { 624 priv->max_tx_power_level = txp->max_power; 625 priv->min_tx_power_level = txp->min_power; 626 } 627 628 nxpwifi_dbg(priv->adapter, INFO, 629 "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n", 630 priv->tx_power_level, priv->max_tx_power_level, 631 priv->min_tx_power_level); 632 633 return 0; 634 } 635 636 static int 637 nxpwifi_cmd_sta_rf_antenna(struct nxpwifi_private *priv, 638 struct host_cmd_ds_command *cmd, 639 u16 cmd_no, void *data_buf, 640 u16 cmd_action, u32 cmd_type) 641 { 642 struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo; 643 struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso; 644 struct nxpwifi_ds_ant_cfg *ant_cfg = 645 (struct nxpwifi_ds_ant_cfg *)data_buf; 646 647 cmd->command = cpu_to_le16(HOST_CMD_RF_ANTENNA); 648 649 switch (cmd_action) { 650 case HOST_ACT_GEN_SET: 651 if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) { 652 cmd->size = cpu_to_le16(sizeof(struct 653 host_cmd_ds_rf_ant_mimo) 654 + S_DS_GEN); 655 ant_mimo->action_tx = cpu_to_le16(HOST_ACT_SET_TX); 656 ant_mimo->tx_ant_mode = 657 cpu_to_le16((u16)ant_cfg->tx_ant); 658 ant_mimo->action_rx = cpu_to_le16(HOST_ACT_SET_RX); 659 ant_mimo->rx_ant_mode = 660 cpu_to_le16((u16)ant_cfg->rx_ant); 661 } else { 662 cmd->size = cpu_to_le16(sizeof(struct 663 host_cmd_ds_rf_ant_siso) + 664 S_DS_GEN); 665 ant_siso->action = cpu_to_le16(HOST_ACT_SET_BOTH); 666 ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant); 667 } 668 break; 669 case HOST_ACT_GEN_GET: 670 if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) { 671 cmd->size = cpu_to_le16(sizeof(struct 672 host_cmd_ds_rf_ant_mimo) + 673 S_DS_GEN); 674 ant_mimo->action_tx = cpu_to_le16(HOST_ACT_GET_TX); 675 ant_mimo->action_rx = cpu_to_le16(HOST_ACT_GET_RX); 676 } else { 677 cmd->size = cpu_to_le16(sizeof(struct 678 host_cmd_ds_rf_ant_siso) + 679 S_DS_GEN); 680 ant_siso->action = cpu_to_le16(HOST_ACT_GET_BOTH); 681 } 682 break; 683 } 684 return 0; 685 } 686 687 static int 688 nxpwifi_ret_sta_rf_antenna(struct nxpwifi_private *priv, 689 struct host_cmd_ds_command *resp, 690 u16 cmdresp_no, 691 void *data_buf) 692 { 693 struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo; 694 struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso; 695 struct nxpwifi_adapter *adapter = priv->adapter; 696 697 if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) { 698 priv->tx_ant = le16_to_cpu(ant_mimo->tx_ant_mode); 699 priv->rx_ant = le16_to_cpu(ant_mimo->rx_ant_mode); 700 nxpwifi_dbg(adapter, INFO, 701 "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t" 702 "Rx action = 0x%x, Rx Mode = 0x%04x\n", 703 le16_to_cpu(ant_mimo->action_tx), 704 le16_to_cpu(ant_mimo->tx_ant_mode), 705 le16_to_cpu(ant_mimo->action_rx), 706 le16_to_cpu(ant_mimo->rx_ant_mode)); 707 } else { 708 priv->tx_ant = le16_to_cpu(ant_siso->ant_mode); 709 priv->rx_ant = le16_to_cpu(ant_siso->ant_mode); 710 nxpwifi_dbg(adapter, INFO, 711 "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n", 712 le16_to_cpu(ant_siso->action), 713 le16_to_cpu(ant_siso->ant_mode)); 714 } 715 return 0; 716 } 717 718 static int 719 nxpwifi_cmd_sta_802_11_deauthenticate(struct nxpwifi_private *priv, 720 struct host_cmd_ds_command *cmd, 721 u16 cmd_no, void *data_buf, 722 u16 cmd_action, u32 cmd_type) 723 { 724 struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; 725 u8 *mac = (u8 *)data_buf; 726 727 cmd->command = cpu_to_le16(HOST_CMD_802_11_DEAUTHENTICATE); 728 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) 729 + S_DS_GEN); 730 731 /* Set AP MAC address */ 732 memcpy(deauth->mac_addr, mac, ETH_ALEN); 733 734 nxpwifi_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr); 735 736 deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); 737 738 return 0; 739 } 740 741 static int 742 nxpwifi_ret_sta_802_11_deauthenticate(struct nxpwifi_private *priv, 743 struct host_cmd_ds_command *resp, 744 u16 cmdresp_no, 745 void *data_buf) 746 { 747 struct nxpwifi_adapter *adapter = priv->adapter; 748 749 adapter->dbg.num_cmd_deauth++; 750 if (!memcmp(resp->params.deauth.mac_addr, 751 &priv->curr_bss_params.bss_descriptor.mac_address, 752 sizeof(resp->params.deauth.mac_addr))) 753 nxpwifi_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING, 754 false); 755 756 return 0; 757 } 758 759 static int 760 nxpwifi_cmd_sta_mac_control(struct nxpwifi_private *priv, 761 struct host_cmd_ds_command *cmd, 762 u16 cmd_no, void *data_buf, 763 u16 cmd_action, u32 cmd_type) 764 { 765 struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; 766 u32 *action = (u32 *)data_buf; 767 768 if (cmd_action != HOST_ACT_GEN_SET) { 769 nxpwifi_dbg(priv->adapter, ERROR, 770 "mac_control: only support set cmd\n"); 771 return -EINVAL; 772 } 773 774 cmd->command = cpu_to_le16(HOST_CMD_MAC_CONTROL); 775 cmd->size = 776 cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); 777 mac_ctrl->action = cpu_to_le32(*action); 778 779 return 0; 780 } 781 782 static int 783 nxpwifi_cmd_sta_802_11_mac_address(struct nxpwifi_private *priv, 784 struct host_cmd_ds_command *cmd, 785 u16 cmd_no, void *data_buf, 786 u16 cmd_action, u32 cmd_type) 787 { 788 cmd->command = cpu_to_le16(HOST_CMD_802_11_MAC_ADDRESS); 789 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + 790 S_DS_GEN); 791 cmd->result = 0; 792 793 cmd->params.mac_addr.action = cpu_to_le16(cmd_action); 794 795 if (cmd_action == HOST_ACT_GEN_SET) 796 memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, 797 ETH_ALEN); 798 799 return 0; 800 } 801 802 static int 803 nxpwifi_ret_sta_802_11_mac_address(struct nxpwifi_private *priv, 804 struct host_cmd_ds_command *resp, 805 u16 cmdresp_no, 806 void *data_buf) 807 { 808 struct host_cmd_ds_802_11_mac_address *cmd_mac_addr; 809 810 cmd_mac_addr = &resp->params.mac_addr; 811 812 memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); 813 814 nxpwifi_dbg(priv->adapter, INFO, 815 "info: set mac address: %pM\n", priv->curr_addr); 816 817 return 0; 818 } 819 820 static int 821 nxpwifi_cmd_sta_802_11d_domain_info(struct nxpwifi_private *priv, 822 struct host_cmd_ds_command *cmd, 823 u16 cmd_no, void *data_buf, 824 u16 cmd_action, u32 cmd_type) 825 { 826 struct nxpwifi_adapter *adapter = priv->adapter; 827 struct host_cmd_ds_802_11d_domain_info *domain_info = 828 &cmd->params.domain_info; 829 struct nxpwifi_ietypes_domain_param_set *domain = 830 &domain_info->domain; 831 struct nxpwifi_ietypes_domain_code *domain_code; 832 u8 no_of_triplet = adapter->domain_reg.no_of_triplet; 833 int triplet_size; 834 835 nxpwifi_dbg(adapter, INFO, 836 "info: 11D: no_of_triplet=0x%x\n", no_of_triplet); 837 838 cmd->command = cpu_to_le16(HOST_CMD_802_11D_DOMAIN_INFO); 839 cmd->size = cpu_to_le16(S_DS_GEN); 840 domain_info->action = cpu_to_le16(cmd_action); 841 le16_unaligned_add_cpu(&cmd->size, sizeof(domain_info->action)); 842 843 if (cmd_action == HOST_ACT_GEN_GET) 844 return 0; 845 846 triplet_size = no_of_triplet * 847 sizeof(struct ieee80211_country_ie_triplet); 848 849 domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY); 850 domain->header.len = 851 cpu_to_le16(sizeof(domain->country_code) + triplet_size); 852 memcpy(domain->country_code, adapter->domain_reg.country_code, 853 sizeof(domain->country_code)); 854 if (no_of_triplet) 855 memcpy(domain->triplet, adapter->domain_reg.triplet, 856 triplet_size); 857 le16_unaligned_add_cpu(&cmd->size, sizeof(*domain) + triplet_size); 858 859 domain_code = (struct nxpwifi_ietypes_domain_code *)((u8 *)cmd + 860 le16_to_cpu(cmd->size)); 861 domain_code->header.type = cpu_to_le16(TLV_TYPE_REGION_DOMAIN_CODE); 862 domain_code->header.len = 863 cpu_to_le16(sizeof(*domain_code) - 864 sizeof(struct nxpwifi_ie_types_header)); 865 le16_unaligned_add_cpu(&cmd->size, sizeof(*domain_code)); 866 867 return 0; 868 } 869 870 static int 871 nxpwifi_ret_sta_802_11d_domain_info(struct nxpwifi_private *priv, 872 struct host_cmd_ds_command *resp, 873 u16 cmdresp_no, 874 void *data_buf) 875 { 876 struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = 877 &resp->params.domain_info_resp; 878 struct nxpwifi_ietypes_domain_param_set *domain = &domain_info->domain; 879 u16 action = le16_to_cpu(domain_info->action); 880 u8 no_of_triplet; 881 882 no_of_triplet = (u8)((le16_to_cpu(domain->header.len) 883 - IEEE80211_COUNTRY_STRING_LEN) 884 / sizeof(struct ieee80211_country_ie_triplet)); 885 886 nxpwifi_dbg(priv->adapter, INFO, 887 "info: 11D Domain Info Resp: no_of_triplet=%d\n", 888 no_of_triplet); 889 890 if (no_of_triplet > NXPWIFI_MAX_TRIPLET_802_11D) { 891 nxpwifi_dbg(priv->adapter, FATAL, 892 "11D: invalid number of triplets %d returned\n", 893 no_of_triplet); 894 return -EINVAL; 895 } 896 897 switch (action) { 898 case HOST_ACT_GEN_SET: /* Proc Set Action */ 899 break; 900 case HOST_ACT_GEN_GET: 901 break; 902 default: 903 nxpwifi_dbg(priv->adapter, ERROR, 904 "11D: invalid action:%d\n", domain_info->action); 905 return -EINVAL; 906 } 907 908 return 0; 909 } 910 911 static int nxpwifi_set_aes_key(struct nxpwifi_private *priv, 912 struct host_cmd_ds_command *cmd, 913 struct nxpwifi_ds_encrypt_key *enc_key, 914 struct host_cmd_ds_802_11_key_material *km) 915 { 916 struct nxpwifi_adapter *adapter = priv->adapter; 917 u16 size, len = KEY_PARAMS_FIXED_LEN; 918 u8 key_type, key_type_igtk; 919 920 if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { 921 key_type = KEY_TYPE_ID_AES; 922 key_type_igtk = KEY_TYPE_ID_AES_CMAC; 923 } else { 924 key_type = KEY_TYPE_ID_GCMP_256; 925 key_type_igtk = KEY_TYPE_ID_BIP_GMAC_256; 926 } 927 928 if (enc_key->is_igtk_key) { 929 km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST); 930 km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK); 931 km->key_param_set.key_type = key_type_igtk; 932 if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { 933 nxpwifi_dbg(adapter, INFO, 934 "%s: Set CMAC AES Key\n", __func__); 935 if (enc_key->is_rx_seq_valid) 936 memcpy(km->key_param_set.key_params.cmac_aes.ipn, 937 enc_key->pn, enc_key->pn_len); 938 km->key_param_set.key_params.cmac_aes.key_len = 939 cpu_to_le16(enc_key->key_len); 940 memcpy(km->key_param_set.key_params.cmac_aes.key, 941 enc_key->key_material, enc_key->key_len); 942 len += sizeof(struct nxpwifi_cmac_aes_param); 943 } else { 944 nxpwifi_dbg(adapter, INFO, 945 "%s: Set GMAC AES Key\n", __func__); 946 if (enc_key->is_rx_seq_valid) 947 memcpy(km->key_param_set.key_params.gmac_aes.ipn, 948 enc_key->pn, enc_key->pn_len); 949 km->key_param_set.key_params.gmac_aes.key_len = 950 cpu_to_le16(enc_key->key_len); 951 memcpy(km->key_param_set.key_params.gmac_aes.key, 952 enc_key->key_material, enc_key->key_len); 953 len += sizeof(struct nxpwifi_gmac_aes_param); 954 } 955 } else if (enc_key->is_igtk_def_key) { 956 nxpwifi_dbg(adapter, INFO, 957 "%s: Set CMAC default Key index\n", __func__); 958 km->key_param_set.key_type = key_type_igtk; 959 km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; 960 } else { 961 nxpwifi_dbg(adapter, INFO, 962 "%s: Set AES Key\n", __func__); 963 if (enc_key->is_rx_seq_valid) 964 memcpy(km->key_param_set.key_params.aes.pn, 965 enc_key->pn, enc_key->pn_len); 966 km->key_param_set.key_type = key_type; 967 km->key_param_set.key_params.aes.key_len = 968 cpu_to_le16(enc_key->key_len); 969 memcpy(km->key_param_set.key_params.aes.key, 970 enc_key->key_material, enc_key->key_len); 971 len += sizeof(struct nxpwifi_aes_param); 972 } 973 974 km->key_param_set.len = cpu_to_le16(len); 975 size = len + sizeof(struct nxpwifi_ie_types_header) + 976 sizeof(km->action) + S_DS_GEN; 977 cmd->size = cpu_to_le16(size); 978 979 return 0; 980 } 981 982 static int 983 nxpwifi_cmd_sta_802_11_key_material(struct nxpwifi_private *priv, 984 struct host_cmd_ds_command *cmd, 985 u16 cmd_no, void *data_buf, 986 u16 cmd_action, u32 cmd_type) 987 { 988 struct nxpwifi_adapter *adapter = priv->adapter; 989 struct nxpwifi_ds_encrypt_key *enc_key = 990 (struct nxpwifi_ds_encrypt_key *)data_buf; 991 u8 *mac = enc_key->mac_addr; 992 u16 key_info, len = KEY_PARAMS_FIXED_LEN; 993 struct host_cmd_ds_802_11_key_material *km = 994 &cmd->params.key_material; 995 996 cmd->command = cpu_to_le16(HOST_CMD_802_11_KEY_MATERIAL); 997 km->action = cpu_to_le16(cmd_action); 998 999 if (cmd_action == HOST_ACT_GEN_GET) { 1000 nxpwifi_dbg(adapter, INFO, "%s: Get key\n", __func__); 1001 km->key_param_set.key_idx = 1002 enc_key->key_index & KEY_INDEX_MASK; 1003 km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); 1004 km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); 1005 ether_addr_copy(km->key_param_set.mac_addr, mac); 1006 1007 if (enc_key->key_index & NXPWIFI_KEY_INDEX_UNICAST) 1008 key_info = KEY_UNICAST; 1009 else 1010 key_info = KEY_MCAST; 1011 1012 if (enc_key->is_igtk_key) 1013 key_info |= KEY_IGTK; 1014 1015 km->key_param_set.key_info = cpu_to_le16(key_info); 1016 1017 cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + 1018 S_DS_GEN + KEY_PARAMS_FIXED_LEN + 1019 sizeof(km->action)); 1020 return 0; 1021 } 1022 1023 memset(&km->key_param_set, 0, 1024 sizeof(struct nxpwifi_ie_type_key_param_set)); 1025 1026 if (enc_key->key_disable) { 1027 nxpwifi_dbg(adapter, INFO, "%s: Remove key\n", __func__); 1028 km->action = cpu_to_le16(HOST_ACT_GEN_REMOVE); 1029 km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); 1030 km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); 1031 km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; 1032 key_info = KEY_MCAST | KEY_UNICAST; 1033 km->key_param_set.key_info = cpu_to_le16(key_info); 1034 ether_addr_copy(km->key_param_set.mac_addr, mac); 1035 cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + 1036 S_DS_GEN + KEY_PARAMS_FIXED_LEN + 1037 sizeof(km->action)); 1038 return 0; 1039 } 1040 1041 km->action = cpu_to_le16(HOST_ACT_GEN_SET); 1042 km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; 1043 km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); 1044 key_info = KEY_ENABLED; 1045 ether_addr_copy(km->key_param_set.mac_addr, mac); 1046 1047 if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) { 1048 nxpwifi_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__); 1049 len += sizeof(struct nxpwifi_wep_param); 1050 km->key_param_set.len = cpu_to_le16(len); 1051 km->key_param_set.key_type = KEY_TYPE_ID_WEP; 1052 1053 if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) { 1054 key_info |= KEY_MCAST | KEY_UNICAST; 1055 } else { 1056 if (enc_key->is_current_wep_key) { 1057 key_info |= KEY_MCAST | KEY_UNICAST; 1058 if (km->key_param_set.key_idx == 1059 (priv->wep_key_curr_index & KEY_INDEX_MASK)) 1060 key_info |= KEY_DEFAULT; 1061 } else { 1062 if (is_broadcast_ether_addr(mac)) 1063 key_info |= KEY_MCAST; 1064 else 1065 key_info |= KEY_UNICAST | KEY_DEFAULT; 1066 } 1067 } 1068 km->key_param_set.key_info = cpu_to_le16(key_info); 1069 1070 km->key_param_set.key_params.wep.key_len = 1071 cpu_to_le16(enc_key->key_len); 1072 memcpy(km->key_param_set.key_params.wep.key, 1073 enc_key->key_material, enc_key->key_len); 1074 1075 cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + 1076 len + sizeof(km->action) + S_DS_GEN); 1077 return 0; 1078 } 1079 1080 if (is_broadcast_ether_addr(mac)) 1081 key_info |= KEY_MCAST | KEY_RX_KEY; 1082 else 1083 key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY; 1084 1085 /* Enable default key for WPA/WPA2 */ 1086 if (!priv->wpa_is_gtk_set) 1087 key_info |= KEY_DEFAULT; 1088 1089 km->key_param_set.key_info = cpu_to_le16(key_info); 1090 1091 if (enc_key->key_cipher != WLAN_CIPHER_SUITE_TKIP && 1092 enc_key->key_len >= WLAN_KEY_LEN_CCMP) 1093 return nxpwifi_set_aes_key(priv, cmd, enc_key, km); 1094 1095 if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { 1096 nxpwifi_dbg(adapter, INFO, 1097 "%s: Set TKIP Key\n", __func__); 1098 if (enc_key->is_rx_seq_valid) 1099 memcpy(km->key_param_set.key_params.tkip.pn, 1100 enc_key->pn, enc_key->pn_len); 1101 km->key_param_set.key_type = KEY_TYPE_ID_TKIP; 1102 km->key_param_set.key_params.tkip.key_len = 1103 cpu_to_le16(enc_key->key_len); 1104 memcpy(km->key_param_set.key_params.tkip.key, 1105 enc_key->key_material, enc_key->key_len); 1106 1107 len += sizeof(struct nxpwifi_tkip_param); 1108 km->key_param_set.len = cpu_to_le16(len); 1109 cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) + 1110 len + sizeof(km->action) + S_DS_GEN); 1111 } 1112 1113 return 0; 1114 } 1115 1116 static int 1117 nxpwifi_ret_sta_802_11_key_material(struct nxpwifi_private *priv, 1118 struct host_cmd_ds_command *resp, 1119 u16 cmdresp_no, 1120 void *data_buf) 1121 { 1122 struct host_cmd_ds_802_11_key_material *key; 1123 int len; 1124 1125 key = &resp->params.key_material; 1126 1127 len = le16_to_cpu(key->key_param_set.key_params.aes.key_len); 1128 if (len > sizeof(key->key_param_set.key_params.aes.key)) 1129 return -EINVAL; 1130 1131 if (le16_to_cpu(key->action) == HOST_ACT_GEN_SET) { 1132 if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { 1133 nxpwifi_dbg(priv->adapter, INFO, 1134 "info: key: GTK is set\n"); 1135 priv->wpa_is_gtk_set = true; 1136 priv->scan_block = false; 1137 priv->port_open = true; 1138 } 1139 } 1140 1141 if (key->key_param_set.key_type != KEY_TYPE_ID_AES && 1142 key->key_param_set.key_type != KEY_TYPE_ID_GCMP_256) 1143 return 0; 1144 1145 memset(priv->aes_key.key_param_set.key_params.aes.key, 0, 1146 sizeof(key->key_param_set.key_params.aes.key)); 1147 priv->aes_key.key_param_set.key_params.aes.key_len = cpu_to_le16(len); 1148 memcpy(priv->aes_key.key_param_set.key_params.aes.key, 1149 key->key_param_set.key_params.aes.key, len); 1150 1151 return 0; 1152 } 1153 1154 static int 1155 nxpwifi_cmd_sta_802_11_bg_scan_config(struct nxpwifi_private *priv, 1156 struct host_cmd_ds_command *cmd, 1157 u16 cmd_no, void *data_buf, 1158 u16 cmd_action, u32 cmd_type) 1159 { 1160 return nxpwifi_cmd_802_11_bg_scan_config(priv, cmd, data_buf); 1161 } 1162 1163 static int 1164 nxpwifi_cmd_sta_802_11_bg_scan_query(struct nxpwifi_private *priv, 1165 struct host_cmd_ds_command *cmd, 1166 u16 cmd_no, void *data_buf, 1167 u16 cmd_action, u32 cmd_type) 1168 { 1169 return nxpwifi_cmd_802_11_bg_scan_query(cmd); 1170 } 1171 1172 static int 1173 nxpwifi_ret_sta_802_11_bg_scan_query(struct nxpwifi_private *priv, 1174 struct host_cmd_ds_command *resp, 1175 u16 cmdresp_no, 1176 void *data_buf) 1177 { 1178 struct nxpwifi_adapter *adapter = priv->adapter; 1179 int ret; 1180 1181 ret = nxpwifi_ret_802_11_scan(priv, resp); 1182 cfg80211_sched_scan_results(priv->wdev.wiphy, 0); 1183 nxpwifi_dbg(adapter, CMD, 1184 "info: CMD_RESP: BG_SCAN result is ready!\n"); 1185 1186 return ret; 1187 } 1188 1189 static int 1190 nxpwifi_cmd_sta_wmm_get_status(struct nxpwifi_private *priv, 1191 struct host_cmd_ds_command *cmd, 1192 u16 cmd_no, void *data_buf, 1193 u16 cmd_action, u32 cmd_type) 1194 { 1195 cmd->command = cpu_to_le16(HOST_CMD_WMM_GET_STATUS); 1196 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + 1197 S_DS_GEN); 1198 1199 return 0; 1200 } 1201 1202 static int 1203 nxpwifi_ret_sta_wmm_get_status(struct nxpwifi_private *priv, 1204 struct host_cmd_ds_command *resp, 1205 u16 cmdresp_no, 1206 void *data_buf) 1207 { 1208 return nxpwifi_ret_wmm_get_status(priv, resp); 1209 } 1210 1211 static int 1212 nxpwifi_cmd_sta_802_11_subsc_evt(struct nxpwifi_private *priv, 1213 struct host_cmd_ds_command *cmd, 1214 u16 cmd_no, void *data_buf, 1215 u16 cmd_action, u32 cmd_type) 1216 { 1217 struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt; 1218 struct nxpwifi_ds_misc_subsc_evt *subsc_evt_cfg = 1219 (struct nxpwifi_ds_misc_subsc_evt *)data_buf; 1220 struct nxpwifi_ie_types_rssi_threshold *rssi_tlv; 1221 u16 event_bitmap; 1222 u8 *pos; 1223 1224 cmd->command = cpu_to_le16(HOST_CMD_802_11_SUBSCRIBE_EVENT); 1225 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) + 1226 S_DS_GEN); 1227 1228 subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action); 1229 nxpwifi_dbg(priv->adapter, CMD, 1230 "cmd: action: %d\n", subsc_evt_cfg->action); 1231 1232 /* For query requests, no configuration TLV structures are to be added. */ 1233 if (subsc_evt_cfg->action == HOST_ACT_GEN_GET) 1234 return 0; 1235 1236 subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events); 1237 1238 event_bitmap = subsc_evt_cfg->events; 1239 nxpwifi_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n", 1240 event_bitmap); 1241 1242 if ((subsc_evt_cfg->action == HOST_ACT_BITWISE_CLR || 1243 subsc_evt_cfg->action == HOST_ACT_BITWISE_SET) && 1244 event_bitmap == 0) { 1245 nxpwifi_dbg(priv->adapter, ERROR, 1246 "Error: No event specified\t" 1247 "for bitwise action type\n"); 1248 return -EINVAL; 1249 } 1250 1251 /* 1252 * Append TLV structures for each of the specified events for 1253 * subscribing or re-configuring. This is not required for 1254 * bitwise unsubscribing request. 1255 */ 1256 if (subsc_evt_cfg->action == HOST_ACT_BITWISE_CLR) 1257 return 0; 1258 1259 pos = ((u8 *)subsc_evt) + 1260 sizeof(struct host_cmd_ds_802_11_subsc_evt); 1261 1262 if (event_bitmap & BITMASK_BCN_RSSI_LOW) { 1263 rssi_tlv = (struct nxpwifi_ie_types_rssi_threshold *)pos; 1264 1265 rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW); 1266 rssi_tlv->header.len = 1267 cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) - 1268 sizeof(struct nxpwifi_ie_types_header)); 1269 rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value; 1270 rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq; 1271 1272 nxpwifi_dbg(priv->adapter, EVENT, 1273 "Cfg Beacon Low Rssi event,\t" 1274 "RSSI:-%d dBm, Freq:%d\n", 1275 subsc_evt_cfg->bcn_l_rssi_cfg.abs_value, 1276 subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq); 1277 1278 pos += sizeof(struct nxpwifi_ie_types_rssi_threshold); 1279 le16_unaligned_add_cpu 1280 (&cmd->size, 1281 sizeof(struct nxpwifi_ie_types_rssi_threshold)); 1282 } 1283 1284 if (event_bitmap & BITMASK_BCN_RSSI_HIGH) { 1285 rssi_tlv = (struct nxpwifi_ie_types_rssi_threshold *)pos; 1286 1287 rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH); 1288 rssi_tlv->header.len = 1289 cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) - 1290 sizeof(struct nxpwifi_ie_types_header)); 1291 rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; 1292 rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; 1293 1294 nxpwifi_dbg(priv->adapter, EVENT, 1295 "Cfg Beacon High Rssi event,\t" 1296 "RSSI:-%d dBm, Freq:%d\n", 1297 subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, 1298 subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); 1299 1300 pos += sizeof(struct nxpwifi_ie_types_rssi_threshold); 1301 le16_unaligned_add_cpu 1302 (&cmd->size, 1303 sizeof(struct nxpwifi_ie_types_rssi_threshold)); 1304 } 1305 1306 return 0; 1307 } 1308 1309 static int 1310 nxpwifi_ret_sta_subsc_evt(struct nxpwifi_private *priv, 1311 struct host_cmd_ds_command *resp, 1312 u16 cmdresp_no, 1313 void *data_buf) 1314 { 1315 struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event = 1316 &resp->params.subsc_evt; 1317 1318 /* 1319 * For every subscribe event command (Get/Set/Clear), FW reports the current 1320 * set of subscribed events 1321 */ 1322 nxpwifi_dbg(priv->adapter, EVENT, 1323 "Bitmap of currently subscribed events: %16x\n", 1324 le16_to_cpu(cmd_sub_event->events)); 1325 1326 return 0; 1327 } 1328 1329 static int 1330 nxpwifi_cmd_sta_802_11_tx_rate_query(struct nxpwifi_private *priv, 1331 struct host_cmd_ds_command *cmd, 1332 u16 cmd_no, void *data_buf, 1333 u16 cmd_action, u32 cmd_type) 1334 { 1335 cmd->command = cpu_to_le16(HOST_CMD_802_11_TX_RATE_QUERY); 1336 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + 1337 S_DS_GEN); 1338 priv->tx_rate = 0; 1339 1340 return 0; 1341 } 1342 1343 static int 1344 nxpwifi_ret_sta_802_11_tx_rate_query(struct nxpwifi_private *priv, 1345 struct host_cmd_ds_command *resp, 1346 u16 cmdresp_no, 1347 void *data_buf) 1348 { 1349 priv->tx_rate = resp->params.tx_rate.tx_rate; 1350 priv->tx_htinfo = resp->params.tx_rate.ht_info; 1351 if (!priv->is_data_rate_auto) 1352 priv->data_rate = 1353 nxpwifi_index_to_data_rate(priv, priv->tx_rate, 1354 priv->tx_htinfo); 1355 1356 return 0; 1357 } 1358 1359 static int 1360 nxpwifi_cmd_sta_mem_access(struct nxpwifi_private *priv, 1361 struct host_cmd_ds_command *cmd, 1362 u16 cmd_no, void *data_buf, 1363 u16 cmd_action, u32 cmd_type) 1364 { 1365 struct nxpwifi_ds_mem_rw *mem_rw = 1366 (struct nxpwifi_ds_mem_rw *)data_buf; 1367 struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem; 1368 1369 cmd->command = cpu_to_le16(HOST_CMD_MEM_ACCESS); 1370 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) + 1371 S_DS_GEN); 1372 1373 mem_access->action = cpu_to_le16(cmd_action); 1374 mem_access->addr = cpu_to_le32(mem_rw->addr); 1375 mem_access->value = cpu_to_le32(mem_rw->value); 1376 1377 return 0; 1378 } 1379 1380 static int 1381 nxpwifi_ret_sta_mem_access(struct nxpwifi_private *priv, 1382 struct host_cmd_ds_command *resp, 1383 u16 cmdresp_no, 1384 void *data_buf) 1385 { 1386 struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem; 1387 1388 priv->mem_rw.addr = le32_to_cpu(mem->addr); 1389 priv->mem_rw.value = le32_to_cpu(mem->value); 1390 1391 return 0; 1392 } 1393 1394 static u32 nxpwifi_parse_cal_cfg(u8 *src, size_t len, u8 *dst) 1395 { 1396 u8 *s = src, *d = dst; 1397 1398 while (s - src < len) { 1399 if (*s && (isspace(*s) || *s == '\t')) { 1400 s++; 1401 continue; 1402 } 1403 if (isxdigit(*s)) { 1404 if (kstrtou8(s, 16, d)) 1405 return 0; 1406 d++; 1407 s += 2; 1408 } else { 1409 s++; 1410 } 1411 } 1412 1413 return d - dst; 1414 } 1415 1416 static int 1417 nxpwifi_cmd_sta_cfg_data(struct nxpwifi_private *priv, 1418 struct host_cmd_ds_command *cmd, 1419 u16 cmd_no, void *data_buf, 1420 u16 cmd_action, u32 cmd_type) 1421 { 1422 struct nxpwifi_adapter *adapter = priv->adapter; 1423 u32 len; 1424 u8 *data = (u8 *)cmd + S_DS_GEN; 1425 1426 if (adapter->cal_data->data && adapter->cal_data->size > 0) { 1427 len = nxpwifi_parse_cal_cfg((u8 *)adapter->cal_data->data, 1428 adapter->cal_data->size, data); 1429 nxpwifi_dbg(adapter, INFO, 1430 "download cfg_data from config file\n"); 1431 } else { 1432 return -EINVAL; 1433 } 1434 1435 cmd->command = cpu_to_le16(HOST_CMD_CFG_DATA); 1436 cmd->size = cpu_to_le16(S_DS_GEN + len); 1437 1438 return 0; 1439 } 1440 1441 static int 1442 nxpwifi_ret_sta_cfg_data(struct nxpwifi_private *priv, 1443 struct host_cmd_ds_command *resp, 1444 u16 cmdresp_no, 1445 void *data_buf) 1446 { 1447 if (resp->result != HOST_RESULT_OK) { 1448 nxpwifi_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n"); 1449 return -EINVAL; 1450 } 1451 1452 return 0; 1453 } 1454 1455 static int 1456 nxpwifi_cmd_sta_ver_ext(struct nxpwifi_private *priv, 1457 struct host_cmd_ds_command *cmd, 1458 u16 cmd_no, void *data_buf, 1459 u16 cmd_action, u32 cmd_type) 1460 { 1461 cmd->command = cpu_to_le16(cmd_no); 1462 cmd->params.verext.version_str_sel = 1463 (u8)(get_unaligned((u32 *)data_buf)); 1464 memcpy(&cmd->params, data_buf, sizeof(struct host_cmd_ds_version_ext)); 1465 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + 1466 S_DS_GEN); 1467 1468 return 0; 1469 } 1470 1471 static int 1472 nxpwifi_ret_sta_ver_ext(struct nxpwifi_private *priv, 1473 struct host_cmd_ds_command *resp, 1474 u16 cmdresp_no, 1475 void *data_buf) 1476 { 1477 struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; 1478 struct host_cmd_ds_version_ext *version_ext = 1479 (struct host_cmd_ds_version_ext *)data_buf; 1480 1481 if (test_and_clear_bit(NXPWIFI_IS_REQUESTING_FW_VEREXT, &priv->adapter->work_flags)) { 1482 if (strncmp(ver_ext->version_str, "ChipRev:20, BB:9b(10.00), RF:40(21)", 1483 NXPWIFI_VERSION_STR_LENGTH) == 0) { 1484 struct nxpwifi_ds_auto_ds auto_ds = { 1485 .auto_ds = DEEP_SLEEP_OFF, 1486 }; 1487 1488 nxpwifi_dbg(priv->adapter, MSG, 1489 "Bad HW revision detected, disabling deep sleep\n"); 1490 1491 if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, 1492 DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, false)) { 1493 nxpwifi_dbg(priv->adapter, MSG, 1494 "Disabling deep sleep failed.\n"); 1495 } 1496 } 1497 1498 return 0; 1499 } 1500 1501 if (version_ext) { 1502 version_ext->version_str_sel = ver_ext->version_str_sel; 1503 memcpy(version_ext->version_str, ver_ext->version_str, 1504 NXPWIFI_VERSION_STR_LENGTH); 1505 memcpy(priv->version_str, ver_ext->version_str, 1506 NXPWIFI_VERSION_STR_LENGTH); 1507 1508 /* Ensure the version string from the firmware is 0-terminated */ 1509 priv->version_str[NXPWIFI_VERSION_STR_LENGTH - 1] = '\0'; 1510 } 1511 return 0; 1512 } 1513 1514 static int 1515 nxpwifi_cmd_append_rpn_expression(struct nxpwifi_private *priv, 1516 struct nxpwifi_mef_entry *mef_entry, 1517 u8 **buffer) 1518 { 1519 struct nxpwifi_mef_filter *filter = mef_entry->filter; 1520 int i, byte_len; 1521 u8 *stack_ptr = *buffer; 1522 1523 for (i = 0; i < NXPWIFI_MEF_MAX_FILTERS; i++) { 1524 filter = &mef_entry->filter[i]; 1525 if (!filter->filt_type) 1526 break; 1527 put_unaligned_le32((u32)filter->repeat, stack_ptr); 1528 stack_ptr += 4; 1529 *stack_ptr = TYPE_DNUM; 1530 stack_ptr += 1; 1531 1532 byte_len = filter->byte_seq[NXPWIFI_MEF_MAX_BYTESEQ]; 1533 memcpy(stack_ptr, filter->byte_seq, byte_len); 1534 stack_ptr += byte_len; 1535 *stack_ptr = byte_len; 1536 stack_ptr += 1; 1537 *stack_ptr = TYPE_BYTESEQ; 1538 stack_ptr += 1; 1539 put_unaligned_le32((u32)filter->offset, stack_ptr); 1540 stack_ptr += 4; 1541 *stack_ptr = TYPE_DNUM; 1542 stack_ptr += 1; 1543 1544 *stack_ptr = filter->filt_type; 1545 stack_ptr += 1; 1546 1547 if (filter->filt_action) { 1548 *stack_ptr = filter->filt_action; 1549 stack_ptr += 1; 1550 } 1551 1552 if (stack_ptr - *buffer > STACK_NBYTES) 1553 return -ENOMEM; 1554 } 1555 1556 *buffer = stack_ptr; 1557 return 0; 1558 } 1559 1560 static int 1561 nxpwifi_cmd_sta_mef_cfg(struct nxpwifi_private *priv, 1562 struct host_cmd_ds_command *cmd, 1563 u16 cmd_no, void *data_buf, 1564 u16 cmd_action, u32 cmd_type) 1565 { 1566 struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; 1567 struct nxpwifi_ds_mef_cfg *mef = 1568 (struct nxpwifi_ds_mef_cfg *)data_buf; 1569 struct nxpwifi_fw_mef_entry *mef_entry = NULL; 1570 u8 *pos = (u8 *)mef_cfg; 1571 u16 i; 1572 int ret = 0; 1573 1574 cmd->command = cpu_to_le16(HOST_CMD_MEF_CFG); 1575 1576 mef_cfg->criteria = cpu_to_le32(mef->criteria); 1577 mef_cfg->num_entries = cpu_to_le16(mef->num_entries); 1578 pos += sizeof(*mef_cfg); 1579 1580 for (i = 0; i < mef->num_entries; i++) { 1581 mef_entry = (struct nxpwifi_fw_mef_entry *)pos; 1582 mef_entry->mode = mef->mef_entry[i].mode; 1583 mef_entry->action = mef->mef_entry[i].action; 1584 pos += sizeof(*mef_entry); 1585 1586 ret = nxpwifi_cmd_append_rpn_expression(priv, 1587 &mef->mef_entry[i], 1588 &pos); 1589 if (ret) 1590 return ret; 1591 1592 mef_entry->exprsize = 1593 cpu_to_le16(pos - mef_entry->expr); 1594 } 1595 cmd->size = cpu_to_le16((u16)(pos - (u8 *)mef_cfg) + S_DS_GEN); 1596 1597 return ret; 1598 } 1599 1600 static int 1601 nxpwifi_cmd_sta_802_11_rssi_info(struct nxpwifi_private *priv, 1602 struct host_cmd_ds_command *cmd, 1603 u16 cmd_no, void *data_buf, 1604 u16 cmd_action, u32 cmd_type) 1605 { 1606 cmd->command = cpu_to_le16(HOST_CMD_RSSI_INFO); 1607 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + 1608 S_DS_GEN); 1609 cmd->params.rssi_info.action = cpu_to_le16(cmd_action); 1610 cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor); 1611 cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor); 1612 1613 /* Reset SNR/NF/RSSI values in private structure */ 1614 priv->data_rssi_last = 0; 1615 priv->data_nf_last = 0; 1616 priv->data_rssi_avg = 0; 1617 priv->data_nf_avg = 0; 1618 priv->bcn_rssi_last = 0; 1619 priv->bcn_nf_last = 0; 1620 priv->bcn_rssi_avg = 0; 1621 priv->bcn_nf_avg = 0; 1622 1623 return 0; 1624 } 1625 1626 static int 1627 nxpwifi_ret_sta_802_11_rssi_info(struct nxpwifi_private *priv, 1628 struct host_cmd_ds_command *resp, 1629 u16 cmdresp_no, 1630 void *data_buf) 1631 { 1632 struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = 1633 &resp->params.rssi_info_rsp; 1634 struct nxpwifi_ds_misc_subsc_evt *subsc_evt = 1635 &priv->async_subsc_evt_storage; 1636 1637 priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); 1638 priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); 1639 1640 priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); 1641 priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); 1642 1643 priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); 1644 priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); 1645 1646 priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); 1647 priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); 1648 1649 if (priv->subsc_evt_rssi_state == EVENT_HANDLED) 1650 return 0; 1651 1652 memset(subsc_evt, 0x00, sizeof(struct nxpwifi_ds_misc_subsc_evt)); 1653 1654 /* Resubscribe low and high rssi events with new thresholds */ 1655 subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; 1656 subsc_evt->action = HOST_ACT_BITWISE_SET; 1657 if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) { 1658 subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - 1659 priv->cqm_rssi_hyst); 1660 subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); 1661 } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) { 1662 subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); 1663 subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + 1664 priv->cqm_rssi_hyst); 1665 } 1666 subsc_evt->bcn_l_rssi_cfg.evt_freq = 1; 1667 subsc_evt->bcn_h_rssi_cfg.evt_freq = 1; 1668 1669 priv->subsc_evt_rssi_state = EVENT_HANDLED; 1670 1671 nxpwifi_send_cmd(priv, HOST_CMD_802_11_SUBSCRIBE_EVENT, 1672 0, 0, subsc_evt, false); 1673 1674 return 0; 1675 } 1676 1677 static int 1678 nxpwifi_cmd_sta_func_init(struct nxpwifi_private *priv, 1679 struct host_cmd_ds_command *cmd, 1680 u16 cmd_no, void *data_buf, 1681 u16 cmd_action, u32 cmd_type) 1682 { 1683 if (priv->adapter->hw_status == NXPWIFI_HW_STATUS_RESET) 1684 priv->adapter->hw_status = NXPWIFI_HW_STATUS_READY; 1685 cmd->command = cpu_to_le16(cmd_no); 1686 cmd->size = cpu_to_le16(S_DS_GEN); 1687 1688 return 0; 1689 } 1690 1691 static int 1692 nxpwifi_cmd_sta_func_shutdown(struct nxpwifi_private *priv, 1693 struct host_cmd_ds_command *cmd, 1694 u16 cmd_no, void *data_buf, 1695 u16 cmd_action, u32 cmd_type) 1696 { 1697 priv->adapter->hw_status = NXPWIFI_HW_STATUS_RESET; 1698 cmd->command = cpu_to_le16(cmd_no); 1699 cmd->size = cpu_to_le16(S_DS_GEN); 1700 1701 return 0; 1702 } 1703 1704 static int 1705 nxpwifi_cmd_sta_11n_cfg(struct nxpwifi_private *priv, 1706 struct host_cmd_ds_command *cmd, 1707 u16 cmd_no, void *data_buf, 1708 u16 cmd_action, u32 cmd_type) 1709 { 1710 return nxpwifi_cmd_11n_cfg(priv, cmd, cmd_action, data_buf); 1711 } 1712 1713 static int 1714 nxpwifi_cmd_sta_11n_addba_req(struct nxpwifi_private *priv, 1715 struct host_cmd_ds_command *cmd, 1716 u16 cmd_no, void *data_buf, 1717 u16 cmd_action, u32 cmd_type) 1718 { 1719 return nxpwifi_cmd_11n_addba_req(cmd, data_buf); 1720 } 1721 1722 static int 1723 nxpwifi_ret_sta_11n_addba_req(struct nxpwifi_private *priv, 1724 struct host_cmd_ds_command *resp, 1725 u16 cmdresp_no, 1726 void *data_buf) 1727 { 1728 return nxpwifi_ret_11n_addba_req(priv, resp); 1729 } 1730 1731 static int 1732 nxpwifi_cmd_sta_11n_addba_rsp(struct nxpwifi_private *priv, 1733 struct host_cmd_ds_command *cmd, 1734 u16 cmd_no, void *data_buf, 1735 u16 cmd_action, u32 cmd_type) 1736 { 1737 return nxpwifi_cmd_11n_addba_rsp_gen(priv, cmd, data_buf); 1738 } 1739 1740 static int 1741 nxpwifi_ret_sta_11n_addba_rsp(struct nxpwifi_private *priv, 1742 struct host_cmd_ds_command *resp, 1743 u16 cmdresp_no, 1744 void *data_buf) 1745 { 1746 return nxpwifi_ret_11n_addba_resp(priv, resp); 1747 } 1748 1749 static int 1750 nxpwifi_cmd_sta_11n_delba(struct nxpwifi_private *priv, 1751 struct host_cmd_ds_command *cmd, 1752 u16 cmd_no, void *data_buf, 1753 u16 cmd_action, u32 cmd_type) 1754 { 1755 return nxpwifi_cmd_11n_delba(cmd, data_buf); 1756 } 1757 1758 static int 1759 nxpwifi_ret_sta_11n_delba(struct nxpwifi_private *priv, 1760 struct host_cmd_ds_command *resp, 1761 u16 cmdresp_no, 1762 void *data_buf) 1763 { 1764 return nxpwifi_ret_11n_delba(priv, resp); 1765 } 1766 1767 static int 1768 nxpwifi_cmd_sta_tx_power_cfg(struct nxpwifi_private *priv, 1769 struct host_cmd_ds_command *cmd, 1770 u16 cmd_no, void *data_buf, 1771 u16 cmd_action, u32 cmd_type) 1772 { 1773 struct nxpwifi_types_power_group *pg_tlv; 1774 struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; 1775 struct host_cmd_ds_txpwr_cfg *txp = 1776 (struct host_cmd_ds_txpwr_cfg *)data_buf; 1777 1778 cmd->command = cpu_to_le16(HOST_CMD_TXPWR_CFG); 1779 cmd->size = 1780 cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); 1781 switch (cmd_action) { 1782 case HOST_ACT_GEN_SET: 1783 if (txp->mode) { 1784 pg_tlv = (struct nxpwifi_types_power_group 1785 *)((unsigned long)txp + 1786 sizeof(struct host_cmd_ds_txpwr_cfg)); 1787 memmove(cmd_txp_cfg, txp, 1788 sizeof(struct host_cmd_ds_txpwr_cfg) + 1789 sizeof(struct nxpwifi_types_power_group) + 1790 le16_to_cpu(pg_tlv->length)); 1791 1792 pg_tlv = (struct nxpwifi_types_power_group *)((u8 *) 1793 cmd_txp_cfg + 1794 sizeof(struct host_cmd_ds_txpwr_cfg)); 1795 cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + 1796 sizeof(struct nxpwifi_types_power_group) + 1797 le16_to_cpu(pg_tlv->length)); 1798 } else { 1799 memmove(cmd_txp_cfg, txp, sizeof(*txp)); 1800 } 1801 cmd_txp_cfg->action = cpu_to_le16(cmd_action); 1802 break; 1803 case HOST_ACT_GEN_GET: 1804 cmd_txp_cfg->action = cpu_to_le16(cmd_action); 1805 break; 1806 } 1807 1808 return 0; 1809 } 1810 1811 static int nxpwifi_get_power_level(struct nxpwifi_private *priv, void *data_buf) 1812 { 1813 int length, max_power = -1, min_power = -1; 1814 struct nxpwifi_types_power_group *pg_tlv_hdr; 1815 struct nxpwifi_power_group *pg; 1816 1817 if (!data_buf) 1818 return -ENOMEM; 1819 1820 pg_tlv_hdr = (struct nxpwifi_types_power_group *)((u8 *)data_buf); 1821 pg = (struct nxpwifi_power_group *) 1822 ((u8 *)pg_tlv_hdr + sizeof(struct nxpwifi_types_power_group)); 1823 length = le16_to_cpu(pg_tlv_hdr->length); 1824 1825 /* At least one structure required to update power */ 1826 if (length < sizeof(struct nxpwifi_power_group)) 1827 return 0; 1828 1829 max_power = pg->power_max; 1830 min_power = pg->power_min; 1831 length -= sizeof(struct nxpwifi_power_group); 1832 1833 while (length >= sizeof(struct nxpwifi_power_group)) { 1834 pg++; 1835 if (max_power < pg->power_max) 1836 max_power = pg->power_max; 1837 1838 if (min_power > pg->power_min) 1839 min_power = pg->power_min; 1840 1841 length -= sizeof(struct nxpwifi_power_group); 1842 } 1843 priv->min_tx_power_level = (u8)min_power; 1844 priv->max_tx_power_level = (u8)max_power; 1845 1846 return 0; 1847 } 1848 1849 static int 1850 nxpwifi_ret_sta_tx_power_cfg(struct nxpwifi_private *priv, 1851 struct host_cmd_ds_command *resp, 1852 u16 cmdresp_no, 1853 void *data_buf) 1854 { 1855 struct nxpwifi_adapter *adapter = priv->adapter; 1856 struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; 1857 struct nxpwifi_types_power_group *pg_tlv_hdr; 1858 struct nxpwifi_power_group *pg; 1859 u16 action = le16_to_cpu(txp_cfg->action); 1860 u16 tlv_buf_left; 1861 1862 pg_tlv_hdr = (struct nxpwifi_types_power_group *) 1863 ((u8 *)txp_cfg + 1864 sizeof(struct host_cmd_ds_txpwr_cfg)); 1865 1866 pg = (struct nxpwifi_power_group *) 1867 ((u8 *)pg_tlv_hdr + 1868 sizeof(struct nxpwifi_types_power_group)); 1869 1870 tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg); 1871 if (tlv_buf_left < 1872 le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr)) 1873 return 0; 1874 1875 switch (action) { 1876 case HOST_ACT_GEN_GET: 1877 if (adapter->hw_status == NXPWIFI_HW_STATUS_INITIALIZING) 1878 nxpwifi_get_power_level(priv, pg_tlv_hdr); 1879 1880 priv->tx_power_level = (u16)pg->power_min; 1881 break; 1882 1883 case HOST_ACT_GEN_SET: 1884 if (!le32_to_cpu(txp_cfg->mode)) 1885 break; 1886 1887 if (pg->power_max == pg->power_min) 1888 priv->tx_power_level = (u16)pg->power_min; 1889 break; 1890 default: 1891 nxpwifi_dbg(adapter, ERROR, 1892 "CMD_RESP: unknown cmd action %d\n", 1893 action); 1894 return 0; 1895 } 1896 nxpwifi_dbg(adapter, INFO, 1897 "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", 1898 priv->tx_power_level, priv->max_tx_power_level, 1899 priv->min_tx_power_level); 1900 1901 return 0; 1902 } 1903 1904 static int 1905 nxpwifi_cmd_sta_tx_rate_cfg(struct nxpwifi_private *priv, 1906 struct host_cmd_ds_command *cmd, 1907 u16 cmd_no, void *data_buf, 1908 u16 cmd_action, u32 cmd_type) 1909 { 1910 struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg; 1911 u16 *pbitmap_rates = (u16 *)data_buf; 1912 struct nxpwifi_rate_scope *rate_scope; 1913 struct nxpwifi_rate_drop_pattern *rate_drop; 1914 u32 i; 1915 1916 cmd->command = cpu_to_le16(HOST_CMD_TX_RATE_CFG); 1917 1918 rate_cfg->action = cpu_to_le16(cmd_action); 1919 rate_cfg->cfg_index = 0; 1920 1921 rate_scope = (struct nxpwifi_rate_scope *)((u8 *)rate_cfg + 1922 sizeof(struct host_cmd_ds_tx_rate_cfg)); 1923 rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE); 1924 rate_scope->length = cpu_to_le16 1925 (sizeof(*rate_scope) - sizeof(struct nxpwifi_ie_types_header)); 1926 if (pbitmap_rates) { 1927 rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]); 1928 rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]); 1929 for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) 1930 rate_scope->ht_mcs_rate_bitmap[i] = 1931 cpu_to_le16(pbitmap_rates[2 + i]); 1932 if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) { 1933 for (i = 0; 1934 i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); 1935 i++) 1936 rate_scope->vht_mcs_rate_bitmap[i] = 1937 cpu_to_le16(pbitmap_rates[10 + i]); 1938 } 1939 } else { 1940 rate_scope->hr_dsss_rate_bitmap = 1941 cpu_to_le16(priv->bitmap_rates[0]); 1942 rate_scope->ofdm_rate_bitmap = 1943 cpu_to_le16(priv->bitmap_rates[1]); 1944 for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) 1945 rate_scope->ht_mcs_rate_bitmap[i] = 1946 cpu_to_le16(priv->bitmap_rates[2 + i]); 1947 if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) { 1948 for (i = 0; 1949 i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); 1950 i++) 1951 rate_scope->vht_mcs_rate_bitmap[i] = 1952 cpu_to_le16(priv->bitmap_rates[10 + i]); 1953 } 1954 } 1955 1956 rate_drop = (struct nxpwifi_rate_drop_pattern *)((u8 *)rate_scope + 1957 sizeof(struct nxpwifi_rate_scope)); 1958 rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); 1959 rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); 1960 rate_drop->rate_drop_mode = 0; 1961 1962 cmd->size = 1963 cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + 1964 sizeof(struct nxpwifi_rate_scope) + 1965 sizeof(struct nxpwifi_rate_drop_pattern)); 1966 1967 return 0; 1968 } 1969 1970 static void nxpwifi_ret_rate_scope(struct nxpwifi_private *priv, u8 *tlv_buf) 1971 { 1972 struct nxpwifi_rate_scope *rate_scope; 1973 int i; 1974 1975 rate_scope = (struct nxpwifi_rate_scope *)tlv_buf; 1976 priv->bitmap_rates[0] = 1977 le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); 1978 priv->bitmap_rates[1] = 1979 le16_to_cpu(rate_scope->ofdm_rate_bitmap); 1980 for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) 1981 priv->bitmap_rates[2 + i] = 1982 le16_to_cpu(rate_scope->ht_mcs_rate_bitmap[i]); 1983 1984 if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) { 1985 for (i = 0; i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); 1986 i++) 1987 priv->bitmap_rates[10 + i] = 1988 le16_to_cpu(rate_scope->vht_mcs_rate_bitmap[i]); 1989 } 1990 } 1991 1992 static int 1993 nxpwifi_ret_sta_tx_rate_cfg(struct nxpwifi_private *priv, 1994 struct host_cmd_ds_command *resp, 1995 u16 cmdresp_no, 1996 void *data_buf) 1997 { 1998 struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; 1999 struct nxpwifi_ie_types_header *head; 2000 u16 tlv, tlv_buf_len, tlv_buf_left; 2001 u8 *tlv_buf; 2002 2003 tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg); 2004 tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg); 2005 2006 while (tlv_buf_left >= sizeof(*head)) { 2007 head = (struct nxpwifi_ie_types_header *)tlv_buf; 2008 tlv = le16_to_cpu(head->type); 2009 tlv_buf_len = le16_to_cpu(head->len); 2010 2011 if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) 2012 break; 2013 2014 switch (tlv) { 2015 case TLV_TYPE_RATE_SCOPE: 2016 nxpwifi_ret_rate_scope(priv, tlv_buf); 2017 break; 2018 /* Add RATE_DROP tlv here */ 2019 } 2020 2021 tlv_buf += (sizeof(*head) + tlv_buf_len); 2022 tlv_buf_left -= (sizeof(*head) + tlv_buf_len); 2023 } 2024 2025 priv->is_data_rate_auto = nxpwifi_is_rate_auto(priv); 2026 2027 if (priv->is_data_rate_auto) 2028 priv->data_rate = 0; 2029 else 2030 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_TX_RATE_QUERY, 2031 HOST_ACT_GEN_GET, 0, NULL, false); 2032 2033 return 0; 2034 } 2035 2036 static int 2037 nxpwifi_cmd_sta_reconfigure_rx_buff(struct nxpwifi_private *priv, 2038 struct host_cmd_ds_command *cmd, 2039 u16 cmd_no, void *data_buf, 2040 u16 cmd_action, u32 cmd_type) 2041 { 2042 return nxpwifi_cmd_recfg_tx_buf(priv, cmd, cmd_action, data_buf); 2043 } 2044 2045 static int 2046 nxpwifi_ret_sta_reconfigure_rx_buff(struct nxpwifi_private *priv, 2047 struct host_cmd_ds_command *resp, 2048 u16 cmdresp_no, 2049 void *data_buf) 2050 { 2051 struct nxpwifi_adapter *adapter = priv->adapter; 2052 2053 if (0xffff != (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) { 2054 adapter->tx_buf_size = 2055 (u16)le16_to_cpu(resp->params.tx_buf.buff_size); 2056 adapter->tx_buf_size = 2057 (adapter->tx_buf_size / NXPWIFI_SDIO_BLOCK_SIZE) * 2058 NXPWIFI_SDIO_BLOCK_SIZE; 2059 adapter->curr_tx_buf_size = adapter->tx_buf_size; 2060 nxpwifi_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n", 2061 adapter->curr_tx_buf_size); 2062 2063 if (adapter->if_ops.update_mp_end_port) { 2064 u16 mp_end_port; 2065 2066 mp_end_port = 2067 le16_to_cpu(resp->params.tx_buf.mp_end_port); 2068 adapter->if_ops.update_mp_end_port(adapter, 2069 mp_end_port); 2070 } 2071 } 2072 2073 return 0; 2074 } 2075 2076 static int 2077 nxpwifi_cmd_sta_chan_report_request(struct nxpwifi_private *priv, 2078 struct host_cmd_ds_command *cmd, 2079 u16 cmd_no, void *data_buf, 2080 u16 cmd_action, u32 cmd_type) 2081 { 2082 return nxpwifi_cmd_issue_chan_report_request(priv, cmd, data_buf); 2083 } 2084 2085 static int 2086 nxpwifi_cmd_sta_amsdu_aggr_ctrl(struct nxpwifi_private *priv, 2087 struct host_cmd_ds_command *cmd, 2088 u16 cmd_no, void *data_buf, 2089 u16 cmd_action, u32 cmd_type) 2090 { 2091 return nxpwifi_cmd_amsdu_aggr_ctrl(cmd, cmd_action, data_buf); 2092 } 2093 2094 static int 2095 nxpwifi_cmd_sta_robust_coex(struct nxpwifi_private *priv, 2096 struct host_cmd_ds_command *cmd, 2097 u16 cmd_no, void *data_buf, 2098 u16 cmd_action, u32 cmd_type) 2099 { 2100 struct host_cmd_ds_robust_coex *coex = &cmd->params.coex; 2101 bool *is_timeshare = (bool *)data_buf; 2102 struct nxpwifi_ie_types_robust_coex *coex_tlv; 2103 2104 cmd->command = cpu_to_le16(HOST_CMD_ROBUST_COEX); 2105 cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN); 2106 2107 coex->action = cpu_to_le16(cmd_action); 2108 coex_tlv = (struct nxpwifi_ie_types_robust_coex *) 2109 ((u8 *)coex + sizeof(*coex)); 2110 coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX); 2111 coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode)); 2112 2113 if (coex->action == HOST_ACT_GEN_GET) 2114 return 0; 2115 2116 if (*is_timeshare) 2117 coex_tlv->mode = cpu_to_le32(NXPWIFI_COEX_MODE_TIMESHARE); 2118 else 2119 coex_tlv->mode = cpu_to_le32(NXPWIFI_COEX_MODE_SPATIAL); 2120 2121 return 0; 2122 } 2123 2124 static int 2125 nxpwifi_ret_sta_robust_coex(struct nxpwifi_private *priv, 2126 struct host_cmd_ds_command *resp, 2127 u16 cmdresp_no, 2128 void *data_buf) 2129 { 2130 struct host_cmd_ds_robust_coex *coex = &resp->params.coex; 2131 bool *is_timeshare = (bool *)data_buf; 2132 struct nxpwifi_ie_types_robust_coex *coex_tlv; 2133 u16 action = le16_to_cpu(coex->action); 2134 u32 mode; 2135 2136 if (!is_timeshare) 2137 return 0; 2138 2139 coex_tlv = (struct nxpwifi_ie_types_robust_coex 2140 *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex)); 2141 if (action == HOST_ACT_GEN_GET) { 2142 mode = le32_to_cpu(coex_tlv->mode); 2143 if (mode == NXPWIFI_COEX_MODE_TIMESHARE) 2144 *is_timeshare = true; 2145 else 2146 *is_timeshare = false; 2147 } 2148 2149 return 0; 2150 } 2151 2152 static int 2153 nxpwifi_cmd_sta_enh_power_mode(struct nxpwifi_private *priv, 2154 struct host_cmd_ds_command *cmd, 2155 u16 cmd_no, void *data_buf, 2156 u16 cmd_action, u32 cmd_type) 2157 { 2158 struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = 2159 &cmd->params.psmode_enh; 2160 u16 ps_bitmap = (u16)cmd_type; 2161 struct nxpwifi_ds_auto_ds *auto_ds = 2162 (struct nxpwifi_ds_auto_ds *)data_buf; 2163 u8 *tlv; 2164 u16 cmd_size = 0; 2165 2166 cmd->command = cpu_to_le16(HOST_CMD_802_11_PS_MODE_ENH); 2167 if (cmd_action == DIS_AUTO_PS) { 2168 psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); 2169 psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); 2170 cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + 2171 sizeof(psmode_enh->params.ps_bitmap)); 2172 } else if (cmd_action == GET_PS) { 2173 psmode_enh->action = cpu_to_le16(GET_PS); 2174 psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); 2175 cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + 2176 sizeof(psmode_enh->params.ps_bitmap)); 2177 } else if (cmd_action == EN_AUTO_PS) { 2178 psmode_enh->action = cpu_to_le16(EN_AUTO_PS); 2179 psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); 2180 cmd_size = S_DS_GEN + sizeof(psmode_enh->action) + 2181 sizeof(psmode_enh->params.ps_bitmap); 2182 tlv = (u8 *)cmd + cmd_size; 2183 if (ps_bitmap & BITMAP_STA_PS) { 2184 struct nxpwifi_adapter *adapter = priv->adapter; 2185 struct nxpwifi_ie_types_ps_param *ps_tlv = 2186 (struct nxpwifi_ie_types_ps_param *)tlv; 2187 struct nxpwifi_ps_param *ps_mode = &ps_tlv->param; 2188 2189 ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM); 2190 ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) - 2191 sizeof(struct nxpwifi_ie_types_header)); 2192 cmd_size += sizeof(*ps_tlv); 2193 tlv += sizeof(*ps_tlv); 2194 nxpwifi_dbg(priv->adapter, CMD, 2195 "cmd: PS Command: Enter PS\n"); 2196 ps_mode->null_pkt_interval = 2197 cpu_to_le16(adapter->null_pkt_interval); 2198 ps_mode->multiple_dtims = 2199 cpu_to_le16(adapter->multiple_dtim); 2200 ps_mode->bcn_miss_timeout = 2201 cpu_to_le16(adapter->bcn_miss_time_out); 2202 ps_mode->local_listen_interval = 2203 cpu_to_le16(adapter->local_listen_interval); 2204 ps_mode->delay_to_ps = 2205 cpu_to_le16(adapter->delay_to_ps); 2206 ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode); 2207 } 2208 if (ps_bitmap & BITMAP_AUTO_DS) { 2209 struct nxpwifi_ie_types_auto_ds_param *auto_ds_tlv = 2210 (struct nxpwifi_ie_types_auto_ds_param *)tlv; 2211 u16 idletime = 0; 2212 2213 auto_ds_tlv->header.type = 2214 cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); 2215 auto_ds_tlv->header.len = 2216 cpu_to_le16(sizeof(*auto_ds_tlv) - 2217 sizeof(struct nxpwifi_ie_types_header)); 2218 cmd_size += sizeof(*auto_ds_tlv); 2219 tlv += sizeof(*auto_ds_tlv); 2220 if (auto_ds) 2221 idletime = auto_ds->idle_time; 2222 nxpwifi_dbg(priv->adapter, CMD, 2223 "cmd: PS Command: Enter Auto Deep Sleep\n"); 2224 auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); 2225 } 2226 cmd->size = cpu_to_le16(cmd_size); 2227 } 2228 return 0; 2229 } 2230 2231 static int 2232 nxpwifi_ret_sta_enh_power_mode(struct nxpwifi_private *priv, 2233 struct host_cmd_ds_command *resp, 2234 u16 cmdresp_no, 2235 void *data_buf) 2236 { 2237 struct nxpwifi_adapter *adapter = priv->adapter; 2238 struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = 2239 &resp->params.psmode_enh; 2240 struct nxpwifi_ds_pm_cfg *pm_cfg = 2241 (struct nxpwifi_ds_pm_cfg *)data_buf; 2242 u16 action = le16_to_cpu(ps_mode->action); 2243 u16 ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); 2244 u16 auto_ps_bitmap = 2245 le16_to_cpu(ps_mode->params.ps_bitmap); 2246 2247 nxpwifi_dbg(adapter, INFO, 2248 "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", 2249 __func__, resp->result, action); 2250 if (action == EN_AUTO_PS) { 2251 if (auto_ps_bitmap & BITMAP_AUTO_DS) { 2252 nxpwifi_dbg(adapter, CMD, 2253 "cmd: Enabled auto deep sleep\n"); 2254 priv->adapter->is_deep_sleep = true; 2255 } 2256 if (auto_ps_bitmap & BITMAP_STA_PS) { 2257 nxpwifi_dbg(adapter, CMD, 2258 "cmd: Enabled STA power save\n"); 2259 if (adapter->sleep_period.period) 2260 nxpwifi_dbg(adapter, CMD, 2261 "cmd: set to uapsd/pps mode\n"); 2262 } 2263 } else if (action == DIS_AUTO_PS) { 2264 if (ps_bitmap & BITMAP_AUTO_DS) { 2265 priv->adapter->is_deep_sleep = false; 2266 nxpwifi_dbg(adapter, CMD, 2267 "cmd: Disabled auto deep sleep\n"); 2268 } 2269 if (ps_bitmap & BITMAP_STA_PS) { 2270 nxpwifi_dbg(adapter, CMD, 2271 "cmd: Disabled STA power save\n"); 2272 if (adapter->sleep_period.period) { 2273 adapter->delay_null_pkt = false; 2274 adapter->tx_lock_flag = false; 2275 adapter->pps_uapsd_mode = false; 2276 } 2277 } 2278 } else if (action == GET_PS) { 2279 if (ps_bitmap & BITMAP_STA_PS) 2280 adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_PSP; 2281 else 2282 adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_CAM; 2283 2284 nxpwifi_dbg(adapter, CMD, 2285 "cmd: ps_bitmap=%#x\n", ps_bitmap); 2286 2287 if (pm_cfg) { 2288 /* This section is for get power save mode */ 2289 if (ps_bitmap & BITMAP_STA_PS) 2290 pm_cfg->param.ps_mode = 1; 2291 else 2292 pm_cfg->param.ps_mode = 0; 2293 } 2294 } 2295 return 0; 2296 } 2297 2298 static int 2299 nxpwifi_cmd_sta_802_11_hs_cfg(struct nxpwifi_private *priv, 2300 struct host_cmd_ds_command *cmd, 2301 u16 cmd_no, void *data_buf, 2302 u16 cmd_action, u32 cmd_type) 2303 { 2304 struct nxpwifi_adapter *adapter = priv->adapter; 2305 struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; 2306 struct nxpwifi_hs_config_param *hscfg_param = 2307 (struct nxpwifi_hs_config_param *)data_buf; 2308 u8 *tlv = (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh); 2309 struct nxpwifi_ps_param_in_hs *psparam_tlv = NULL; 2310 bool hs_activate = false; 2311 u16 size; 2312 2313 if (!hscfg_param) 2314 /* New Activate command */ 2315 hs_activate = true; 2316 cmd->command = cpu_to_le16(HOST_CMD_802_11_HS_CFG_ENH); 2317 2318 if (!hs_activate && 2319 hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL) && 2320 (adapter->arp_filter_size > 0 && 2321 adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE)) { 2322 nxpwifi_dbg(adapter, CMD, 2323 "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", 2324 adapter->arp_filter_size); 2325 memcpy(((u8 *)hs_cfg) + 2326 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), 2327 adapter->arp_filter, adapter->arp_filter_size); 2328 size = adapter->arp_filter_size + 2329 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) 2330 + S_DS_GEN; 2331 tlv = (u8 *)hs_cfg 2332 + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) 2333 + adapter->arp_filter_size; 2334 } else { 2335 size = S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh); 2336 } 2337 if (hs_activate) { 2338 hs_cfg->action = cpu_to_le16(HS_ACTIVATE); 2339 hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED); 2340 2341 adapter->hs_activated_manually = true; 2342 nxpwifi_dbg(priv->adapter, CMD, 2343 "cmd: Activating host sleep manually\n"); 2344 } else { 2345 hs_cfg->action = cpu_to_le16(HS_CONFIGURE); 2346 hs_cfg->params.hs_config.conditions = hscfg_param->conditions; 2347 hs_cfg->params.hs_config.gpio = hscfg_param->gpio; 2348 hs_cfg->params.hs_config.gap = hscfg_param->gap; 2349 2350 size += sizeof(struct nxpwifi_ps_param_in_hs); 2351 psparam_tlv = (struct nxpwifi_ps_param_in_hs *)tlv; 2352 psparam_tlv->header.type = 2353 cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS); 2354 psparam_tlv->header.len = 2355 cpu_to_le16(sizeof(struct nxpwifi_ps_param_in_hs) 2356 - sizeof(struct nxpwifi_ie_types_header)); 2357 psparam_tlv->hs_wake_int = cpu_to_le32(HS_DEF_WAKE_INTERVAL); 2358 psparam_tlv->hs_inact_timeout = 2359 cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT); 2360 2361 nxpwifi_dbg(adapter, CMD, 2362 "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", 2363 hs_cfg->params.hs_config.conditions, 2364 hs_cfg->params.hs_config.gpio, 2365 hs_cfg->params.hs_config.gap); 2366 } 2367 cmd->size = cpu_to_le16(size); 2368 2369 return 0; 2370 } 2371 2372 static int 2373 nxpwifi_ret_sta_802_11_hs_cfg(struct nxpwifi_private *priv, 2374 struct host_cmd_ds_command *resp, 2375 u16 cmdresp_no, 2376 void *data_buf) 2377 { 2378 return nxpwifi_ret_802_11_hs_cfg(priv, resp); 2379 } 2380 2381 static int 2382 nxpwifi_cmd_sta_set_bss_mode(struct nxpwifi_private *priv, 2383 struct host_cmd_ds_command *cmd, 2384 u16 cmd_no, void *data_buf, 2385 u16 cmd_action, u32 cmd_type) 2386 { 2387 cmd->command = cpu_to_le16(cmd_no); 2388 if (priv->bss_mode == NL80211_IFTYPE_STATION) 2389 cmd->params.bss_mode.con_type = CONNECTION_TYPE_INFRA; 2390 else if (priv->bss_mode == NL80211_IFTYPE_AP) 2391 cmd->params.bss_mode.con_type = CONNECTION_TYPE_AP; 2392 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_set_bss_mode) + 2393 S_DS_GEN); 2394 2395 return 0; 2396 } 2397 2398 static int 2399 nxpwifi_cmd_sta_802_11_net_monitor(struct nxpwifi_private *priv, 2400 struct host_cmd_ds_command *cmd, 2401 u16 cmd_no, void *data_buf, 2402 u16 cmd_action, u32 cmd_type) 2403 { 2404 struct nxpwifi_802_11_net_monitor *net_mon; 2405 struct host_cmd_ds_802_11_net_monitor *cmd_net_mon = 2406 &cmd->params.net_mon; 2407 struct chan_band_param *chan_band = NULL; 2408 u8 sec_chan_offset = 0; 2409 u32 bw_offset = 0; 2410 2411 net_mon = (struct nxpwifi_802_11_net_monitor *)data_buf; 2412 2413 cmd->size = cpu_to_le16(S_DS_GEN + 2414 sizeof(struct host_cmd_ds_802_11_net_monitor) + 2415 sizeof(struct chan_band_param)); 2416 cmd->command = cpu_to_le16(cmd_no); 2417 cmd_net_mon->action = cpu_to_le16(cmd_action); 2418 2419 if (cmd_action == HOST_ACT_GEN_SET) { 2420 if (net_mon->enable_net_mon) { 2421 cmd_net_mon->enable_net_mon = cpu_to_le16(0x1); 2422 cmd_net_mon->filter_flag = cpu_to_le16((u16) 2423 net_mon->filter_flag); 2424 } 2425 2426 if (net_mon->enable_net_mon && net_mon->channel) { 2427 chan_band = &cmd_net_mon->monitor_chan.chan_band_param[0]; 2428 cmd_net_mon->monitor_chan.header.type = 2429 cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); 2430 cmd_net_mon->monitor_chan.header.len = 2431 cpu_to_le16(sizeof(struct chan_band_param)); 2432 chan_band->chan_number = (u8)net_mon->channel; 2433 chan_band->band_cfg.chan_band = 2434 nxpwifi_band_to_radio_type((u16)net_mon->band); 2435 2436 if (net_mon->band & BAND_GN || 2437 net_mon->band & BAND_AN || 2438 net_mon->band & BAND_GAC || 2439 net_mon->band & BAND_AAC) { 2440 bw_offset = net_mon->chan_bandwidth; 2441 if (bw_offset == CHANNEL_BW_40MHZ_ABOVE) { 2442 chan_band->band_cfg.chan_2O_ffset = 2443 NXPWIFI_SEC_CHAN_ABOVE; 2444 chan_band->band_cfg.chan_width = 2445 CHAN_BW_40MHZ; 2446 } else if (bw_offset == CHANNEL_BW_40MHZ_BELOW) { 2447 chan_band->band_cfg.chan_2O_ffset = 2448 NXPWIFI_SEC_CHAN_BELOW; 2449 chan_band->band_cfg.chan_width = 2450 CHAN_BW_40MHZ; 2451 } else if (bw_offset == CHANNEL_BW_80MHZ) { 2452 sec_chan_offset = 2453 nxpwifi_get_sec_chan_offset(net_mon->channel); 2454 if (sec_chan_offset == NXPWIFI_SEC_CHAN_ABOVE) 2455 chan_band->band_cfg.chan_2O_ffset = 2456 NXPWIFI_SEC_CHAN_ABOVE; 2457 else if (sec_chan_offset == NXPWIFI_SEC_CHAN_BELOW) 2458 chan_band->band_cfg.chan_2O_ffset = 2459 NXPWIFI_SEC_CHAN_BELOW; 2460 chan_band->band_cfg.chan_width = CHAN_BW_80MHZ; 2461 } 2462 } 2463 } 2464 } 2465 return 0; 2466 } 2467 2468 static int 2469 nxpwifi_ret_sta_802_11_net_monitor(struct nxpwifi_private *priv, 2470 struct host_cmd_ds_command *resp, 2471 u16 cmdresp_no, 2472 void *data_buf) 2473 { 2474 struct host_cmd_ds_802_11_net_monitor *cmd_net_mon = &resp->params.net_mon; 2475 2476 nxpwifi_dbg(priv->adapter, CMD, 2477 "cmd: NET_MONITOR_CMD: action: %d, enable: %d, flag: %d ch: %d band: %d bw: %d offset: %d\n", 2478 le16_to_cpu(cmd_net_mon->action), 2479 le16_to_cpu(cmd_net_mon->enable_net_mon), 2480 le16_to_cpu(cmd_net_mon->filter_flag), 2481 cmd_net_mon->monitor_chan.chan_band_param[0].chan_number, 2482 cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_band, 2483 cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_width, 2484 cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_2O_ffset); 2485 priv->adapter->enable_net_mon = le16_to_cpu(cmd_net_mon->enable_net_mon); 2486 return 0; 2487 } 2488 2489 static int 2490 nxpwifi_cmd_sta_802_11_scan_ext(struct nxpwifi_private *priv, 2491 struct host_cmd_ds_command *cmd, 2492 u16 cmd_no, void *data_buf, 2493 u16 cmd_action, u32 cmd_type) 2494 { 2495 return nxpwifi_cmd_802_11_scan_ext(priv, cmd, data_buf); 2496 } 2497 2498 static int 2499 nxpwifi_ret_sta_802_11_scan_ext(struct nxpwifi_private *priv, 2500 struct host_cmd_ds_command *resp, 2501 u16 cmdresp_no, 2502 void *data_buf) 2503 { 2504 struct nxpwifi_adapter *adapter = priv->adapter; 2505 int ret; 2506 2507 ret = nxpwifi_ret_802_11_scan_ext(priv, resp); 2508 adapter->curr_cmd->wait_q_enabled = false; 2509 2510 return ret; 2511 } 2512 2513 static int 2514 nxpwifi_cmd_sta_coalesce_cfg(struct nxpwifi_private *priv, 2515 struct host_cmd_ds_command *cmd, 2516 u16 cmd_no, void *data_buf, 2517 u16 cmd_action, u32 cmd_type) 2518 { 2519 struct host_cmd_ds_coalesce_cfg *coalesce_cfg = 2520 &cmd->params.coalesce_cfg; 2521 struct nxpwifi_ds_coalesce_cfg *cfg = 2522 (struct nxpwifi_ds_coalesce_cfg *)data_buf; 2523 struct coalesce_filt_field_param *param; 2524 u16 cnt, idx, length; 2525 struct coalesce_receive_filt_rule *rule; 2526 2527 cmd->command = cpu_to_le16(HOST_CMD_COALESCE_CFG); 2528 cmd->size = cpu_to_le16(S_DS_GEN); 2529 2530 coalesce_cfg->action = cpu_to_le16(cmd_action); 2531 coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules); 2532 rule = (void *)coalesce_cfg->rule_data; 2533 2534 for (cnt = 0; cnt < cfg->num_of_rules; cnt++) { 2535 rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE); 2536 rule->max_coalescing_delay = 2537 cpu_to_le16(cfg->rule[cnt].max_coalescing_delay); 2538 rule->pkt_type = cfg->rule[cnt].pkt_type; 2539 rule->num_of_fields = cfg->rule[cnt].num_of_fields; 2540 2541 length = 0; 2542 2543 param = rule->params; 2544 for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) { 2545 param->operation = cfg->rule[cnt].params[idx].operation; 2546 param->operand_len = 2547 cfg->rule[cnt].params[idx].operand_len; 2548 param->offset = 2549 cpu_to_le16(cfg->rule[cnt].params[idx].offset); 2550 memcpy(param->operand_byte_stream, 2551 cfg->rule[cnt].params[idx].operand_byte_stream, 2552 param->operand_len); 2553 2554 length += sizeof(struct coalesce_filt_field_param); 2555 2556 param++; 2557 } 2558 2559 /* 2560 * Total rule length is sizeof max_coalescing_delay(u16), 2561 * num_of_fields(u8), pkt_type(u8) and total length of the all 2562 * params 2563 */ 2564 rule->header.len = cpu_to_le16(length + sizeof(u16) + 2565 sizeof(u8) + sizeof(u8)); 2566 2567 /* Add the rule length to the command size */ 2568 le16_unaligned_add_cpu(&cmd->size, 2569 le16_to_cpu(rule->header.len) + 2570 sizeof(struct nxpwifi_ie_types_header)); 2571 2572 rule = (void *)((u8 *)rule->params + length); 2573 } 2574 2575 /* Add sizeof action, num_of_rules to total command length */ 2576 le16_unaligned_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16)); 2577 2578 return 0; 2579 } 2580 2581 static int 2582 nxpwifi_cmd_sta_mgmt_frame_reg(struct nxpwifi_private *priv, 2583 struct host_cmd_ds_command *cmd, 2584 u16 cmd_no, void *data_buf, 2585 u16 cmd_action, u32 cmd_type) 2586 { 2587 cmd->command = cpu_to_le16(cmd_no); 2588 cmd->params.reg_mask.action = cpu_to_le16(cmd_action); 2589 cmd->params.reg_mask.mask = 2590 cpu_to_le32(get_unaligned((u32 *)data_buf)); 2591 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) + 2592 S_DS_GEN); 2593 2594 return 0; 2595 } 2596 2597 static int 2598 nxpwifi_cmd_sta_remain_on_chan(struct nxpwifi_private *priv, 2599 struct host_cmd_ds_command *cmd, 2600 u16 cmd_no, void *data_buf, 2601 u16 cmd_action, u32 cmd_type) 2602 { 2603 cmd->command = cpu_to_le16(cmd_no); 2604 memcpy(&cmd->params, data_buf, 2605 sizeof(struct host_cmd_ds_remain_on_chan)); 2606 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + 2607 S_DS_GEN); 2608 2609 return 0; 2610 } 2611 2612 static int 2613 nxpwifi_ret_sta_remain_on_chan(struct nxpwifi_private *priv, 2614 struct host_cmd_ds_command *resp, 2615 u16 cmdresp_no, 2616 void *data_buf) 2617 { 2618 struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg; 2619 struct host_cmd_ds_remain_on_chan *roc_cfg = 2620 (struct host_cmd_ds_remain_on_chan *)data_buf; 2621 2622 if (roc_cfg) 2623 memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg)); 2624 2625 return 0; 2626 } 2627 2628 static int 2629 nxpwifi_cmd_sta_gtk_rekey_offload(struct nxpwifi_private *priv, 2630 struct host_cmd_ds_command *cmd, 2631 u16 cmd_no, void *data_buf, 2632 u16 cmd_action, u32 cmd_type) 2633 { 2634 struct host_cmd_ds_gtk_rekey_params *rekey = &cmd->params.rekey; 2635 struct cfg80211_gtk_rekey_data *data = 2636 (struct cfg80211_gtk_rekey_data *)data_buf; 2637 u64 rekey_ctr; 2638 2639 cmd->command = cpu_to_le16(HOST_CMD_GTK_REKEY_OFFLOAD_CFG); 2640 cmd->size = cpu_to_le16(sizeof(*rekey) + S_DS_GEN); 2641 2642 rekey->action = cpu_to_le16(cmd_action); 2643 if (cmd_action == HOST_ACT_GEN_SET) { 2644 memcpy(rekey->kek, data->kek, NL80211_KEK_LEN); 2645 memcpy(rekey->kck, data->kck, NL80211_KCK_LEN); 2646 rekey_ctr = be64_to_cpup((__be64 *)data->replay_ctr); 2647 rekey->replay_ctr_low = cpu_to_le32((u32)rekey_ctr); 2648 rekey->replay_ctr_high = 2649 cpu_to_le32((u32)((u64)rekey_ctr >> 32)); 2650 } 2651 2652 return 0; 2653 } 2654 2655 static int 2656 nxpwifi_cmd_sta_11ac_cfg(struct nxpwifi_private *priv, 2657 struct host_cmd_ds_command *cmd, 2658 u16 cmd_no, void *data_buf, 2659 u16 cmd_action, u32 cmd_type) 2660 { 2661 return nxpwifi_cmd_11ac_cfg(priv, cmd, cmd_action, data_buf); 2662 } 2663 2664 static int 2665 nxpwifi_cmd_sta_hs_wakeup_reason(struct nxpwifi_private *priv, 2666 struct host_cmd_ds_command *cmd, 2667 u16 cmd_no, void *data_buf, 2668 u16 cmd_action, u32 cmd_type) 2669 { 2670 cmd->command = cpu_to_le16(HOST_CMD_HS_WAKEUP_REASON); 2671 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) + 2672 S_DS_GEN); 2673 2674 return 0; 2675 } 2676 2677 static int 2678 nxpwifi_ret_sta_hs_wakeup_reason(struct nxpwifi_private *priv, 2679 struct host_cmd_ds_command *resp, 2680 u16 cmdresp_no, 2681 void *data_buf) 2682 { 2683 struct host_cmd_ds_wakeup_reason *wakeup_reason = 2684 (struct host_cmd_ds_wakeup_reason *)data_buf; 2685 2686 if (!wakeup_reason) 2687 return 0; 2688 2689 wakeup_reason->wakeup_reason = 2690 resp->params.hs_wakeup_reason.wakeup_reason; 2691 2692 return 0; 2693 } 2694 2695 static int 2696 nxpwifi_cmd_sta_mc_policy(struct nxpwifi_private *priv, 2697 struct host_cmd_ds_command *cmd, 2698 u16 cmd_no, void *data_buf, 2699 u16 cmd_action, u32 cmd_type) 2700 { 2701 struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy; 2702 const u16 *drcs_info = data_buf; 2703 2704 mc_pol->action = cpu_to_le16(cmd_action); 2705 mc_pol->policy = cpu_to_le16(*drcs_info); 2706 cmd->command = cpu_to_le16(HOST_CMD_MC_POLICY); 2707 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) + 2708 S_DS_GEN); 2709 return 0; 2710 } 2711 2712 static int 2713 nxpwifi_cmd_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv, 2714 struct host_cmd_ds_command *cmd, 2715 u16 cmd_no, void *data_buf, 2716 u16 cmd_action, u32 cmd_type) 2717 { 2718 struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = 2719 &cmd->params.sdio_rx_aggr_cfg; 2720 2721 cmd->command = cpu_to_le16(HOST_CMD_SDIO_SP_RX_AGGR_CFG); 2722 cmd->size = 2723 cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) + 2724 S_DS_GEN); 2725 cfg->action = cmd_action; 2726 if (cmd_action == HOST_ACT_GEN_SET) 2727 cfg->enable = *(u8 *)data_buf; 2728 2729 return 0; 2730 } 2731 2732 static int 2733 nxpwifi_ret_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv, 2734 struct host_cmd_ds_command *resp, 2735 u16 cmdresp_no, 2736 void *data_buf) 2737 { 2738 struct nxpwifi_adapter *adapter = priv->adapter; 2739 struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = 2740 &resp->params.sdio_rx_aggr_cfg; 2741 2742 adapter->sdio_rx_aggr_enable = cfg->enable; 2743 adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size); 2744 2745 return 0; 2746 } 2747 2748 static int 2749 nxpwifi_cmd_sta_get_chan_info(struct nxpwifi_private *priv, 2750 struct host_cmd_ds_command *cmd, 2751 u16 cmd_no, void *data_buf, 2752 u16 cmd_action, u32 cmd_type) 2753 { 2754 struct host_cmd_ds_sta_configure *sta_cfg_cmd = &cmd->params.sta_cfg; 2755 struct host_cmd_tlv_channel_band *tlv_band_channel = 2756 (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer; 2757 2758 cmd->command = cpu_to_le16(HOST_CMD_STA_CONFIGURE); 2759 cmd->size = cpu_to_le16(sizeof(*sta_cfg_cmd) + 2760 sizeof(*tlv_band_channel) + S_DS_GEN); 2761 sta_cfg_cmd->action = cpu_to_le16(cmd_action); 2762 memset(tlv_band_channel, 0, sizeof(*tlv_band_channel)); 2763 tlv_band_channel->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); 2764 tlv_band_channel->header.len = cpu_to_le16(sizeof(*tlv_band_channel) - 2765 sizeof(struct nxpwifi_ie_types_header)); 2766 2767 return 0; 2768 } 2769 2770 static int 2771 nxpwifi_ret_sta_get_chan_info(struct nxpwifi_private *priv, 2772 struct host_cmd_ds_command *resp, 2773 u16 cmdresp_no, 2774 void *data_buf) 2775 { 2776 struct host_cmd_ds_sta_configure *sta_cfg_cmd = &resp->params.sta_cfg; 2777 struct nxpwifi_channel_band *channel_band = 2778 (struct nxpwifi_channel_band *)data_buf; 2779 struct host_cmd_tlv_channel_band *tlv_band_channel; 2780 2781 if (!channel_band) 2782 return 0; 2783 2784 tlv_band_channel = 2785 (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer; 2786 memcpy(&channel_band->band_config, &tlv_band_channel->band_config, 2787 sizeof(struct nxpwifi_band_config)); 2788 channel_band->channel = tlv_band_channel->channel; 2789 2790 return 0; 2791 } 2792 2793 static int 2794 nxpwifi_cmd_sta_chan_region_cfg(struct nxpwifi_private *priv, 2795 struct host_cmd_ds_command *cmd, 2796 u16 cmd_no, void *data_buf, 2797 u16 cmd_action, u32 cmd_type) 2798 { 2799 struct host_cmd_ds_chan_region_cfg *reg = &cmd->params.reg_cfg; 2800 2801 cmd->command = cpu_to_le16(HOST_CMD_CHAN_REGION_CFG); 2802 cmd->size = cpu_to_le16(sizeof(*reg) + S_DS_GEN); 2803 2804 if (cmd_action == HOST_ACT_GEN_GET) 2805 reg->action = cpu_to_le16(cmd_action); 2806 2807 return 0; 2808 } 2809 2810 static struct ieee80211_regdomain * 2811 nxpwifi_create_custom_regdomain(struct nxpwifi_private *priv, 2812 u8 *buf, u16 buf_len) 2813 { 2814 u16 num_chan = buf_len / 2; 2815 struct ieee80211_regdomain *regd; 2816 struct ieee80211_reg_rule *rule; 2817 bool new_rule; 2818 int idx, freq, prev_freq = 0; 2819 u32 bw, prev_bw = 0; 2820 u8 chflags, prev_chflags = 0, valid_rules = 0; 2821 2822 if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES)) 2823 return ERR_PTR(-EINVAL); 2824 2825 regd = kzalloc_flex(*regd, reg_rules, num_chan, GFP_KERNEL); 2826 if (!regd) 2827 return ERR_PTR(-ENOMEM); 2828 2829 for (idx = 0; idx < num_chan; idx++) { 2830 u8 chan; 2831 enum nl80211_band band; 2832 2833 chan = *buf++; 2834 if (!chan) { 2835 kfree(regd); 2836 return NULL; 2837 } 2838 chflags = *buf++; 2839 band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; 2840 freq = ieee80211_channel_to_frequency(chan, band); 2841 new_rule = false; 2842 2843 if (chflags & NXPWIFI_CHANNEL_DISABLED) 2844 continue; 2845 2846 if (band == NL80211_BAND_5GHZ) { 2847 if (!(chflags & NXPWIFI_CHANNEL_NOHT80)) 2848 bw = MHZ_TO_KHZ(80); 2849 else if (!(chflags & NXPWIFI_CHANNEL_NOHT40)) 2850 bw = MHZ_TO_KHZ(40); 2851 else 2852 bw = MHZ_TO_KHZ(20); 2853 } else { 2854 if (!(chflags & NXPWIFI_CHANNEL_NOHT40)) 2855 bw = MHZ_TO_KHZ(40); 2856 else 2857 bw = MHZ_TO_KHZ(20); 2858 } 2859 2860 if (idx == 0 || prev_chflags != chflags || prev_bw != bw || 2861 freq - prev_freq > 20) { 2862 valid_rules++; 2863 new_rule = true; 2864 } 2865 2866 rule = ®d->reg_rules[valid_rules - 1]; 2867 2868 rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10); 2869 2870 prev_chflags = chflags; 2871 prev_freq = freq; 2872 prev_bw = bw; 2873 2874 if (!new_rule) 2875 continue; 2876 2877 rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10); 2878 rule->power_rule.max_eirp = DBM_TO_MBM(19); 2879 2880 if (chflags & NXPWIFI_CHANNEL_PASSIVE) 2881 rule->flags = NL80211_RRF_NO_IR; 2882 2883 if (chflags & NXPWIFI_CHANNEL_DFS) 2884 rule->flags = NL80211_RRF_DFS; 2885 2886 rule->freq_range.max_bandwidth_khz = bw; 2887 } 2888 2889 regd->n_reg_rules = valid_rules; 2890 regd->alpha2[0] = '9'; 2891 regd->alpha2[1] = '9'; 2892 2893 return regd; 2894 } 2895 2896 static int 2897 nxpwifi_ret_sta_chan_region_cfg(struct nxpwifi_private *priv, 2898 struct host_cmd_ds_command *resp, 2899 u16 cmdresp_no, 2900 void *data_buf) 2901 { 2902 struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg; 2903 u16 action = le16_to_cpu(reg->action); 2904 u16 tlv, tlv_buf_len, tlv_buf_left; 2905 struct nxpwifi_ie_types_header *head; 2906 struct ieee80211_regdomain *regd; 2907 u8 *tlv_buf; 2908 2909 if (action != HOST_ACT_GEN_GET) 2910 return 0; 2911 2912 tlv_buf = (u8 *)reg + sizeof(*reg); 2913 tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg); 2914 2915 while (tlv_buf_left >= sizeof(*head)) { 2916 head = (struct nxpwifi_ie_types_header *)tlv_buf; 2917 tlv = le16_to_cpu(head->type); 2918 tlv_buf_len = le16_to_cpu(head->len); 2919 2920 if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) 2921 break; 2922 2923 switch (tlv) { 2924 case TLV_TYPE_CHAN_ATTR_CFG: 2925 nxpwifi_dbg_dump(priv->adapter, CMD_D, "CHAN:", 2926 (u8 *)head + sizeof(*head), 2927 tlv_buf_len); 2928 regd = nxpwifi_create_custom_regdomain(priv, (u8 *)head 2929 + sizeof(*head), 2930 tlv_buf_len); 2931 if (!IS_ERR(regd)) 2932 priv->adapter->regd = regd; 2933 break; 2934 } 2935 2936 tlv_buf += (sizeof(*head) + tlv_buf_len); 2937 tlv_buf_left -= (sizeof(*head) + tlv_buf_len); 2938 } 2939 2940 return 0; 2941 } 2942 2943 static int 2944 nxpwifi_cmd_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv, 2945 struct host_cmd_ds_command *cmd, 2946 u16 cmd_no, void *data_buf, 2947 u16 cmd_action, u32 cmd_type) 2948 { 2949 cmd->command = cpu_to_le16(cmd_no); 2950 cmd->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action); 2951 cmd->params.pkt_aggr_ctrl.enable = cpu_to_le16(*(u16 *)data_buf); 2952 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) + 2953 S_DS_GEN); 2954 2955 return 0; 2956 } 2957 2958 static int 2959 nxpwifi_ret_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv, 2960 struct host_cmd_ds_command *resp, 2961 u16 cmdresp_no, 2962 void *data_buf) 2963 { 2964 struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl = 2965 &resp->params.pkt_aggr_ctrl; 2966 struct nxpwifi_adapter *adapter = priv->adapter; 2967 2968 adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable); 2969 if (adapter->bus_aggr.enable) 2970 adapter->intf_hdr_len = INTF_HEADER_LEN; 2971 adapter->bus_aggr.mode = NXPWIFI_BUS_AGGR_MODE_LEN_V2; 2972 adapter->bus_aggr.tx_aggr_max_size = 2973 le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size); 2974 adapter->bus_aggr.tx_aggr_max_num = 2975 le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num); 2976 adapter->bus_aggr.tx_aggr_align = 2977 le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align); 2978 2979 return 0; 2980 } 2981 2982 static int 2983 nxpwifi_cmd_sta_11ax_cfg(struct nxpwifi_private *priv, 2984 struct host_cmd_ds_command *cmd, 2985 u16 cmd_no, void *data_buf, 2986 u16 cmd_action, u32 cmd_type) 2987 { 2988 return nxpwifi_cmd_11ax_cfg(priv, cmd, cmd_action, data_buf); 2989 } 2990 2991 static int 2992 nxpwifi_ret_sta_11ax_cfg(struct nxpwifi_private *priv, 2993 struct host_cmd_ds_command *resp, 2994 u16 cmdresp_no, 2995 void *data_buf) 2996 { 2997 return nxpwifi_ret_11ax_cfg(priv, resp, data_buf); 2998 } 2999 3000 static int 3001 nxpwifi_cmd_sta_11ax_cmd(struct nxpwifi_private *priv, 3002 struct host_cmd_ds_command *cmd, 3003 u16 cmd_no, void *data_buf, 3004 u16 cmd_action, u32 cmd_type) 3005 { 3006 return nxpwifi_cmd_11ax_cmd(priv, cmd, cmd_action, data_buf); 3007 } 3008 3009 static int 3010 nxpwifi_ret_sta_11ax_cmd(struct nxpwifi_private *priv, 3011 struct host_cmd_ds_command *resp, 3012 u16 cmdresp_no, 3013 void *data_buf) 3014 { 3015 return nxpwifi_ret_11ax_cmd(priv, resp, data_buf); 3016 } 3017 3018 static int 3019 nxpwifi_cmd_sta_twt_cfg(struct nxpwifi_private *priv, 3020 struct host_cmd_ds_command *cmd, 3021 u16 cmd_no, void *data_buf, 3022 u16 cmd_action, u32 cmd_type) 3023 { 3024 return nxpwifi_cmd_twt_cfg(priv, cmd, cmd_action, data_buf); 3025 } 3026 3027 static int 3028 nxpwifi_ret_sta_twt_cfg(struct nxpwifi_private *priv, 3029 struct host_cmd_ds_command *resp, 3030 u16 cmdresp_no, 3031 void *data_buf) 3032 { 3033 return nxpwifi_ret_twt_cfg(priv, resp, data_buf); 3034 } 3035 3036 static const struct nxpwifi_cmd_entry cmd_table_sta[] = { 3037 {.cmd_no = HOST_CMD_GET_HW_SPEC, 3038 .prepare_cmd = nxpwifi_cmd_sta_get_hw_spec, 3039 .cmd_resp = nxpwifi_ret_sta_get_hw_spec}, 3040 {.cmd_no = HOST_CMD_802_11_SCAN, 3041 .prepare_cmd = nxpwifi_cmd_sta_802_11_scan, 3042 .cmd_resp = nxpwifi_ret_sta_802_11_scan}, 3043 {.cmd_no = HOST_CMD_802_11_GET_LOG, 3044 .prepare_cmd = nxpwifi_cmd_sta_802_11_get_log, 3045 .cmd_resp = nxpwifi_ret_sta_802_11_get_log}, 3046 {.cmd_no = HOST_CMD_MAC_MULTICAST_ADR, 3047 .prepare_cmd = nxpwifi_cmd_sta_mac_multicast_adr, 3048 .cmd_resp = NULL}, 3049 {.cmd_no = HOST_CMD_802_11_ASSOCIATE, 3050 .prepare_cmd = nxpwifi_cmd_sta_802_11_associate, 3051 .cmd_resp = nxpwifi_ret_sta_802_11_associate}, 3052 {.cmd_no = HOST_CMD_802_11_SNMP_MIB, 3053 .prepare_cmd = nxpwifi_cmd_sta_802_11_snmp_mib, 3054 .cmd_resp = nxpwifi_ret_sta_802_11_snmp_mib}, 3055 {.cmd_no = HOST_CMD_MAC_REG_ACCESS, 3056 .prepare_cmd = nxpwifi_cmd_sta_reg_access, 3057 .cmd_resp = nxpwifi_ret_sta_reg_access}, 3058 {.cmd_no = HOST_CMD_BBP_REG_ACCESS, 3059 .prepare_cmd = nxpwifi_cmd_sta_reg_access, 3060 .cmd_resp = nxpwifi_ret_sta_reg_access}, 3061 {.cmd_no = HOST_CMD_RF_REG_ACCESS, 3062 .prepare_cmd = nxpwifi_cmd_sta_reg_access, 3063 .cmd_resp = nxpwifi_ret_sta_reg_access}, 3064 {.cmd_no = HOST_CMD_RF_TX_PWR, 3065 .prepare_cmd = nxpwifi_cmd_sta_rf_tx_pwr, 3066 .cmd_resp = nxpwifi_ret_sta_rf_tx_pwr}, 3067 {.cmd_no = HOST_CMD_RF_ANTENNA, 3068 .prepare_cmd = nxpwifi_cmd_sta_rf_antenna, 3069 .cmd_resp = nxpwifi_ret_sta_rf_antenna}, 3070 {.cmd_no = HOST_CMD_802_11_DEAUTHENTICATE, 3071 .prepare_cmd = nxpwifi_cmd_sta_802_11_deauthenticate, 3072 .cmd_resp = nxpwifi_ret_sta_802_11_deauthenticate}, 3073 {.cmd_no = HOST_CMD_MAC_CONTROL, 3074 .prepare_cmd = nxpwifi_cmd_sta_mac_control, 3075 .cmd_resp = NULL}, 3076 {.cmd_no = HOST_CMD_802_11_MAC_ADDRESS, 3077 .prepare_cmd = nxpwifi_cmd_sta_802_11_mac_address, 3078 .cmd_resp = nxpwifi_ret_sta_802_11_mac_address}, 3079 {.cmd_no = HOST_CMD_802_11_EEPROM_ACCESS, 3080 .prepare_cmd = nxpwifi_cmd_sta_reg_access, 3081 .cmd_resp = nxpwifi_ret_sta_reg_access}, 3082 {.cmd_no = HOST_CMD_802_11D_DOMAIN_INFO, 3083 .prepare_cmd = nxpwifi_cmd_sta_802_11d_domain_info, 3084 .cmd_resp = nxpwifi_ret_sta_802_11d_domain_info}, 3085 {.cmd_no = HOST_CMD_802_11_KEY_MATERIAL, 3086 .prepare_cmd = nxpwifi_cmd_sta_802_11_key_material, 3087 .cmd_resp = nxpwifi_ret_sta_802_11_key_material}, 3088 {.cmd_no = HOST_CMD_802_11_BG_SCAN_CONFIG, 3089 .prepare_cmd = nxpwifi_cmd_sta_802_11_bg_scan_config, 3090 .cmd_resp = NULL}, 3091 {.cmd_no = HOST_CMD_802_11_BG_SCAN_QUERY, 3092 .prepare_cmd = nxpwifi_cmd_sta_802_11_bg_scan_query, 3093 .cmd_resp = nxpwifi_ret_sta_802_11_bg_scan_query}, 3094 {.cmd_no = HOST_CMD_WMM_GET_STATUS, 3095 .prepare_cmd = nxpwifi_cmd_sta_wmm_get_status, 3096 .cmd_resp = nxpwifi_ret_sta_wmm_get_status}, 3097 {.cmd_no = HOST_CMD_802_11_SUBSCRIBE_EVENT, 3098 .prepare_cmd = nxpwifi_cmd_sta_802_11_subsc_evt, 3099 .cmd_resp = nxpwifi_ret_sta_subsc_evt}, 3100 {.cmd_no = HOST_CMD_802_11_TX_RATE_QUERY, 3101 .prepare_cmd = nxpwifi_cmd_sta_802_11_tx_rate_query, 3102 .cmd_resp = nxpwifi_ret_sta_802_11_tx_rate_query}, 3103 {.cmd_no = HOST_CMD_MEM_ACCESS, 3104 .prepare_cmd = nxpwifi_cmd_sta_mem_access, 3105 .cmd_resp = nxpwifi_ret_sta_mem_access}, 3106 {.cmd_no = HOST_CMD_CFG_DATA, 3107 .prepare_cmd = nxpwifi_cmd_sta_cfg_data, 3108 .cmd_resp = nxpwifi_ret_sta_cfg_data}, 3109 {.cmd_no = HOST_CMD_VERSION_EXT, 3110 .prepare_cmd = nxpwifi_cmd_sta_ver_ext, 3111 .cmd_resp = nxpwifi_ret_sta_ver_ext}, 3112 {.cmd_no = HOST_CMD_MEF_CFG, 3113 .prepare_cmd = nxpwifi_cmd_sta_mef_cfg, 3114 .cmd_resp = NULL}, 3115 {.cmd_no = HOST_CMD_RSSI_INFO, 3116 .prepare_cmd = nxpwifi_cmd_sta_802_11_rssi_info, 3117 .cmd_resp = nxpwifi_ret_sta_802_11_rssi_info}, 3118 {.cmd_no = HOST_CMD_FUNC_INIT, 3119 .prepare_cmd = nxpwifi_cmd_sta_func_init, 3120 .cmd_resp = NULL}, 3121 {.cmd_no = HOST_CMD_FUNC_SHUTDOWN, 3122 .prepare_cmd = nxpwifi_cmd_sta_func_shutdown, 3123 .cmd_resp = NULL}, 3124 {.cmd_no = HOST_CMD_PMIC_REG_ACCESS, 3125 .prepare_cmd = nxpwifi_cmd_sta_reg_access, 3126 .cmd_resp = nxpwifi_ret_sta_reg_access}, 3127 {.cmd_no = HOST_CMD_11N_CFG, 3128 .prepare_cmd = nxpwifi_cmd_sta_11n_cfg, 3129 .cmd_resp = NULL}, 3130 {.cmd_no = HOST_CMD_11N_ADDBA_REQ, 3131 .prepare_cmd = nxpwifi_cmd_sta_11n_addba_req, 3132 .cmd_resp = nxpwifi_ret_sta_11n_addba_req}, 3133 {.cmd_no = HOST_CMD_11N_ADDBA_RSP, 3134 .prepare_cmd = nxpwifi_cmd_sta_11n_addba_rsp, 3135 .cmd_resp = nxpwifi_ret_sta_11n_addba_rsp}, 3136 {.cmd_no = HOST_CMD_11N_DELBA, 3137 .prepare_cmd = nxpwifi_cmd_sta_11n_delba, 3138 .cmd_resp = nxpwifi_ret_sta_11n_delba}, 3139 {.cmd_no = HOST_CMD_TXPWR_CFG, 3140 .prepare_cmd = nxpwifi_cmd_sta_tx_power_cfg, 3141 .cmd_resp = nxpwifi_ret_sta_tx_power_cfg}, 3142 {.cmd_no = HOST_CMD_TX_RATE_CFG, 3143 .prepare_cmd = nxpwifi_cmd_sta_tx_rate_cfg, 3144 .cmd_resp = nxpwifi_ret_sta_tx_rate_cfg}, 3145 {.cmd_no = HOST_CMD_RECONFIGURE_TX_BUFF, 3146 .prepare_cmd = nxpwifi_cmd_sta_reconfigure_rx_buff, 3147 .cmd_resp = nxpwifi_ret_sta_reconfigure_rx_buff}, 3148 {.cmd_no = HOST_CMD_CHAN_REPORT_REQUEST, 3149 .prepare_cmd = nxpwifi_cmd_sta_chan_report_request, 3150 .cmd_resp = NULL}, 3151 {.cmd_no = HOST_CMD_AMSDU_AGGR_CTRL, 3152 .prepare_cmd = nxpwifi_cmd_sta_amsdu_aggr_ctrl, 3153 .cmd_resp = NULL}, 3154 {.cmd_no = HOST_CMD_ROBUST_COEX, 3155 .prepare_cmd = nxpwifi_cmd_sta_robust_coex, 3156 .cmd_resp = nxpwifi_ret_sta_robust_coex}, 3157 {.cmd_no = HOST_CMD_802_11_PS_MODE_ENH, 3158 .prepare_cmd = nxpwifi_cmd_sta_enh_power_mode, 3159 .cmd_resp = nxpwifi_ret_sta_enh_power_mode}, 3160 {.cmd_no = HOST_CMD_802_11_HS_CFG_ENH, 3161 .prepare_cmd = nxpwifi_cmd_sta_802_11_hs_cfg, 3162 .cmd_resp = nxpwifi_ret_sta_802_11_hs_cfg}, 3163 {.cmd_no = HOST_CMD_CAU_REG_ACCESS, 3164 .prepare_cmd = nxpwifi_cmd_sta_reg_access, 3165 .cmd_resp = nxpwifi_ret_sta_reg_access}, 3166 {.cmd_no = HOST_CMD_SET_BSS_MODE, 3167 .prepare_cmd = nxpwifi_cmd_sta_set_bss_mode, 3168 .cmd_resp = NULL}, 3169 {.cmd_no = HOST_CMD_802_11_NET_MONITOR, 3170 .prepare_cmd = nxpwifi_cmd_sta_802_11_net_monitor, 3171 .cmd_resp = nxpwifi_ret_sta_802_11_net_monitor}, 3172 {.cmd_no = HOST_CMD_802_11_SCAN_EXT, 3173 .prepare_cmd = nxpwifi_cmd_sta_802_11_scan_ext, 3174 .cmd_resp = nxpwifi_ret_sta_802_11_scan_ext}, 3175 {.cmd_no = HOST_CMD_COALESCE_CFG, 3176 .prepare_cmd = nxpwifi_cmd_sta_coalesce_cfg, 3177 .cmd_resp = NULL}, 3178 {.cmd_no = HOST_CMD_MGMT_FRAME_REG, 3179 .prepare_cmd = nxpwifi_cmd_sta_mgmt_frame_reg, 3180 .cmd_resp = NULL}, 3181 {.cmd_no = HOST_CMD_REMAIN_ON_CHAN, 3182 .prepare_cmd = nxpwifi_cmd_sta_remain_on_chan, 3183 .cmd_resp = nxpwifi_ret_sta_remain_on_chan}, 3184 {.cmd_no = HOST_CMD_GTK_REKEY_OFFLOAD_CFG, 3185 .prepare_cmd = nxpwifi_cmd_sta_gtk_rekey_offload, 3186 .cmd_resp = NULL}, 3187 {.cmd_no = HOST_CMD_11AC_CFG, 3188 .prepare_cmd = nxpwifi_cmd_sta_11ac_cfg, 3189 .cmd_resp = NULL}, 3190 {.cmd_no = HOST_CMD_HS_WAKEUP_REASON, 3191 .prepare_cmd = nxpwifi_cmd_sta_hs_wakeup_reason, 3192 .cmd_resp = nxpwifi_ret_sta_hs_wakeup_reason}, 3193 {.cmd_no = HOST_CMD_MC_POLICY, 3194 .prepare_cmd = nxpwifi_cmd_sta_mc_policy, 3195 .cmd_resp = NULL}, 3196 {.cmd_no = HOST_CMD_FW_DUMP_EVENT, 3197 .prepare_cmd = nxpwifi_cmd_fill_head_only, 3198 .cmd_resp = NULL}, 3199 {.cmd_no = HOST_CMD_SDIO_SP_RX_AGGR_CFG, 3200 .prepare_cmd = nxpwifi_cmd_sta_sdio_rx_aggr_cfg, 3201 .cmd_resp = nxpwifi_ret_sta_sdio_rx_aggr_cfg}, 3202 {.cmd_no = HOST_CMD_STA_CONFIGURE, 3203 .prepare_cmd = nxpwifi_cmd_sta_get_chan_info, 3204 .cmd_resp = nxpwifi_ret_sta_get_chan_info}, 3205 {.cmd_no = HOST_CMD_CHAN_REGION_CFG, 3206 .prepare_cmd = nxpwifi_cmd_sta_chan_region_cfg, 3207 .cmd_resp = nxpwifi_ret_sta_chan_region_cfg}, 3208 {.cmd_no = HOST_CMD_PACKET_AGGR_CTRL, 3209 .prepare_cmd = nxpwifi_cmd_sta_pkt_aggr_ctrl, 3210 .cmd_resp = nxpwifi_ret_sta_pkt_aggr_ctrl}, 3211 {.cmd_no = HOST_CMD_11AX_CFG, 3212 .prepare_cmd = nxpwifi_cmd_sta_11ax_cfg, 3213 .cmd_resp = nxpwifi_ret_sta_11ax_cfg}, 3214 {.cmd_no = HOST_CMD_11AX_CMD, 3215 .prepare_cmd = nxpwifi_cmd_sta_11ax_cmd, 3216 .cmd_resp = nxpwifi_ret_sta_11ax_cmd}, 3217 {.cmd_no = HOST_CMD_TWT_CFG, 3218 .prepare_cmd = nxpwifi_cmd_sta_twt_cfg, 3219 .cmd_resp = nxpwifi_ret_sta_twt_cfg}, 3220 }; 3221 3222 /* 3223 * Prepare a command before sending it to firmware by invoking the 3224 * appropriate handler based on the command ID. 3225 */ 3226 int nxpwifi_sta_prepare_cmd(struct nxpwifi_private *priv, 3227 struct cmd_ctrl_node *cmd_node, 3228 u16 cmd_action, u32 cmd_oid) 3229 3230 { 3231 struct nxpwifi_adapter *adapter = priv->adapter; 3232 u16 cmd_no = cmd_node->cmd_no; 3233 struct host_cmd_ds_command *cmd = 3234 (struct host_cmd_ds_command *)cmd_node->skb->data; 3235 void *data_buf = cmd_node->data_buf; 3236 int i, ret = -EINVAL; 3237 3238 for (i = 0; i < ARRAY_SIZE(cmd_table_sta); i++) { 3239 if (cmd_no == cmd_table_sta[i].cmd_no) { 3240 if (cmd_table_sta[i].prepare_cmd) 3241 ret = cmd_table_sta[i].prepare_cmd(priv, cmd, 3242 cmd_no, 3243 data_buf, 3244 cmd_action, 3245 cmd_oid); 3246 cmd_node->cmd_resp = cmd_table_sta[i].cmd_resp; 3247 break; 3248 } 3249 } 3250 3251 if (i == ARRAY_SIZE(cmd_table_sta)) 3252 nxpwifi_dbg(adapter, ERROR, 3253 "%s: unknown command: %#x\n", 3254 __func__, cmd_no); 3255 else 3256 nxpwifi_dbg(adapter, CMD, 3257 "%s: command: %#x\n", 3258 __func__, cmd_no); 3259 3260 return ret; 3261 } 3262 3263 /* 3264 * Initialize firmware after download or during virtual interface 3265 * reinitialization to bring the device to a working state. 3266 */ 3267 int nxpwifi_sta_init_cmd(struct nxpwifi_private *priv, u8 first_sta, bool init) 3268 { 3269 struct nxpwifi_adapter *adapter = priv->adapter; 3270 int ret; 3271 struct nxpwifi_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; 3272 struct nxpwifi_ds_auto_ds auto_ds; 3273 enum state_11d_t state_11d; 3274 struct nxpwifi_ds_11n_tx_cfg tx_cfg; 3275 u8 sdio_sp_rx_aggr_enable; 3276 3277 if (first_sta) { 3278 ret = nxpwifi_send_cmd(priv, HOST_CMD_FUNC_INIT, 3279 HOST_ACT_GEN_SET, 0, NULL, true); 3280 if (ret) 3281 return ret; 3282 3283 if (adapter->cal_data) 3284 nxpwifi_send_cmd(priv, HOST_CMD_CFG_DATA, 3285 HOST_ACT_GEN_SET, 0, NULL, true); 3286 3287 /* Read MAC address from HW */ 3288 ret = nxpwifi_send_cmd(priv, HOST_CMD_GET_HW_SPEC, 3289 HOST_ACT_GEN_GET, 0, NULL, true); 3290 if (ret) 3291 return ret; 3292 3293 /* * Set SDIO Single Port RX Aggr Info */ 3294 if (priv->adapter->iface_type == NXPWIFI_SDIO && 3295 ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) && 3296 !priv->adapter->host_disable_sdio_rx_aggr) { 3297 sdio_sp_rx_aggr_enable = true; 3298 ret = nxpwifi_send_cmd(priv, 3299 HOST_CMD_SDIO_SP_RX_AGGR_CFG, 3300 HOST_ACT_GEN_SET, 0, 3301 &sdio_sp_rx_aggr_enable, 3302 true); 3303 if (ret) { 3304 nxpwifi_dbg(priv->adapter, ERROR, 3305 "error while enabling SP aggregation..disable it"); 3306 adapter->sdio_rx_aggr_enable = false; 3307 } 3308 } 3309 3310 /* Reconfigure tx buf size */ 3311 ret = nxpwifi_send_cmd(priv, HOST_CMD_RECONFIGURE_TX_BUFF, 3312 HOST_ACT_GEN_SET, 0, 3313 &priv->adapter->tx_buf_size, true); 3314 if (ret) 3315 return ret; 3316 3317 if (priv->bss_type != NXPWIFI_BSS_TYPE_UAP) { 3318 /* Enable IEEE PS by default */ 3319 priv->adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_PSP; 3320 ret = nxpwifi_send_cmd(priv, 3321 HOST_CMD_802_11_PS_MODE_ENH, 3322 EN_AUTO_PS, BITMAP_STA_PS, NULL, 3323 true); 3324 if (ret) 3325 return ret; 3326 } 3327 3328 nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REGION_CFG, 3329 HOST_ACT_GEN_GET, 0, NULL, true); 3330 } 3331 3332 /* get tx rate */ 3333 ret = nxpwifi_send_cmd(priv, HOST_CMD_TX_RATE_CFG, 3334 HOST_ACT_GEN_GET, 0, NULL, true); 3335 if (ret) 3336 return ret; 3337 priv->data_rate = 0; 3338 3339 /* get tx power */ 3340 ret = nxpwifi_send_cmd(priv, HOST_CMD_RF_TX_PWR, 3341 HOST_ACT_GEN_GET, 0, NULL, true); 3342 if (ret) 3343 return ret; 3344 3345 memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); 3346 amsdu_aggr_ctrl.enable = true; 3347 /* Send request to firmware */ 3348 ret = nxpwifi_send_cmd(priv, HOST_CMD_AMSDU_AGGR_CTRL, 3349 HOST_ACT_GEN_SET, 0, 3350 &amsdu_aggr_ctrl, true); 3351 if (ret) 3352 return ret; 3353 /* MAC Control must be the last command in init_fw */ 3354 /* set MAC Control */ 3355 ret = nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL, 3356 HOST_ACT_GEN_SET, 0, 3357 &priv->curr_pkt_filter, true); 3358 if (ret) 3359 return ret; 3360 3361 if (!disable_auto_ds && first_sta && 3362 priv->bss_type != NXPWIFI_BSS_TYPE_UAP) { 3363 /* Enable auto deep sleep */ 3364 auto_ds.auto_ds = DEEP_SLEEP_ON; 3365 auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; 3366 ret = nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH, 3367 EN_AUTO_PS, BITMAP_AUTO_DS, 3368 &auto_ds, true); 3369 if (ret) 3370 return ret; 3371 } 3372 3373 if (priv->bss_type != NXPWIFI_BSS_TYPE_UAP) { 3374 /* Send cmd to FW to enable/disable 11D function */ 3375 state_11d = ENABLE_11D; 3376 ret = nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, 3377 HOST_ACT_GEN_SET, DOT11D_I, 3378 &state_11d, true); 3379 if (ret) 3380 nxpwifi_dbg(priv->adapter, ERROR, 3381 "11D: failed to enable 11D\n"); 3382 } 3383 3384 /* 3385 * Send cmd to FW to configure 11n specific configuration 3386 * (Short GI, Channel BW, Green field support etc.) for transmit 3387 */ 3388 tx_cfg.tx_htcap = NXPWIFI_FW_DEF_HTTXCFG; 3389 ret = nxpwifi_send_cmd(priv, HOST_CMD_11N_CFG, 3390 HOST_ACT_GEN_SET, 0, &tx_cfg, true); 3391 3392 return ret; 3393 } 3394