root/drivers/net/wireless/intel/iwlwifi/mvm/power.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iwl_mvm_beacon_filter_send_cmd
  2. iwl_mvm_beacon_filter_set_cqm_params
  3. iwl_mvm_power_log
  4. iwl_mvm_power_configure_uapsd
  5. iwl_mvm_p2p_standalone_iterator
  6. iwl_mvm_power_allow_uapsd
  7. iwl_mvm_power_is_radar
  8. iwl_mvm_power_config_skip_dtim
  9. iwl_mvm_power_build_cmd
  10. iwl_mvm_power_send_cmd
  11. iwl_mvm_power_update_device
  12. iwl_mvm_power_vif_assoc
  13. iwl_mvm_power_uapsd_misbehav_ap_iterator
  14. iwl_mvm_power_uapsd_misbehaving_ap_notif
  15. iwl_mvm_power_disable_pm_iterator
  16. iwl_mvm_power_ps_disabled_iterator
  17. iwl_mvm_power_get_vifs_iterator
  18. iwl_mvm_power_set_pm
  19. iwl_mvm_power_mac_dbgfs_read
  20. iwl_mvm_beacon_filter_debugfs_parameters
  21. _iwl_mvm_enable_beacon_filter
  22. iwl_mvm_enable_beacon_filter
  23. _iwl_mvm_disable_beacon_filter
  24. iwl_mvm_disable_beacon_filter
  25. iwl_mvm_power_set_ps
  26. iwl_mvm_power_set_ba
  27. iwl_mvm_power_update_ps
  28. iwl_mvm_power_update_mac

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

/* [<][>][^][v][top][bottom][index][help] */