| .. | .. |
|---|
| 8 | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
|---|
| 9 | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
|---|
| 10 | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
|---|
| 11 | + * Copyright (C) 2018 - 2019 Intel Corporation |
|---|
| 11 | 12 | * |
|---|
| 12 | 13 | * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | 14 | * it under the terms of version 2 of the GNU General Public License as |
|---|
| .. | .. |
|---|
| 17 | 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 19 | 20 | * General Public License for more details. |
|---|
| 20 | | - * |
|---|
| 21 | | - * You should have received a copy of the GNU General Public License |
|---|
| 22 | | - * along with this program; if not, write to the Free Software |
|---|
| 23 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, |
|---|
| 24 | | - * USA |
|---|
| 25 | 21 | * |
|---|
| 26 | 22 | * The full GNU General Public License is included in this distribution |
|---|
| 27 | 23 | * in the file called COPYING. |
|---|
| .. | .. |
|---|
| 35 | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
|---|
| 36 | 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
|---|
| 37 | 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
|---|
| 34 | + * Copyright (C) 2018 - 2019 Intel Corporation |
|---|
| 38 | 35 | * All rights reserved. |
|---|
| 39 | 36 | * |
|---|
| 40 | 37 | * Redistribution and use in source and binary forms, with or without |
|---|
| .. | .. |
|---|
| 84 | 81 | struct iwl_beacon_filter_cmd *cmd, |
|---|
| 85 | 82 | u32 flags) |
|---|
| 86 | 83 | { |
|---|
| 84 | + u16 len; |
|---|
| 85 | + |
|---|
| 87 | 86 | IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", |
|---|
| 88 | 87 | le32_to_cpu(cmd->ba_enable_beacon_abort)); |
|---|
| 89 | 88 | IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", |
|---|
| .. | .. |
|---|
| 106 | 105 | le32_to_cpu(cmd->bf_temp_fast_filter)); |
|---|
| 107 | 106 | IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n", |
|---|
| 108 | 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); |
|---|
| 109 | 122 | |
|---|
| 110 | 123 | return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags, |
|---|
| 111 | | - sizeof(struct iwl_beacon_filter_cmd), cmd); |
|---|
| 124 | + len, cmd); |
|---|
| 112 | 125 | } |
|---|
| 113 | 126 | |
|---|
| 114 | 127 | static |
|---|
| 115 | 128 | void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm, |
|---|
| 116 | 129 | struct ieee80211_vif *vif, |
|---|
| 117 | | - struct iwl_beacon_filter_cmd *cmd, |
|---|
| 118 | | - bool d0i3) |
|---|
| 130 | + struct iwl_beacon_filter_cmd *cmd) |
|---|
| 119 | 131 | { |
|---|
| 120 | 132 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
|---|
| 121 | 133 | |
|---|
| 122 | | - if (vif->bss_conf.cqm_rssi_thold && !d0i3) { |
|---|
| 134 | + if (vif->bss_conf.cqm_rssi_thold) { |
|---|
| 123 | 135 | cmd->bf_energy_delta = |
|---|
| 124 | 136 | cpu_to_le32(vif->bss_conf.cqm_rssi_hyst); |
|---|
| 125 | 137 | /* fw uses an absolute value for this */ |
|---|
| .. | .. |
|---|
| 186 | 198 | if (!mvmvif->queue_params[ac].uapsd) |
|---|
| 187 | 199 | continue; |
|---|
| 188 | 200 | |
|---|
| 189 | | - if (mvm->fwrt.cur_fw_img != IWL_UCODE_WOWLAN) |
|---|
| 201 | + if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) |
|---|
| 190 | 202 | cmd->flags |= |
|---|
| 191 | 203 | cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK); |
|---|
| 192 | 204 | |
|---|
| .. | .. |
|---|
| 221 | 233 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK); |
|---|
| 222 | 234 | cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL); |
|---|
| 223 | 235 | cmd->snooze_window = |
|---|
| 224 | | - (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) ? |
|---|
| 236 | + test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ? |
|---|
| 225 | 237 | cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) : |
|---|
| 226 | 238 | cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW); |
|---|
| 227 | 239 | } |
|---|
| 228 | 240 | |
|---|
| 229 | 241 | cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len; |
|---|
| 230 | 242 | |
|---|
| 231 | | - if (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN || cmd->flags & |
|---|
| 232 | | - cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { |
|---|
| 243 | + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) || |
|---|
| 244 | + cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { |
|---|
| 233 | 245 | cmd->rx_data_timeout_uapsd = |
|---|
| 234 | 246 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); |
|---|
| 235 | 247 | cmd->tx_data_timeout_uapsd = |
|---|
| .. | .. |
|---|
| 342 | 354 | |
|---|
| 343 | 355 | static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, |
|---|
| 344 | 356 | struct ieee80211_vif *vif, |
|---|
| 345 | | - struct iwl_mac_power_cmd *cmd, |
|---|
| 346 | | - bool host_awake) |
|---|
| 357 | + struct iwl_mac_power_cmd *cmd) |
|---|
| 347 | 358 | { |
|---|
| 348 | 359 | int dtimper = vif->bss_conf.dtim_period ?: 1; |
|---|
| 349 | 360 | int skip; |
|---|
| .. | .. |
|---|
| 358 | 369 | if (dtimper >= 10) |
|---|
| 359 | 370 | return; |
|---|
| 360 | 371 | |
|---|
| 361 | | - /* TODO: check that multicast wake lock is off */ |
|---|
| 362 | | - |
|---|
| 363 | | - if (host_awake) { |
|---|
| 372 | + if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) { |
|---|
| 364 | 373 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP) |
|---|
| 365 | 374 | return; |
|---|
| 366 | 375 | skip = 2; |
|---|
| .. | .. |
|---|
| 380 | 389 | |
|---|
| 381 | 390 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, |
|---|
| 382 | 391 | struct ieee80211_vif *vif, |
|---|
| 383 | | - struct iwl_mac_power_cmd *cmd, |
|---|
| 384 | | - bool host_awake) |
|---|
| 392 | + struct iwl_mac_power_cmd *cmd) |
|---|
| 385 | 393 | { |
|---|
| 386 | 394 | int dtimper, bi; |
|---|
| 387 | 395 | int keep_alive; |
|---|
| .. | .. |
|---|
| 427 | 435 | cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; |
|---|
| 428 | 436 | } |
|---|
| 429 | 437 | |
|---|
| 430 | | - iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); |
|---|
| 438 | + iwl_mvm_power_config_skip_dtim(mvm, vif, cmd); |
|---|
| 431 | 439 | |
|---|
| 432 | | - if (!host_awake) { |
|---|
| 440 | + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) { |
|---|
| 433 | 441 | cmd->rx_data_timeout = |
|---|
| 434 | 442 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); |
|---|
| 435 | 443 | cmd->tx_data_timeout = |
|---|
| .. | .. |
|---|
| 502 | 510 | { |
|---|
| 503 | 511 | struct iwl_mac_power_cmd cmd = {}; |
|---|
| 504 | 512 | |
|---|
| 505 | | - iwl_mvm_power_build_cmd(mvm, vif, &cmd, |
|---|
| 506 | | - mvm->fwrt.cur_fw_img != IWL_UCODE_WOWLAN); |
|---|
| 513 | + iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
|---|
| 507 | 514 | iwl_mvm_power_log(mvm, &cmd); |
|---|
| 508 | 515 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
|---|
| 509 | 516 | memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); |
|---|
| .. | .. |
|---|
| 526 | 533 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); |
|---|
| 527 | 534 | |
|---|
| 528 | 535 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
|---|
| 529 | | - if ((mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) ? |
|---|
| 536 | + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ? |
|---|
| 530 | 537 | mvm->disable_power_off_d3 : mvm->disable_power_off) |
|---|
| 531 | 538 | cmd.flags &= |
|---|
| 532 | 539 | cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); |
|---|
| 533 | 540 | #endif |
|---|
| 541 | + if (mvm->ext_clock_valid) |
|---|
| 542 | + cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK); |
|---|
| 543 | + |
|---|
| 534 | 544 | IWL_DEBUG_POWER(mvm, |
|---|
| 535 | 545 | "Sending device power command with flags = 0x%X\n", |
|---|
| 536 | 546 | cmd.flags); |
|---|
| .. | .. |
|---|
| 610 | 620 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
|---|
| 611 | 621 | struct iwl_power_vifs *power_iterator = _data; |
|---|
| 612 | 622 | bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX; |
|---|
| 623 | + |
|---|
| 624 | + if (!mvmvif->uploaded) |
|---|
| 625 | + return; |
|---|
| 613 | 626 | |
|---|
| 614 | 627 | switch (ieee80211_vif_type_p2p(vif)) { |
|---|
| 615 | 628 | case NL80211_IFTYPE_P2P_DEVICE: |
|---|
| .. | .. |
|---|
| 833 | 846 | static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, |
|---|
| 834 | 847 | struct ieee80211_vif *vif, |
|---|
| 835 | 848 | struct iwl_beacon_filter_cmd *cmd, |
|---|
| 836 | | - u32 cmd_flags, |
|---|
| 837 | | - bool d0i3) |
|---|
| 849 | + u32 cmd_flags) |
|---|
| 838 | 850 | { |
|---|
| 839 | 851 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
|---|
| 840 | 852 | int ret; |
|---|
| .. | .. |
|---|
| 843 | 855 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
|---|
| 844 | 856 | return 0; |
|---|
| 845 | 857 | |
|---|
| 846 | | - iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd, d0i3); |
|---|
| 847 | | - if (!d0i3) |
|---|
| 848 | | - iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd); |
|---|
| 858 | + iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd); |
|---|
| 859 | + iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd); |
|---|
| 849 | 860 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags); |
|---|
| 850 | 861 | |
|---|
| 851 | | - /* don't change bf_enabled in case of temporary d0i3 configuration */ |
|---|
| 852 | | - if (!ret && !d0i3) |
|---|
| 862 | + if (!ret) |
|---|
| 853 | 863 | mvmvif->bf_data.bf_enabled = true; |
|---|
| 854 | 864 | |
|---|
| 855 | 865 | return ret; |
|---|
| .. | .. |
|---|
| 864 | 874 | .bf_enable_beacon_filter = cpu_to_le32(1), |
|---|
| 865 | 875 | }; |
|---|
| 866 | 876 | |
|---|
| 867 | | - return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false); |
|---|
| 877 | + return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags); |
|---|
| 868 | 878 | } |
|---|
| 869 | 879 | |
|---|
| 870 | 880 | static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, |
|---|
| 871 | 881 | struct ieee80211_vif *vif, |
|---|
| 872 | | - u32 flags, bool d0i3) |
|---|
| 882 | + u32 flags) |
|---|
| 873 | 883 | { |
|---|
| 874 | 884 | struct iwl_beacon_filter_cmd cmd = {}; |
|---|
| 875 | 885 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
|---|
| .. | .. |
|---|
| 880 | 890 | |
|---|
| 881 | 891 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); |
|---|
| 882 | 892 | |
|---|
| 883 | | - /* don't change bf_enabled in case of temporary d0i3 configuration */ |
|---|
| 884 | | - if (!ret && !d0i3) |
|---|
| 893 | + if (!ret) |
|---|
| 885 | 894 | mvmvif->bf_data.bf_enabled = false; |
|---|
| 886 | 895 | |
|---|
| 887 | 896 | return ret; |
|---|
| .. | .. |
|---|
| 891 | 900 | struct ieee80211_vif *vif, |
|---|
| 892 | 901 | u32 flags) |
|---|
| 893 | 902 | { |
|---|
| 894 | | - return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false); |
|---|
| 903 | + return _iwl_mvm_disable_beacon_filter(mvm, vif, flags); |
|---|
| 895 | 904 | } |
|---|
| 896 | 905 | |
|---|
| 897 | 906 | static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) |
|---|
| .. | .. |
|---|
| 934 | 943 | if (!mvmvif->bf_data.bf_enabled) |
|---|
| 935 | 944 | return 0; |
|---|
| 936 | 945 | |
|---|
| 937 | | - if (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) |
|---|
| 946 | + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) |
|---|
| 938 | 947 | cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); |
|---|
| 939 | 948 | |
|---|
| 940 | 949 | mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled || |
|---|
| .. | .. |
|---|
| 942 | 951 | !vif->bss_conf.ps || |
|---|
| 943 | 952 | iwl_mvm_vif_low_latency(mvmvif)); |
|---|
| 944 | 953 | |
|---|
| 945 | | - return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); |
|---|
| 954 | + return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0); |
|---|
| 946 | 955 | } |
|---|
| 947 | 956 | |
|---|
| 948 | 957 | int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) |
|---|
| .. | .. |
|---|
| 1005 | 1014 | return iwl_mvm_power_set_ba(mvm, vifs.bss_vif); |
|---|
| 1006 | 1015 | |
|---|
| 1007 | 1016 | return 0; |
|---|
| 1008 | | -} |
|---|
| 1009 | | - |
|---|
| 1010 | | -int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, |
|---|
| 1011 | | - struct ieee80211_vif *vif, |
|---|
| 1012 | | - bool enable, u32 flags) |
|---|
| 1013 | | -{ |
|---|
| 1014 | | - int ret; |
|---|
| 1015 | | - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
|---|
| 1016 | | - struct iwl_mac_power_cmd cmd = {}; |
|---|
| 1017 | | - |
|---|
| 1018 | | - if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
|---|
| 1019 | | - return 0; |
|---|
| 1020 | | - |
|---|
| 1021 | | - if (!vif->bss_conf.assoc) |
|---|
| 1022 | | - return 0; |
|---|
| 1023 | | - |
|---|
| 1024 | | - iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable); |
|---|
| 1025 | | - |
|---|
| 1026 | | - iwl_mvm_power_log(mvm, &cmd); |
|---|
| 1027 | | -#ifdef CONFIG_IWLWIFI_DEBUGFS |
|---|
| 1028 | | - memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); |
|---|
| 1029 | | -#endif |
|---|
| 1030 | | - ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags, |
|---|
| 1031 | | - sizeof(cmd), &cmd); |
|---|
| 1032 | | - if (ret) |
|---|
| 1033 | | - return ret; |
|---|
| 1034 | | - |
|---|
| 1035 | | - /* configure beacon filtering */ |
|---|
| 1036 | | - if (mvmvif != mvm->bf_allowed_vif) |
|---|
| 1037 | | - return 0; |
|---|
| 1038 | | - |
|---|
| 1039 | | - if (enable) { |
|---|
| 1040 | | - struct iwl_beacon_filter_cmd cmd_bf = { |
|---|
| 1041 | | - IWL_BF_CMD_CONFIG_D0I3, |
|---|
| 1042 | | - .bf_enable_beacon_filter = cpu_to_le32(1), |
|---|
| 1043 | | - }; |
|---|
| 1044 | | - /* |
|---|
| 1045 | | - * When beacon storing is supported - disable beacon filtering |
|---|
| 1046 | | - * altogether - the latest beacon will be sent when exiting d0i3 |
|---|
| 1047 | | - */ |
|---|
| 1048 | | - if (fw_has_capa(&mvm->fw->ucode_capa, |
|---|
| 1049 | | - IWL_UCODE_TLV_CAPA_BEACON_STORING)) |
|---|
| 1050 | | - ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags, |
|---|
| 1051 | | - true); |
|---|
| 1052 | | - else |
|---|
| 1053 | | - ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, |
|---|
| 1054 | | - flags, true); |
|---|
| 1055 | | - } else { |
|---|
| 1056 | | - if (mvmvif->bf_data.bf_enabled) |
|---|
| 1057 | | - ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags); |
|---|
| 1058 | | - else |
|---|
| 1059 | | - ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags); |
|---|
| 1060 | | - } |
|---|
| 1061 | | - |
|---|
| 1062 | | - return ret; |
|---|
| 1063 | 1017 | } |
|---|