1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * nxpwifi: commands and events 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 16 static void nxpwifi_cancel_pending_ioctl(struct nxpwifi_adapter *adapter); 17 18 /* Initialize command node; set defaults; buffers are supplied by caller. */ 19 static void 20 nxpwifi_init_cmd_node(struct nxpwifi_private *priv, 21 struct cmd_ctrl_node *cmd_node, 22 u32 cmd_no, void *data_buf, bool sync) 23 { 24 cmd_node->priv = priv; 25 cmd_node->cmd_no = cmd_no; 26 27 if (sync) { 28 cmd_node->wait_q_enabled = true; 29 cmd_node->cmd_wait_q_woken = false; 30 cmd_node->condition = &cmd_node->cmd_wait_q_woken; 31 } 32 cmd_node->data_buf = data_buf; 33 cmd_node->cmd_skb = cmd_node->skb; 34 cmd_node->cmd_resp = NULL; 35 } 36 37 /* Get a free command node from cmd_free_q; return NULL if none. */ 38 static struct cmd_ctrl_node * 39 nxpwifi_get_cmd_node(struct nxpwifi_adapter *adapter) 40 { 41 struct cmd_ctrl_node *cmd_node; 42 43 spin_lock_bh(&adapter->cmd_free_q_lock); 44 if (list_empty(&adapter->cmd_free_q)) { 45 nxpwifi_dbg(adapter, ERROR, 46 "GET_CMD_NODE: cmd node not available\n"); 47 spin_unlock_bh(&adapter->cmd_free_q_lock); 48 return NULL; 49 } 50 cmd_node = list_first_entry(&adapter->cmd_free_q, 51 struct cmd_ctrl_node, list); 52 list_del(&cmd_node->list); 53 spin_unlock_bh(&adapter->cmd_free_q_lock); 54 55 return cmd_node; 56 } 57 58 /* Reset cmd node state; trim cmd skb; complete and clear resp_skb if present. */ 59 static void 60 nxpwifi_clean_cmd_node(struct nxpwifi_adapter *adapter, 61 struct cmd_ctrl_node *cmd_node) 62 { 63 cmd_node->cmd_no = 0; 64 cmd_node->cmd_flag = 0; 65 cmd_node->data_buf = NULL; 66 cmd_node->wait_q_enabled = false; 67 68 if (cmd_node->cmd_skb) 69 skb_trim(cmd_node->cmd_skb, 0); 70 71 if (cmd_node->resp_skb) { 72 adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb); 73 cmd_node->resp_skb = NULL; 74 } 75 } 76 77 /* Optionally complete waiters, clean the node, and add it back to cmd_free_q. */ 78 static void 79 nxpwifi_insert_cmd_to_free_q(struct nxpwifi_adapter *adapter, 80 struct cmd_ctrl_node *cmd_node) 81 { 82 if (!cmd_node) 83 return; 84 85 if (cmd_node->wait_q_enabled) 86 nxpwifi_complete_cmd(adapter, cmd_node); 87 /* Clean the node */ 88 nxpwifi_clean_cmd_node(adapter, cmd_node); 89 90 /* Insert node into cmd_free_q */ 91 spin_lock_bh(&adapter->cmd_free_q_lock); 92 list_add_tail(&cmd_node->list, &adapter->cmd_free_q); 93 spin_unlock_bh(&adapter->cmd_free_q_lock); 94 } 95 96 /* Reuse a command node. */ 97 void nxpwifi_recycle_cmd_node(struct nxpwifi_adapter *adapter, 98 struct cmd_ctrl_node *cmd_node) 99 { 100 struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; 101 102 nxpwifi_insert_cmd_to_free_q(adapter, cmd_node); 103 104 atomic_dec(&adapter->cmd_pending); 105 nxpwifi_dbg(adapter, CMD, 106 "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", 107 le16_to_cpu(host_cmd->command), 108 atomic_read(&adapter->cmd_pending)); 109 } 110 111 /* Copy host command (userspace-provided) into the driver cmd buffer. */ 112 static int nxpwifi_cmd_host_cmd(struct nxpwifi_private *priv, 113 struct cmd_ctrl_node *cmd_node) 114 { 115 struct host_cmd_ds_command *cmd; 116 struct nxpwifi_ds_misc_cmd *pcmd_ptr; 117 118 cmd = (struct host_cmd_ds_command *)cmd_node->skb->data; 119 pcmd_ptr = (struct nxpwifi_ds_misc_cmd *)cmd_node->data_buf; 120 121 /* Copy the HOST command to command buffer */ 122 memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len); 123 nxpwifi_dbg(priv->adapter, CMD, 124 "cmd: host cmd size = %d\n", pcmd_ptr->len); 125 return 0; 126 } 127 128 /* Send prepared command to FW: set seq no, adjust skb length, log, start timer. */ 129 static int nxpwifi_dnld_cmd_to_fw(struct nxpwifi_private *priv, 130 struct cmd_ctrl_node *cmd_node) 131 { 132 struct nxpwifi_adapter *adapter = priv->adapter; 133 int ret; 134 struct host_cmd_ds_command *host_cmd; 135 u16 cmd_code; 136 u16 cmd_size; 137 138 if (!adapter || !cmd_node) 139 return -EINVAL; 140 141 host_cmd = (struct host_cmd_ds_command *)(cmd_node->cmd_skb->data); 142 143 /* Sanity test */ 144 if (host_cmd->size == 0) { 145 nxpwifi_dbg(adapter, ERROR, 146 "DNLD_CMD: host_cmd is null\t" 147 "or cmd size is 0, not sending\n"); 148 if (cmd_node->wait_q_enabled) 149 adapter->cmd_wait_q.status = -1; 150 nxpwifi_recycle_cmd_node(adapter, cmd_node); 151 return -EINVAL; 152 } 153 154 cmd_code = le16_to_cpu(host_cmd->command); 155 cmd_node->cmd_no = cmd_code; 156 cmd_size = le16_to_cpu(host_cmd->size); 157 158 if (adapter->hw_status == NXPWIFI_HW_STATUS_RESET && 159 cmd_code != HOST_CMD_FUNC_SHUTDOWN && 160 cmd_code != HOST_CMD_FUNC_INIT) { 161 nxpwifi_dbg(adapter, ERROR, 162 "DNLD_CMD: FW in reset state, ignore cmd %#x\n", 163 cmd_code); 164 nxpwifi_recycle_cmd_node(adapter, cmd_node); 165 nxpwifi_queue_work(adapter, &adapter->main_work); 166 return -EPERM; 167 } 168 169 /* Set command sequence number */ 170 adapter->seq_num++; 171 host_cmd->seq_num = cpu_to_le16(HOST_SET_SEQ_NO_BSS_INFO 172 (adapter->seq_num, 173 cmd_node->priv->bss_num, 174 cmd_node->priv->bss_type)); 175 176 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 177 adapter->curr_cmd = cmd_node; 178 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 179 180 /* Adjust skb length */ 181 if (cmd_node->cmd_skb->len > cmd_size) 182 /* 183 * cmd_size is less than sizeof(struct host_cmd_ds_command). 184 * Trim off the unused portion. 185 */ 186 skb_trim(cmd_node->cmd_skb, cmd_size); 187 else if (cmd_node->cmd_skb->len < cmd_size) 188 /* 189 * cmd_size is larger than sizeof(struct host_cmd_ds_command) 190 * because we have appended custom element TLV. Increase skb length 191 * accordingly. 192 */ 193 skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); 194 195 nxpwifi_dbg(adapter, CMD, 196 "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", 197 cmd_code, 198 get_unaligned_le16((u8 *)host_cmd + S_DS_GEN), 199 cmd_size, le16_to_cpu(host_cmd->seq_num)); 200 nxpwifi_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size); 201 202 skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len); 203 ret = adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_CMD, 204 cmd_node->cmd_skb, NULL); 205 skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len); 206 207 if (ret) { 208 nxpwifi_dbg(adapter, ERROR, 209 "DNLD_CMD: host to card failed\n"); 210 if (cmd_node->wait_q_enabled) 211 adapter->cmd_wait_q.status = -1; 212 nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); 213 214 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 215 adapter->curr_cmd = NULL; 216 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 217 218 adapter->dbg.num_cmd_host_to_card_failure++; 219 return ret; 220 } 221 222 /* Save the last command id and action to debug log */ 223 adapter->dbg.last_cmd_index = 224 (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; 225 adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code; 226 adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] = 227 get_unaligned_le16((u8 *)host_cmd + S_DS_GEN); 228 229 /* 230 * Setup the timer after transmit command, except that specific 231 * command might not have command response. 232 */ 233 if (cmd_code != HOST_CMD_FW_DUMP_EVENT) 234 mod_timer(&adapter->cmd_timer, 235 jiffies + msecs_to_jiffies(NXPWIFI_TIMER_10S)); 236 237 /* Clear BSS_NO_BITS from HOST */ 238 cmd_code &= HOST_CMD_ID_MASK; 239 240 return 0; 241 } 242 243 /* Send sleep-confirm command to FW; set seq no; resp may be skipped when resp_ctrl=0. */ 244 static int nxpwifi_dnld_sleep_confirm_cmd(struct nxpwifi_adapter *adapter) 245 { 246 int ret; 247 struct nxpwifi_private *priv; 248 struct nxpwifi_opt_sleep_confirm *sleep_cfm_buf = 249 (struct nxpwifi_opt_sleep_confirm *) 250 adapter->sleep_cfm->data; 251 252 priv = nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); 253 254 adapter->seq_num++; 255 sleep_cfm_buf->seq_num = 256 cpu_to_le16(HOST_SET_SEQ_NO_BSS_INFO 257 (adapter->seq_num, priv->bss_num, 258 priv->bss_type)); 259 260 nxpwifi_dbg(adapter, CMD, 261 "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", 262 le16_to_cpu(sleep_cfm_buf->command), 263 le16_to_cpu(sleep_cfm_buf->action), 264 le16_to_cpu(sleep_cfm_buf->size), 265 le16_to_cpu(sleep_cfm_buf->seq_num)); 266 nxpwifi_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf, 267 le16_to_cpu(sleep_cfm_buf->size)); 268 269 skb_push(adapter->sleep_cfm, adapter->intf_hdr_len); 270 ret = adapter->if_ops.host_to_card(adapter, NXPWIFI_TYPE_CMD, 271 adapter->sleep_cfm, NULL); 272 skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len); 273 274 if (ret) { 275 nxpwifi_dbg(adapter, ERROR, "SLEEP_CFM: failed\n"); 276 adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; 277 return ret; 278 } 279 280 if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) 281 /* Response is not needed for sleep confirm command */ 282 adapter->ps_state = PS_STATE_SLEEP; 283 else 284 adapter->ps_state = PS_STATE_SLEEP_CFM; 285 286 if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && 287 (test_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags) && 288 !adapter->sleep_period.period)) { 289 adapter->pm_wakeup_card_req = true; 290 nxpwifi_hs_activated_event(nxpwifi_get_priv 291 (adapter, NXPWIFI_BSS_ROLE_ANY), true); 292 } 293 294 return ret; 295 } 296 297 /* Allocate cmd pool and link all nodes to cmd_free_q (used/returned by cmds). */ 298 int nxpwifi_alloc_cmd_buffer(struct nxpwifi_adapter *adapter) 299 { 300 struct cmd_ctrl_node *cmd_array; 301 u32 i; 302 303 /* Allocate and initialize struct cmd_ctrl_node */ 304 cmd_array = kzalloc_objs(struct cmd_ctrl_node, 305 NXPWIFI_NUM_OF_CMD_BUFFER); 306 if (!cmd_array) 307 return -ENOMEM; 308 309 adapter->cmd_pool = cmd_array; 310 311 /* Allocate and initialize command buffers */ 312 for (i = 0; i < NXPWIFI_NUM_OF_CMD_BUFFER; i++) { 313 cmd_array[i].skb = dev_alloc_skb(NXPWIFI_SIZE_OF_CMD_BUFFER); 314 if (!cmd_array[i].skb) 315 return -ENOMEM; 316 } 317 318 for (i = 0; i < NXPWIFI_NUM_OF_CMD_BUFFER; i++) 319 nxpwifi_insert_cmd_to_free_q(adapter, &cmd_array[i]); 320 321 return 0; 322 } 323 324 /* Free cmd pool; release any remaining resp skbs. */ 325 void nxpwifi_free_cmd_buffer(struct nxpwifi_adapter *adapter) 326 { 327 struct cmd_ctrl_node *cmd_array; 328 u32 i; 329 330 /* Need to check if cmd pool is allocated or not */ 331 if (!adapter->cmd_pool) { 332 nxpwifi_dbg(adapter, FATAL, 333 "info: FREE_CMD_BUF: cmd_pool is null\n"); 334 return; 335 } 336 337 cmd_array = adapter->cmd_pool; 338 339 /* Release shared memory buffers */ 340 for (i = 0; i < NXPWIFI_NUM_OF_CMD_BUFFER; i++) { 341 if (cmd_array[i].skb) { 342 nxpwifi_dbg(adapter, CMD, 343 "cmd: free cmd buffer %d\n", i); 344 dev_kfree_skb_any(cmd_array[i].skb); 345 } 346 if (!cmd_array[i].resp_skb) 347 continue; 348 349 dev_kfree_skb_any(cmd_array[i].resp_skb); 350 } 351 /* Release struct cmd_ctrl_node */ 352 if (adapter->cmd_pool) { 353 nxpwifi_dbg(adapter, CMD, 354 "cmd: free cmd pool\n"); 355 kfree(adapter->cmd_pool); 356 adapter->cmd_pool = NULL; 357 } 358 } 359 360 /* 361 * Handle FW event: select per-BSS priv, fill rxinfo, dispatch to STA/UAP handler, complete. 362 */ 363 int nxpwifi_process_event(struct nxpwifi_adapter *adapter) 364 { 365 int ret, i; 366 struct nxpwifi_private *priv = 367 nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); 368 struct sk_buff *skb = adapter->event_skb; 369 u32 eventcause; 370 struct nxpwifi_rxinfo *rx_info; 371 372 if ((adapter->event_cause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) { 373 for (i = 0; i < adapter->priv_num; i++) { 374 priv = adapter->priv[i]; 375 if (nxpwifi_is_11h_active(priv)) { 376 adapter->event_cause |= 377 ((priv->bss_num & 0xff) << 16) | 378 ((priv->bss_type & 0xff) << 24); 379 break; 380 } 381 } 382 } 383 384 eventcause = adapter->event_cause; 385 386 /* Save the last event to debug log */ 387 adapter->dbg.last_event_index = 388 (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; 389 adapter->dbg.last_event[adapter->dbg.last_event_index] = 390 (u16)eventcause; 391 392 /* Get BSS number and corresponding priv */ 393 priv = nxpwifi_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), 394 EVENT_GET_BSS_TYPE(eventcause)); 395 if (!priv) 396 priv = nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); 397 398 /* Clear BSS_NO_BITS from event */ 399 eventcause &= EVENT_ID_MASK; 400 adapter->event_cause = eventcause; 401 402 if (skb) { 403 rx_info = NXPWIFI_SKB_RXCB(skb); 404 memset(rx_info, 0, sizeof(*rx_info)); 405 rx_info->bss_num = priv->bss_num; 406 rx_info->bss_type = priv->bss_type; 407 nxpwifi_dbg_dump(adapter, EVT_D, "Event Buf:", 408 skb->data, skb->len); 409 } 410 411 nxpwifi_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause); 412 413 if (priv->bss_role == NXPWIFI_BSS_ROLE_UAP) 414 ret = nxpwifi_process_uap_event(priv); 415 else 416 ret = nxpwifi_process_sta_event(priv); 417 418 adapter->event_cause = 0; 419 adapter->event_skb = NULL; 420 adapter->if_ops.event_complete(adapter, skb); 421 422 return ret; 423 } 424 425 /* 426 * Prepare and queue a command: sanity checks, get node, init, fill, and enqueue/dispatch. 427 */ 428 int nxpwifi_send_cmd(struct nxpwifi_private *priv, u16 cmd_no, 429 u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync) 430 { 431 int ret; 432 struct nxpwifi_adapter *adapter = priv->adapter; 433 struct cmd_ctrl_node *cmd_node; 434 435 if (!adapter) { 436 pr_err("PREP_CMD: adapter is NULL\n"); 437 return -EINVAL; 438 } 439 440 if (test_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags)) { 441 nxpwifi_dbg(adapter, ERROR, 442 "PREP_CMD: device in suspended state\n"); 443 return -EPERM; 444 } 445 446 if (test_bit(NXPWIFI_IS_HS_ENABLING, &adapter->work_flags) && 447 cmd_no != HOST_CMD_802_11_HS_CFG_ENH) { 448 nxpwifi_dbg(adapter, ERROR, 449 "PREP_CMD: host entering sleep state\n"); 450 return -EPERM; 451 } 452 453 if (test_bit(NXPWIFI_SURPRISE_REMOVED, &adapter->work_flags)) { 454 nxpwifi_dbg(adapter, ERROR, 455 "PREP_CMD: card is removed\n"); 456 return -EPERM; 457 } 458 459 if (test_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags)) { 460 nxpwifi_dbg(adapter, ERROR, 461 "PREP_CMD: FW is in bad state\n"); 462 return -EPERM; 463 } 464 465 if (adapter->hw_status == NXPWIFI_HW_STATUS_RESET) { 466 if (cmd_no != HOST_CMD_FUNC_INIT) { 467 nxpwifi_dbg(adapter, ERROR, 468 "PREP_CMD: FW in reset state\n"); 469 return -EPERM; 470 } 471 } 472 473 if (priv->adapter->hs_activated_manually && 474 cmd_no != HOST_CMD_802_11_HS_CFG_ENH) { 475 nxpwifi_cancel_hs(priv, NXPWIFI_ASYNC_CMD); 476 priv->adapter->hs_activated_manually = false; 477 } 478 479 /* Get a new command node */ 480 cmd_node = nxpwifi_get_cmd_node(adapter); 481 482 if (!cmd_node) { 483 nxpwifi_dbg(adapter, ERROR, 484 "PREP_CMD: no free cmd node\n"); 485 return -ENOMEM; 486 } 487 488 /* Initialize the command node */ 489 nxpwifi_init_cmd_node(priv, cmd_node, cmd_no, data_buf, sync); 490 491 if (!cmd_node->cmd_skb) { 492 nxpwifi_dbg(adapter, ERROR, 493 "PREP_CMD: no free cmd buf\n"); 494 return -ENOMEM; 495 } 496 497 skb_put_zero(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)); 498 499 /* Prepare command */ 500 if (cmd_no) { 501 switch (cmd_no) { 502 case HOST_CMD_UAP_SYS_CONFIG: 503 case HOST_CMD_UAP_BSS_START: 504 case HOST_CMD_UAP_BSS_STOP: 505 case HOST_CMD_UAP_STA_DEAUTH: 506 case HOST_CMD_APCMD_SYS_RESET: 507 case HOST_CMD_APCMD_STA_LIST: 508 case HOST_CMD_CHAN_REPORT_REQUEST: 509 case HOST_CMD_ADD_NEW_STATION: 510 ret = nxpwifi_uap_prepare_cmd(priv, cmd_node, 511 cmd_action, cmd_oid); 512 break; 513 default: 514 ret = nxpwifi_sta_prepare_cmd(priv, cmd_node, 515 cmd_action, cmd_oid); 516 break; 517 } 518 } else { 519 ret = nxpwifi_cmd_host_cmd(priv, cmd_node); 520 cmd_node->cmd_flag |= CMD_F_HOSTCMD; 521 } 522 523 /* Return error, since the command preparation failed */ 524 if (ret) { 525 nxpwifi_dbg(adapter, ERROR, 526 "PREP_CMD: cmd %#x preparation failed\n", 527 cmd_no); 528 nxpwifi_insert_cmd_to_free_q(adapter, cmd_node); 529 return ret; 530 } 531 532 /* Send command */ 533 if (cmd_no == HOST_CMD_802_11_SCAN || 534 cmd_no == HOST_CMD_802_11_SCAN_EXT) { 535 nxpwifi_queue_scan_cmd(priv, cmd_node); 536 } else { 537 nxpwifi_insert_cmd_to_pending_q(adapter, cmd_node); 538 nxpwifi_queue_work(adapter, &adapter->main_work); 539 if (cmd_node->wait_q_enabled) 540 ret = nxpwifi_wait_queue_complete(adapter, cmd_node); 541 } 542 543 return ret; 544 } 545 546 /* Queue command to cmd_pending_q; EXIT_PS and HS_ACTIVATE go to the head. */ 547 void 548 nxpwifi_insert_cmd_to_pending_q(struct nxpwifi_adapter *adapter, 549 struct cmd_ctrl_node *cmd_node) 550 { 551 struct host_cmd_ds_command *host_cmd = NULL; 552 u16 command; 553 bool add_tail = true; 554 555 host_cmd = (struct host_cmd_ds_command *)(cmd_node->cmd_skb->data); 556 if (!host_cmd) { 557 nxpwifi_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n"); 558 return; 559 } 560 561 command = le16_to_cpu(host_cmd->command); 562 563 /* Exit_PS command needs to be queued in the header always. */ 564 if (command == HOST_CMD_802_11_PS_MODE_ENH) { 565 struct host_cmd_ds_802_11_ps_mode_enh *pm = 566 &host_cmd->params.psmode_enh; 567 if ((le16_to_cpu(pm->action) == DIS_PS) || 568 (le16_to_cpu(pm->action) == DIS_AUTO_PS)) { 569 if (adapter->ps_state != PS_STATE_AWAKE) 570 add_tail = false; 571 } 572 } 573 574 /* Same with exit host sleep cmd, luckily that can't happen at the same time as EXIT_PS */ 575 if (command == HOST_CMD_802_11_HS_CFG_ENH) { 576 struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = 577 &host_cmd->params.opt_hs_cfg; 578 579 if (le16_to_cpu(hs_cfg->action) == HS_ACTIVATE) 580 add_tail = false; 581 } 582 583 spin_lock_bh(&adapter->cmd_pending_q_lock); 584 if (add_tail) 585 list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); 586 else 587 list_add(&cmd_node->list, &adapter->cmd_pending_q); 588 spin_unlock_bh(&adapter->cmd_pending_q_lock); 589 590 atomic_inc(&adapter->cmd_pending); 591 nxpwifi_dbg(adapter, CMD, 592 "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n", 593 command, atomic_read(&adapter->cmd_pending)); 594 } 595 596 /* Dequeue next cmd and download to FW; if HS active (except HS_CFG), deactivate it. */ 597 int nxpwifi_exec_next_cmd(struct nxpwifi_adapter *adapter) 598 { 599 struct nxpwifi_private *priv; 600 struct cmd_ctrl_node *cmd_node; 601 int ret = 0; 602 struct host_cmd_ds_command *host_cmd; 603 604 /* Check if already in processing */ 605 if (adapter->curr_cmd) { 606 nxpwifi_dbg(adapter, FATAL, 607 "EXEC_NEXT_CMD: cmd in processing\n"); 608 return -EBUSY; 609 } 610 611 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 612 /* Check if any command is pending */ 613 spin_lock_bh(&adapter->cmd_pending_q_lock); 614 if (list_empty(&adapter->cmd_pending_q)) { 615 spin_unlock_bh(&adapter->cmd_pending_q_lock); 616 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 617 return -ENODATA; 618 } 619 cmd_node = list_first_entry(&adapter->cmd_pending_q, 620 struct cmd_ctrl_node, list); 621 622 host_cmd = (struct host_cmd_ds_command *)(cmd_node->cmd_skb->data); 623 priv = cmd_node->priv; 624 625 if (adapter->ps_state != PS_STATE_AWAKE) { 626 nxpwifi_dbg(adapter, ERROR, 627 "%s: cannot send cmd in sleep state,\t" 628 "this should not happen\n", __func__); 629 spin_unlock_bh(&adapter->cmd_pending_q_lock); 630 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 631 return ret; 632 } 633 634 list_del(&cmd_node->list); 635 spin_unlock_bh(&adapter->cmd_pending_q_lock); 636 637 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 638 ret = nxpwifi_dnld_cmd_to_fw(priv, cmd_node); 639 priv = nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); 640 /* 641 * Any command sent to the firmware when host is in sleep 642 * mode should de-configure host sleep. We should skip the 643 * host sleep configuration command itself though 644 */ 645 if (priv && host_cmd->command != 646 cpu_to_le16(HOST_CMD_802_11_HS_CFG_ENH)) { 647 if (adapter->hs_activated) { 648 clear_bit(NXPWIFI_IS_HS_CONFIGURED, 649 &adapter->work_flags); 650 nxpwifi_hs_activated_event(priv, false); 651 } 652 } 653 654 return ret; 655 } 656 657 static void 658 nxpwifi_process_cmdresp_error(struct nxpwifi_private *priv, 659 struct host_cmd_ds_command *resp) 660 { 661 struct nxpwifi_adapter *adapter = priv->adapter; 662 struct host_cmd_ds_802_11_ps_mode_enh *pm; 663 664 nxpwifi_dbg(adapter, ERROR, 665 "CMD_RESP: cmd %#x error, result=%#x\n", 666 resp->command, resp->result); 667 668 if (adapter->curr_cmd->wait_q_enabled) 669 adapter->cmd_wait_q.status = -1; 670 671 switch (le16_to_cpu(resp->command)) { 672 case HOST_CMD_802_11_PS_MODE_ENH: 673 pm = &resp->params.psmode_enh; 674 nxpwifi_dbg(adapter, ERROR, 675 "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n", 676 resp->result, le16_to_cpu(pm->action)); 677 break; 678 case HOST_CMD_802_11_SCAN: 679 case HOST_CMD_802_11_SCAN_EXT: 680 nxpwifi_cancel_scan(adapter); 681 break; 682 683 case HOST_CMD_MAC_CONTROL: 684 break; 685 686 case HOST_CMD_SDIO_SP_RX_AGGR_CFG: 687 nxpwifi_dbg(adapter, MSG, 688 "SDIO RX single-port aggregation Not support\n"); 689 break; 690 691 default: 692 break; 693 } 694 /* Handling errors here */ 695 nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); 696 697 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 698 adapter->curr_cmd = NULL; 699 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 700 } 701 702 /* Handle command response: validate, cancel timer, dispatch, set status, recycle node. */ 703 int nxpwifi_process_cmdresp(struct nxpwifi_adapter *adapter) 704 { 705 struct host_cmd_ds_command *resp; 706 struct nxpwifi_private *priv = 707 nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); 708 int ret = 0; 709 u16 orig_cmdresp_no; 710 u16 cmdresp_no; 711 u16 cmdresp_result; 712 713 if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { 714 resp = (struct host_cmd_ds_command *)adapter->upld_buf; 715 nxpwifi_dbg(adapter, ERROR, 716 "CMD_RESP: NULL curr_cmd, %#x\n", 717 le16_to_cpu(resp->command)); 718 return -EINVAL; 719 } 720 721 resp = (struct host_cmd_ds_command *)adapter->curr_cmd->resp_skb->data; 722 orig_cmdresp_no = le16_to_cpu(resp->command); 723 cmdresp_no = (orig_cmdresp_no & HOST_CMD_ID_MASK); 724 725 if (adapter->curr_cmd->cmd_no != cmdresp_no) { 726 nxpwifi_dbg(adapter, ERROR, 727 "cmdresp error: cmd=0x%x cmd_resp=0x%x\n", 728 adapter->curr_cmd->cmd_no, cmdresp_no); 729 return -EINVAL; 730 } 731 /* Now we got response from FW, cancel the command timer */ 732 timer_delete_sync(&adapter->cmd_timer); 733 clear_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags); 734 735 if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { 736 /* Copy original response back to response buffer */ 737 struct nxpwifi_ds_misc_cmd *hostcmd; 738 u16 size = le16_to_cpu(resp->size); 739 740 nxpwifi_dbg(adapter, INFO, 741 "info: host cmd resp size = %d\n", size); 742 size = min_t(u16, size, NXPWIFI_SIZE_OF_CMD_BUFFER); 743 if (adapter->curr_cmd->data_buf) { 744 hostcmd = adapter->curr_cmd->data_buf; 745 hostcmd->len = size; 746 memcpy(hostcmd->cmd, resp, size); 747 } 748 } 749 750 /* Get BSS number and corresponding priv */ 751 priv = nxpwifi_get_priv_by_id 752 (adapter, HOST_GET_BSS_NO(le16_to_cpu(resp->seq_num)), 753 HOST_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); 754 if (!priv) 755 priv = nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY); 756 /* Clear RET_BIT from HOST */ 757 resp->command = cpu_to_le16(orig_cmdresp_no & HOST_CMD_ID_MASK); 758 759 cmdresp_no = le16_to_cpu(resp->command); 760 cmdresp_result = le16_to_cpu(resp->result); 761 762 /* Save the last command response to debug log */ 763 adapter->dbg.last_cmd_resp_index = 764 (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; 765 adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = 766 orig_cmdresp_no; 767 768 nxpwifi_dbg(adapter, CMD, 769 "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", 770 orig_cmdresp_no, cmdresp_result, 771 le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); 772 nxpwifi_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp, 773 le16_to_cpu(resp->size)); 774 775 if (!(orig_cmdresp_no & HOST_RET_BIT)) { 776 nxpwifi_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n"); 777 if (adapter->curr_cmd->wait_q_enabled) 778 adapter->cmd_wait_q.status = -1; 779 780 nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); 781 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 782 adapter->curr_cmd = NULL; 783 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 784 return -EINVAL; 785 } 786 787 if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { 788 adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD; 789 if (cmdresp_result == HOST_RESULT_OK && 790 cmdresp_no == HOST_CMD_802_11_HS_CFG_ENH) 791 ret = nxpwifi_ret_802_11_hs_cfg(priv, resp); 792 } else { 793 if (resp->result != HOST_RESULT_OK) { 794 nxpwifi_process_cmdresp_error(priv, resp); 795 return -EFAULT; 796 } 797 if (adapter->curr_cmd->cmd_resp) { 798 void *data_buf = adapter->curr_cmd->data_buf; 799 800 ret = adapter->curr_cmd->cmd_resp(priv, resp, 801 cmdresp_no, 802 data_buf); 803 } 804 } 805 806 if (adapter->curr_cmd) { 807 if (adapter->curr_cmd->wait_q_enabled) 808 adapter->cmd_wait_q.status = ret; 809 810 nxpwifi_recycle_cmd_node(adapter, adapter->curr_cmd); 811 812 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 813 adapter->curr_cmd = NULL; 814 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 815 } 816 817 return ret; 818 } 819 820 void nxpwifi_process_assoc_resp(struct nxpwifi_adapter *adapter) 821 { 822 struct cfg80211_rx_assoc_resp_data assoc_resp = { 823 .uapsd_queues = -1, 824 }; 825 struct nxpwifi_private *priv = 826 nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_STA); 827 828 if (priv->assoc_rsp_size) { 829 assoc_resp.links[0].bss = priv->req_bss; 830 assoc_resp.buf = priv->assoc_rsp_buf; 831 assoc_resp.len = priv->assoc_rsp_size; 832 cfg80211_rx_assoc_resp(priv->netdev, 833 &assoc_resp); 834 priv->assoc_rsp_size = 0; 835 } 836 } 837 838 /* 839 * Command timeout handler: mark timed out, cancel pending IOCTL, dump/reset device if provided. 840 */ 841 void 842 nxpwifi_cmd_timeout_func(struct timer_list *t) 843 { 844 struct nxpwifi_adapter *adapter = timer_container_of(adapter, t, cmd_timer); 845 struct cmd_ctrl_node *cmd_node; 846 847 set_bit(NXPWIFI_IS_CMD_TIMEDOUT, &adapter->work_flags); 848 if (!adapter->curr_cmd) { 849 nxpwifi_dbg(adapter, ERROR, 850 "cmd: empty curr_cmd\n"); 851 return; 852 } 853 cmd_node = adapter->curr_cmd; 854 if (cmd_node) { 855 adapter->dbg.timeout_cmd_id = 856 adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; 857 adapter->dbg.timeout_cmd_act = 858 adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; 859 nxpwifi_dbg(adapter, MSG, 860 "%s: Timeout cmd id = %#x, act = %#x\n", __func__, 861 adapter->dbg.timeout_cmd_id, 862 adapter->dbg.timeout_cmd_act); 863 864 nxpwifi_dbg(adapter, MSG, 865 "num_data_h2c_failure = %d\n", 866 adapter->dbg.num_tx_host_to_card_failure); 867 nxpwifi_dbg(adapter, MSG, 868 "num_cmd_h2c_failure = %d\n", 869 adapter->dbg.num_cmd_host_to_card_failure); 870 871 nxpwifi_dbg(adapter, MSG, 872 "is_cmd_timedout = %d\n", 873 test_bit(NXPWIFI_IS_CMD_TIMEDOUT, 874 &adapter->work_flags)); 875 nxpwifi_dbg(adapter, MSG, 876 "num_tx_timeout = %d\n", 877 adapter->dbg.num_tx_timeout); 878 879 nxpwifi_dbg(adapter, MSG, 880 "last_cmd_index = %d\n", 881 adapter->dbg.last_cmd_index); 882 nxpwifi_dbg(adapter, MSG, 883 "last_cmd_id: %*ph\n", 884 (int)sizeof(adapter->dbg.last_cmd_id), 885 adapter->dbg.last_cmd_id); 886 nxpwifi_dbg(adapter, MSG, 887 "last_cmd_act: %*ph\n", 888 (int)sizeof(adapter->dbg.last_cmd_act), 889 adapter->dbg.last_cmd_act); 890 891 nxpwifi_dbg(adapter, MSG, 892 "last_cmd_resp_index = %d\n", 893 adapter->dbg.last_cmd_resp_index); 894 nxpwifi_dbg(adapter, MSG, 895 "last_cmd_resp_id: %*ph\n", 896 (int)sizeof(adapter->dbg.last_cmd_resp_id), 897 adapter->dbg.last_cmd_resp_id); 898 899 nxpwifi_dbg(adapter, MSG, 900 "last_event_index = %d\n", 901 adapter->dbg.last_event_index); 902 nxpwifi_dbg(adapter, MSG, 903 "last_event: %*ph\n", 904 (int)sizeof(adapter->dbg.last_event), 905 adapter->dbg.last_event); 906 907 nxpwifi_dbg(adapter, MSG, 908 "data_sent=%d cmd_sent=%d\n", 909 adapter->data_sent, adapter->cmd_sent); 910 911 nxpwifi_dbg(adapter, MSG, 912 "ps_mode=%d ps_state=%d\n", 913 adapter->ps_mode, adapter->ps_state); 914 915 if (cmd_node->wait_q_enabled) { 916 adapter->cmd_wait_q.status = -ETIMEDOUT; 917 nxpwifi_cancel_pending_ioctl(adapter); 918 } 919 } 920 921 if (adapter->if_ops.device_dump) 922 adapter->if_ops.device_dump(adapter); 923 924 if (adapter->if_ops.card_reset) 925 adapter->if_ops.card_reset(adapter); 926 } 927 928 void 929 nxpwifi_cancel_pending_scan_cmd(struct nxpwifi_adapter *adapter) 930 { 931 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; 932 933 /* Cancel all pending scan command */ 934 spin_lock_bh(&adapter->scan_pending_q_lock); 935 list_for_each_entry_safe(cmd_node, tmp_node, 936 &adapter->scan_pending_q, list) { 937 list_del(&cmd_node->list); 938 cmd_node->wait_q_enabled = false; 939 nxpwifi_insert_cmd_to_free_q(adapter, cmd_node); 940 } 941 spin_unlock_bh(&adapter->scan_pending_q_lock); 942 } 943 944 /* 945 * Cancel current cmd (if waiting), all pending cmds, and pending scan cmds; complete with error. 946 */ 947 void 948 nxpwifi_cancel_all_pending_cmd(struct nxpwifi_adapter *adapter) 949 { 950 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; 951 952 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 953 /* Cancel current cmd */ 954 if (adapter->curr_cmd && adapter->curr_cmd->wait_q_enabled) { 955 adapter->cmd_wait_q.status = -1; 956 nxpwifi_complete_cmd(adapter, adapter->curr_cmd); 957 adapter->curr_cmd->wait_q_enabled = false; 958 /* no recycle probably wait for response */ 959 } 960 /* Cancel all pending command */ 961 spin_lock_bh(&adapter->cmd_pending_q_lock); 962 list_for_each_entry_safe(cmd_node, tmp_node, 963 &adapter->cmd_pending_q, list) { 964 list_del(&cmd_node->list); 965 966 if (cmd_node->wait_q_enabled) 967 adapter->cmd_wait_q.status = -1; 968 nxpwifi_recycle_cmd_node(adapter, cmd_node); 969 } 970 spin_unlock_bh(&adapter->cmd_pending_q_lock); 971 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 972 973 nxpwifi_cancel_scan(adapter); 974 } 975 976 /* Cancel current/pending commands for the pending IOCTL; also cancel scan cmds. */ 977 static void 978 nxpwifi_cancel_pending_ioctl(struct nxpwifi_adapter *adapter) 979 { 980 struct cmd_ctrl_node *cmd_node = NULL; 981 982 if (adapter->curr_cmd && 983 adapter->curr_cmd->wait_q_enabled) { 984 spin_lock_bh(&adapter->nxpwifi_cmd_lock); 985 cmd_node = adapter->curr_cmd; 986 /* 987 * Be careful when setting curr_cmd = NULL: 988 * nxpwifi_process_cmdresp expects a non-NULL pointer. 989 * This is safe here because only cmd_timeout calls this path 990 * and no response is expected at that point. 991 */ 992 adapter->curr_cmd = NULL; 993 spin_unlock_bh(&adapter->nxpwifi_cmd_lock); 994 995 nxpwifi_recycle_cmd_node(adapter, cmd_node); 996 } 997 998 nxpwifi_cancel_scan(adapter); 999 } 1000 1001 /* If no cmd/event/tx is pending, send sleep-confirm to FW; otherwise defer. */ 1002 void 1003 nxpwifi_check_ps_cond(struct nxpwifi_adapter *adapter) 1004 { 1005 if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) && 1006 !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) 1007 nxpwifi_dnld_sleep_confirm_cmd(adapter); 1008 else 1009 nxpwifi_dbg(adapter, CMD, 1010 "cmd: Delay Sleep Confirm (%s%s%s%s)\n", 1011 (adapter->cmd_sent) ? "D" : "", 1012 atomic_read(&adapter->tx_hw_pending) ? "T" : "", 1013 (adapter->curr_cmd) ? "C" : "", 1014 (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); 1015 } 1016 1017 /* Generate HS activated/deactivated event for userspace; update flags and wake waiters. */ 1018 void 1019 nxpwifi_hs_activated_event(struct nxpwifi_private *priv, u8 activated) 1020 { 1021 if (activated) { 1022 if (test_bit(NXPWIFI_IS_HS_CONFIGURED, 1023 &priv->adapter->work_flags)) { 1024 priv->adapter->hs_activated = true; 1025 nxpwifi_update_rxreor_flags(priv->adapter, 1026 RXREOR_FORCE_NO_DROP); 1027 nxpwifi_dbg(priv->adapter, EVENT, 1028 "event: hs_activated\n"); 1029 priv->adapter->hs_activate_wait_q_woken = true; 1030 wake_up_interruptible(&priv->adapter->hs_activate_wait_q); 1031 } else { 1032 nxpwifi_dbg(priv->adapter, EVENT, 1033 "event: HS not configured\n"); 1034 } 1035 } else { 1036 nxpwifi_dbg(priv->adapter, EVENT, 1037 "event: hs_deactivated\n"); 1038 priv->adapter->hs_activated = false; 1039 } 1040 } 1041 1042 /* Handle HS_CFG response: update HS configured/activated flags and emit HS events. */ 1043 int nxpwifi_ret_802_11_hs_cfg(struct nxpwifi_private *priv, 1044 struct host_cmd_ds_command *resp) 1045 { 1046 struct nxpwifi_adapter *adapter = priv->adapter; 1047 struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg = 1048 &resp->params.opt_hs_cfg; 1049 u32 conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); 1050 1051 if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) { 1052 nxpwifi_hs_activated_event(priv, true); 1053 goto done; 1054 } else { 1055 nxpwifi_dbg(adapter, CMD, 1056 "cmd: CMD_RESP: HS_CFG cmd reply\t" 1057 " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n", 1058 resp->result, conditions, 1059 phs_cfg->params.hs_config.gpio, 1060 phs_cfg->params.hs_config.gap); 1061 } 1062 if (conditions != HS_CFG_CANCEL) { 1063 set_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); 1064 } else { 1065 clear_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); 1066 if (adapter->hs_activated) 1067 nxpwifi_hs_activated_event(priv, false); 1068 } 1069 1070 done: 1071 return 0; 1072 } 1073 1074 /* On power-up interrupt, wake device and cancel HS if armed; clear flags and notify. */ 1075 void 1076 nxpwifi_process_hs_config(struct nxpwifi_adapter *adapter) 1077 { 1078 nxpwifi_dbg(adapter, INFO, 1079 "info: %s: auto cancelling host sleep\t" 1080 "since there is interrupt from the firmware\n", 1081 __func__); 1082 1083 adapter->if_ops.wakeup(adapter); 1084 1085 if (adapter->hs_activated_manually) { 1086 nxpwifi_cancel_hs(nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY), 1087 NXPWIFI_ASYNC_CMD); 1088 adapter->hs_activated_manually = false; 1089 } 1090 1091 adapter->hs_activated = false; 1092 clear_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags); 1093 clear_bit(NXPWIFI_IS_SUSPENDED, &adapter->work_flags); 1094 nxpwifi_hs_activated_event(nxpwifi_get_priv(adapter, 1095 NXPWIFI_BSS_ROLE_ANY), 1096 false); 1097 } 1098 EXPORT_SYMBOL_GPL(nxpwifi_process_hs_config); 1099 1100 /* Handle sleep-confirm response; set ps_state and hs activation accordingly. */ 1101 void 1102 nxpwifi_process_sleep_confirm_resp(struct nxpwifi_adapter *adapter, 1103 u8 *pbuf, u32 upld_len) 1104 { 1105 struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *)pbuf; 1106 u16 result = le16_to_cpu(cmd->result); 1107 u16 command = le16_to_cpu(cmd->command); 1108 u16 seq_num = le16_to_cpu(cmd->seq_num); 1109 1110 if (!upld_len) { 1111 nxpwifi_dbg(adapter, ERROR, 1112 "%s: cmd size is 0\n", __func__); 1113 return; 1114 } 1115 1116 nxpwifi_dbg(adapter, CMD, 1117 "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", 1118 command, result, le16_to_cpu(cmd->size), seq_num); 1119 1120 /* Update sequence number */ 1121 seq_num = HOST_GET_SEQ_NO(seq_num); 1122 /* Clear RET_BIT from HOST */ 1123 command &= HOST_CMD_ID_MASK; 1124 1125 if (command != HOST_CMD_802_11_PS_MODE_ENH) { 1126 nxpwifi_dbg(adapter, ERROR, 1127 "%s: rcvd unexpected resp for cmd %#x, result = %x\n", 1128 __func__, command, result); 1129 return; 1130 } 1131 1132 if (result) { 1133 nxpwifi_dbg(adapter, ERROR, 1134 "%s: sleep confirm cmd failed\n", 1135 __func__); 1136 adapter->pm_wakeup_card_req = false; 1137 adapter->ps_state = PS_STATE_AWAKE; 1138 return; 1139 } 1140 adapter->pm_wakeup_card_req = true; 1141 if (test_bit(NXPWIFI_IS_HS_CONFIGURED, &adapter->work_flags)) 1142 nxpwifi_hs_activated_event(nxpwifi_get_priv 1143 (adapter, NXPWIFI_BSS_ROLE_ANY), 1144 true); 1145 adapter->ps_state = PS_STATE_SLEEP; 1146 cmd->command = cpu_to_le16(command); 1147 cmd->seq_num = cpu_to_le16(seq_num); 1148 } 1149 EXPORT_SYMBOL_GPL(nxpwifi_process_sleep_confirm_resp); 1150 1151 int nxpwifi_mgmt_frame_reg(struct nxpwifi_private *priv, u32 mask) 1152 { 1153 return nxpwifi_send_cmd(priv, HOST_CMD_MGMT_FRAME_REG, HOST_ACT_GEN_SET, 1154 0, &mask, false); 1155 } 1156 1157 int nxpwifi_set_uap_sys_cfg(struct nxpwifi_private *priv, 1158 struct nxpwifi_uap_bss_param *cfg) 1159 { 1160 return nxpwifi_send_cmd(priv, HOST_CMD_UAP_SYS_CONFIG, HOST_ACT_GEN_SET, 1161 UAP_BSS_PARAMS_I, cfg, false); 1162 } 1163 1164 int nxpwifi_set_rts(struct nxpwifi_private *priv, u32 rts_thr) 1165 { 1166 if (rts_thr < NXPWIFI_RTS_THRESHOLD_MIN || rts_thr > NXPWIFI_RTS_THRESHOLD_MAX) 1167 rts_thr = NXPWIFI_RTS_THRESHOLD_MAX; 1168 1169 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, 1170 HOST_ACT_GEN_SET, RTS_THRESH_I, &rts_thr, true); 1171 } 1172 1173 int nxpwifi_set_frag(struct nxpwifi_private *priv, u32 frag_thr) 1174 { 1175 if (frag_thr < NXPWIFI_FRAG_THRESHOLD_MIN || 1176 frag_thr > NXPWIFI_FRAG_THRESHOLD_MAX) 1177 frag_thr = NXPWIFI_FRAG_THRESHOLD_MAX; 1178 1179 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, 1180 HOST_ACT_GEN_SET, FRAG_THRESH_I, &frag_thr, 1181 true); 1182 } 1183 1184 int nxpwifi_set_bss_mode(struct nxpwifi_private *priv) 1185 { 1186 return nxpwifi_send_cmd(priv, HOST_CMD_SET_BSS_MODE, HOST_ACT_GEN_SET, 1187 0, NULL, true); 1188 } 1189 1190 int nxpwifi_config_monitor_mode(struct nxpwifi_private *priv, 1191 struct nxpwifi_802_11_net_monitor *cfg) 1192 { 1193 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_NET_MONITOR, 1194 HOST_ACT_GEN_SET, 0, cfg, true); 1195 } 1196 1197 int nxpwifi_get_tx_pwr(struct nxpwifi_private *priv) 1198 { 1199 return nxpwifi_send_cmd(priv, HOST_CMD_RF_TX_PWR, HOST_ACT_GEN_GET, 0, 1200 NULL, true); 1201 } 1202 1203 int nxpwifi_apply_regdomain(struct nxpwifi_private *priv) 1204 { 1205 return nxpwifi_send_cmd(priv, HOST_CMD_802_11D_DOMAIN_INFO, HOST_ACT_GEN_SET, 1206 0, NULL, false); 1207 } 1208 1209 int nxpwifi_get_rssi_info(struct nxpwifi_private *priv) 1210 { 1211 return nxpwifi_send_cmd(priv, HOST_CMD_RSSI_INFO, HOST_ACT_GEN_GET, 0, 1212 NULL, true); 1213 } 1214 1215 int nxpwifi_get_802_11_snmp_mib(struct nxpwifi_private *priv, u16 oid, void *value) 1216 { 1217 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB, HOST_ACT_GEN_GET, 1218 oid, value, true); 1219 } 1220 1221 int nxpwifi_set_rf_antenna(struct nxpwifi_private *priv, void *antcfg) 1222 { 1223 return nxpwifi_send_cmd(priv, HOST_CMD_RF_ANTENNA, HOST_ACT_GEN_SET, 0, antcfg, 1224 true); 1225 } 1226 1227 int nxpwifi_get_rf_antenna(struct nxpwifi_private *priv, u32 *tx_ant, u32 *rx_ant) 1228 { 1229 int ret; 1230 1231 ret = nxpwifi_send_cmd(priv, HOST_CMD_RF_ANTENNA, HOST_ACT_GEN_GET, 0, NULL, true); 1232 1233 if (!ret) { 1234 *tx_ant = priv->tx_ant; 1235 *rx_ant = priv->rx_ant; 1236 } 1237 1238 return ret; 1239 } 1240 1241 int nxpwifi_ap_stop_bss(struct nxpwifi_private *priv) 1242 { 1243 return nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_STOP, HOST_ACT_GEN_SET, 1244 0, NULL, true); 1245 } 1246 1247 int nxpwifi_ap_sys_reset(struct nxpwifi_private *priv) 1248 { 1249 return nxpwifi_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, 1250 HOST_ACT_GEN_SET, 0, NULL, true); 1251 } 1252 1253 int nxpwifi_ap_get_sta_list(struct nxpwifi_private *priv) 1254 { 1255 return nxpwifi_send_cmd(priv, HOST_CMD_APCMD_STA_LIST, HOST_ACT_GEN_GET, 1256 0, NULL, true); 1257 } 1258 1259 int nxpwifi_set_tx_rate(struct nxpwifi_private *priv, void *bitmap_rates) 1260 { 1261 return nxpwifi_send_cmd(priv, HOST_CMD_TX_RATE_CFG, HOST_ACT_GEN_SET, 0, 1262 bitmap_rates, true); 1263 } 1264 1265 int nxpwifi_802_11_subscribe_event(struct nxpwifi_private *priv, 1266 struct nxpwifi_ds_misc_subsc_evt *subsc_evt) 1267 { 1268 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_SUBSCRIBE_EVENT, 0, 0, subsc_evt, 1269 true); 1270 } 1271 1272 int nxpwifi_uap_sta_deauth(struct nxpwifi_private *priv, u8 *mac) 1273 { 1274 return nxpwifi_send_cmd(priv, HOST_CMD_UAP_STA_DEAUTH, HOST_ACT_GEN_SET, 0, mac, true); 1275 } 1276 1277 int nxpwifi_bg_scan_config(struct nxpwifi_private *priv, void *bg_scan_cfg) 1278 { 1279 return nxpwifi_send_cmd(priv, HOST_CMD_802_11_BG_SCAN_CONFIG, HOST_ACT_GEN_SET, 1280 0, bg_scan_cfg, true); 1281 } 1282 1283 int nxpwifi_mef_cfg(struct nxpwifi_private *priv, void *mef_cfg) 1284 { 1285 return nxpwifi_send_cmd(priv, HOST_CMD_MEF_CFG, HOST_ACT_GEN_SET, 0, mef_cfg, 1286 true); 1287 } 1288 1289 int nxpwifi_coalesce_cfg(struct nxpwifi_private *priv, void *coalesce_cfg) 1290 { 1291 return nxpwifi_send_cmd(priv, HOST_CMD_COALESCE_CFG, HOST_ACT_GEN_SET, 0, 1292 coalesce_cfg, true); 1293 } 1294 1295 int nxpwifi_add_new_station(struct nxpwifi_private *priv, void *add_sta) 1296 { 1297 return nxpwifi_send_cmd(priv, HOST_CMD_ADD_NEW_STATION, HOST_ACT_ADD_STA, 0, 1298 add_sta, true); 1299 } 1300 1301 int nxpwifi_hostcmd(struct nxpwifi_private *priv, struct nxpwifi_ds_misc_cmd *hostcmd) 1302 { 1303 return nxpwifi_send_cmd(priv, 0, 0, 0, hostcmd, true); 1304 } 1305 1306 int nxpwifi_chan_report_request(struct nxpwifi_private *priv, void *radar_params) 1307 { 1308 return nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REPORT_REQUEST, HOST_ACT_GEN_SET, 0, 1309 radar_params, true); 1310 } 1311