aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/cmdevt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwifiex/cmdevt.c')
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c150
1 files changed, 103 insertions, 47 deletions
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 1ddc8b2e3722..b41155829220 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -37,13 +37,12 @@
37static void 37static void
38mwifiex_init_cmd_node(struct mwifiex_private *priv, 38mwifiex_init_cmd_node(struct mwifiex_private *priv,
39 struct cmd_ctrl_node *cmd_node, 39 struct cmd_ctrl_node *cmd_node,
40 u32 cmd_oid, void *data_buf) 40 u32 cmd_oid, void *data_buf, bool sync)
41{ 41{
42 cmd_node->priv = priv; 42 cmd_node->priv = priv;
43 cmd_node->cmd_oid = cmd_oid; 43 cmd_node->cmd_oid = cmd_oid;
44 if (priv->adapter->cmd_wait_q_required) { 44 if (sync) {
45 cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; 45 cmd_node->wait_q_enabled = true;
46 priv->adapter->cmd_wait_q_required = false;
47 cmd_node->cmd_wait_q_woken = false; 46 cmd_node->cmd_wait_q_woken = false;
48 cmd_node->condition = &cmd_node->cmd_wait_q_woken; 47 cmd_node->condition = &cmd_node->cmd_wait_q_woken;
49 } 48 }
@@ -166,8 +165,10 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
166 dev_err(adapter->dev, 165 dev_err(adapter->dev,
167 "DNLD_CMD: FW in reset state, ignore cmd %#x\n", 166 "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
168 cmd_code); 167 cmd_code);
169 mwifiex_complete_cmd(adapter, cmd_node); 168 if (cmd_node->wait_q_enabled)
169 mwifiex_complete_cmd(adapter, cmd_node);
170 mwifiex_recycle_cmd_node(adapter, cmd_node); 170 mwifiex_recycle_cmd_node(adapter, cmd_node);
171 queue_work(adapter->workqueue, &adapter->main_work);
171 return -1; 172 return -1;
172 } 173 }
173 174
@@ -480,28 +481,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
480} 481}
481 482
482/* 483/*
483 * This function is used to send synchronous command to the firmware. 484 * This function prepares a command and send it to the firmware.
484 *
485 * it allocates a wait queue for the command and wait for the command
486 * response.
487 */
488int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
489 u16 cmd_action, u32 cmd_oid, void *data_buf)
490{
491 int ret = 0;
492 struct mwifiex_adapter *adapter = priv->adapter;
493
494 adapter->cmd_wait_q_required = true;
495
496 ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
497 data_buf);
498
499 return ret;
500}
501
502
503/*
504 * This function prepares a command and asynchronously send it to the firmware.
505 * 485 *
506 * Preparation includes - 486 * Preparation includes -
507 * - Sanity tests to make sure the card is still present or the FW 487 * - Sanity tests to make sure the card is still present or the FW
@@ -511,8 +491,8 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
511 * - Fill up the non-default parameters and buffer pointers 491 * - Fill up the non-default parameters and buffer pointers
512 * - Add the command to pending queue 492 * - Add the command to pending queue
513 */ 493 */
514int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, 494int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
515 u16 cmd_action, u32 cmd_oid, void *data_buf) 495 u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync)
516{ 496{
517 int ret; 497 int ret;
518 struct mwifiex_adapter *adapter = priv->adapter; 498 struct mwifiex_adapter *adapter = priv->adapter;
@@ -534,6 +514,11 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
534 return -1; 514 return -1;
535 } 515 }
536 516
517 if (adapter->is_cmd_timedout) {
518 dev_err(adapter->dev, "PREP_CMD: FW is in bad state\n");
519 return -1;
520 }
521
537 if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { 522 if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) {
538 if (cmd_no != HostCmd_CMD_FUNC_INIT) { 523 if (cmd_no != HostCmd_CMD_FUNC_INIT) {
539 dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); 524 dev_err(adapter->dev, "PREP_CMD: FW in reset state\n");
@@ -550,7 +535,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
550 } 535 }
551 536
552 /* Initialize the command node */ 537 /* Initialize the command node */
553 mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf); 538 mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync);
554 539
555 if (!cmd_node->cmd_skb) { 540 if (!cmd_node->cmd_skb) {
556 dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); 541 dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n");
@@ -595,7 +580,8 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
595 } 580 }
596 581
597 /* Send command */ 582 /* Send command */
598 if (cmd_no == HostCmd_CMD_802_11_SCAN) { 583 if (cmd_no == HostCmd_CMD_802_11_SCAN ||
584 cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
599 mwifiex_queue_scan_cmd(priv, cmd_node); 585 mwifiex_queue_scan_cmd(priv, cmd_node);
600 } else { 586 } else {
601 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); 587 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
@@ -785,7 +771,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
785 unsigned long flags; 771 unsigned long flags;
786 772
787 /* Now we got response from FW, cancel the command timer */ 773 /* Now we got response from FW, cancel the command timer */
788 del_timer(&adapter->cmd_timer); 774 del_timer_sync(&adapter->cmd_timer);
789 775
790 if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { 776 if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
791 resp = (struct host_cmd_ds_command *) adapter->upld_buf; 777 resp = (struct host_cmd_ds_command *) adapter->upld_buf;
@@ -794,7 +780,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
794 return -1; 780 return -1;
795 } 781 }
796 782
797 adapter->num_cmd_timeout = 0; 783 adapter->is_cmd_timedout = 0;
798 784
799 resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; 785 resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data;
800 if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { 786 if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
@@ -905,8 +891,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
905 struct cmd_ctrl_node *cmd_node; 891 struct cmd_ctrl_node *cmd_node;
906 struct timeval tstamp; 892 struct timeval tstamp;
907 893
908 adapter->num_cmd_timeout++; 894 adapter->is_cmd_timedout = 1;
909 adapter->dbg.num_cmd_timeout++;
910 if (!adapter->curr_cmd) { 895 if (!adapter->curr_cmd) {
911 dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); 896 dev_dbg(adapter->dev, "cmd: empty curr_cmd\n");
912 return; 897 return;
@@ -929,8 +914,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
929 dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", 914 dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n",
930 adapter->dbg.num_cmd_host_to_card_failure); 915 adapter->dbg.num_cmd_host_to_card_failure);
931 916
932 dev_err(adapter->dev, "num_cmd_timeout = %d\n", 917 dev_err(adapter->dev, "is_cmd_timedout = %d\n",
933 adapter->dbg.num_cmd_timeout); 918 adapter->is_cmd_timedout);
934 dev_err(adapter->dev, "num_tx_timeout = %d\n", 919 dev_err(adapter->dev, "num_tx_timeout = %d\n",
935 adapter->dbg.num_tx_timeout); 920 adapter->dbg.num_tx_timeout);
936 921
@@ -987,7 +972,9 @@ void
987mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) 972mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
988{ 973{
989 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; 974 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
990 unsigned long flags; 975 unsigned long flags, cmd_flags;
976 struct mwifiex_private *priv;
977 int i;
991 978
992 /* Cancel current cmd */ 979 /* Cancel current cmd */
993 if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { 980 if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
@@ -1027,9 +1014,21 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
1027 } 1014 }
1028 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); 1015 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
1029 1016
1030 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); 1017 if (adapter->scan_processing) {
1031 adapter->scan_processing = false; 1018 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
1032 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 1019 adapter->scan_processing = false;
1020 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
1021 for (i = 0; i < adapter->priv_num; i++) {
1022 priv = adapter->priv[i];
1023 if (!priv)
1024 continue;
1025 if (priv->scan_request) {
1026 dev_dbg(adapter->dev, "info: aborting scan\n");
1027 cfg80211_scan_done(priv->scan_request, 1);
1028 priv->scan_request = NULL;
1029 }
1030 }
1031 }
1033} 1032}
1034 1033
1035/* 1034/*
@@ -1048,7 +1047,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
1048 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; 1047 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
1049 unsigned long cmd_flags; 1048 unsigned long cmd_flags;
1050 unsigned long scan_pending_q_flags; 1049 unsigned long scan_pending_q_flags;
1051 bool cancel_scan_cmd = false; 1050 struct mwifiex_private *priv;
1051 int i;
1052 1052
1053 if ((adapter->curr_cmd) && 1053 if ((adapter->curr_cmd) &&
1054 (adapter->curr_cmd->wait_q_enabled)) { 1054 (adapter->curr_cmd->wait_q_enabled)) {
@@ -1074,15 +1074,24 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
1074 mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 1074 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
1075 spin_lock_irqsave(&adapter->scan_pending_q_lock, 1075 spin_lock_irqsave(&adapter->scan_pending_q_lock,
1076 scan_pending_q_flags); 1076 scan_pending_q_flags);
1077 cancel_scan_cmd = true;
1078 } 1077 }
1079 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, 1078 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1080 scan_pending_q_flags); 1079 scan_pending_q_flags);
1081 1080
1082 if (cancel_scan_cmd) { 1081 if (adapter->scan_processing) {
1083 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); 1082 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
1084 adapter->scan_processing = false; 1083 adapter->scan_processing = false;
1085 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); 1084 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
1085 for (i = 0; i < adapter->priv_num; i++) {
1086 priv = adapter->priv[i];
1087 if (!priv)
1088 continue;
1089 if (priv->scan_request) {
1090 dev_dbg(adapter->dev, "info: aborting scan\n");
1091 cfg80211_scan_done(priv->scan_request, 1);
1092 priv->scan_request = NULL;
1093 }
1094 }
1086 } 1095 }
1087 adapter->cmd_wait_q.status = -1; 1096 adapter->cmd_wait_q.status = -1;
1088} 1097}
@@ -1454,7 +1463,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1454{ 1463{
1455 struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; 1464 struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
1456 struct mwifiex_adapter *adapter = priv->adapter; 1465 struct mwifiex_adapter *adapter = priv->adapter;
1457 int i; 1466 struct mwifiex_ie_types_header *tlv;
1467 struct hw_spec_fw_api_rev *api_rev;
1468 u16 resp_size, api_id;
1469 int i, left_len, parsed_len = 0;
1458 1470
1459 adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); 1471 adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
1460 1472
@@ -1490,6 +1502,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1490 } 1502 }
1491 1503
1492 adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); 1504 adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
1505 adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
1493 adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); 1506 adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna);
1494 1507
1495 if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { 1508 if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
@@ -1498,8 +1511,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1498 /* Copy 11AC cap */ 1511 /* Copy 11AC cap */
1499 adapter->hw_dot_11ac_dev_cap = 1512 adapter->hw_dot_11ac_dev_cap =
1500 le32_to_cpu(hw_spec->dot_11ac_dev_cap); 1513 le32_to_cpu(hw_spec->dot_11ac_dev_cap);
1501 adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap; 1514 adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
1502 adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap; 1515 & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
1516 adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
1517 & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
1503 1518
1504 /* Copy 11AC mcs */ 1519 /* Copy 11AC mcs */
1505 adapter->hw_dot_11ac_mcs_support = 1520 adapter->hw_dot_11ac_mcs_support =
@@ -1510,6 +1525,46 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1510 adapter->is_hw_11ac_capable = false; 1525 adapter->is_hw_11ac_capable = false;
1511 } 1526 }
1512 1527
1528 resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
1529 if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
1530 /* we have variable HW SPEC information */
1531 left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
1532 while (left_len > sizeof(struct mwifiex_ie_types_header)) {
1533 tlv = (void *)&hw_spec->tlvs + parsed_len;
1534 switch (le16_to_cpu(tlv->type)) {
1535 case TLV_TYPE_FW_API_REV:
1536 api_rev = (struct hw_spec_fw_api_rev *)tlv;
1537 api_id = le16_to_cpu(api_rev->api_id);
1538 switch (api_id) {
1539 case KEY_API_VER_ID:
1540 adapter->fw_key_api_major_ver =
1541 api_rev->major_ver;
1542 adapter->fw_key_api_minor_ver =
1543 api_rev->minor_ver;
1544 dev_dbg(adapter->dev,
1545 "fw_key_api v%d.%d\n",
1546 adapter->fw_key_api_major_ver,
1547 adapter->fw_key_api_minor_ver);
1548 break;
1549 default:
1550 dev_warn(adapter->dev,
1551 "Unknown FW api_id: %d\n",
1552 api_id);
1553 break;
1554 }
1555 break;
1556 default:
1557 dev_warn(adapter->dev,
1558 "Unknown GET_HW_SPEC TLV type: %#x\n",
1559 le16_to_cpu(tlv->type));
1560 break;
1561 }
1562 parsed_len += le16_to_cpu(tlv->len) +
1563 sizeof(struct mwifiex_ie_types_header);
1564 left_len -= parsed_len;
1565 }
1566 }
1567
1513 dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", 1568 dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n",
1514 adapter->fw_release_number); 1569 adapter->fw_release_number);
1515 dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", 1570 dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n",
@@ -1538,6 +1593,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1538 1593
1539 adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); 1594 adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
1540 adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; 1595 adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
1596 adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support;
1541 1597
1542 if (adapter->if_ops.update_mp_end_port) 1598 if (adapter->if_ops.update_mp_end_port)
1543 adapter->if_ops.update_mp_end_port(adapter, 1599 adapter->if_ops.update_mp_end_port(adapter,