diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c deleted file mode 100644 index e68a475e3071..000000000000 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ /dev/null | |||
@@ -1,295 +0,0 @@ | |||
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) 2012 - 2014 Intel Corporation. All rights reserved. | ||
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of version 2 of the GNU General Public License as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
23 | * USA | ||
24 | * | ||
25 | * The full GNU General Public License is included in this distribution | ||
26 | * in the file called COPYING. | ||
27 | * | ||
28 | * Contact Information: | ||
29 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
30 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
31 | * | ||
32 | * BSD LICENSE | ||
33 | * | ||
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | ||
35 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | ||
36 | * All rights reserved. | ||
37 | * | ||
38 | * Redistribution and use in source and binary forms, with or without | ||
39 | * modification, are permitted provided that the following conditions | ||
40 | * are met: | ||
41 | * | ||
42 | * * Redistributions of source code must retain the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer. | ||
44 | * * Redistributions in binary form must reproduce the above copyright | ||
45 | * notice, this list of conditions and the following disclaimer in | ||
46 | * the documentation and/or other materials provided with the | ||
47 | * distribution. | ||
48 | * * Neither the name Intel Corporation nor the names of its | ||
49 | * contributors may be used to endorse or promote products derived | ||
50 | * from this software without specific prior written permission. | ||
51 | * | ||
52 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
53 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
54 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
55 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
56 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
57 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
58 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
59 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
60 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
61 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
62 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
63 | * | ||
64 | *****************************************************************************/ | ||
65 | |||
66 | #include <net/mac80211.h> | ||
67 | #include "fw-api.h" | ||
68 | #include "mvm.h" | ||
69 | |||
70 | /* Maps the driver specific channel width definition to the fw values */ | ||
71 | u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef) | ||
72 | { | ||
73 | switch (chandef->width) { | ||
74 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
75 | case NL80211_CHAN_WIDTH_20: | ||
76 | return PHY_VHT_CHANNEL_MODE20; | ||
77 | case NL80211_CHAN_WIDTH_40: | ||
78 | return PHY_VHT_CHANNEL_MODE40; | ||
79 | case NL80211_CHAN_WIDTH_80: | ||
80 | return PHY_VHT_CHANNEL_MODE80; | ||
81 | case NL80211_CHAN_WIDTH_160: | ||
82 | return PHY_VHT_CHANNEL_MODE160; | ||
83 | default: | ||
84 | WARN(1, "Invalid channel width=%u", chandef->width); | ||
85 | return PHY_VHT_CHANNEL_MODE20; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Maps the driver specific control channel position (relative to the center | ||
91 | * freq) definitions to the the fw values | ||
92 | */ | ||
93 | u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef) | ||
94 | { | ||
95 | switch (chandef->chan->center_freq - chandef->center_freq1) { | ||
96 | case -70: | ||
97 | return PHY_VHT_CTRL_POS_4_BELOW; | ||
98 | case -50: | ||
99 | return PHY_VHT_CTRL_POS_3_BELOW; | ||
100 | case -30: | ||
101 | return PHY_VHT_CTRL_POS_2_BELOW; | ||
102 | case -10: | ||
103 | return PHY_VHT_CTRL_POS_1_BELOW; | ||
104 | case 10: | ||
105 | return PHY_VHT_CTRL_POS_1_ABOVE; | ||
106 | case 30: | ||
107 | return PHY_VHT_CTRL_POS_2_ABOVE; | ||
108 | case 50: | ||
109 | return PHY_VHT_CTRL_POS_3_ABOVE; | ||
110 | case 70: | ||
111 | return PHY_VHT_CTRL_POS_4_ABOVE; | ||
112 | default: | ||
113 | WARN(1, "Invalid channel definition"); | ||
114 | case 0: | ||
115 | /* | ||
116 | * The FW is expected to check the control channel position only | ||
117 | * when in HT/VHT and the channel width is not 20MHz. Return | ||
118 | * this value as the default one. | ||
119 | */ | ||
120 | return PHY_VHT_CTRL_POS_1_BELOW; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Construct the generic fields of the PHY context command | ||
126 | */ | ||
127 | static void iwl_mvm_phy_ctxt_cmd_hdr(struct iwl_mvm_phy_ctxt *ctxt, | ||
128 | struct iwl_phy_context_cmd *cmd, | ||
129 | u32 action, u32 apply_time) | ||
130 | { | ||
131 | memset(cmd, 0, sizeof(struct iwl_phy_context_cmd)); | ||
132 | |||
133 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(ctxt->id, | ||
134 | ctxt->color)); | ||
135 | cmd->action = cpu_to_le32(action); | ||
136 | cmd->apply_time = cpu_to_le32(apply_time); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Add the phy configuration to the PHY context command | ||
141 | */ | ||
142 | static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | ||
143 | struct iwl_phy_context_cmd *cmd, | ||
144 | struct cfg80211_chan_def *chandef, | ||
145 | u8 chains_static, u8 chains_dynamic) | ||
146 | { | ||
147 | u8 active_cnt, idle_cnt; | ||
148 | |||
149 | /* Set the channel info data */ | ||
150 | cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? | ||
151 | PHY_BAND_24 : PHY_BAND_5); | ||
152 | |||
153 | cmd->ci.channel = chandef->chan->hw_value; | ||
154 | cmd->ci.width = iwl_mvm_get_channel_width(chandef); | ||
155 | cmd->ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef); | ||
156 | |||
157 | /* Set rx the chains */ | ||
158 | idle_cnt = chains_static; | ||
159 | active_cnt = chains_dynamic; | ||
160 | |||
161 | /* In scenarios where we only ever use a single-stream rates, | ||
162 | * i.e. legacy 11b/g/a associations, single-stream APs or even | ||
163 | * static SMPS, enable both chains to get diversity, improving | ||
164 | * the case where we're far enough from the AP that attenuation | ||
165 | * between the two antennas is sufficiently different to impact | ||
166 | * performance. | ||
167 | */ | ||
168 | if (active_cnt == 1 && iwl_mvm_rx_diversity_allowed(mvm)) { | ||
169 | idle_cnt = 2; | ||
170 | active_cnt = 2; | ||
171 | } | ||
172 | |||
173 | cmd->rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) << | ||
174 | PHY_RX_CHAIN_VALID_POS); | ||
175 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); | ||
176 | cmd->rxchain_info |= cpu_to_le32(active_cnt << | ||
177 | PHY_RX_CHAIN_MIMO_CNT_POS); | ||
178 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
179 | if (unlikely(mvm->dbgfs_rx_phyinfo)) | ||
180 | cmd->rxchain_info = cpu_to_le32(mvm->dbgfs_rx_phyinfo); | ||
181 | #endif | ||
182 | |||
183 | cmd->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Send a command to apply the current phy configuration. The command is send | ||
188 | * only if something in the configuration changed: in case that this is the | ||
189 | * first time that the phy configuration is applied or in case that the phy | ||
190 | * configuration changed from the previous apply. | ||
191 | */ | ||
192 | static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, | ||
193 | struct iwl_mvm_phy_ctxt *ctxt, | ||
194 | struct cfg80211_chan_def *chandef, | ||
195 | u8 chains_static, u8 chains_dynamic, | ||
196 | u32 action, u32 apply_time) | ||
197 | { | ||
198 | struct iwl_phy_context_cmd cmd; | ||
199 | int ret; | ||
200 | |||
201 | /* Set the command header fields */ | ||
202 | iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, action, apply_time); | ||
203 | |||
204 | /* Set the command data */ | ||
205 | iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef, | ||
206 | chains_static, chains_dynamic); | ||
207 | |||
208 | ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0, | ||
209 | sizeof(struct iwl_phy_context_cmd), | ||
210 | &cmd); | ||
211 | if (ret) | ||
212 | IWL_ERR(mvm, "PHY ctxt cmd error. ret=%d\n", ret); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Send a command to add a PHY context based on the current HW configuration. | ||
218 | */ | ||
219 | int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | ||
220 | struct cfg80211_chan_def *chandef, | ||
221 | u8 chains_static, u8 chains_dynamic) | ||
222 | { | ||
223 | WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | ||
224 | ctxt->ref); | ||
225 | lockdep_assert_held(&mvm->mutex); | ||
226 | |||
227 | ctxt->channel = chandef->chan; | ||
228 | |||
229 | return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, | ||
230 | chains_static, chains_dynamic, | ||
231 | FW_CTXT_ACTION_ADD, 0); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Update the number of references to the given PHY context. This is valid only | ||
236 | * in case the PHY context was already created, i.e., its reference count > 0. | ||
237 | */ | ||
238 | void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) | ||
239 | { | ||
240 | lockdep_assert_held(&mvm->mutex); | ||
241 | ctxt->ref++; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Send a command to modify the PHY context based on the current HW | ||
246 | * configuration. Note that the function does not check that the configuration | ||
247 | * changed. | ||
248 | */ | ||
249 | int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | ||
250 | struct cfg80211_chan_def *chandef, | ||
251 | u8 chains_static, u8 chains_dynamic) | ||
252 | { | ||
253 | lockdep_assert_held(&mvm->mutex); | ||
254 | |||
255 | ctxt->channel = chandef->chan; | ||
256 | return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, | ||
257 | chains_static, chains_dynamic, | ||
258 | FW_CTXT_ACTION_MODIFY, 0); | ||
259 | } | ||
260 | |||
261 | void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) | ||
262 | { | ||
263 | lockdep_assert_held(&mvm->mutex); | ||
264 | |||
265 | if (WARN_ON_ONCE(!ctxt)) | ||
266 | return; | ||
267 | |||
268 | ctxt->ref--; | ||
269 | } | ||
270 | |||
271 | static void iwl_mvm_binding_iterator(void *_data, u8 *mac, | ||
272 | struct ieee80211_vif *vif) | ||
273 | { | ||
274 | unsigned long *data = _data; | ||
275 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
276 | |||
277 | if (!mvmvif->phy_ctxt) | ||
278 | return; | ||
279 | |||
280 | if (vif->type == NL80211_IFTYPE_STATION || | ||
281 | vif->type == NL80211_IFTYPE_AP) | ||
282 | __set_bit(mvmvif->phy_ctxt->id, data); | ||
283 | } | ||
284 | |||
285 | int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm) | ||
286 | { | ||
287 | unsigned long phy_ctxt_counter = 0; | ||
288 | |||
289 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
290 | IEEE80211_IFACE_ITER_NORMAL, | ||
291 | iwl_mvm_binding_iterator, | ||
292 | &phy_ctxt_counter); | ||
293 | |||
294 | return hweight8(phy_ctxt_counter); | ||
295 | } | ||