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