diff options
author | David Spinadel <david.spinadel@intel.com> | 2013-07-31 11:07:21 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-10-02 12:00:31 -0400 |
commit | 507cadf262fe67cd71e02247b240706be12f1042 (patch) | |
tree | 41ba62eb94fc906607361cf656ce6e64ce902d3d | |
parent | 272b98c6455f00884f0350f775c5342358ebb73f (diff) |
iwlwifi: mvm: implement NoA testing using testmode cmd
For testing, implement setting continuous NoA duration
using a new MVM-specific testmode command.
Signed-off-by: David Spinadel <david.spinadel@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/quota.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/testmode.h | 91 |
4 files changed, 195 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 9833cdf6177c..43d0011a4308 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include "iwl-eeprom-parse.h" | 77 | #include "iwl-eeprom-parse.h" |
78 | #include "fw-api-scan.h" | 78 | #include "fw-api-scan.h" |
79 | #include "iwl-phy-db.h" | 79 | #include "iwl-phy-db.h" |
80 | #include "testmode.h" | ||
80 | 81 | ||
81 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { | 82 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { |
82 | { | 83 | { |
@@ -699,6 +700,12 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
699 | * interface is be handled as part of the stop_ap flow. | 700 | * interface is be handled as part of the stop_ap flow. |
700 | */ | 701 | */ |
701 | if (vif->type == NL80211_IFTYPE_AP) { | 702 | if (vif->type == NL80211_IFTYPE_AP) { |
703 | #ifdef CONFIG_NL80211_TESTMODE | ||
704 | if (vif == mvm->noa_vif) { | ||
705 | mvm->noa_vif = NULL; | ||
706 | mvm->noa_duration = 0; | ||
707 | } | ||
708 | #endif | ||
702 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); | 709 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); |
703 | goto out_release; | 710 | goto out_release; |
704 | } | 711 | } |
@@ -1559,6 +1566,62 @@ static void iwl_mvm_mac_rssi_callback(struct ieee80211_hw *hw, | |||
1559 | iwl_mvm_bt_rssi_event(mvm, vif, rssi_event); | 1566 | iwl_mvm_bt_rssi_event(mvm, vif, rssi_event); |
1560 | } | 1567 | } |
1561 | 1568 | ||
1569 | #ifdef CONFIG_NL80211_TESTMODE | ||
1570 | static const struct nla_policy iwl_mvm_tm_policy[IWL_MVM_TM_ATTR_MAX + 1] = { | ||
1571 | [IWL_MVM_TM_ATTR_CMD] = { .type = NLA_U32 }, | ||
1572 | [IWL_MVM_TM_ATTR_NOA_DURATION] = { .type = NLA_U32 }, | ||
1573 | }; | ||
1574 | |||
1575 | static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, | ||
1576 | struct ieee80211_vif *vif, | ||
1577 | void *data, int len) | ||
1578 | { | ||
1579 | struct nlattr *tb[IWL_MVM_TM_ATTR_MAX + 1]; | ||
1580 | int err; | ||
1581 | u32 noa_duration; | ||
1582 | |||
1583 | err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy); | ||
1584 | if (err) | ||
1585 | return err; | ||
1586 | |||
1587 | if (!tb[IWL_MVM_TM_ATTR_CMD]) | ||
1588 | return -EINVAL; | ||
1589 | |||
1590 | switch (nla_get_u32(tb[IWL_MVM_TM_ATTR_CMD])) { | ||
1591 | case IWL_MVM_TM_CMD_SET_NOA: | ||
1592 | if (!vif || vif->type != NL80211_IFTYPE_AP || !vif->p2p || | ||
1593 | !vif->bss_conf.enable_beacon || | ||
1594 | !tb[IWL_MVM_TM_ATTR_NOA_DURATION]) | ||
1595 | return -EINVAL; | ||
1596 | |||
1597 | noa_duration = nla_get_u32(tb[IWL_MVM_TM_ATTR_NOA_DURATION]); | ||
1598 | if (noa_duration >= vif->bss_conf.beacon_int) | ||
1599 | return -EINVAL; | ||
1600 | |||
1601 | mvm->noa_duration = noa_duration; | ||
1602 | mvm->noa_vif = vif; | ||
1603 | |||
1604 | return iwl_mvm_update_quotas(mvm, NULL); | ||
1605 | } | ||
1606 | |||
1607 | return -EOPNOTSUPP; | ||
1608 | } | ||
1609 | |||
1610 | static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, | ||
1611 | struct ieee80211_vif *vif, | ||
1612 | void *data, int len) | ||
1613 | { | ||
1614 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
1615 | int err; | ||
1616 | |||
1617 | mutex_lock(&mvm->mutex); | ||
1618 | err = __iwl_mvm_mac_testmode_cmd(mvm, vif, data, len); | ||
1619 | mutex_unlock(&mvm->mutex); | ||
1620 | |||
1621 | return err; | ||
1622 | } | ||
1623 | #endif | ||
1624 | |||
1562 | struct ieee80211_ops iwl_mvm_hw_ops = { | 1625 | struct ieee80211_ops iwl_mvm_hw_ops = { |
1563 | .tx = iwl_mvm_mac_tx, | 1626 | .tx = iwl_mvm_mac_tx, |
1564 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 1627 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
@@ -1595,6 +1658,8 @@ struct ieee80211_ops iwl_mvm_hw_ops = { | |||
1595 | 1658 | ||
1596 | .set_tim = iwl_mvm_set_tim, | 1659 | .set_tim = iwl_mvm_set_tim, |
1597 | 1660 | ||
1661 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) | ||
1662 | |||
1598 | #ifdef CONFIG_PM_SLEEP | 1663 | #ifdef CONFIG_PM_SLEEP |
1599 | /* look at d3.c */ | 1664 | /* look at d3.c */ |
1600 | .suspend = iwl_mvm_suspend, | 1665 | .suspend = iwl_mvm_suspend, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b0389279cc1e..2becb091a055 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -529,6 +529,11 @@ struct iwl_mvm { | |||
529 | s32 temperature; /* Celsius */ | 529 | s32 temperature; /* Celsius */ |
530 | 530 | ||
531 | const struct iwl_mvm_power_ops *pm_ops; | 531 | const struct iwl_mvm_power_ops *pm_ops; |
532 | |||
533 | #ifdef CONFIG_NL80211_TESTMODE | ||
534 | u32 noa_duration; | ||
535 | struct ieee80211_vif *noa_vif; | ||
536 | #endif | ||
532 | }; | 537 | }; |
533 | 538 | ||
534 | /* Extract MVM priv from op_mode and _hw */ | 539 | /* Extract MVM priv from op_mode and _hw */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 5c6ae16ec52b..6c724a076427 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -129,6 +129,38 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
129 | } | 129 | } |
130 | } | 130 | } |
131 | 131 | ||
132 | static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm, | ||
133 | struct iwl_time_quota_cmd *cmd) | ||
134 | { | ||
135 | #ifdef CONFIG_NL80211_TESTMODE | ||
136 | struct iwl_mvm_vif *mvmvif; | ||
137 | int i, phy_id = -1, beacon_int = 0; | ||
138 | |||
139 | if (!mvm->noa_duration || !mvm->noa_vif) | ||
140 | return; | ||
141 | |||
142 | mvmvif = iwl_mvm_vif_from_mac80211(mvm->noa_vif); | ||
143 | if (!mvmvif->ap_active) | ||
144 | return; | ||
145 | |||
146 | phy_id = mvmvif->phy_ctxt->id; | ||
147 | beacon_int = mvm->noa_vif->bss_conf.beacon_int; | ||
148 | |||
149 | for (i = 0; i < MAX_BINDINGS; i++) { | ||
150 | u32 id_n_c = le32_to_cpu(cmd->quotas[i].id_and_color); | ||
151 | u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS; | ||
152 | u32 quota = le32_to_cpu(cmd->quotas[i].quota); | ||
153 | |||
154 | if (id != phy_id) | ||
155 | continue; | ||
156 | |||
157 | quota *= (beacon_int - mvm->noa_duration) / beacon_int; | ||
158 | |||
159 | cmd->quotas[i].quota = cpu_to_le32(quota); | ||
160 | } | ||
161 | #endif | ||
162 | } | ||
163 | |||
132 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | 164 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) |
133 | { | 165 | { |
134 | struct iwl_time_quota_cmd cmd = {}; | 166 | struct iwl_time_quota_cmd cmd = {}; |
@@ -196,6 +228,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
196 | /* Give the remainder of the session to the first binding */ | 228 | /* Give the remainder of the session to the first binding */ |
197 | le32_add_cpu(&cmd.quotas[0].quota, quota_rem); | 229 | le32_add_cpu(&cmd.quotas[0].quota, quota_rem); |
198 | 230 | ||
231 | iwl_mvm_adjust_quota_for_noa(mvm, &cmd); | ||
232 | |||
199 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, | 233 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, |
200 | sizeof(cmd), &cmd); | 234 | sizeof(cmd), &cmd); |
201 | if (ret) | 235 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/testmode.h b/drivers/net/wireless/iwlwifi/mvm/testmode.h new file mode 100644 index 000000000000..e3df4992a371 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/testmode.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #ifndef __IWL_MVM_TESTMODE_H__ | ||
65 | #define __IWL_MVM_TESTMODE_H__ | ||
66 | |||
67 | /** | ||
68 | * enum iwl_mvm_testmode_attrs - testmode attributes inside NL80211_ATTR_TESTDATA | ||
69 | * @IWL_MVM_TM_ATTR_UNSPEC: (invalid attribute) | ||
70 | * @IWL_MVM_TM_ATTR_CMD: sub command, see &enum iwl_mvm_testmode_commands (u32) | ||
71 | * @IWL_MVM_TM_ATTR_NOA_DURATION: requested NoA duration (u32) | ||
72 | */ | ||
73 | enum iwl_mvm_testmode_attrs { | ||
74 | IWL_MVM_TM_ATTR_UNSPEC, | ||
75 | IWL_MVM_TM_ATTR_CMD, | ||
76 | IWL_MVM_TM_ATTR_NOA_DURATION, | ||
77 | |||
78 | /* keep last */ | ||
79 | NUM_IWL_MVM_TM_ATTRS, | ||
80 | IWL_MVM_TM_ATTR_MAX = NUM_IWL_MVM_TM_ATTRS - 1, | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * enum iwl_mvm_testmode_commands - MVM testmode commands | ||
85 | * @IWL_MVM_TM_CMD_SET_NOA: set NoA on GO vif for testing | ||
86 | */ | ||
87 | enum iwl_mvm_testmode_commands { | ||
88 | IWL_MVM_TM_CMD_SET_NOA, | ||
89 | }; | ||
90 | |||
91 | #endif /* __IWL_MVM_TESTMODE_H__ */ | ||