1 /* 2 * NXP Wireless LAN device driver: commands and events 3 * 4 * Copyright 2011-2020 NXP 5 * 6 * This software file (the "File") is distributed by NXP 7 * under the terms of the GNU General Public License Version 2, June 1991 8 * (the "License"). You may use, redistribute and/or modify this File in 9 * accordance with the terms and conditions of the License, a copy of which 10 * is available by writing to the Free Software Foundation, Inc., 11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 * 14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 * this warranty disclaimer. 18 */ 19 20 #include <asm/unaligned.h> 21 #include "decl.h" 22 #include "ioctl.h" 23 #include "util.h" 24 #include "fw.h" 25 #include "main.h" 26 #include "wmm.h" 27 #include "11n.h" 28 29 static void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); 30 31 /* 32 * This function initializes a command node. 33 * 34 * The actual allocation of the node is not done by this function. It only 35 * initiates a node by filling it with default parameters. Similarly, 36 * allocation of the different buffers used (IOCTL buffer, data buffer) are 37 * not done by this function either. 38 */ 39 static void 40 mwifiex_init_cmd_node(struct mwifiex_private *priv, 41 struct cmd_ctrl_node *cmd_node, 42 u32 cmd_no, void *data_buf, bool sync) 43 { 44 cmd_node->priv = priv; 45 cmd_node->cmd_no = cmd_no; 46 47 if (sync) { 48 cmd_node->wait_q_enabled = true; 49 cmd_node->cmd_wait_q_woken = false; 50 cmd_node->condition = &cmd_node->cmd_wait_q_woken; 51 } 52 cmd_node->data_buf = data_buf; 53 cmd_node->cmd_skb = cmd_node->skb; 54 } 55 56 /* 57 * This function returns a command node from the free queue depending upon 58 * availability. 59 */ 60 static struct cmd_ctrl_node * 61 mwifiex_get_cmd_node(struct mwifiex_adapter *adapter) 62 { 63 struct cmd_ctrl_node *cmd_node; 64 65 spin_lock_bh(&adapter->cmd_free_q_lock); 66 if (list_empty(&adapter->cmd_free_q)) { 67 mwifiex_dbg(adapter, ERROR, 68 "GET_CMD_NODE: cmd node not available\n"); 69 spin_unlock_bh(&adapter->cmd_free_q_lock); 70 return NULL; 71 } 72 cmd_node = list_first_entry(&adapter->cmd_free_q, 73 struct cmd_ctrl_node, list); 74 list_del(&cmd_node->list); 75 spin_unlock_bh(&adapter->cmd_free_q_lock); 76 77 return cmd_node; 78 } 79 80 /* 81 * This function cleans up a command node. 82 * 83 * The function resets the fields including the buffer pointers. 84 * This function does not try to free the buffers. They must be 85 * freed before calling this function. 86 * 87 * This function will however call the receive completion callback 88 * in case a response buffer is still available before resetting 89 * the pointer. 90 */ 91 static void 92 mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, 93 struct cmd_ctrl_node *cmd_node) 94 { 95 cmd_node->cmd_no = 0; 96 cmd_node->cmd_flag = 0; 97 cmd_node->data_buf = NULL; 98 cmd_node->wait_q_enabled = false; 99 100 if (cmd_node->cmd_skb) 101 skb_trim(cmd_node->cmd_skb, 0); 102 103 if (cmd_node->resp_skb) { 104 adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb); 105 cmd_node->resp_skb = NULL; 106 } 107 } 108 109 /* 110 * This function returns a command to the command free queue. 111 * 112 * The function also calls the completion callback if required, before 113 * cleaning the command node and re-inserting it into the free queue. 114 */ 115 static void 116 mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, 117 struct cmd_ctrl_node *cmd_node) 118 { 119 if (!cmd_node) 120 return; 121 122 if (cmd_node->wait_q_enabled) 123 mwifiex_complete_cmd(adapter, cmd_node); 124 /* Clean the node */ 125 mwifiex_clean_cmd_node(adapter, cmd_node); 126 127 /* Insert node into cmd_free_q */ 128 spin_lock_bh(&adapter->cmd_free_q_lock); 129 list_add_tail(&cmd_node->list, &adapter->cmd_free_q); 130 spin_unlock_bh(&adapter->cmd_free_q_lock); 131 } 132 133 /* This function reuses a command node. */ 134 void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, 135 struct cmd_ctrl_node *cmd_node) 136 { 137 struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; 138 139 mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 140 141 atomic_dec(&adapter->cmd_pending); 142 mwifiex_dbg(adapter, CMD, 143 "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", 144 le16_to_cpu(host_cmd->command), 145 atomic_read(&adapter->cmd_pending)); 146 } 147 148 /* 149 * This function sends a host command to the firmware. 150 * 151 * The function copies the host command into the driver command 152 * buffer, which will be transferred to the firmware later by the 153 * main thread. 154 */ 155 static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv, 156 struct host_cmd_ds_command *cmd, 157 struct mwifiex_ds_misc_cmd *pcmd_ptr) 158 { 159 /* Copy the HOST command to command buffer */ 160 memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len); 161 mwifiex_dbg(priv->adapter, CMD, 162 "cmd: host cmd size = %d\n", pcmd_ptr->len); 163 return 0; 164 } 165 166 /* 167 * This function downloads a command to the firmware. 168 * 169 * The function performs sanity tests, sets the command sequence 170 * number and size, converts the header fields to CPU format before 171 * sending. Afterwards, it logs the command ID and action for debugging 172 * and sets up the command timeout timer. 173 */ 174 static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, 175 struct cmd_ctrl_node *cmd_node) 176 { 177 178 struct mwifiex_adapter *adapter = priv->adapter; 179 int ret; 180 struct host_cmd_ds_command *host_cmd; 181 uint16_t cmd_code; 182 uint16_t cmd_size; 183 184 if (!adapter || !cmd_node) 185 return -1; 186 187 host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); 188 189 /* Sanity test */ 190 if (host_cmd == NULL || host_cmd->size == 0) { 191 mwifiex_dbg(adapter, ERROR, 192 "DNLD_CMD: host_cmd is null\t" 193 "or cmd size is 0, not sending\n"); 194 if (cmd_node->wait_q_enabled) 195 adapter->cmd_wait_q.status = -1; 196 mwifiex_recycle_cmd_node(adapter, cmd_node); 197 return -1; 198 } 199 200 cmd_code = le16_to_cpu(host_cmd->command); 201 cmd_node->cmd_no = cmd_code; 202 cmd_size = le16_to_cpu(host_cmd->size); 203 204 if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET && 205 cmd_code != HostCmd_CMD_FUNC_SHUTDOWN && 206 cmd_code != HostCmd_CMD_FUNC_INIT) { 207 mwifiex_dbg(adapter, ERROR, 208 "DNLD_CMD: FW in reset state, ignore cmd %#x\n", 209 cmd_code); 210 mwifiex_recycle_cmd_node(adapter, cmd_node); 211 queue_work(adapter->workqueue, &adapter->main_work); 212 return -1; 213 } 214 215 /* Set command sequence number */ 216 adapter->seq_num++; 217 host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO 218 (adapter->seq_num, 219 cmd_node->priv->bss_num, 220 cmd_node->priv->bss_type)); 221 222 spin_lock_bh(&adapter->mwifiex_cmd_lock); 223 adapter->curr_cmd = cmd_node; 224 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 225 226 /* Adjust skb length */ 227 if (cmd_node->cmd_skb->len > cmd_size) 228 /* 229 * cmd_size is less than sizeof(struct host_cmd_ds_command). 230 * Trim off the unused portion. 231 */ 232 skb_trim(cmd_node->cmd_skb, cmd_size); 233 else if (cmd_node->cmd_skb->len < cmd_size) 234 /* 235 * cmd_size is larger than sizeof(struct host_cmd_ds_command) 236 * because we have appended custom IE TLV. Increase skb length 237 * accordingly. 238 */ 239 skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); 240 241 mwifiex_dbg(adapter, CMD, 242 "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", 243 cmd_code, 244 get_unaligned_le16((u8 *)host_cmd + S_DS_GEN), 245 cmd_size, le16_to_cpu(host_cmd->seq_num)); 246 mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size); 247 248 if (adapter->iface_type == MWIFIEX_USB) { 249 skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN); 250 put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, 251 cmd_node->cmd_skb->data); 252 adapter->cmd_sent = true; 253 ret = adapter->if_ops.host_to_card(adapter, 254 MWIFIEX_USB_EP_CMD_EVENT, 255 cmd_node->cmd_skb, NULL); 256 skb_pull(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN); 257 if (ret == -EBUSY) 258 cmd_node->cmd_skb = NULL; 259 } else { 260 skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len); 261 ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, 262 cmd_node->cmd_skb, NULL); 263 skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len); 264 } 265 266 if (ret == -1) { 267 mwifiex_dbg(adapter, ERROR, 268 "DNLD_CMD: host to card failed\n"); 269 if (adapter->iface_type == MWIFIEX_USB) 270 adapter->cmd_sent = false; 271 if (cmd_node->wait_q_enabled) 272 adapter->cmd_wait_q.status = -1; 273 mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); 274 275 spin_lock_bh(&adapter->mwifiex_cmd_lock); 276 adapter->curr_cmd = NULL; 277 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 278 279 adapter->dbg.num_cmd_host_to_card_failure++; 280 return -1; 281 } 282 283 /* Save the last command id and action to debug log */ 284 adapter->dbg.last_cmd_index = 285 (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; 286 adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code; 287 adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] = 288 get_unaligned_le16((u8 *)host_cmd + S_DS_GEN); 289 290 /* Setup the timer after transmit command, except that specific 291 * command might not have command response. 292 */ 293 if (cmd_code != HostCmd_CMD_FW_DUMP_EVENT) 294 mod_timer(&adapter->cmd_timer, 295 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); 296 297 /* Clear BSS_NO_BITS from HostCmd */ 298 cmd_code &= HostCmd_CMD_ID_MASK; 299 300 return 0; 301 } 302 303 /* 304 * This function downloads a sleep confirm command to the firmware. 305 * 306 * The function performs sanity tests, sets the command sequence 307 * number and size, converts the header fields to CPU format before 308 * sending. 309 * 310 * No responses are needed for sleep confirm command. 311 */ 312 static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) 313 { 314 int ret; 315 struct mwifiex_private *priv; 316 struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = 317 (struct mwifiex_opt_sleep_confirm *) 318 adapter->sleep_cfm->data; 319 struct sk_buff *sleep_cfm_tmp; 320 321 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 322 323 adapter->seq_num++; 324 sleep_cfm_buf->seq_num = 325 cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO 326 (adapter->seq_num, priv->bss_num, 327 priv->bss_type))); 328 329 mwifiex_dbg(adapter, CMD, 330 "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", 331 le16_to_cpu(sleep_cfm_buf->command), 332 le16_to_cpu(sleep_cfm_buf->action), 333 le16_to_cpu(sleep_cfm_buf->size), 334 le16_to_cpu(sleep_cfm_buf->seq_num)); 335 mwifiex_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf, 336 le16_to_cpu(sleep_cfm_buf->size)); 337 338 if (adapter->iface_type == MWIFIEX_USB) { 339 sleep_cfm_tmp = 340 dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) 341 + MWIFIEX_TYPE_LEN); 342 if (!sleep_cfm_tmp) { 343 mwifiex_dbg(adapter, ERROR, 344 "SLEEP_CFM: dev_alloc_skb failed\n"); 345 return -ENOMEM; 346 } 347 348 skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm) 349 + MWIFIEX_TYPE_LEN); 350 put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, sleep_cfm_tmp->data); 351 memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN, 352 adapter->sleep_cfm->data, 353 sizeof(struct mwifiex_opt_sleep_confirm)); 354 ret = adapter->if_ops.host_to_card(adapter, 355 MWIFIEX_USB_EP_CMD_EVENT, 356 sleep_cfm_tmp, NULL); 357 if (ret != -EBUSY) 358 dev_kfree_skb_any(sleep_cfm_tmp); 359 } else { 360 skb_push(adapter->sleep_cfm, adapter->intf_hdr_len); 361 ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, 362 adapter->sleep_cfm, NULL); 363 skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len); 364 } 365 366 if (ret == -1) { 367 mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n"); 368 adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; 369 return -1; 370 } 371 372 if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) 373 /* Response is not needed for sleep confirm command */ 374 adapter->ps_state = PS_STATE_SLEEP; 375 else 376 adapter->ps_state = PS_STATE_SLEEP_CFM; 377 378 if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && 379 (test_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags) && 380 !adapter->sleep_period.period)) { 381 adapter->pm_wakeup_card_req = true; 382 mwifiex_hs_activated_event(mwifiex_get_priv 383 (adapter, MWIFIEX_BSS_ROLE_ANY), true); 384 } 385 386 return ret; 387 } 388 389 /* 390 * This function allocates the command buffers and links them to 391 * the command free queue. 392 * 393 * The driver uses a pre allocated number of command buffers, which 394 * are created at driver initializations and freed at driver cleanup. 395 * Every command needs to obtain a command buffer from this pool before 396 * it can be issued. The command free queue lists the command buffers 397 * currently free to use, while the command pending queue lists the 398 * command buffers already in use and awaiting handling. Command buffers 399 * are returned to the free queue after use. 400 */ 401 int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) 402 { 403 struct cmd_ctrl_node *cmd_array; 404 u32 i; 405 406 /* Allocate and initialize struct cmd_ctrl_node */ 407 cmd_array = kcalloc(MWIFIEX_NUM_OF_CMD_BUFFER, 408 sizeof(struct cmd_ctrl_node), GFP_KERNEL); 409 if (!cmd_array) 410 return -ENOMEM; 411 412 adapter->cmd_pool = cmd_array; 413 414 /* Allocate and initialize command buffers */ 415 for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { 416 cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); 417 if (!cmd_array[i].skb) { 418 mwifiex_dbg(adapter, ERROR, 419 "unable to allocate command buffer\n"); 420 return -ENOMEM; 421 } 422 } 423 424 for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) 425 mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]); 426 427 return 0; 428 } 429 430 /* 431 * This function frees the command buffers. 432 * 433 * The function calls the completion callback for all the command 434 * buffers that still have response buffers associated with them. 435 */ 436 void mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) 437 { 438 struct cmd_ctrl_node *cmd_array; 439 u32 i; 440 441 /* Need to check if cmd pool is allocated or not */ 442 if (!adapter->cmd_pool) { 443 mwifiex_dbg(adapter, FATAL, 444 "info: FREE_CMD_BUF: cmd_pool is null\n"); 445 return; 446 } 447 448 cmd_array = adapter->cmd_pool; 449 450 /* Release shared memory buffers */ 451 for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { 452 if (cmd_array[i].skb) { 453 mwifiex_dbg(adapter, CMD, 454 "cmd: free cmd buffer %d\n", i); 455 dev_kfree_skb_any(cmd_array[i].skb); 456 } 457 if (!cmd_array[i].resp_skb) 458 continue; 459 460 if (adapter->iface_type == MWIFIEX_USB) 461 adapter->if_ops.cmdrsp_complete(adapter, 462 cmd_array[i].resp_skb); 463 else 464 dev_kfree_skb_any(cmd_array[i].resp_skb); 465 } 466 /* Release struct cmd_ctrl_node */ 467 if (adapter->cmd_pool) { 468 mwifiex_dbg(adapter, CMD, 469 "cmd: free cmd pool\n"); 470 kfree(adapter->cmd_pool); 471 adapter->cmd_pool = NULL; 472 } 473 } 474 475 /* 476 * This function handles events generated by firmware. 477 * 478 * Event body of events received from firmware are not used (though they are 479 * saved), only the event ID is used. Some events are re-invoked by 480 * the driver, with a new event body. 481 * 482 * After processing, the function calls the completion callback 483 * for cleanup. 484 */ 485 int mwifiex_process_event(struct mwifiex_adapter *adapter) 486 { 487 int ret, i; 488 struct mwifiex_private *priv = 489 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 490 struct sk_buff *skb = adapter->event_skb; 491 u32 eventcause; 492 struct mwifiex_rxinfo *rx_info; 493 494 if ((adapter->event_cause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) { 495 for (i = 0; i < adapter->priv_num; i++) { 496 priv = adapter->priv[i]; 497 if (priv && mwifiex_is_11h_active(priv)) { 498 adapter->event_cause |= 499 ((priv->bss_num & 0xff) << 16) | 500 ((priv->bss_type & 0xff) << 24); 501 break; 502 } 503 } 504 } 505 506 eventcause = adapter->event_cause; 507 508 /* Save the last event to debug log */ 509 adapter->dbg.last_event_index = 510 (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; 511 adapter->dbg.last_event[adapter->dbg.last_event_index] = 512 (u16) eventcause; 513 514 /* Get BSS number and corresponding priv */ 515 priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), 516 EVENT_GET_BSS_TYPE(eventcause)); 517 if (!priv) 518 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 519 520 /* Clear BSS_NO_BITS from event */ 521 eventcause &= EVENT_ID_MASK; 522 adapter->event_cause = eventcause; 523 524 if (skb) { 525 rx_info = MWIFIEX_SKB_RXCB(skb); 526 memset(rx_info, 0, sizeof(*rx_info)); 527 rx_info->bss_num = priv->bss_num; 528 rx_info->bss_type = priv->bss_type; 529 mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", 530 skb->data, skb->len); 531 } 532 533 mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause); 534 535 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) 536 ret = mwifiex_process_uap_event(priv); 537 else 538 ret = mwifiex_process_sta_event(priv); 539 540 adapter->event_cause = 0; 541 adapter->event_skb = NULL; 542 adapter->if_ops.event_complete(adapter, skb); 543 544 return ret; 545 } 546 547 /* 548 * This function prepares a command and send it to the firmware. 549 * 550 * Preparation includes - 551 * - Sanity tests to make sure the card is still present or the FW 552 * is not reset 553 * - Getting a new command node from the command free queue 554 * - Initializing the command node for default parameters 555 * - Fill up the non-default parameters and buffer pointers 556 * - Add the command to pending queue 557 */ 558 int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, 559 u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync) 560 { 561 int ret; 562 struct mwifiex_adapter *adapter = priv->adapter; 563 struct cmd_ctrl_node *cmd_node; 564 struct host_cmd_ds_command *cmd_ptr; 565 566 if (!adapter) { 567 pr_err("PREP_CMD: adapter is NULL\n"); 568 return -1; 569 } 570 571 if (test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) { 572 mwifiex_dbg(adapter, ERROR, 573 "PREP_CMD: device in suspended state\n"); 574 return -1; 575 } 576 577 if (test_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags) && 578 cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) { 579 mwifiex_dbg(adapter, ERROR, 580 "PREP_CMD: host entering sleep state\n"); 581 return -1; 582 } 583 584 if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags)) { 585 mwifiex_dbg(adapter, ERROR, 586 "PREP_CMD: card is removed\n"); 587 return -1; 588 } 589 590 if (test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) { 591 mwifiex_dbg(adapter, ERROR, 592 "PREP_CMD: FW is in bad state\n"); 593 return -1; 594 } 595 596 if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { 597 if (cmd_no != HostCmd_CMD_FUNC_INIT) { 598 mwifiex_dbg(adapter, ERROR, 599 "PREP_CMD: FW in reset state\n"); 600 return -1; 601 } 602 } 603 /* We don't expect commands in manufacturing mode. They are cooked 604 * in application and ready to download buffer is passed to the driver 605 */ 606 if (adapter->mfg_mode && cmd_no) { 607 dev_dbg(adapter->dev, "Ignoring commands in manufacturing mode\n"); 608 return -1; 609 } 610 611 612 /* Get a new command node */ 613 cmd_node = mwifiex_get_cmd_node(adapter); 614 615 if (!cmd_node) { 616 mwifiex_dbg(adapter, ERROR, 617 "PREP_CMD: no free cmd node\n"); 618 return -1; 619 } 620 621 /* Initialize the command node */ 622 mwifiex_init_cmd_node(priv, cmd_node, cmd_no, data_buf, sync); 623 624 if (!cmd_node->cmd_skb) { 625 mwifiex_dbg(adapter, ERROR, 626 "PREP_CMD: no free cmd buf\n"); 627 return -1; 628 } 629 630 skb_put_zero(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)); 631 632 cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); 633 cmd_ptr->command = cpu_to_le16(cmd_no); 634 cmd_ptr->result = 0; 635 636 /* Prepare command */ 637 if (cmd_no) { 638 switch (cmd_no) { 639 case HostCmd_CMD_UAP_SYS_CONFIG: 640 case HostCmd_CMD_UAP_BSS_START: 641 case HostCmd_CMD_UAP_BSS_STOP: 642 case HostCmd_CMD_UAP_STA_DEAUTH: 643 case HOST_CMD_APCMD_SYS_RESET: 644 case HOST_CMD_APCMD_STA_LIST: 645 ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, 646 cmd_oid, data_buf, 647 cmd_ptr); 648 break; 649 default: 650 ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, 651 cmd_oid, data_buf, 652 cmd_ptr); 653 break; 654 } 655 } else { 656 ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); 657 cmd_node->cmd_flag |= CMD_F_HOSTCMD; 658 } 659 660 /* Return error, since the command preparation failed */ 661 if (ret) { 662 mwifiex_dbg(adapter, ERROR, 663 "PREP_CMD: cmd %#x preparation failed\n", 664 cmd_no); 665 mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 666 return -1; 667 } 668 669 /* Send command */ 670 if (cmd_no == HostCmd_CMD_802_11_SCAN || 671 cmd_no == HostCmd_CMD_802_11_SCAN_EXT) { 672 mwifiex_queue_scan_cmd(priv, cmd_node); 673 } else { 674 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node); 675 queue_work(adapter->workqueue, &adapter->main_work); 676 if (cmd_node->wait_q_enabled) 677 ret = mwifiex_wait_queue_complete(adapter, cmd_node); 678 } 679 680 return ret; 681 } 682 683 /* 684 * This function queues a command to the command pending queue. 685 * 686 * This in effect adds the command to the command list to be executed. 687 * Exit PS command is handled specially, by placing it always to the 688 * front of the command queue. 689 */ 690 void 691 mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, 692 struct cmd_ctrl_node *cmd_node) 693 { 694 struct host_cmd_ds_command *host_cmd = NULL; 695 u16 command; 696 bool add_tail = true; 697 698 host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); 699 if (!host_cmd) { 700 mwifiex_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n"); 701 return; 702 } 703 704 command = le16_to_cpu(host_cmd->command); 705 706 /* Exit_PS command needs to be queued in the header always. */ 707 if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { 708 struct host_cmd_ds_802_11_ps_mode_enh *pm = 709 &host_cmd->params.psmode_enh; 710 if ((le16_to_cpu(pm->action) == DIS_PS) || 711 (le16_to_cpu(pm->action) == DIS_AUTO_PS)) { 712 if (adapter->ps_state != PS_STATE_AWAKE) 713 add_tail = false; 714 } 715 } 716 717 spin_lock_bh(&adapter->cmd_pending_q_lock); 718 if (add_tail) 719 list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); 720 else 721 list_add(&cmd_node->list, &adapter->cmd_pending_q); 722 spin_unlock_bh(&adapter->cmd_pending_q_lock); 723 724 atomic_inc(&adapter->cmd_pending); 725 mwifiex_dbg(adapter, CMD, 726 "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n", 727 command, atomic_read(&adapter->cmd_pending)); 728 } 729 730 /* 731 * This function executes the next command in command pending queue. 732 * 733 * This function will fail if a command is already in processing stage, 734 * otherwise it will dequeue the first command from the command pending 735 * queue and send to the firmware. 736 * 737 * If the device is currently in host sleep mode, any commands, except the 738 * host sleep configuration command will de-activate the host sleep. For PS 739 * mode, the function will put the firmware back to sleep if applicable. 740 */ 741 int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) 742 { 743 struct mwifiex_private *priv; 744 struct cmd_ctrl_node *cmd_node; 745 int ret = 0; 746 struct host_cmd_ds_command *host_cmd; 747 748 /* Check if already in processing */ 749 if (adapter->curr_cmd) { 750 mwifiex_dbg(adapter, FATAL, 751 "EXEC_NEXT_CMD: cmd in processing\n"); 752 return -1; 753 } 754 755 spin_lock_bh(&adapter->mwifiex_cmd_lock); 756 /* Check if any command is pending */ 757 spin_lock_bh(&adapter->cmd_pending_q_lock); 758 if (list_empty(&adapter->cmd_pending_q)) { 759 spin_unlock_bh(&adapter->cmd_pending_q_lock); 760 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 761 return 0; 762 } 763 cmd_node = list_first_entry(&adapter->cmd_pending_q, 764 struct cmd_ctrl_node, list); 765 766 host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); 767 priv = cmd_node->priv; 768 769 if (adapter->ps_state != PS_STATE_AWAKE) { 770 mwifiex_dbg(adapter, ERROR, 771 "%s: cannot send cmd in sleep state,\t" 772 "this should not happen\n", __func__); 773 spin_unlock_bh(&adapter->cmd_pending_q_lock); 774 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 775 return ret; 776 } 777 778 list_del(&cmd_node->list); 779 spin_unlock_bh(&adapter->cmd_pending_q_lock); 780 781 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 782 ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node); 783 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 784 /* Any command sent to the firmware when host is in sleep 785 * mode should de-configure host sleep. We should skip the 786 * host sleep configuration command itself though 787 */ 788 if (priv && (host_cmd->command != 789 cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) { 790 if (adapter->hs_activated) { 791 clear_bit(MWIFIEX_IS_HS_CONFIGURED, 792 &adapter->work_flags); 793 mwifiex_hs_activated_event(priv, false); 794 } 795 } 796 797 return ret; 798 } 799 800 /* 801 * This function handles the command response. 802 * 803 * After processing, the function cleans the command node and puts 804 * it back to the command free queue. 805 */ 806 int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) 807 { 808 struct host_cmd_ds_command *resp; 809 struct mwifiex_private *priv = 810 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 811 int ret = 0; 812 uint16_t orig_cmdresp_no; 813 uint16_t cmdresp_no; 814 uint16_t cmdresp_result; 815 816 if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { 817 resp = (struct host_cmd_ds_command *) adapter->upld_buf; 818 mwifiex_dbg(adapter, ERROR, 819 "CMD_RESP: NULL curr_cmd, %#x\n", 820 le16_to_cpu(resp->command)); 821 return -1; 822 } 823 824 resp = (struct host_cmd_ds_command *)adapter->curr_cmd->resp_skb->data; 825 orig_cmdresp_no = le16_to_cpu(resp->command); 826 cmdresp_no = (orig_cmdresp_no & HostCmd_CMD_ID_MASK); 827 828 if (adapter->curr_cmd->cmd_no != cmdresp_no) { 829 mwifiex_dbg(adapter, ERROR, 830 "cmdresp error: cmd=0x%x cmd_resp=0x%x\n", 831 adapter->curr_cmd->cmd_no, cmdresp_no); 832 return -1; 833 } 834 /* Now we got response from FW, cancel the command timer */ 835 del_timer_sync(&adapter->cmd_timer); 836 clear_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags); 837 838 if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { 839 /* Copy original response back to response buffer */ 840 struct mwifiex_ds_misc_cmd *hostcmd; 841 uint16_t size = le16_to_cpu(resp->size); 842 mwifiex_dbg(adapter, INFO, 843 "info: host cmd resp size = %d\n", size); 844 size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER); 845 if (adapter->curr_cmd->data_buf) { 846 hostcmd = adapter->curr_cmd->data_buf; 847 hostcmd->len = size; 848 memcpy(hostcmd->cmd, resp, size); 849 } 850 } 851 852 /* Get BSS number and corresponding priv */ 853 priv = mwifiex_get_priv_by_id(adapter, 854 HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)), 855 HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); 856 if (!priv) 857 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 858 /* Clear RET_BIT from HostCmd */ 859 resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK); 860 861 cmdresp_no = le16_to_cpu(resp->command); 862 cmdresp_result = le16_to_cpu(resp->result); 863 864 /* Save the last command response to debug log */ 865 adapter->dbg.last_cmd_resp_index = 866 (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; 867 adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = 868 orig_cmdresp_no; 869 870 mwifiex_dbg(adapter, CMD, 871 "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", 872 orig_cmdresp_no, cmdresp_result, 873 le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); 874 mwifiex_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp, 875 le16_to_cpu(resp->size)); 876 877 if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { 878 mwifiex_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n"); 879 if (adapter->curr_cmd->wait_q_enabled) 880 adapter->cmd_wait_q.status = -1; 881 882 mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); 883 spin_lock_bh(&adapter->mwifiex_cmd_lock); 884 adapter->curr_cmd = NULL; 885 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 886 return -1; 887 } 888 889 if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { 890 adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD; 891 if ((cmdresp_result == HostCmd_RESULT_OK) && 892 (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH)) 893 ret = mwifiex_ret_802_11_hs_cfg(priv, resp); 894 } else { 895 /* handle response */ 896 ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp); 897 } 898 899 /* Check init command response */ 900 if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { 901 if (ret) { 902 mwifiex_dbg(adapter, ERROR, 903 "%s: cmd %#x failed during\t" 904 "initialization\n", __func__, cmdresp_no); 905 mwifiex_init_fw_complete(adapter); 906 return -1; 907 } else if (adapter->last_init_cmd == cmdresp_no) 908 adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE; 909 } 910 911 if (adapter->curr_cmd) { 912 if (adapter->curr_cmd->wait_q_enabled) 913 adapter->cmd_wait_q.status = ret; 914 915 mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); 916 917 spin_lock_bh(&adapter->mwifiex_cmd_lock); 918 adapter->curr_cmd = NULL; 919 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 920 } 921 922 return ret; 923 } 924 925 /* 926 * This function handles the timeout of command sending. 927 * 928 * It will re-send the same command again. 929 */ 930 void 931 mwifiex_cmd_timeout_func(struct timer_list *t) 932 { 933 struct mwifiex_adapter *adapter = from_timer(adapter, t, cmd_timer); 934 struct cmd_ctrl_node *cmd_node; 935 936 set_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags); 937 if (!adapter->curr_cmd) { 938 mwifiex_dbg(adapter, ERROR, 939 "cmd: empty curr_cmd\n"); 940 return; 941 } 942 cmd_node = adapter->curr_cmd; 943 if (cmd_node) { 944 adapter->dbg.timeout_cmd_id = 945 adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; 946 adapter->dbg.timeout_cmd_act = 947 adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; 948 mwifiex_dbg(adapter, MSG, 949 "%s: Timeout cmd id = %#x, act = %#x\n", __func__, 950 adapter->dbg.timeout_cmd_id, 951 adapter->dbg.timeout_cmd_act); 952 953 mwifiex_dbg(adapter, MSG, 954 "num_data_h2c_failure = %d\n", 955 adapter->dbg.num_tx_host_to_card_failure); 956 mwifiex_dbg(adapter, MSG, 957 "num_cmd_h2c_failure = %d\n", 958 adapter->dbg.num_cmd_host_to_card_failure); 959 960 mwifiex_dbg(adapter, MSG, 961 "is_cmd_timedout = %d\n", 962 test_bit(MWIFIEX_IS_CMD_TIMEDOUT, 963 &adapter->work_flags)); 964 mwifiex_dbg(adapter, MSG, 965 "num_tx_timeout = %d\n", 966 adapter->dbg.num_tx_timeout); 967 968 mwifiex_dbg(adapter, MSG, 969 "last_cmd_index = %d\n", 970 adapter->dbg.last_cmd_index); 971 mwifiex_dbg(adapter, MSG, 972 "last_cmd_id: %*ph\n", 973 (int)sizeof(adapter->dbg.last_cmd_id), 974 adapter->dbg.last_cmd_id); 975 mwifiex_dbg(adapter, MSG, 976 "last_cmd_act: %*ph\n", 977 (int)sizeof(adapter->dbg.last_cmd_act), 978 adapter->dbg.last_cmd_act); 979 980 mwifiex_dbg(adapter, MSG, 981 "last_cmd_resp_index = %d\n", 982 adapter->dbg.last_cmd_resp_index); 983 mwifiex_dbg(adapter, MSG, 984 "last_cmd_resp_id: %*ph\n", 985 (int)sizeof(adapter->dbg.last_cmd_resp_id), 986 adapter->dbg.last_cmd_resp_id); 987 988 mwifiex_dbg(adapter, MSG, 989 "last_event_index = %d\n", 990 adapter->dbg.last_event_index); 991 mwifiex_dbg(adapter, MSG, 992 "last_event: %*ph\n", 993 (int)sizeof(adapter->dbg.last_event), 994 adapter->dbg.last_event); 995 996 mwifiex_dbg(adapter, MSG, 997 "data_sent=%d cmd_sent=%d\n", 998 adapter->data_sent, adapter->cmd_sent); 999 1000 mwifiex_dbg(adapter, MSG, 1001 "ps_mode=%d ps_state=%d\n", 1002 adapter->ps_mode, adapter->ps_state); 1003 1004 if (cmd_node->wait_q_enabled) { 1005 adapter->cmd_wait_q.status = -ETIMEDOUT; 1006 mwifiex_cancel_pending_ioctl(adapter); 1007 } 1008 } 1009 if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { 1010 mwifiex_init_fw_complete(adapter); 1011 return; 1012 } 1013 1014 if (adapter->if_ops.device_dump) 1015 adapter->if_ops.device_dump(adapter); 1016 1017 if (adapter->if_ops.card_reset) 1018 adapter->if_ops.card_reset(adapter); 1019 } 1020 1021 void 1022 mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter) 1023 { 1024 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; 1025 1026 /* Cancel all pending scan command */ 1027 spin_lock_bh(&adapter->scan_pending_q_lock); 1028 list_for_each_entry_safe(cmd_node, tmp_node, 1029 &adapter->scan_pending_q, list) { 1030 list_del(&cmd_node->list); 1031 cmd_node->wait_q_enabled = false; 1032 mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 1033 } 1034 spin_unlock_bh(&adapter->scan_pending_q_lock); 1035 } 1036 1037 /* 1038 * This function cancels all the pending commands. 1039 * 1040 * The current command, all commands in command pending queue and all scan 1041 * commands in scan pending queue are cancelled. All the completion callbacks 1042 * are called with failure status to ensure cleanup. 1043 */ 1044 void 1045 mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) 1046 { 1047 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; 1048 1049 spin_lock_bh(&adapter->mwifiex_cmd_lock); 1050 /* Cancel current cmd */ 1051 if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { 1052 adapter->cmd_wait_q.status = -1; 1053 mwifiex_complete_cmd(adapter, adapter->curr_cmd); 1054 adapter->curr_cmd->wait_q_enabled = false; 1055 /* no recycle probably wait for response */ 1056 } 1057 /* Cancel all pending command */ 1058 spin_lock_bh(&adapter->cmd_pending_q_lock); 1059 list_for_each_entry_safe(cmd_node, tmp_node, 1060 &adapter->cmd_pending_q, list) { 1061 list_del(&cmd_node->list); 1062 1063 if (cmd_node->wait_q_enabled) 1064 adapter->cmd_wait_q.status = -1; 1065 mwifiex_recycle_cmd_node(adapter, cmd_node); 1066 } 1067 spin_unlock_bh(&adapter->cmd_pending_q_lock); 1068 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 1069 1070 mwifiex_cancel_scan(adapter); 1071 } 1072 1073 /* 1074 * This function cancels all pending commands that matches with 1075 * the given IOCTL request. 1076 * 1077 * Both the current command buffer and the pending command queue are 1078 * searched for matching IOCTL request. The completion callback of 1079 * the matched command is called with failure status to ensure cleanup. 1080 * In case of scan commands, all pending commands in scan pending queue 1081 * are cancelled. 1082 */ 1083 static void 1084 mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) 1085 { 1086 struct cmd_ctrl_node *cmd_node = NULL; 1087 1088 if ((adapter->curr_cmd) && 1089 (adapter->curr_cmd->wait_q_enabled)) { 1090 spin_lock_bh(&adapter->mwifiex_cmd_lock); 1091 cmd_node = adapter->curr_cmd; 1092 /* setting curr_cmd to NULL is quite dangerous, because 1093 * mwifiex_process_cmdresp checks curr_cmd to be != NULL 1094 * at the beginning then relies on it and dereferences 1095 * it at will 1096 * this probably works since mwifiex_cmd_timeout_func 1097 * is the only caller of this function and responses 1098 * at that point 1099 */ 1100 adapter->curr_cmd = NULL; 1101 spin_unlock_bh(&adapter->mwifiex_cmd_lock); 1102 1103 mwifiex_recycle_cmd_node(adapter, cmd_node); 1104 } 1105 1106 mwifiex_cancel_scan(adapter); 1107 } 1108 1109 /* 1110 * This function sends the sleep confirm command to firmware, if 1111 * possible. 1112 * 1113 * The sleep confirm command cannot be issued if command response, 1114 * data response or event response is awaiting handling, or if we 1115 * are in the middle of sending a command, or expecting a command 1116 * response. 1117 */ 1118 void 1119 mwifiex_check_ps_cond(struct mwifiex_adapter *adapter) 1120 { 1121 if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) && 1122 !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) 1123 mwifiex_dnld_sleep_confirm_cmd(adapter); 1124 else 1125 mwifiex_dbg(adapter, CMD, 1126 "cmd: Delay Sleep Confirm (%s%s%s%s)\n", 1127 (adapter->cmd_sent) ? "D" : "", 1128 atomic_read(&adapter->tx_hw_pending) ? "T" : "", 1129 (adapter->curr_cmd) ? "C" : "", 1130 (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); 1131 } 1132 1133 /* 1134 * This function sends a Host Sleep activated event to applications. 1135 * 1136 * This event is generated by the driver, with a blank event body. 1137 */ 1138 void 1139 mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) 1140 { 1141 if (activated) { 1142 if (test_bit(MWIFIEX_IS_HS_CONFIGURED, 1143 &priv->adapter->work_flags)) { 1144 priv->adapter->hs_activated = true; 1145 mwifiex_update_rxreor_flags(priv->adapter, 1146 RXREOR_FORCE_NO_DROP); 1147 mwifiex_dbg(priv->adapter, EVENT, 1148 "event: hs_activated\n"); 1149 priv->adapter->hs_activate_wait_q_woken = true; 1150 wake_up_interruptible( 1151 &priv->adapter->hs_activate_wait_q); 1152 } else { 1153 mwifiex_dbg(priv->adapter, EVENT, 1154 "event: HS not configured\n"); 1155 } 1156 } else { 1157 mwifiex_dbg(priv->adapter, EVENT, 1158 "event: hs_deactivated\n"); 1159 priv->adapter->hs_activated = false; 1160 } 1161 } 1162 1163 /* 1164 * This function handles the command response of a Host Sleep configuration 1165 * command. 1166 * 1167 * Handling includes changing the header fields into CPU format 1168 * and setting the current host sleep activation status in driver. 1169 * 1170 * In case host sleep status change, the function generates an event to 1171 * notify the applications. 1172 */ 1173 int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, 1174 struct host_cmd_ds_command *resp) 1175 { 1176 struct mwifiex_adapter *adapter = priv->adapter; 1177 struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg = 1178 &resp->params.opt_hs_cfg; 1179 uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); 1180 1181 if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) && 1182 adapter->iface_type != MWIFIEX_USB) { 1183 mwifiex_hs_activated_event(priv, true); 1184 return 0; 1185 } else { 1186 mwifiex_dbg(adapter, CMD, 1187 "cmd: CMD_RESP: HS_CFG cmd reply\t" 1188 " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n", 1189 resp->result, conditions, 1190 phs_cfg->params.hs_config.gpio, 1191 phs_cfg->params.hs_config.gap); 1192 } 1193 if (conditions != HS_CFG_CANCEL) { 1194 set_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags); 1195 if (adapter->iface_type == MWIFIEX_USB) 1196 mwifiex_hs_activated_event(priv, true); 1197 } else { 1198 clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags); 1199 if (adapter->hs_activated) 1200 mwifiex_hs_activated_event(priv, false); 1201 } 1202 1203 return 0; 1204 } 1205 1206 /* 1207 * This function wakes up the adapter and generates a Host Sleep 1208 * cancel event on receiving the power up interrupt. 1209 */ 1210 void 1211 mwifiex_process_hs_config(struct mwifiex_adapter *adapter) 1212 { 1213 mwifiex_dbg(adapter, INFO, 1214 "info: %s: auto cancelling host sleep\t" 1215 "since there is interrupt from the firmware\n", 1216 __func__); 1217 1218 adapter->if_ops.wakeup(adapter); 1219 adapter->hs_activated = false; 1220 clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags); 1221 clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags); 1222 mwifiex_hs_activated_event(mwifiex_get_priv(adapter, 1223 MWIFIEX_BSS_ROLE_ANY), 1224 false); 1225 } 1226 EXPORT_SYMBOL_GPL(mwifiex_process_hs_config); 1227 1228 /* 1229 * This function handles the command response of a sleep confirm command. 1230 * 1231 * The function sets the card state to SLEEP if the response indicates success. 1232 */ 1233 void 1234 mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter, 1235 u8 *pbuf, u32 upld_len) 1236 { 1237 struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf; 1238 struct mwifiex_private *priv = 1239 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 1240 uint16_t result = le16_to_cpu(cmd->result); 1241 uint16_t command = le16_to_cpu(cmd->command); 1242 uint16_t seq_num = le16_to_cpu(cmd->seq_num); 1243 1244 if (!upld_len) { 1245 mwifiex_dbg(adapter, ERROR, 1246 "%s: cmd size is 0\n", __func__); 1247 return; 1248 } 1249 1250 mwifiex_dbg(adapter, CMD, 1251 "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", 1252 command, result, le16_to_cpu(cmd->size), seq_num); 1253 1254 /* Get BSS number and corresponding priv */ 1255 priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), 1256 HostCmd_GET_BSS_TYPE(seq_num)); 1257 if (!priv) 1258 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 1259 1260 /* Update sequence number */ 1261 seq_num = HostCmd_GET_SEQ_NO(seq_num); 1262 /* Clear RET_BIT from HostCmd */ 1263 command &= HostCmd_CMD_ID_MASK; 1264 1265 if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { 1266 mwifiex_dbg(adapter, ERROR, 1267 "%s: rcvd unexpected resp for cmd %#x, result = %x\n", 1268 __func__, command, result); 1269 return; 1270 } 1271 1272 if (result) { 1273 mwifiex_dbg(adapter, ERROR, 1274 "%s: sleep confirm cmd failed\n", 1275 __func__); 1276 adapter->pm_wakeup_card_req = false; 1277 adapter->ps_state = PS_STATE_AWAKE; 1278 return; 1279 } 1280 adapter->pm_wakeup_card_req = true; 1281 if (test_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags)) 1282 mwifiex_hs_activated_event(mwifiex_get_priv 1283 (adapter, MWIFIEX_BSS_ROLE_ANY), 1284 true); 1285 adapter->ps_state = PS_STATE_SLEEP; 1286 cmd->command = cpu_to_le16(command); 1287 cmd->seq_num = cpu_to_le16(seq_num); 1288 } 1289 EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp); 1290 1291 /* 1292 * This function prepares an enhanced power mode command. 1293 * 1294 * This function can be used to disable power save or to configure 1295 * power save with auto PS or STA PS or auto deep sleep. 1296 * 1297 * Preparation includes - 1298 * - Setting command ID, action and proper size 1299 * - Setting Power Save bitmap, PS parameters TLV, PS mode TLV, 1300 * auto deep sleep TLV (as required) 1301 * - Ensuring correct endian-ness 1302 */ 1303 int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, 1304 struct host_cmd_ds_command *cmd, 1305 u16 cmd_action, uint16_t ps_bitmap, 1306 struct mwifiex_ds_auto_ds *auto_ds) 1307 { 1308 struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = 1309 &cmd->params.psmode_enh; 1310 u8 *tlv; 1311 u16 cmd_size = 0; 1312 1313 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); 1314 if (cmd_action == DIS_AUTO_PS) { 1315 psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); 1316 psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); 1317 cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + 1318 sizeof(psmode_enh->params.ps_bitmap)); 1319 } else if (cmd_action == GET_PS) { 1320 psmode_enh->action = cpu_to_le16(GET_PS); 1321 psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); 1322 cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + 1323 sizeof(psmode_enh->params.ps_bitmap)); 1324 } else if (cmd_action == EN_AUTO_PS) { 1325 psmode_enh->action = cpu_to_le16(EN_AUTO_PS); 1326 psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); 1327 cmd_size = S_DS_GEN + sizeof(psmode_enh->action) + 1328 sizeof(psmode_enh->params.ps_bitmap); 1329 tlv = (u8 *) cmd + cmd_size; 1330 if (ps_bitmap & BITMAP_STA_PS) { 1331 struct mwifiex_adapter *adapter = priv->adapter; 1332 struct mwifiex_ie_types_ps_param *ps_tlv = 1333 (struct mwifiex_ie_types_ps_param *) tlv; 1334 struct mwifiex_ps_param *ps_mode = &ps_tlv->param; 1335 ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM); 1336 ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) - 1337 sizeof(struct mwifiex_ie_types_header)); 1338 cmd_size += sizeof(*ps_tlv); 1339 tlv += sizeof(*ps_tlv); 1340 mwifiex_dbg(priv->adapter, CMD, 1341 "cmd: PS Command: Enter PS\n"); 1342 ps_mode->null_pkt_interval = 1343 cpu_to_le16(adapter->null_pkt_interval); 1344 ps_mode->multiple_dtims = 1345 cpu_to_le16(adapter->multiple_dtim); 1346 ps_mode->bcn_miss_timeout = 1347 cpu_to_le16(adapter->bcn_miss_time_out); 1348 ps_mode->local_listen_interval = 1349 cpu_to_le16(adapter->local_listen_interval); 1350 ps_mode->adhoc_wake_period = 1351 cpu_to_le16(adapter->adhoc_awake_period); 1352 ps_mode->delay_to_ps = 1353 cpu_to_le16(adapter->delay_to_ps); 1354 ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode); 1355 1356 } 1357 if (ps_bitmap & BITMAP_AUTO_DS) { 1358 struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv = 1359 (struct mwifiex_ie_types_auto_ds_param *) tlv; 1360 u16 idletime = 0; 1361 1362 auto_ds_tlv->header.type = 1363 cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); 1364 auto_ds_tlv->header.len = 1365 cpu_to_le16(sizeof(*auto_ds_tlv) - 1366 sizeof(struct mwifiex_ie_types_header)); 1367 cmd_size += sizeof(*auto_ds_tlv); 1368 tlv += sizeof(*auto_ds_tlv); 1369 if (auto_ds) 1370 idletime = auto_ds->idle_time; 1371 mwifiex_dbg(priv->adapter, CMD, 1372 "cmd: PS Command: Enter Auto Deep Sleep\n"); 1373 auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); 1374 } 1375 cmd->size = cpu_to_le16(cmd_size); 1376 } 1377 return 0; 1378 } 1379 1380 /* 1381 * This function handles the command response of an enhanced power mode 1382 * command. 1383 * 1384 * Handling includes changing the header fields into CPU format 1385 * and setting the current enhanced power mode in driver. 1386 */ 1387 int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, 1388 struct host_cmd_ds_command *resp, 1389 struct mwifiex_ds_pm_cfg *pm_cfg) 1390 { 1391 struct mwifiex_adapter *adapter = priv->adapter; 1392 struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = 1393 &resp->params.psmode_enh; 1394 uint16_t action = le16_to_cpu(ps_mode->action); 1395 uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); 1396 uint16_t auto_ps_bitmap = 1397 le16_to_cpu(ps_mode->params.ps_bitmap); 1398 1399 mwifiex_dbg(adapter, INFO, 1400 "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", 1401 __func__, resp->result, action); 1402 if (action == EN_AUTO_PS) { 1403 if (auto_ps_bitmap & BITMAP_AUTO_DS) { 1404 mwifiex_dbg(adapter, CMD, 1405 "cmd: Enabled auto deep sleep\n"); 1406 priv->adapter->is_deep_sleep = true; 1407 } 1408 if (auto_ps_bitmap & BITMAP_STA_PS) { 1409 mwifiex_dbg(adapter, CMD, 1410 "cmd: Enabled STA power save\n"); 1411 if (adapter->sleep_period.period) 1412 mwifiex_dbg(adapter, CMD, 1413 "cmd: set to uapsd/pps mode\n"); 1414 } 1415 } else if (action == DIS_AUTO_PS) { 1416 if (ps_bitmap & BITMAP_AUTO_DS) { 1417 priv->adapter->is_deep_sleep = false; 1418 mwifiex_dbg(adapter, CMD, 1419 "cmd: Disabled auto deep sleep\n"); 1420 } 1421 if (ps_bitmap & BITMAP_STA_PS) { 1422 mwifiex_dbg(adapter, CMD, 1423 "cmd: Disabled STA power save\n"); 1424 if (adapter->sleep_period.period) { 1425 adapter->delay_null_pkt = false; 1426 adapter->tx_lock_flag = false; 1427 adapter->pps_uapsd_mode = false; 1428 } 1429 } 1430 } else if (action == GET_PS) { 1431 if (ps_bitmap & BITMAP_STA_PS) 1432 adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; 1433 else 1434 adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; 1435 1436 mwifiex_dbg(adapter, CMD, 1437 "cmd: ps_bitmap=%#x\n", ps_bitmap); 1438 1439 if (pm_cfg) { 1440 /* This section is for get power save mode */ 1441 if (ps_bitmap & BITMAP_STA_PS) 1442 pm_cfg->param.ps_mode = 1; 1443 else 1444 pm_cfg->param.ps_mode = 0; 1445 } 1446 } 1447 return 0; 1448 } 1449 1450 /* 1451 * This function prepares command to get hardware specifications. 1452 * 1453 * Preparation includes - 1454 * - Setting command ID, action and proper size 1455 * - Setting permanent address parameter 1456 * - Ensuring correct endian-ness 1457 */ 1458 int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, 1459 struct host_cmd_ds_command *cmd) 1460 { 1461 struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec; 1462 1463 cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC); 1464 cmd->size = 1465 cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN); 1466 memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); 1467 1468 return 0; 1469 } 1470 1471 /* 1472 * This function handles the command response of get hardware 1473 * specifications. 1474 * 1475 * Handling includes changing the header fields into CPU format 1476 * and saving/updating the following parameters in driver - 1477 * - Firmware capability information 1478 * - Firmware band settings 1479 * - Ad-hoc start band and channel 1480 * - Ad-hoc 11n activation status 1481 * - Firmware release number 1482 * - Number of antennas 1483 * - Hardware address 1484 * - Hardware interface version 1485 * - Firmware version 1486 * - Region code 1487 * - 11n capabilities 1488 * - MCS support fields 1489 * - MP end port 1490 */ 1491 int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, 1492 struct host_cmd_ds_command *resp) 1493 { 1494 struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; 1495 struct mwifiex_adapter *adapter = priv->adapter; 1496 struct mwifiex_ie_types_header *tlv; 1497 struct hw_spec_api_rev *api_rev; 1498 u16 resp_size, api_id; 1499 int i, left_len, parsed_len = 0; 1500 1501 adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); 1502 1503 if (IS_SUPPORT_MULTI_BANDS(adapter)) 1504 adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter); 1505 else 1506 adapter->fw_bands = BAND_B; 1507 1508 adapter->config_bands = adapter->fw_bands; 1509 1510 if (adapter->fw_bands & BAND_A) { 1511 if (adapter->fw_bands & BAND_GN) { 1512 adapter->config_bands |= BAND_AN; 1513 adapter->fw_bands |= BAND_AN; 1514 } 1515 if (adapter->fw_bands & BAND_AN) { 1516 adapter->adhoc_start_band = BAND_A | BAND_AN; 1517 adapter->adhoc_11n_enabled = true; 1518 } else { 1519 adapter->adhoc_start_band = BAND_A; 1520 } 1521 priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A; 1522 } else if (adapter->fw_bands & BAND_GN) { 1523 adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; 1524 priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; 1525 adapter->adhoc_11n_enabled = true; 1526 } else if (adapter->fw_bands & BAND_G) { 1527 adapter->adhoc_start_band = BAND_G | BAND_B; 1528 priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; 1529 } else if (adapter->fw_bands & BAND_B) { 1530 adapter->adhoc_start_band = BAND_B; 1531 priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; 1532 } 1533 1534 adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); 1535 adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; 1536 adapter->number_of_antenna = 1537 le16_to_cpu(hw_spec->number_of_antenna) & 0xf; 1538 1539 if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { 1540 adapter->is_hw_11ac_capable = true; 1541 1542 /* Copy 11AC cap */ 1543 adapter->hw_dot_11ac_dev_cap = 1544 le32_to_cpu(hw_spec->dot_11ac_dev_cap); 1545 adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap 1546 & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; 1547 adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap 1548 & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; 1549 1550 /* Copy 11AC mcs */ 1551 adapter->hw_dot_11ac_mcs_support = 1552 le32_to_cpu(hw_spec->dot_11ac_mcs_support); 1553 adapter->usr_dot_11ac_mcs_support = 1554 adapter->hw_dot_11ac_mcs_support; 1555 } else { 1556 adapter->is_hw_11ac_capable = false; 1557 } 1558 1559 resp_size = le16_to_cpu(resp->size) - S_DS_GEN; 1560 if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) { 1561 /* we have variable HW SPEC information */ 1562 left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec); 1563 while (left_len > sizeof(struct mwifiex_ie_types_header)) { 1564 tlv = (void *)&hw_spec->tlvs + parsed_len; 1565 switch (le16_to_cpu(tlv->type)) { 1566 case TLV_TYPE_API_REV: 1567 api_rev = (struct hw_spec_api_rev *)tlv; 1568 api_id = le16_to_cpu(api_rev->api_id); 1569 switch (api_id) { 1570 case KEY_API_VER_ID: 1571 adapter->key_api_major_ver = 1572 api_rev->major_ver; 1573 adapter->key_api_minor_ver = 1574 api_rev->minor_ver; 1575 mwifiex_dbg(adapter, INFO, 1576 "key_api v%d.%d\n", 1577 adapter->key_api_major_ver, 1578 adapter->key_api_minor_ver); 1579 break; 1580 case FW_API_VER_ID: 1581 adapter->fw_api_ver = 1582 api_rev->major_ver; 1583 mwifiex_dbg(adapter, INFO, 1584 "Firmware api version %d\n", 1585 adapter->fw_api_ver); 1586 break; 1587 default: 1588 mwifiex_dbg(adapter, FATAL, 1589 "Unknown api_id: %d\n", 1590 api_id); 1591 break; 1592 } 1593 break; 1594 default: 1595 mwifiex_dbg(adapter, FATAL, 1596 "Unknown GET_HW_SPEC TLV type: %#x\n", 1597 le16_to_cpu(tlv->type)); 1598 break; 1599 } 1600 parsed_len += le16_to_cpu(tlv->len) + 1601 sizeof(struct mwifiex_ie_types_header); 1602 left_len -= le16_to_cpu(tlv->len) + 1603 sizeof(struct mwifiex_ie_types_header); 1604 } 1605 } 1606 1607 mwifiex_dbg(adapter, INFO, 1608 "info: GET_HW_SPEC: fw_release_number- %#x\n", 1609 adapter->fw_release_number); 1610 mwifiex_dbg(adapter, INFO, 1611 "info: GET_HW_SPEC: permanent addr: %pM\n", 1612 hw_spec->permanent_addr); 1613 mwifiex_dbg(adapter, INFO, 1614 "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n", 1615 le16_to_cpu(hw_spec->hw_if_version), 1616 le16_to_cpu(hw_spec->version)); 1617 1618 ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr); 1619 adapter->region_code = le16_to_cpu(hw_spec->region_code); 1620 1621 for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) 1622 /* Use the region code to search for the index */ 1623 if (adapter->region_code == region_code_index[i]) 1624 break; 1625 1626 /* If it's unidentified region code, use the default (world) */ 1627 if (i >= MWIFIEX_MAX_REGION_CODE) { 1628 adapter->region_code = 0x00; 1629 mwifiex_dbg(adapter, WARN, 1630 "cmd: unknown region code, use default (USA)\n"); 1631 } 1632 1633 adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); 1634 adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; 1635 adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support; 1636 1637 if (adapter->if_ops.update_mp_end_port) 1638 adapter->if_ops.update_mp_end_port(adapter, 1639 le16_to_cpu(hw_spec->mp_end_port)); 1640 1641 if (adapter->fw_api_ver == MWIFIEX_FW_V15) 1642 adapter->scan_chan_gap_enabled = true; 1643 1644 return 0; 1645 } 1646 1647 /* This function handles the command response of hs wakeup reason 1648 * command. 1649 */ 1650 int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv, 1651 struct host_cmd_ds_command *resp, 1652 struct host_cmd_ds_wakeup_reason *wakeup_reason) 1653 { 1654 wakeup_reason->wakeup_reason = 1655 resp->params.hs_wakeup_reason.wakeup_reason; 1656 1657 return 0; 1658 } 1659