static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mac_power_cmd cmd = {}; struct iwl_mvm_vif *mvmvif __maybe_unused = iwl_mvm_vif_from_mac80211(vif); if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); #ifdef CPTCFG_IWLWIFI_DEBUGFS if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && mvmvif->dbgfs_pm.disable_power_off) cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); #endif iwl_mvm_power_log(mvm, &cmd); return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC, sizeof(cmd), &cmd); }
static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { int ret; bool ba_enable; struct iwl_mac_power_cmd cmd = {}; if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; /* * TODO: The following vif_count verification is temporary condition. * Avoid power mode update if more than one interface is currently * active. Remove this condition when FW will support power management * on multiple MACs. */ IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n", mvm->vif_count); if (mvm->vif_count > 1) return 0; iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_log(mvm, &cmd); ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC, sizeof(cmd), &cmd); if (ret) return ret; ba_enable = !!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)); return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); }
static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { int ret; bool ba_enable; struct iwl_mac_power_cmd cmd = {}; if (vif->type != NL80211_IFTYPE_STATION) return 0; if (vif->p2p && !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)) return 0; iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_log(mvm, &cmd); ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC, sizeof(cmd), &cmd); if (ret) return ret; ba_enable = !!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)); return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); }
int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool enable, u32 flags) { int ret; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mac_power_cmd cmd = {}; if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; if (!vif->bss_conf.assoc) return 0; iwl_mvm_power_build_cmd(mvm, vif, &cmd); if (enable) { /* configure skip over dtim up to 306TU - 314 msec */ int dtimper = vif->bss_conf.dtim_period ?: 1; int dtimper_tu = dtimper * vif->bss_conf.beacon_int; bool radar_detect = iwl_mvm_power_is_radar(vif); if (WARN_ON(!dtimper_tu)) return 0; /* Check skip over DTIM conditions */ /* TODO: check that multicast wake lock is off */ if (!radar_detect && (dtimper < 10)) { cmd.skip_dtim_periods = 306 / dtimper_tu; if (cmd.skip_dtim_periods) cmd.flags |= cpu_to_le16( POWER_FLAGS_SKIP_OVER_DTIM_MSK); } } iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); #endif ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags, sizeof(cmd), &cmd); if (ret) return ret; /* configure beacon filtering */ if (mvmvif != mvm->bf_allowed_vif) return 0; if (enable) { struct iwl_beacon_filter_cmd cmd_bf = { IWL_BF_CMD_CONFIG_D0I3, .bf_enable_beacon_filter = cpu_to_le32(1), }; ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, flags, true); } else { if (mvmvif->bf_data.bf_enabled)
static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mac_power_cmd cmd = {}; iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); #endif return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0, sizeof(cmd), &cmd); }
int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool enable, u32 flags) { int ret; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mac_power_cmd cmd = {}; if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; if (!vif->bss_conf.assoc) return 0; iwl_mvm_power_build_cmd(mvm, vif, &cmd); if (enable) { /* configure skip over dtim up to 300 msec */ int dtimper = mvm->hw->conf.ps_dtim_period ?: 1; int dtimper_msec = dtimper * vif->bss_conf.beacon_int; if (WARN_ON(!dtimper_msec)) return 0; cmd.skip_dtim_periods = 300 / dtimper_msec; if (cmd.skip_dtim_periods) cmd.flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); } iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); #endif ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags, sizeof(cmd), &cmd); if (ret) return ret; /* configure beacon filtering */ if (mvmvif != mvm->bf_allowed_vif) return 0; if (enable) { struct iwl_beacon_filter_cmd cmd_bf = { IWL_BF_CMD_CONFIG_D0I3, .bf_enable_beacon_filter = cpu_to_le32(1), }; ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, flags, true); } else { if (mvmvif->bf_data.bf_enabled)