iwlwifi: mvm: remove command/return value from RX handlers
[platform/kernel/linux-rpi.git] / 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 void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
513                                               struct iwl_rx_cmd_buffer *rxb)
514 {
515         struct iwl_rx_packet *pkt = rxb_addr(rxb);
516         struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
517         u8 ap_sta_id = le32_to_cpu(notif->sta_id);
518
519         ieee80211_iterate_active_interfaces_atomic(
520                 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
521                 iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
522 }
523
524 struct iwl_power_vifs {
525         struct iwl_mvm *mvm;
526         struct ieee80211_vif *bf_vif;
527         struct ieee80211_vif *bss_vif;
528         struct ieee80211_vif *p2p_vif;
529         struct ieee80211_vif *ap_vif;
530         struct ieee80211_vif *monitor_vif;
531         bool p2p_active;
532         bool bss_active;
533         bool ap_active;
534         bool monitor_active;
535 };
536
537 static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
538                                               struct ieee80211_vif *vif)
539 {
540         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
541
542         mvmvif->pm_enabled = false;
543 }
544
545 static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
546                                                struct ieee80211_vif *vif)
547 {
548         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
549         bool *disable_ps = _data;
550
551         if (mvmvif->phy_ctxt)
552                 if (mvmvif->phy_ctxt->id < MAX_PHYS)
553                         *disable_ps |= mvmvif->ps_disabled;
554 }
555
556 static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
557                                             struct ieee80211_vif *vif)
558 {
559         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
560         struct iwl_power_vifs *power_iterator = _data;
561
562         switch (ieee80211_vif_type_p2p(vif)) {
563         case NL80211_IFTYPE_P2P_DEVICE:
564                 break;
565
566         case NL80211_IFTYPE_P2P_GO:
567         case NL80211_IFTYPE_AP:
568                 /* only a single MAC of the same type */
569                 WARN_ON(power_iterator->ap_vif);
570                 power_iterator->ap_vif = vif;
571                 if (mvmvif->phy_ctxt)
572                         if (mvmvif->phy_ctxt->id < MAX_PHYS)
573                                 power_iterator->ap_active = true;
574                 break;
575
576         case NL80211_IFTYPE_MONITOR:
577                 /* only a single MAC of the same type */
578                 WARN_ON(power_iterator->monitor_vif);
579                 power_iterator->monitor_vif = vif;
580                 if (mvmvif->phy_ctxt)
581                         if (mvmvif->phy_ctxt->id < MAX_PHYS)
582                                 power_iterator->monitor_active = true;
583                 break;
584
585         case NL80211_IFTYPE_P2P_CLIENT:
586                 /* only a single MAC of the same type */
587                 WARN_ON(power_iterator->p2p_vif);
588                 power_iterator->p2p_vif = vif;
589                 if (mvmvif->phy_ctxt)
590                         if (mvmvif->phy_ctxt->id < MAX_PHYS)
591                                 power_iterator->p2p_active = true;
592                 break;
593
594         case NL80211_IFTYPE_STATION:
595                 /* only a single MAC of the same type */
596                 WARN_ON(power_iterator->bss_vif);
597                 power_iterator->bss_vif = vif;
598                 if (mvmvif->phy_ctxt)
599                         if (mvmvif->phy_ctxt->id < MAX_PHYS)
600                                 power_iterator->bss_active = true;
601
602                 if (mvmvif->bf_data.bf_enabled &&
603                     !WARN_ON(power_iterator->bf_vif))
604                         power_iterator->bf_vif = vif;
605
606                 break;
607
608         default:
609                 break;
610         }
611 }
612
613 static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
614                                  struct iwl_power_vifs *vifs)
615 {
616         struct iwl_mvm_vif *bss_mvmvif = NULL;
617         struct iwl_mvm_vif *p2p_mvmvif = NULL;
618         struct iwl_mvm_vif *ap_mvmvif = NULL;
619         bool client_same_channel = false;
620         bool ap_same_channel = false;
621
622         lockdep_assert_held(&mvm->mutex);
623
624         /* set pm_enable to false */
625         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
626                                         IEEE80211_IFACE_ITER_NORMAL,
627                                         iwl_mvm_power_disable_pm_iterator,
628                                         NULL);
629
630         if (vifs->bss_vif)
631                 bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
632
633         if (vifs->p2p_vif)
634                 p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
635
636         if (vifs->ap_vif)
637                 ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
638
639         /* don't allow PM if any TDLS stations exist */
640         if (iwl_mvm_tdls_sta_count(mvm, NULL))
641                 return;
642
643         /* enable PM on bss if bss stand alone */
644         if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
645                 bss_mvmvif->pm_enabled = true;
646                 return;
647         }
648
649         /* enable PM on p2p if p2p stand alone */
650         if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
651                 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
652                         p2p_mvmvif->pm_enabled = true;
653                 return;
654         }
655
656         if (vifs->bss_active && vifs->p2p_active)
657                 client_same_channel = (bss_mvmvif->phy_ctxt->id ==
658                                        p2p_mvmvif->phy_ctxt->id);
659         if (vifs->bss_active && vifs->ap_active)
660                 ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
661                                    ap_mvmvif->phy_ctxt->id);
662
663         /* clients are not stand alone: enable PM if DCM */
664         if (!(client_same_channel || ap_same_channel) &&
665             (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {
666                 if (vifs->bss_active)
667                         bss_mvmvif->pm_enabled = true;
668                 if (vifs->p2p_active &&
669                     (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM))
670                         p2p_mvmvif->pm_enabled = true;
671                 return;
672         }
673
674         /*
675          * There is only one channel in the system and there are only
676          * bss and p2p clients that share it
677          */
678         if (client_same_channel && !vifs->ap_active &&
679             (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM)) {
680                 /* share same channel*/
681                 bss_mvmvif->pm_enabled = true;
682                 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
683                         p2p_mvmvif->pm_enabled = true;
684         }
685 }
686
687 #ifdef CONFIG_IWLWIFI_DEBUGFS
688 int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
689                                  struct ieee80211_vif *vif, char *buf,
690                                  int bufsz)
691 {
692         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
693         struct iwl_mac_power_cmd cmd = {};
694         int pos = 0;
695
696         mutex_lock(&mvm->mutex);
697         memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
698         mutex_unlock(&mvm->mutex);
699
700         pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
701                          iwlmvm_mod_params.power_scheme);
702         pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
703                          le16_to_cpu(cmd.flags));
704         pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
705                          le16_to_cpu(cmd.keep_alive_seconds));
706
707         if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
708                 return pos;
709
710         pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
711                          (cmd.flags &
712                          cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
713         pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
714                          cmd.skip_dtim_periods);
715         if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
716                 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
717                                  le32_to_cpu(cmd.rx_data_timeout));
718                 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
719                                  le32_to_cpu(cmd.tx_data_timeout));
720         }
721         if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
722                 pos += scnprintf(buf+pos, bufsz-pos,
723                                  "lprx_rssi_threshold = %d\n",
724                                  cmd.lprx_rssi_threshold);
725
726         if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
727                 return pos;
728
729         pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
730                          le32_to_cpu(cmd.rx_data_timeout_uapsd));
731         pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
732                          le32_to_cpu(cmd.tx_data_timeout_uapsd));
733         pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
734         pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
735                          cmd.uapsd_ac_flags);
736         pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
737                          cmd.uapsd_max_sp);
738         pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
739                          cmd.heavy_tx_thld_packets);
740         pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
741                          cmd.heavy_rx_thld_packets);
742         pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
743                          cmd.heavy_tx_thld_percentage);
744         pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
745                          cmd.heavy_rx_thld_percentage);
746         pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
747                          (cmd.flags &
748                           cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
749                          1 : 0);
750
751         if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
752                 return pos;
753
754         pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
755                          cmd.snooze_interval);
756         pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
757                          cmd.snooze_window);
758
759         return pos;
760 }
761
762 void
763 iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
764                                          struct iwl_beacon_filter_cmd *cmd)
765 {
766         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
767         struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
768
769         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
770                 cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
771         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
772                 cmd->bf_roaming_energy_delta =
773                                 cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
774         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
775                 cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
776         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
777                 cmd->bf_temp_threshold =
778                                 cpu_to_le32(dbgfs_bf->bf_temp_threshold);
779         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
780                 cmd->bf_temp_fast_filter =
781                                 cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
782         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
783                 cmd->bf_temp_slow_filter =
784                                 cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
785         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
786                 cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
787         if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
788                 cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
789         if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
790                 cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
791         if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
792                 cmd->ba_enable_beacon_abort =
793                                 cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
794 }
795 #endif
796
797 static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
798                                          struct ieee80211_vif *vif,
799                                          struct iwl_beacon_filter_cmd *cmd,
800                                          u32 cmd_flags,
801                                          bool d0i3)
802 {
803         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
804         int ret;
805
806         if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
807             vif->type != NL80211_IFTYPE_STATION || vif->p2p)
808                 return 0;
809
810         iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
811         if (!d0i3)
812                 iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
813         ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
814
815         /* don't change bf_enabled in case of temporary d0i3 configuration */
816         if (!ret && !d0i3)
817                 mvmvif->bf_data.bf_enabled = true;
818
819         return ret;
820 }
821
822 int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
823                                  struct ieee80211_vif *vif,
824                                  u32 flags)
825 {
826         struct iwl_beacon_filter_cmd cmd = {
827                 IWL_BF_CMD_CONFIG_DEFAULTS,
828                 .bf_enable_beacon_filter = cpu_to_le32(1),
829         };
830
831         return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
832 }
833
834 static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
835                                        struct ieee80211_vif *vif,
836                                        bool enable)
837 {
838         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
839         struct iwl_beacon_filter_cmd cmd = {
840                 IWL_BF_CMD_CONFIG_DEFAULTS,
841                 .bf_enable_beacon_filter = cpu_to_le32(1),
842         };
843
844         if (!mvmvif->bf_data.bf_enabled)
845                 return 0;
846
847         if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
848                 cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
849
850         mvmvif->bf_data.ba_enabled = enable;
851         return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);
852 }
853
854 int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
855                                   struct ieee80211_vif *vif,
856                                   u32 flags)
857 {
858         struct iwl_beacon_filter_cmd cmd = {};
859         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
860         int ret;
861
862         if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
863                 return 0;
864
865         ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
866
867         if (!ret)
868                 mvmvif->bf_data.bf_enabled = false;
869
870         return ret;
871 }
872
873 static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
874 {
875         bool disable_ps;
876         int ret;
877
878         /* disable PS if CAM */
879         disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
880         /* ...or if any of the vifs require PS to be off */
881         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
882                                         IEEE80211_IFACE_ITER_NORMAL,
883                                         iwl_mvm_power_ps_disabled_iterator,
884                                         &disable_ps);
885
886         /* update device power state if it has changed */
887         if (mvm->ps_disabled != disable_ps) {
888                 bool old_ps_disabled = mvm->ps_disabled;
889
890                 mvm->ps_disabled = disable_ps;
891                 ret = iwl_mvm_power_update_device(mvm);
892                 if (ret) {
893                         mvm->ps_disabled = old_ps_disabled;
894                         return ret;
895                 }
896         }
897
898         return 0;
899 }
900
901 static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
902                                 struct iwl_power_vifs *vifs)
903 {
904         struct iwl_mvm_vif *mvmvif;
905         bool ba_enable;
906
907         if (!vifs->bf_vif)
908                 return 0;
909
910         mvmvif = iwl_mvm_vif_from_mac80211(vifs->bf_vif);
911
912         ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||
913                       !vifs->bf_vif->bss_conf.ps ||
914                       iwl_mvm_vif_low_latency(mvmvif));
915
916         return iwl_mvm_update_beacon_abort(mvm, vifs->bf_vif, ba_enable);
917 }
918
919 int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
920 {
921         struct iwl_power_vifs vifs = {
922                 .mvm = mvm,
923         };
924         int ret;
925
926         lockdep_assert_held(&mvm->mutex);
927
928         /* get vifs info */
929         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
930                                         IEEE80211_IFACE_ITER_NORMAL,
931                                         iwl_mvm_power_get_vifs_iterator, &vifs);
932
933         ret = iwl_mvm_power_set_ps(mvm);
934         if (ret)
935                 return ret;
936
937         return iwl_mvm_power_set_ba(mvm, &vifs);
938 }
939
940 int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
941 {
942         struct iwl_power_vifs vifs = {
943                 .mvm = mvm,
944         };
945         int ret;
946
947         lockdep_assert_held(&mvm->mutex);
948
949         /* get vifs info */
950         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
951                                         IEEE80211_IFACE_ITER_NORMAL,
952                                         iwl_mvm_power_get_vifs_iterator, &vifs);
953
954         iwl_mvm_power_set_pm(mvm, &vifs);
955
956         ret = iwl_mvm_power_set_ps(mvm);
957         if (ret)
958                 return ret;
959
960         if (vifs.bss_vif) {
961                 ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
962                 if (ret)
963                         return ret;
964         }
965
966         if (vifs.p2p_vif) {
967                 ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
968                 if (ret)
969                         return ret;
970         }
971
972         return iwl_mvm_power_set_ba(mvm, &vifs);
973 }
974
975 int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
976                                    struct ieee80211_vif *vif,
977                                    bool enable, u32 flags)
978 {
979         int ret;
980         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
981         struct iwl_mac_power_cmd cmd = {};
982
983         if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
984                 return 0;
985
986         if (!vif->bss_conf.assoc)
987                 return 0;
988
989         iwl_mvm_power_build_cmd(mvm, vif, &cmd);
990         if (enable) {
991                 /* configure skip over dtim up to 306TU - 314 msec */
992                 int dtimper = vif->bss_conf.dtim_period ?: 1;
993                 int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
994                 bool radar_detect = iwl_mvm_power_is_radar(vif);
995
996                 if (WARN_ON(!dtimper_tu))
997                         return 0;
998
999                 /* Check skip over DTIM conditions */
1000                 /* TODO: check that multicast wake lock is off */
1001                 if (!radar_detect && (dtimper < 10)) {
1002                         cmd.skip_dtim_periods = 306 / dtimper_tu;
1003                         if (cmd.skip_dtim_periods)
1004                                 cmd.flags |= cpu_to_le16(
1005                                         POWER_FLAGS_SKIP_OVER_DTIM_MSK);
1006                 }
1007         }
1008         iwl_mvm_power_log(mvm, &cmd);
1009 #ifdef CONFIG_IWLWIFI_DEBUGFS
1010         memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
1011 #endif
1012         ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
1013                                    sizeof(cmd), &cmd);
1014         if (ret)
1015                 return ret;
1016
1017         /* configure beacon filtering */
1018         if (mvmvif != mvm->bf_allowed_vif)
1019                 return 0;
1020
1021         if (enable) {
1022                 struct iwl_beacon_filter_cmd cmd_bf = {
1023                         IWL_BF_CMD_CONFIG_D0I3,
1024                         .bf_enable_beacon_filter = cpu_to_le32(1),
1025                 };
1026                 ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
1027                                                     flags, true);
1028         } else {
1029                 if (mvmvif->bf_data.bf_enabled)
1030                         ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
1031                 else
1032                         ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
1033         }
1034
1035         return ret;
1036 }