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