|
|
@@ -298,8 +298,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|
|
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
|
|
|
cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
|
|
|
|
|
|
- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
|
|
|
- mvm->ps_prevented)
|
|
|
+ if (mvm->ps_disabled)
|
|
|
return;
|
|
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
|
|
@@ -309,8 +308,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|
|
mvmvif->dbgfs_pm.disable_power_off)
|
|
|
cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
|
|
#endif
|
|
|
- if (!vif->bss_conf.ps || mvm->bound_vif_cnt > 1 ||
|
|
|
- iwl_mvm_vif_low_latency(mvmvif))
|
|
|
+ if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) ||
|
|
|
+ mvm->pm_disabled)
|
|
|
return;
|
|
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
|
|
@@ -417,7 +416,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|
|
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
|
|
}
|
|
|
|
|
|
-static int _iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
|
|
|
+static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
|
|
|
struct ieee80211_vif *vif)
|
|
|
{
|
|
|
struct iwl_mac_power_cmd cmd = {};
|
|
|
@@ -439,39 +438,22 @@ static int _iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
|
|
|
sizeof(cmd), &cmd);
|
|
|
}
|
|
|
|
|
|
-int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
|
|
|
- struct ieee80211_vif *vif)
|
|
|
-
|
|
|
-{
|
|
|
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
- bool ba_enable;
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
|
|
|
- return 0;
|
|
|
-
|
|
|
- ret = _iwl_mvm_power_mac_update_mode(mvm, vif);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
-
|
|
|
- ba_enable = !(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
|
|
|
- mvm->ps_prevented || mvm->bound_vif_cnt > 1 ||
|
|
|
- !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif));
|
|
|
-
|
|
|
- return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
|
|
|
-}
|
|
|
-
|
|
|
-static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable)
|
|
|
+int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
struct iwl_device_power_cmd cmd = {
|
|
|
.flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
|
|
|
};
|
|
|
|
|
|
+ if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
|
|
|
+ return 0;
|
|
|
+
|
|
|
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
|
|
|
return 0;
|
|
|
|
|
|
- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
|
|
|
- force_disable)
|
|
|
+ if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
|
|
|
+ mvm->ps_disabled = true;
|
|
|
+
|
|
|
+ if (mvm->ps_disabled)
|
|
|
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
|
|
@@ -488,14 +470,6 @@ static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable)
|
|
|
&cmd);
|
|
|
}
|
|
|
|
|
|
-int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
|
|
|
-{
|
|
|
- if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
|
|
|
- return 0;
|
|
|
-
|
|
|
- return _iwl_mvm_power_update_device(mvm, false);
|
|
|
-}
|
|
|
-
|
|
|
void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
{
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
@@ -534,64 +508,119 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-struct iwl_mvm_power_iterator {
|
|
|
- struct iwl_mvm *mvm;
|
|
|
+struct iwl_power_constraint {
|
|
|
struct ieee80211_vif *bf_vif;
|
|
|
+ struct ieee80211_vif *bss_vif;
|
|
|
+ bool pm_disabled;
|
|
|
+ bool ps_disabled;
|
|
|
};
|
|
|
|
|
|
-static void iwl_mvm_power_binding_iterator(void *_data, u8 *mac,
|
|
|
- struct ieee80211_vif *vif)
|
|
|
+static void iwl_mvm_power_iterator(void *_data, u8 *mac,
|
|
|
+ struct ieee80211_vif *vif)
|
|
|
{
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
- struct iwl_mvm_power_iterator *power_iterator = _data;
|
|
|
- struct iwl_mvm *mvm = power_iterator->mvm;
|
|
|
- int ret;
|
|
|
+ struct iwl_power_constraint *power_iterator = _data;
|
|
|
+
|
|
|
+ switch (ieee80211_vif_type_p2p(vif)) {
|
|
|
+ case NL80211_IFTYPE_P2P_DEVICE:
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NL80211_IFTYPE_P2P_GO:
|
|
|
+ case NL80211_IFTYPE_AP:
|
|
|
+ /* no BSS power mgmt if we have an active AP */
|
|
|
+ if (mvmvif->ap_ibss_active)
|
|
|
+ power_iterator->pm_disabled = true;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NL80211_IFTYPE_MONITOR:
|
|
|
+ /* no BSS power mgmt and no device power save */
|
|
|
+ power_iterator->pm_disabled = true;
|
|
|
+ power_iterator->ps_disabled = true;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NL80211_IFTYPE_P2P_CLIENT:
|
|
|
+ /* no BSS power mgmt if we have a P2P client*/
|
|
|
+ power_iterator->pm_disabled = true;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NL80211_IFTYPE_STATION:
|
|
|
+ /* we should have only one BSS vif */
|
|
|
+ WARN_ON(power_iterator->bss_vif);
|
|
|
+ power_iterator->bss_vif = vif;
|
|
|
+
|
|
|
+ if (mvmvif->bf_data.bf_enabled &&
|
|
|
+ !WARN_ON(power_iterator->bf_vif))
|
|
|
+ power_iterator->bf_vif = vif;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- ret = _iwl_mvm_power_mac_update_mode(mvm, vif);
|
|
|
+static void
|
|
|
+iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm,
|
|
|
+ struct iwl_power_constraint *constraint)
|
|
|
+{
|
|
|
+ lockdep_assert_held(&mvm->mutex);
|
|
|
+
|
|
|
+ if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {
|
|
|
+ constraint->pm_disabled = true;
|
|
|
+ constraint->ps_disabled = true;
|
|
|
+ }
|
|
|
|
|
|
- if (mvmvif->bf_data.bf_enabled && !WARN_ON(power_iterator->bf_vif))
|
|
|
- power_iterator->bf_vif = vif;
|
|
|
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
|
|
+ IEEE80211_IFACE_ITER_NORMAL,
|
|
|
+ iwl_mvm_power_iterator, constraint);
|
|
|
|
|
|
- WARN_ONCE(ret, "Failed to update power parameters on a specific vif\n");
|
|
|
+ /* TODO: remove this and determine this variable in the iterator */
|
|
|
+ if (mvm->bound_vif_cnt > 1)
|
|
|
+ constraint->pm_disabled = true;
|
|
|
}
|
|
|
|
|
|
-void iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
|
|
|
- struct ieee80211_vif *vif, bool assign)
|
|
|
+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
{
|
|
|
- bool ba_enable;
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
- struct iwl_mvm_power_iterator power_it = {
|
|
|
- .mvm = mvm,
|
|
|
- };
|
|
|
+ struct iwl_power_constraint constraint = {};
|
|
|
+ bool ba_enable;
|
|
|
+ int ret;
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ iwl_mvm_power_get_global_constraint(mvm, &constraint);
|
|
|
+ mvm->ps_disabled = constraint.ps_disabled;
|
|
|
+ mvm->pm_disabled = constraint.pm_disabled;
|
|
|
|
|
|
+ /* don't update device power state unless we add / remove monitor */
|
|
|
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
|
|
- int ret = _iwl_mvm_power_update_device(mvm, assign);
|
|
|
- mvm->ps_prevented = assign;
|
|
|
- WARN_ONCE(ret, "Failed to update power device state\n");
|
|
|
+ ret = iwl_mvm_power_update_device(mvm);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
- ieee80211_iterate_active_interfaces(mvm->hw,
|
|
|
- IEEE80211_IFACE_ITER_NORMAL,
|
|
|
- iwl_mvm_power_binding_iterator,
|
|
|
- &power_it);
|
|
|
+ ret = iwl_mvm_power_send_cmd(mvm, vif);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
- if (!power_it.bf_vif)
|
|
|
- return;
|
|
|
+ if (constraint.bss_vif && vif != constraint.bss_vif) {
|
|
|
+ ret = iwl_mvm_power_send_cmd(mvm, constraint.bss_vif);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!constraint.bf_vif)
|
|
|
+ return 0;
|
|
|
|
|
|
- vif = power_it.bf_vif;
|
|
|
+ vif = constraint.bf_vif;
|
|
|
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
|
|
- ba_enable = !(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM ||
|
|
|
- mvm->ps_prevented || mvm->bound_vif_cnt > 1 ||
|
|
|
+ ba_enable = !(constraint.pm_disabled || constraint.ps_disabled ||
|
|
|
!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif));
|
|
|
|
|
|
- WARN_ON_ONCE(iwl_mvm_update_beacon_abort(mvm, power_it.bf_vif,
|
|
|
- ba_enable));
|
|
|
+ return iwl_mvm_update_beacon_abort(mvm, constraint.bf_vif, ba_enable);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|