iwlwifi: mvm: replace leading spaces by tabs
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / mvm / power.c
CommitLineData
8ca151b5
JB
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 *
51368bf7 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8ca151b5
JB
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
410dc5aa 25 * in the file called COPYING.
8ca151b5
JB
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 *
51368bf7 33 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8ca151b5
JB
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#include <linux/kernel.h>
65#include <linux/module.h>
66#include <linux/slab.h>
8ca151b5
JB
67
68#include <net/mac80211.h>
69
70#include "iwl-debug.h"
71#include "mvm.h"
72#include "iwl-modparams.h"
73#include "fw-api-power.h"
74
75#define POWER_KEEP_ALIVE_PERIOD_SEC 25
76
d623d24a 77static
e811ada7 78int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
3dd37d05
EP
79 struct iwl_beacon_filter_cmd *cmd,
80 u32 flags)
071d4990 81{
d623d24a
EG
82 IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
83 le32_to_cpu(cmd->ba_enable_beacon_abort));
84 IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
85 le32_to_cpu(cmd->ba_escape_timer));
86 IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
87 le32_to_cpu(cmd->bf_debug_flag));
88 IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
89 le32_to_cpu(cmd->bf_enable_beacon_filter));
90 IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
91 le32_to_cpu(cmd->bf_energy_delta));
92 IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
93 le32_to_cpu(cmd->bf_escape_timer));
94 IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
95 le32_to_cpu(cmd->bf_roaming_energy_delta));
96 IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
97 le32_to_cpu(cmd->bf_roaming_state));
98 IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
99 le32_to_cpu(cmd->bf_temp_threshold));
100 IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
101 le32_to_cpu(cmd->bf_temp_fast_filter));
102 IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
103 le32_to_cpu(cmd->bf_temp_slow_filter));
104
105 return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
106 sizeof(struct iwl_beacon_filter_cmd), cmd);
071d4990
AB
107}
108
a20fd398
AO
109static
110void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
111 struct ieee80211_vif *vif,
112 struct iwl_beacon_filter_cmd *cmd)
113{
114 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
115
116 if (vif->bss_conf.cqm_rssi_thold) {
117 cmd->bf_energy_delta =
118 cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
119 /* fw uses an absolute value for this */
120 cmd->bf_roaming_state =
121 cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
122 }
123 cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
124}
125
e811ada7
AB
126int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
127 struct ieee80211_vif *vif, bool enable)
071d4990
AB
128{
129 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
130 struct iwl_beacon_filter_cmd cmd = {
131 IWL_BF_CMD_CONFIG_DEFAULTS,
5dca7c24
HG
132 .bf_enable_beacon_filter = cpu_to_le32(1),
133 .ba_enable_beacon_abort = cpu_to_le32(enable),
071d4990
AB
134 };
135
a20fd398 136 if (!mvmvif->bf_data.bf_enabled)
071d4990
AB
137 return 0;
138
8434925f
AB
139 if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
140 cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
141
a20fd398
AO
142 mvmvif->bf_data.ba_enabled = enable;
143 iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);
b571a697 144 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
3dd37d05 145 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, CMD_SYNC);
071d4990
AB
146}
147
3f0b2b3e 148static void iwl_mvm_power_log(struct iwl_mvm *mvm,
e811ada7 149 struct iwl_mac_power_cmd *cmd)
3f0b2b3e
AB
150{
151 IWL_DEBUG_POWER(mvm,
e811ada7
AB
152 "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
153 cmd->id_and_color, iwlmvm_mod_params.power_scheme,
3f0b2b3e 154 le16_to_cpu(cmd->flags));
e811ada7
AB
155 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
156 le16_to_cpu(cmd->keep_alive_seconds));
3f0b2b3e 157
e3c588ec
AB
158 if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
159 IWL_DEBUG_POWER(mvm, "Disable power management\n");
160 return;
161 }
162
163 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
164 le32_to_cpu(cmd->rx_data_timeout));
165 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
166 le32_to_cpu(cmd->tx_data_timeout));
167 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
168 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
169 cmd->skip_dtim_periods);
170 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
171 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
172 cmd->lprx_rssi_threshold);
173 if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
174 IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
175 IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
176 le32_to_cpu(cmd->rx_data_timeout_uapsd));
177 IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
178 le32_to_cpu(cmd->tx_data_timeout_uapsd));
179 IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
180 IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
181 IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
3f0b2b3e
AB
182 }
183}
184
175a70b7
AB
185static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
186 struct ieee80211_vif *vif,
187 struct iwl_mac_power_cmd *cmd)
188{
189 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
190 enum ieee80211_ac_numbers ac;
191 bool tid_found = false;
192
193 for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
194 if (!mvmvif->queue_params[ac].uapsd)
195 continue;
196
197 if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
198 cmd->flags |=
199 cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
200
201 cmd->uapsd_ac_flags |= BIT(ac);
202
203 /* QNDP TID - the highest TID with no admission control */
204 if (!tid_found && !mvmvif->queue_params[ac].acm) {
205 tid_found = true;
206 switch (ac) {
207 case IEEE80211_AC_VO:
208 cmd->qndp_tid = 6;
209 break;
210 case IEEE80211_AC_VI:
211 cmd->qndp_tid = 5;
212 break;
213 case IEEE80211_AC_BE:
214 cmd->qndp_tid = 0;
215 break;
216 case IEEE80211_AC_BK:
217 cmd->qndp_tid = 1;
218 break;
219 }
220 }
221 }
222
223 if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
224 return;
225
226 cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
227
228 if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
229 BIT(IEEE80211_AC_VI) |
230 BIT(IEEE80211_AC_BE) |
231 BIT(IEEE80211_AC_BK))) {
232 cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
233 cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
234 cmd->snooze_window = (mvm->cur_ucode == IWL_UCODE_WOWLAN) ?
235 cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
236 cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
237 }
238
239 cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP;
240
241 if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags &
242 cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
243 cmd->rx_data_timeout_uapsd =
244 cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
245 cmd->tx_data_timeout_uapsd =
246 cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
247 } else {
248 cmd->rx_data_timeout_uapsd =
249 cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
250 cmd->tx_data_timeout_uapsd =
251 cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
252 }
253
254 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
255 cmd->heavy_tx_thld_packets =
256 IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
257 cmd->heavy_rx_thld_packets =
258 IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
259 } else {
260 cmd->heavy_tx_thld_packets =
261 IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
262 cmd->heavy_rx_thld_packets =
263 IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
264 }
265 cmd->heavy_tx_thld_percentage =
266 IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
267 cmd->heavy_rx_thld_percentage =
268 IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
269}
270
e811ada7
AB
271static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
272 struct ieee80211_vif *vif,
273 struct iwl_mac_power_cmd *cmd)
8ca151b5
JB
274{
275 struct ieee80211_hw *hw = mvm->hw;
8ca151b5
JB
276 struct ieee80211_chanctx_conf *chanctx_conf;
277 struct ieee80211_channel *chan;
278 int dtimper, dtimper_msec;
279 int keep_alive;
280 bool radar_detect = false;
b571a697
AB
281 struct iwl_mvm_vif *mvmvif __maybe_unused =
282 iwl_mvm_vif_from_mac80211(vif);
51498cf6 283 bool allow_uapsd = true;
8ca151b5 284
e811ada7
AB
285 cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
286 mvmvif->color));
287 dtimper = hw->conf.ps_dtim_period ?: 1;
288
e16cf7ec
AB
289 /*
290 * Regardless of power management state the driver must set
291 * keep alive period. FW will use it for sending keep alive NDPs
e811ada7
AB
292 * immediately after association. Check that keep alive period
293 * is at least 3 * DTIM
e16cf7ec 294 */
e811ada7
AB
295 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
296 keep_alive = max_t(int, 3 * dtimper_msec,
297 MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
298 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
299 cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
e16cf7ec 300
e5e7aa8e 301 if (mvm->ps_disabled)
8ca151b5
JB
302 return;
303
9a613048
AB
304 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
305
e5e7aa8e 306 if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) ||
19889025 307 !mvmvif->pm_enabled)
9a613048
AB
308 return;
309
310 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
8ca151b5 311
bd4ace2a
AB
312 if (vif->bss_conf.beacon_rate &&
313 (vif->bss_conf.beacon_rate->bitrate == 10 ||
314 vif->bss_conf.beacon_rate->bitrate == 60)) {
315 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
e811ada7 316 cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
bd4ace2a
AB
317 }
318
8ca151b5
JB
319 /* Check if radar detection is required on current channel */
320 rcu_read_lock();
321 chanctx_conf = rcu_dereference(vif->chanctx_conf);
322 WARN_ON(!chanctx_conf);
323 if (chanctx_conf) {
324 chan = chanctx_conf->def.chan;
325 radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
326 }
327 rcu_read_unlock();
328
329 /* Check skip over DTIM conditions */
330 if (!radar_detect && (dtimper <= 10) &&
ee1e8422
AB
331 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
332 mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
f4a3e2fe 333 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
e811ada7 334 cmd->skip_dtim_periods = 3;
5b1dbfc3 335 }
8ca151b5 336
ee1e8422 337 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
99545924
JB
338 cmd->rx_data_timeout =
339 cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
340 cmd->tx_data_timeout =
341 cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
ee1e8422 342 } else {
99545924
JB
343 cmd->rx_data_timeout =
344 cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
345 cmd->tx_data_timeout =
346 cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
ee1e8422 347 }
b571a697 348
51498cf6
AB
349 if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
350 ETH_ALEN))
351 allow_uapsd = false;
75209672
AB
352
353 if (vif->p2p &&
354 !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD))
355 allow_uapsd = false;
51498cf6
AB
356 /*
357 * Avoid using uAPSD if P2P client is associated to GO that uses
358 * opportunistic power save. This is due to current FW limitation.
359 */
360 if (vif->p2p &&
361 vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
362 IEEE80211_P2P_OPPPS_ENABLE_BIT)
363 allow_uapsd = false;
364
365 if (allow_uapsd)
175a70b7 366 iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
e3c588ec 367
b571a697
AB
368#ifdef CONFIG_IWLWIFI_DEBUGFS
369 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
e811ada7
AB
370 cmd->keep_alive_seconds =
371 cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
b571a697
AB
372 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
373 if (mvmvif->dbgfs_pm.skip_over_dtim)
374 cmd->flags |=
375 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
376 else
377 cmd->flags &=
378 cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
379 }
380 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
381 cmd->rx_data_timeout =
382 cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
383 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
384 cmd->tx_data_timeout =
385 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
386 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
e811ada7 387 cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
bd4ace2a
AB
388 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
389 if (mvmvif->dbgfs_pm.lprx_ena)
390 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
391 else
392 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
393 }
394 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
e811ada7 395 cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
89716344
AB
396 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
397 if (mvmvif->dbgfs_pm.snooze_ena)
398 cmd->flags |=
399 cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
400 else
401 cmd->flags &=
402 cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
403 }
e45a941d
AB
404 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
405 u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
406 if (mvmvif->dbgfs_pm.uapsd_misbehaving)
407 cmd->flags |= cpu_to_le16(flag);
408 else
409 cmd->flags &= cpu_to_le16(flag);
410 }
b571a697 411#endif /* CONFIG_IWLWIFI_DEBUGFS */
8ca151b5
JB
412}
413
e5e7aa8e 414static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
e811ada7 415 struct ieee80211_vif *vif)
8ca151b5 416{
e811ada7 417 struct iwl_mac_power_cmd cmd = {};
8ca151b5 418
f4a3e2fe 419 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
3f0b2b3e 420 iwl_mvm_power_log(mvm, &cmd);
474b50c3
EG
421#ifdef CONFIG_IWLWIFI_DEBUGFS
422 memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
423#endif
8ca151b5 424
06280a2b
EG
425 return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
426 sizeof(cmd), &cmd);
427}
428
e5e7aa8e 429int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
64b928c4
AB
430{
431 struct iwl_device_power_cmd cmd = {
432 .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
433 };
434
e5e7aa8e
EG
435 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
436 mvm->ps_disabled = true;
437
438 if (mvm->ps_disabled)
64b928c4
AB
439 cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
440
441#ifdef CONFIG_IWLWIFI_DEBUGFS
442 if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 :
443 mvm->disable_power_off)
444 cmd.flags &=
445 cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
446#endif
447 IWL_DEBUG_POWER(mvm,
448 "Sending device power command with flags = 0x%X\n",
449 cmd.flags);
450
451 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd),
452 &cmd);
453}
454
175a70b7
AB
455void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
456{
457 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
458
459 if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
460 ETH_ALEN))
461 memset(mvmvif->uapsd_misbehaving_bssid, 0, ETH_ALEN);
462}
463
464static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
465 struct ieee80211_vif *vif)
466{
467 u8 *ap_sta_id = _data;
468 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
469
470 /* The ap_sta_id is not expected to change during current association
471 * so no explicit protection is needed
472 */
473 if (mvmvif->ap_sta_id == *ap_sta_id)
474 memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
475 ETH_ALEN);
476}
477
478int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
479 struct iwl_rx_cmd_buffer *rxb,
480 struct iwl_device_cmd *cmd)
481{
482 struct iwl_rx_packet *pkt = rxb_addr(rxb);
483 struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
484 u8 ap_sta_id = le32_to_cpu(notif->sta_id);
485
486 ieee80211_iterate_active_interfaces_atomic(
487 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
488 iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
489
490 return 0;
491}
492
19889025 493struct iwl_power_vifs {
06280a2b 494 struct ieee80211_vif *bf_vif;
e5e7aa8e 495 struct ieee80211_vif *bss_vif;
8ea0c68f 496 struct ieee80211_vif *p2p_vif;
19889025
AA
497 struct ieee80211_vif *ap_vif;
498 struct ieee80211_vif *monitor_vif;
499 bool p2p_active;
500 bool bss_active;
501 bool ap_active;
502 bool monitor_active;
06280a2b
EG
503};
504
e5e7aa8e
EG
505static void iwl_mvm_power_iterator(void *_data, u8 *mac,
506 struct ieee80211_vif *vif)
1c2abf72 507{
06280a2b 508 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
19889025 509 struct iwl_power_vifs *power_iterator = _data;
e5e7aa8e 510
19889025 511 mvmvif->pm_enabled = false;
e5e7aa8e
EG
512 switch (ieee80211_vif_type_p2p(vif)) {
513 case NL80211_IFTYPE_P2P_DEVICE:
514 break;
515
516 case NL80211_IFTYPE_P2P_GO:
517 case NL80211_IFTYPE_AP:
19889025
AA
518 /* only a single MAC of the same type */
519 WARN_ON(power_iterator->ap_vif);
520 power_iterator->ap_vif = vif;
521 if (mvmvif->phy_ctxt)
522 if (mvmvif->phy_ctxt->id < MAX_PHYS)
523 power_iterator->ap_active = true;
e5e7aa8e
EG
524 break;
525
526 case NL80211_IFTYPE_MONITOR:
19889025
AA
527 /* only a single MAC of the same type */
528 WARN_ON(power_iterator->monitor_vif);
529 power_iterator->monitor_vif = vif;
530 if (mvmvif->phy_ctxt)
531 if (mvmvif->phy_ctxt->id < MAX_PHYS)
532 power_iterator->monitor_active = true;
e5e7aa8e
EG
533 break;
534
535 case NL80211_IFTYPE_P2P_CLIENT:
19889025 536 /* only a single MAC of the same type */
8ea0c68f
AA
537 WARN_ON(power_iterator->p2p_vif);
538 power_iterator->p2p_vif = vif;
19889025
AA
539 if (mvmvif->phy_ctxt)
540 if (mvmvif->phy_ctxt->id < MAX_PHYS)
541 power_iterator->p2p_active = true;
e5e7aa8e
EG
542 break;
543
544 case NL80211_IFTYPE_STATION:
19889025 545 /* only a single MAC of the same type */
e5e7aa8e
EG
546 WARN_ON(power_iterator->bss_vif);
547 power_iterator->bss_vif = vif;
19889025
AA
548 if (mvmvif->phy_ctxt)
549 if (mvmvif->phy_ctxt->id < MAX_PHYS)
550 power_iterator->bss_active = true;
e5e7aa8e
EG
551
552 if (mvmvif->bf_data.bf_enabled &&
553 !WARN_ON(power_iterator->bf_vif))
554 power_iterator->bf_vif = vif;
7303dd7f 555
e5e7aa8e
EG
556 break;
557
558 default:
559 break;
560 }
561}
1c2abf72 562
e5e7aa8e 563static void
19889025
AA
564iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
565 struct iwl_power_vifs *vifs)
e5e7aa8e 566{
19889025
AA
567 struct iwl_mvm_vif *bss_mvmvif = NULL;
568 struct iwl_mvm_vif *p2p_mvmvif = NULL;
569 struct iwl_mvm_vif *ap_mvmvif = NULL;
570 bool client_same_channel = false;
571 bool ap_same_channel = false;
e5e7aa8e 572
19889025 573 lockdep_assert_held(&mvm->mutex);
06280a2b 574
19889025 575 /* get vifs info + set pm_enable to false */
e5e7aa8e
EG
576 ieee80211_iterate_active_interfaces_atomic(mvm->hw,
577 IEEE80211_IFACE_ITER_NORMAL,
19889025
AA
578 iwl_mvm_power_iterator, vifs);
579
580 if (vifs->bss_vif)
581 bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
582
583 if (vifs->p2p_vif)
584 p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
585
586 if (vifs->ap_vif)
587 ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
588
589 /* enable PM on bss if bss stand alone */
590 if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
591 bss_mvmvif->pm_enabled = true;
592 return;
593 }
594
595 /* enable PM on p2p if p2p stand alone */
596 if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
597 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
598 p2p_mvmvif->pm_enabled = true;
599 return;
600 }
601
602 if (vifs->bss_active && vifs->p2p_active)
603 client_same_channel = (bss_mvmvif->phy_ctxt->id ==
604 p2p_mvmvif->phy_ctxt->id);
605 if (vifs->bss_active && vifs->ap_active)
606 ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
607 ap_mvmvif->phy_ctxt->id);
608
609 /* bss is not stand alone: enable PM if alone on its channel */
610 if (vifs->bss_active && !(client_same_channel || ap_same_channel) &&
611 (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {
612 bss_mvmvif->pm_enabled = true;
613 return;
614 }
615
616 /*
617 * There is only one channel in the system and there are only
618 * bss and p2p clients that share it
619 */
620 if (client_same_channel && !vifs->ap_active &&
621 (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM)) {
622 /* share same channel*/
623 bss_mvmvif->pm_enabled = true;
624 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
625 p2p_mvmvif->pm_enabled = true;
626 }
1c2abf72
AB
627}
628
e5e7aa8e 629int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1c2abf72 630{
19889025
AA
631 struct iwl_mvm_vif *mvmvif;
632 struct iwl_power_vifs vifs = {};
e5e7aa8e
EG
633 bool ba_enable;
634 int ret;
06280a2b
EG
635
636 lockdep_assert_held(&mvm->mutex);
637
19889025 638 iwl_mvm_power_set_pm(mvm, &vifs);
c1cb92fc 639
19889025
AA
640 /* disable PS if CAM */
641 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {
642 mvm->ps_disabled = true;
643 } else {
e5e7aa8e 644 /* don't update device power state unless we add / remove monitor */
19889025
AA
645 if (vifs.monitor_vif) {
646 if (vifs.monitor_active)
647 mvm->ps_disabled = true;
648 ret = iwl_mvm_power_update_device(mvm);
649 if (ret)
650 return ret;
651 }
92d85562
AB
652 }
653
19889025
AA
654 if (vifs.bss_vif) {
655 ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
e5e7aa8e
EG
656 if (ret)
657 return ret;
658 }
659
19889025
AA
660 if (vifs.p2p_vif) {
661 ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
8ea0c68f
AA
662 if (ret)
663 return ret;
664 }
665
19889025 666 if (!vifs.bf_vif)
e5e7aa8e 667 return 0;
06280a2b 668
19889025 669 vif = vifs.bf_vif;
06280a2b
EG
670 mvmvif = iwl_mvm_vif_from_mac80211(vif);
671
19889025 672 ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||
06280a2b
EG
673 !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif));
674
19889025 675 return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable);
1c2abf72
AB
676}
677
b571a697 678#ifdef CONFIG_IWLWIFI_DEBUGFS
c1cb92fc
EG
679int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
680 struct ieee80211_vif *vif, char *buf,
681 int bufsz)
e811ada7 682{
474b50c3 683 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
e811ada7
AB
684 struct iwl_mac_power_cmd cmd = {};
685 int pos = 0;
686
474b50c3
EG
687 mutex_lock(&mvm->mutex);
688 memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
689 mutex_unlock(&mvm->mutex);
e811ada7 690
e811ada7
AB
691 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
692 iwlmvm_mod_params.power_scheme);
693 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
694 le16_to_cpu(cmd.flags));
695 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
696 le16_to_cpu(cmd.keep_alive_seconds));
697
175a70b7
AB
698 if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
699 return pos;
700
701 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
702 (cmd.flags &
703 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
704 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
705 cmd.skip_dtim_periods);
706 if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
707 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
708 le32_to_cpu(cmd.rx_data_timeout));
709 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
710 le32_to_cpu(cmd.tx_data_timeout));
e811ada7 711 }
175a70b7
AB
712 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
713 pos += scnprintf(buf+pos, bufsz-pos,
714 "lprx_rssi_threshold = %d\n",
715 cmd.lprx_rssi_threshold);
716
717 if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
718 return pos;
719
720 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
721 le32_to_cpu(cmd.rx_data_timeout_uapsd));
722 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
723 le32_to_cpu(cmd.tx_data_timeout_uapsd));
724 pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
725 pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
726 cmd.uapsd_ac_flags);
727 pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
728 cmd.uapsd_max_sp);
729 pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
730 cmd.heavy_tx_thld_packets);
731 pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
732 cmd.heavy_rx_thld_packets);
733 pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
734 cmd.heavy_tx_thld_percentage);
735 pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
736 cmd.heavy_rx_thld_percentage);
737 pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
738 (cmd.flags &
739 cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
740 1 : 0);
741
742 if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
743 return pos;
744
745 pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
746 cmd.snooze_interval);
747 pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
748 cmd.snooze_window);
749
e811ada7
AB
750 return pos;
751}
752
b571a697
AB
753void
754iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
755 struct iwl_beacon_filter_cmd *cmd)
756{
757 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
758 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
759
760 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
5dca7c24 761 cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
b571a697
AB
762 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
763 cmd->bf_roaming_energy_delta =
5dca7c24 764 cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
b571a697 765 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
5dca7c24
HG
766 cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
767 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
768 cmd->bf_temp_threshold =
769 cpu_to_le32(dbgfs_bf->bf_temp_threshold);
770 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
771 cmd->bf_temp_fast_filter =
772 cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
773 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
774 cmd->bf_temp_slow_filter =
775 cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
b571a697 776 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
5dca7c24 777 cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
b571a697
AB
778 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
779 cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
780 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
781 cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
782 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
5dca7c24
HG
783 cmd->ba_enable_beacon_abort =
784 cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
b571a697
AB
785}
786#endif
787
3dd37d05
EP
788static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
789 struct ieee80211_vif *vif,
790 struct iwl_beacon_filter_cmd *cmd,
791 u32 cmd_flags,
792 bool d0i3)
7df15b1e
HG
793{
794 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
071d4990 795 int ret;
7df15b1e
HG
796
797 if (mvmvif != mvm->bf_allowed_vif ||
798 vif->type != NL80211_IFTYPE_STATION || vif->p2p)
799 return 0;
800
3dd37d05
EP
801 iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
802 if (!d0i3)
803 iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
804 ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
071d4990 805
3dd37d05
EP
806 /* don't change bf_enabled in case of temporary d0i3 configuration */
807 if (!ret && !d0i3)
a20fd398 808 mvmvif->bf_data.bf_enabled = true;
071d4990
AB
809
810 return ret;
7df15b1e
HG
811}
812
3dd37d05
EP
813int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
814 struct ieee80211_vif *vif,
815 u32 flags)
816{
817 struct iwl_beacon_filter_cmd cmd = {
818 IWL_BF_CMD_CONFIG_DEFAULTS,
819 .bf_enable_beacon_filter = cpu_to_le32(1),
820 };
821
822 return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
823}
824
7df15b1e 825int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
3dd37d05
EP
826 struct ieee80211_vif *vif,
827 u32 flags)
7df15b1e 828{
071d4990
AB
829 struct iwl_beacon_filter_cmd cmd = {};
830 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
831 int ret;
7df15b1e 832
73e5f2c5 833 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
7df15b1e
HG
834 return 0;
835
3dd37d05 836 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
071d4990
AB
837
838 if (!ret)
a20fd398 839 mvmvif->bf_data.bf_enabled = false;
071d4990
AB
840
841 return ret;
7df15b1e 842}
e811ada7 843
3dd37d05
EP
844int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
845 struct ieee80211_vif *vif,
846 bool enable, u32 flags)
847{
848 int ret;
849 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
850 struct iwl_mac_power_cmd cmd = {};
851
852 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
853 return 0;
854
855 if (!vif->bss_conf.assoc)
856 return 0;
857
858 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
859 if (enable) {
860 /* configure skip over dtim up to 300 msec */
861 int dtimper = mvm->hw->conf.ps_dtim_period ?: 1;
862 int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
863
864 if (WARN_ON(!dtimper_msec))
865 return 0;
866
867 cmd.flags |=
868 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
869 cmd.skip_dtim_periods = 300 / dtimper_msec;
870 }
871 iwl_mvm_power_log(mvm, &cmd);
474b50c3
EG
872#ifdef CONFIG_IWLWIFI_DEBUGFS
873 memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
874#endif
3dd37d05
EP
875 ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
876 sizeof(cmd), &cmd);
877 if (ret)
878 return ret;
879
880 /* configure beacon filtering */
881 if (mvmvif != mvm->bf_allowed_vif)
882 return 0;
883
884 if (enable) {
885 struct iwl_beacon_filter_cmd cmd_bf = {
886 IWL_BF_CMD_CONFIG_D0I3,
887 .bf_enable_beacon_filter = cpu_to_le32(1),
888 };
889 ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
890 flags, true);
891 } else {
892 if (mvmvif->bf_data.bf_enabled)
893 ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
894 else
895 ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
896 }
897
898 return ret;
899}
900
a20fd398 901int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
3dd37d05
EP
902 struct ieee80211_vif *vif,
903 bool force,
904 u32 flags)
a20fd398
AO
905{
906 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
907
3dd37d05 908 if (mvmvif != mvm->bf_allowed_vif)
a20fd398
AO
909 return 0;
910
3dd37d05
EP
911 if (!mvmvif->bf_data.bf_enabled) {
912 /* disable beacon filtering explicitly if force is true */
913 if (force)
914 return iwl_mvm_disable_beacon_filter(mvm, vif, flags);
915 return 0;
916 }
917
918 return iwl_mvm_enable_beacon_filter(mvm, vif, flags);
a20fd398 919}
This page took 0.139407 seconds and 5 git commands to generate.