Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /*
0003  * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
0004  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
0005  * Copyright (C) 2015-2017 Intel Deutschland GmbH
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/slab.h>
0010 #include <linux/etherdevice.h>
0011 
0012 #include <net/mac80211.h>
0013 
0014 #include "iwl-debug.h"
0015 #include "mvm.h"
0016 #include "iwl-modparams.h"
0017 #include "fw/api/power.h"
0018 
0019 #define POWER_KEEP_ALIVE_PERIOD_SEC    25
0020 
0021 static
0022 int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
0023                    struct iwl_beacon_filter_cmd *cmd,
0024                    u32 flags)
0025 {
0026     u16 len;
0027 
0028     IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
0029             le32_to_cpu(cmd->ba_enable_beacon_abort));
0030     IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
0031             le32_to_cpu(cmd->ba_escape_timer));
0032     IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
0033             le32_to_cpu(cmd->bf_debug_flag));
0034     IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
0035             le32_to_cpu(cmd->bf_enable_beacon_filter));
0036     IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
0037             le32_to_cpu(cmd->bf_energy_delta));
0038     IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
0039             le32_to_cpu(cmd->bf_escape_timer));
0040     IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
0041             le32_to_cpu(cmd->bf_roaming_energy_delta));
0042     IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
0043             le32_to_cpu(cmd->bf_roaming_state));
0044     IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
0045             le32_to_cpu(cmd->bf_temp_threshold));
0046     IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
0047             le32_to_cpu(cmd->bf_temp_fast_filter));
0048     IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
0049             le32_to_cpu(cmd->bf_temp_slow_filter));
0050     IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n",
0051             le32_to_cpu(cmd->bf_threshold_absolute_low[0]),
0052             le32_to_cpu(cmd->bf_threshold_absolute_low[1]));
0053 
0054     IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n",
0055             le32_to_cpu(cmd->bf_threshold_absolute_high[0]),
0056             le32_to_cpu(cmd->bf_threshold_absolute_high[1]));
0057 
0058     if (fw_has_api(&mvm->fw->ucode_capa,
0059                IWL_UCODE_TLV_API_BEACON_FILTER_V4))
0060         len = sizeof(struct iwl_beacon_filter_cmd);
0061     else
0062         len = offsetof(struct iwl_beacon_filter_cmd,
0063                    bf_threshold_absolute_low);
0064 
0065     return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
0066                     len, cmd);
0067 }
0068 
0069 static
0070 void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
0071                       struct ieee80211_vif *vif,
0072                       struct iwl_beacon_filter_cmd *cmd)
0073 {
0074     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0075 
0076     if (vif->bss_conf.cqm_rssi_thold) {
0077         cmd->bf_energy_delta =
0078             cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
0079         /* fw uses an absolute value for this */
0080         cmd->bf_roaming_state =
0081             cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
0082     }
0083     cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
0084 }
0085 
0086 static void iwl_mvm_power_log(struct iwl_mvm *mvm,
0087                   struct iwl_mac_power_cmd *cmd)
0088 {
0089     IWL_DEBUG_POWER(mvm,
0090             "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
0091             cmd->id_and_color, iwlmvm_mod_params.power_scheme,
0092             le16_to_cpu(cmd->flags));
0093     IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
0094             le16_to_cpu(cmd->keep_alive_seconds));
0095 
0096     if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
0097         IWL_DEBUG_POWER(mvm, "Disable power management\n");
0098         return;
0099     }
0100 
0101     IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
0102             le32_to_cpu(cmd->rx_data_timeout));
0103     IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
0104             le32_to_cpu(cmd->tx_data_timeout));
0105     if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
0106         IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
0107                 cmd->skip_dtim_periods);
0108     if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
0109         IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
0110                 cmd->lprx_rssi_threshold);
0111     if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
0112         IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
0113         IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
0114                 le32_to_cpu(cmd->rx_data_timeout_uapsd));
0115         IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
0116                 le32_to_cpu(cmd->tx_data_timeout_uapsd));
0117         IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
0118         IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
0119         IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
0120     }
0121 }
0122 
0123 static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
0124                       struct ieee80211_vif *vif,
0125                       struct iwl_mac_power_cmd *cmd)
0126 {
0127     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0128     enum ieee80211_ac_numbers ac;
0129     bool tid_found = false;
0130 
0131     if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ||
0132         cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
0133         cmd->rx_data_timeout_uapsd =
0134             cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
0135         cmd->tx_data_timeout_uapsd =
0136             cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
0137     } else {
0138         cmd->rx_data_timeout_uapsd =
0139             cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
0140         cmd->tx_data_timeout_uapsd =
0141             cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
0142     }
0143 
0144 #ifdef CONFIG_IWLWIFI_DEBUGFS
0145     /* set advanced pm flag with no uapsd ACs to enable ps-poll */
0146     if (mvmvif->dbgfs_pm.use_ps_poll) {
0147         cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
0148         return;
0149     }
0150 #endif
0151 
0152     for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
0153         if (!mvmvif->queue_params[ac].uapsd)
0154             continue;
0155 
0156         if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
0157             cmd->flags |=
0158                 cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
0159 
0160         cmd->uapsd_ac_flags |= BIT(ac);
0161 
0162         /* QNDP TID - the highest TID with no admission control */
0163         if (!tid_found && !mvmvif->queue_params[ac].acm) {
0164             tid_found = true;
0165             switch (ac) {
0166             case IEEE80211_AC_VO:
0167                 cmd->qndp_tid = 6;
0168                 break;
0169             case IEEE80211_AC_VI:
0170                 cmd->qndp_tid = 5;
0171                 break;
0172             case IEEE80211_AC_BE:
0173                 cmd->qndp_tid = 0;
0174                 break;
0175             case IEEE80211_AC_BK:
0176                 cmd->qndp_tid = 1;
0177                 break;
0178             }
0179         }
0180     }
0181 
0182     cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
0183 
0184     if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
0185                     BIT(IEEE80211_AC_VI) |
0186                     BIT(IEEE80211_AC_BE) |
0187                     BIT(IEEE80211_AC_BK))) {
0188         cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
0189         cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
0190         cmd->snooze_window =
0191             test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
0192                 cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
0193                 cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
0194     }
0195 
0196     cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
0197 
0198     if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
0199         cmd->heavy_tx_thld_packets =
0200             IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
0201         cmd->heavy_rx_thld_packets =
0202             IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
0203     } else {
0204         cmd->heavy_tx_thld_packets =
0205             IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
0206         cmd->heavy_rx_thld_packets =
0207             IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
0208     }
0209     cmd->heavy_tx_thld_percentage =
0210         IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
0211     cmd->heavy_rx_thld_percentage =
0212         IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
0213 }
0214 
0215 static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac,
0216                         struct ieee80211_vif *vif)
0217 {
0218     bool *is_p2p_standalone = _data;
0219 
0220     switch (ieee80211_vif_type_p2p(vif)) {
0221     case NL80211_IFTYPE_P2P_GO:
0222     case NL80211_IFTYPE_AP:
0223         *is_p2p_standalone = false;
0224         break;
0225     case NL80211_IFTYPE_STATION:
0226         if (vif->cfg.assoc)
0227             *is_p2p_standalone = false;
0228         break;
0229 
0230     default:
0231         break;
0232     }
0233 }
0234 
0235 static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
0236                        struct ieee80211_vif *vif)
0237 {
0238     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0239 
0240     if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
0241             ETH_ALEN))
0242         return false;
0243 
0244     /*
0245      * Avoid using uAPSD if P2P client is associated to GO that uses
0246      * opportunistic power save. This is due to current FW limitation.
0247      */
0248     if (vif->p2p &&
0249         (vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
0250         IEEE80211_P2P_OPPPS_ENABLE_BIT))
0251         return false;
0252 
0253     /*
0254      * Avoid using uAPSD if client is in DCM -
0255      * low latency issue in Miracast
0256      */
0257     if (iwl_mvm_phy_ctx_count(mvm) >= 2)
0258         return false;
0259 
0260     if (vif->p2p) {
0261         /* Allow U-APSD only if p2p is stand alone */
0262         bool is_p2p_standalone = true;
0263 
0264         if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
0265             return false;
0266 
0267         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
0268                     IEEE80211_IFACE_ITER_NORMAL,
0269                     iwl_mvm_p2p_standalone_iterator,
0270                     &is_p2p_standalone);
0271 
0272         if (!is_p2p_standalone)
0273             return false;
0274     }
0275 
0276     return true;
0277 }
0278 
0279 static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
0280 {
0281     struct ieee80211_chanctx_conf *chanctx_conf;
0282     struct ieee80211_channel *chan;
0283     bool radar_detect = false;
0284 
0285     rcu_read_lock();
0286     chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
0287     WARN_ON(!chanctx_conf);
0288     if (chanctx_conf) {
0289         chan = chanctx_conf->def.chan;
0290         radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
0291     }
0292     rcu_read_unlock();
0293 
0294     return radar_detect;
0295 }
0296 
0297 static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
0298                        struct ieee80211_vif *vif,
0299                        struct iwl_mac_power_cmd *cmd)
0300 {
0301     int dtimper = vif->bss_conf.dtim_period ?: 1;
0302     int skip;
0303 
0304     /* disable, in case we're supposed to override */
0305     cmd->skip_dtim_periods = 0;
0306     cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
0307 
0308     if (iwl_mvm_power_is_radar(vif))
0309         return;
0310 
0311     if (dtimper >= 10)
0312         return;
0313 
0314     if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
0315         if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
0316             return;
0317         skip = 2;
0318     } else {
0319         int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
0320 
0321         if (WARN_ON(!dtimper_tu))
0322             return;
0323         /* configure skip over dtim up to 306TU - 314 msec */
0324         skip = max_t(u8, 1, 306 / dtimper_tu);
0325     }
0326 
0327     /* the firmware really expects "look at every X DTIMs", so add 1 */
0328     cmd->skip_dtim_periods = 1 + skip;
0329     cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
0330 }
0331 
0332 static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
0333                     struct ieee80211_vif *vif,
0334                     struct iwl_mac_power_cmd *cmd)
0335 {
0336     int dtimper, bi;
0337     int keep_alive;
0338     struct iwl_mvm_vif *mvmvif __maybe_unused =
0339         iwl_mvm_vif_from_mac80211(vif);
0340 
0341     cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
0342                                 mvmvif->color));
0343     dtimper = vif->bss_conf.dtim_period;
0344     bi = vif->bss_conf.beacon_int;
0345 
0346     /*
0347      * Regardless of power management state the driver must set
0348      * keep alive period. FW will use it for sending keep alive NDPs
0349      * immediately after association. Check that keep alive period
0350      * is at least 3 * DTIM
0351      */
0352     keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
0353                   USEC_PER_SEC);
0354     keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
0355     cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
0356 
0357     if (mvm->ps_disabled)
0358         return;
0359 
0360     cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
0361 
0362     if (!vif->cfg.ps || !mvmvif->pm_enabled)
0363         return;
0364 
0365     if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
0366         (!fw_has_capa(&mvm->fw->ucode_capa,
0367              IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
0368          !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
0369         return;
0370 
0371     cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
0372 
0373     if (vif->bss_conf.beacon_rate &&
0374         (vif->bss_conf.beacon_rate->bitrate == 10 ||
0375          vif->bss_conf.beacon_rate->bitrate == 60)) {
0376         cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
0377         cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
0378     }
0379 
0380     iwl_mvm_power_config_skip_dtim(mvm, vif, cmd);
0381 
0382     if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
0383         cmd->rx_data_timeout =
0384             cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
0385         cmd->tx_data_timeout =
0386             cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
0387     } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
0388            fw_has_capa(&mvm->fw->ucode_capa,
0389                    IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
0390         cmd->tx_data_timeout =
0391             cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
0392         cmd->rx_data_timeout =
0393             cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
0394     } else {
0395         cmd->rx_data_timeout =
0396             cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
0397         cmd->tx_data_timeout =
0398             cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
0399     }
0400 
0401     if (iwl_mvm_power_allow_uapsd(mvm, vif))
0402         iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
0403 
0404 #ifdef CONFIG_IWLWIFI_DEBUGFS
0405     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
0406         cmd->keep_alive_seconds =
0407             cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
0408     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
0409         if (mvmvif->dbgfs_pm.skip_over_dtim)
0410             cmd->flags |=
0411                 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
0412         else
0413             cmd->flags &=
0414                 cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
0415     }
0416     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
0417         cmd->rx_data_timeout =
0418             cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
0419     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
0420         cmd->tx_data_timeout =
0421             cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
0422     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
0423         cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
0424     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
0425         if (mvmvif->dbgfs_pm.lprx_ena)
0426             cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
0427         else
0428             cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
0429     }
0430     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
0431         cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
0432     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
0433         if (mvmvif->dbgfs_pm.snooze_ena)
0434             cmd->flags |=
0435                 cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
0436         else
0437             cmd->flags &=
0438                 cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
0439     }
0440     if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
0441         u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
0442         if (mvmvif->dbgfs_pm.uapsd_misbehaving)
0443             cmd->flags |= cpu_to_le16(flag);
0444         else
0445             cmd->flags &= cpu_to_le16(flag);
0446     }
0447 #endif /* CONFIG_IWLWIFI_DEBUGFS */
0448 }
0449 
0450 static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
0451                      struct ieee80211_vif *vif)
0452 {
0453     struct iwl_mac_power_cmd cmd = {};
0454 
0455     iwl_mvm_power_build_cmd(mvm, vif, &cmd);
0456     iwl_mvm_power_log(mvm, &cmd);
0457 #ifdef CONFIG_IWLWIFI_DEBUGFS
0458     memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
0459 #endif
0460 
0461     return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
0462                     sizeof(cmd), &cmd);
0463 }
0464 
0465 int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
0466 {
0467     struct iwl_device_power_cmd cmd = {
0468         .flags = 0,
0469     };
0470 
0471     if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
0472         mvm->ps_disabled = true;
0473 
0474     if (!mvm->ps_disabled)
0475         cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
0476 
0477 #ifdef CONFIG_IWLWIFI_DEBUGFS
0478     if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
0479             mvm->disable_power_off_d3 : mvm->disable_power_off)
0480         cmd.flags &=
0481             cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
0482 #endif
0483     if (mvm->ext_clock_valid)
0484         cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
0485 
0486     IWL_DEBUG_POWER(mvm,
0487             "Sending device power command with flags = 0x%X\n",
0488             cmd.flags);
0489 
0490     return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
0491                     &cmd);
0492 }
0493 
0494 void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
0495 {
0496     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0497 
0498     if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
0499            ETH_ALEN))
0500         eth_zero_addr(mvmvif->uapsd_misbehaving_bssid);
0501 }
0502 
0503 static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
0504                              struct ieee80211_vif *vif)
0505 {
0506     u8 *ap_sta_id = _data;
0507     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0508 
0509     /* The ap_sta_id is not expected to change during current association
0510      * so no explicit protection is needed
0511      */
0512     if (mvmvif->ap_sta_id == *ap_sta_id)
0513         memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
0514                ETH_ALEN);
0515 }
0516 
0517 void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
0518                           struct iwl_rx_cmd_buffer *rxb)
0519 {
0520     struct iwl_rx_packet *pkt = rxb_addr(rxb);
0521     struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
0522     u8 ap_sta_id = le32_to_cpu(notif->sta_id);
0523 
0524     ieee80211_iterate_active_interfaces_atomic(
0525         mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
0526         iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
0527 }
0528 
0529 struct iwl_power_vifs {
0530     struct iwl_mvm *mvm;
0531     struct ieee80211_vif *bss_vif;
0532     struct ieee80211_vif *p2p_vif;
0533     struct ieee80211_vif *ap_vif;
0534     struct ieee80211_vif *monitor_vif;
0535     bool p2p_active;
0536     bool bss_active;
0537     bool ap_active;
0538     bool monitor_active;
0539 };
0540 
0541 static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
0542                           struct ieee80211_vif *vif)
0543 {
0544     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0545 
0546     mvmvif->pm_enabled = false;
0547 }
0548 
0549 static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
0550                            struct ieee80211_vif *vif)
0551 {
0552     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0553     bool *disable_ps = _data;
0554 
0555     if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX)
0556         *disable_ps |= mvmvif->ps_disabled;
0557 }
0558 
0559 static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
0560                         struct ieee80211_vif *vif)
0561 {
0562     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0563     struct iwl_power_vifs *power_iterator = _data;
0564     bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
0565 
0566     if (!mvmvif->uploaded)
0567         return;
0568 
0569     switch (ieee80211_vif_type_p2p(vif)) {
0570     case NL80211_IFTYPE_P2P_DEVICE:
0571         break;
0572 
0573     case NL80211_IFTYPE_P2P_GO:
0574     case NL80211_IFTYPE_AP:
0575         /* only a single MAC of the same type */
0576         WARN_ON(power_iterator->ap_vif);
0577         power_iterator->ap_vif = vif;
0578         if (active)
0579             power_iterator->ap_active = true;
0580         break;
0581 
0582     case NL80211_IFTYPE_MONITOR:
0583         /* only a single MAC of the same type */
0584         WARN_ON(power_iterator->monitor_vif);
0585         power_iterator->monitor_vif = vif;
0586         if (active)
0587             power_iterator->monitor_active = true;
0588         break;
0589 
0590     case NL80211_IFTYPE_P2P_CLIENT:
0591         /* only a single MAC of the same type */
0592         WARN_ON(power_iterator->p2p_vif);
0593         power_iterator->p2p_vif = vif;
0594         if (active)
0595             power_iterator->p2p_active = true;
0596         break;
0597 
0598     case NL80211_IFTYPE_STATION:
0599         power_iterator->bss_vif = vif;
0600         if (active)
0601             power_iterator->bss_active = true;
0602         break;
0603 
0604     default:
0605         break;
0606     }
0607 }
0608 
0609 static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
0610                  struct iwl_power_vifs *vifs)
0611 {
0612     struct iwl_mvm_vif *bss_mvmvif = NULL;
0613     struct iwl_mvm_vif *p2p_mvmvif = NULL;
0614     struct iwl_mvm_vif *ap_mvmvif = NULL;
0615     bool client_same_channel = false;
0616     bool ap_same_channel = false;
0617 
0618     lockdep_assert_held(&mvm->mutex);
0619 
0620     /* set pm_enable to false */
0621     ieee80211_iterate_active_interfaces_atomic(mvm->hw,
0622                     IEEE80211_IFACE_ITER_NORMAL,
0623                     iwl_mvm_power_disable_pm_iterator,
0624                     NULL);
0625 
0626     if (vifs->bss_vif)
0627         bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
0628 
0629     if (vifs->p2p_vif)
0630         p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
0631 
0632     if (vifs->ap_vif)
0633         ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
0634 
0635     /* don't allow PM if any TDLS stations exist */
0636     if (iwl_mvm_tdls_sta_count(mvm, NULL))
0637         return;
0638 
0639     /* enable PM on bss if bss stand alone */
0640     if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
0641         bss_mvmvif->pm_enabled = true;
0642         return;
0643     }
0644 
0645     /* enable PM on p2p if p2p stand alone */
0646     if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
0647         p2p_mvmvif->pm_enabled = true;
0648         return;
0649     }
0650 
0651     if (vifs->bss_active && vifs->p2p_active)
0652         client_same_channel = (bss_mvmvif->phy_ctxt->id ==
0653                        p2p_mvmvif->phy_ctxt->id);
0654     if (vifs->bss_active && vifs->ap_active)
0655         ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
0656                    ap_mvmvif->phy_ctxt->id);
0657 
0658     /* clients are not stand alone: enable PM if DCM */
0659     if (!(client_same_channel || ap_same_channel)) {
0660         if (vifs->bss_active)
0661             bss_mvmvif->pm_enabled = true;
0662         if (vifs->p2p_active)
0663             p2p_mvmvif->pm_enabled = true;
0664         return;
0665     }
0666 
0667     /*
0668      * There is only one channel in the system and there are only
0669      * bss and p2p clients that share it
0670      */
0671     if (client_same_channel && !vifs->ap_active) {
0672         /* share same channel*/
0673         bss_mvmvif->pm_enabled = true;
0674         p2p_mvmvif->pm_enabled = true;
0675     }
0676 }
0677 
0678 #ifdef CONFIG_IWLWIFI_DEBUGFS
0679 int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
0680                  struct ieee80211_vif *vif, char *buf,
0681                  int bufsz)
0682 {
0683     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0684     struct iwl_mac_power_cmd cmd = {};
0685     int pos = 0;
0686 
0687     mutex_lock(&mvm->mutex);
0688     memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
0689     mutex_unlock(&mvm->mutex);
0690 
0691     pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
0692              iwlmvm_mod_params.power_scheme);
0693     pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
0694              le16_to_cpu(cmd.flags));
0695     pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
0696              le16_to_cpu(cmd.keep_alive_seconds));
0697 
0698     if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
0699         return pos;
0700 
0701     pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
0702              (cmd.flags &
0703              cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
0704     pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
0705              cmd.skip_dtim_periods);
0706     if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
0707         pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
0708                  le32_to_cpu(cmd.rx_data_timeout));
0709         pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
0710                  le32_to_cpu(cmd.tx_data_timeout));
0711     }
0712     if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
0713         pos += scnprintf(buf+pos, bufsz-pos,
0714                  "lprx_rssi_threshold = %d\n",
0715                  cmd.lprx_rssi_threshold);
0716 
0717     if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
0718         return pos;
0719 
0720     pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
0721              le32_to_cpu(cmd.rx_data_timeout_uapsd));
0722     pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
0723              le32_to_cpu(cmd.tx_data_timeout_uapsd));
0724     pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
0725     pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
0726              cmd.uapsd_ac_flags);
0727     pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
0728              cmd.uapsd_max_sp);
0729     pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
0730              cmd.heavy_tx_thld_packets);
0731     pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
0732              cmd.heavy_rx_thld_packets);
0733     pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
0734              cmd.heavy_tx_thld_percentage);
0735     pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
0736              cmd.heavy_rx_thld_percentage);
0737     pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
0738              (cmd.flags &
0739               cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
0740              1 : 0);
0741 
0742     if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
0743         return pos;
0744 
0745     pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
0746              cmd.snooze_interval);
0747     pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
0748              cmd.snooze_window);
0749 
0750     return pos;
0751 }
0752 
0753 void
0754 iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
0755                      struct iwl_beacon_filter_cmd *cmd)
0756 {
0757     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0758     struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
0759 
0760     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
0761         cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
0762     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
0763         cmd->bf_roaming_energy_delta =
0764                 cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
0765     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
0766         cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
0767     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
0768         cmd->bf_temp_threshold =
0769                 cpu_to_le32(dbgfs_bf->bf_temp_threshold);
0770     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
0771         cmd->bf_temp_fast_filter =
0772                 cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
0773     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
0774         cmd->bf_temp_slow_filter =
0775                 cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
0776     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
0777         cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
0778     if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
0779         cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
0780     if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
0781         cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
0782     if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
0783         cmd->ba_enable_beacon_abort =
0784                 cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
0785 }
0786 #endif
0787 
0788 static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
0789                      struct ieee80211_vif *vif,
0790                      struct iwl_beacon_filter_cmd *cmd,
0791                      u32 cmd_flags)
0792 {
0793     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0794     int ret;
0795 
0796     if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
0797         vif->type != NL80211_IFTYPE_STATION || vif->p2p)
0798         return 0;
0799 
0800     iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
0801     iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
0802     ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
0803 
0804     if (!ret)
0805         mvmvif->bf_data.bf_enabled = true;
0806 
0807     return ret;
0808 }
0809 
0810 int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
0811                  struct ieee80211_vif *vif,
0812                  u32 flags)
0813 {
0814     struct iwl_beacon_filter_cmd cmd = {
0815         IWL_BF_CMD_CONFIG_DEFAULTS,
0816         .bf_enable_beacon_filter = cpu_to_le32(1),
0817     };
0818 
0819     return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags);
0820 }
0821 
0822 static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
0823                       struct ieee80211_vif *vif,
0824                       u32 flags)
0825 {
0826     struct iwl_beacon_filter_cmd cmd = {};
0827     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0828     int ret;
0829 
0830     if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
0831         return 0;
0832 
0833     ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
0834 
0835     if (!ret)
0836         mvmvif->bf_data.bf_enabled = false;
0837 
0838     return ret;
0839 }
0840 
0841 int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
0842                   struct ieee80211_vif *vif,
0843                   u32 flags)
0844 {
0845     return _iwl_mvm_disable_beacon_filter(mvm, vif, flags);
0846 }
0847 
0848 static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
0849 {
0850     bool disable_ps;
0851     int ret;
0852 
0853     /* disable PS if CAM */
0854     disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
0855     /* ...or if any of the vifs require PS to be off */
0856     ieee80211_iterate_active_interfaces_atomic(mvm->hw,
0857                     IEEE80211_IFACE_ITER_NORMAL,
0858                     iwl_mvm_power_ps_disabled_iterator,
0859                     &disable_ps);
0860 
0861     /* update device power state if it has changed */
0862     if (mvm->ps_disabled != disable_ps) {
0863         bool old_ps_disabled = mvm->ps_disabled;
0864 
0865         mvm->ps_disabled = disable_ps;
0866         ret = iwl_mvm_power_update_device(mvm);
0867         if (ret) {
0868             mvm->ps_disabled = old_ps_disabled;
0869             return ret;
0870         }
0871     }
0872 
0873     return 0;
0874 }
0875 
0876 static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
0877                 struct ieee80211_vif *vif)
0878 {
0879     struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
0880     struct iwl_beacon_filter_cmd cmd = {
0881         IWL_BF_CMD_CONFIG_DEFAULTS,
0882         .bf_enable_beacon_filter = cpu_to_le32(1),
0883     };
0884 
0885     if (!mvmvif->bf_data.bf_enabled)
0886         return 0;
0887 
0888     if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
0889         cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
0890 
0891     mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
0892                        mvm->ps_disabled ||
0893                        !vif->cfg.ps ||
0894                        iwl_mvm_vif_low_latency(mvmvif));
0895 
0896     return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0);
0897 }
0898 
0899 int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
0900 {
0901     struct iwl_power_vifs vifs = {
0902         .mvm = mvm,
0903     };
0904     int ret;
0905 
0906     lockdep_assert_held(&mvm->mutex);
0907 
0908     /* get vifs info */
0909     ieee80211_iterate_active_interfaces_atomic(mvm->hw,
0910                     IEEE80211_IFACE_ITER_NORMAL,
0911                     iwl_mvm_power_get_vifs_iterator, &vifs);
0912 
0913     ret = iwl_mvm_power_set_ps(mvm);
0914     if (ret)
0915         return ret;
0916 
0917     if (vifs.bss_vif)
0918         return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
0919 
0920     return 0;
0921 }
0922 
0923 int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
0924 {
0925     struct iwl_power_vifs vifs = {
0926         .mvm = mvm,
0927     };
0928     int ret;
0929 
0930     lockdep_assert_held(&mvm->mutex);
0931 
0932     /* get vifs info */
0933     ieee80211_iterate_active_interfaces_atomic(mvm->hw,
0934                     IEEE80211_IFACE_ITER_NORMAL,
0935                     iwl_mvm_power_get_vifs_iterator, &vifs);
0936 
0937     iwl_mvm_power_set_pm(mvm, &vifs);
0938 
0939     ret = iwl_mvm_power_set_ps(mvm);
0940     if (ret)
0941         return ret;
0942 
0943     if (vifs.bss_vif) {
0944         ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
0945         if (ret)
0946             return ret;
0947     }
0948 
0949     if (vifs.p2p_vif) {
0950         ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
0951         if (ret)
0952             return ret;
0953     }
0954 
0955     if (vifs.bss_vif)
0956         return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
0957 
0958     return 0;
0959 }