int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, bool force) { int ret; bool update_chains; lockdep_assert_held(&priv->mutex); /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) return 0; if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete use sleep_power_next, need to be updated */ memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); if (test_bit(STATUS_SCANNING, &priv->status) && !force) { IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); return 0; } if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) set_bit(STATUS_POWER_PMI, &priv->status); ret = iwl_set_power(priv, cmd); if (!ret) { if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) clear_bit(STATUS_POWER_PMI, &priv->status); if (priv->cfg->ops->lib->update_chain_flags && update_chains) priv->cfg->ops->lib->update_chain_flags(priv); else if (priv->cfg->ops->lib->update_chain_flags) IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " "calibration running: %d\n", priv->chain_noise_data.state); memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)); } else IWL_ERR(priv, "set power fail, ret = %d", ret); return ret; }
/* * compute the final power mode index */ int iwl_power_update_mode(struct iwl_priv *priv, bool force) { struct iwl_power_mgr *setting = &(priv->power_data); int ret = 0; u16 uninitialized_var(final_mode); bool update_chains; /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; final_mode = priv->power_data.user_power_setting; if (setting->power_disabled) final_mode = IWL_POWER_MODE_CAM; if (iwl_is_ready_rf(priv) && ((setting->power_mode != final_mode) || force)) { struct iwl_powertable_cmd cmd; if (final_mode != IWL_POWER_MODE_CAM) set_bit(STATUS_POWER_PMI, &priv->status); iwl_update_power_cmd(priv, &cmd, final_mode); cmd.keep_alive_beacons = 0; if (final_mode == IWL_POWER_INDEX_5) cmd.flags |= IWL_POWER_FAST_PD; ret = iwl_set_power(priv, &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); if (priv->cfg->ops->lib->update_chain_flags && update_chains) priv->cfg->ops->lib->update_chain_flags(priv); else IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " "calibration running: %d\n", priv->chain_noise_data.state); if (!ret) setting->power_mode = final_mode; } return ret; }
int iwl_power_update_mode(struct iwl_priv *priv, bool force) { int ret = 0; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && (priv->hw->conf.flags & IEEE80211_CONF_PS); bool update_chains; struct iwl_powertable_cmd cmd; int dtimper; /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; if (priv->vif) dtimper = priv->vif->bss_conf.dtim_period; else dtimper = 1; if (priv->cfg->broken_powersave) iwl_power_sleep_cam_cmd(priv, &cmd); else if (priv->cfg->supports_idle && priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); else if (tt->state >= IWL_TI_1) iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); else if (!enabled) iwl_power_sleep_cam_cmd(priv, &cmd); else if (priv->power_data.debug_sleep_level_override >= 0) iwl_static_sleep_cmd(priv, &cmd, priv->power_data.debug_sleep_level_override, dtimper); else if (no_sleep_autoadjust) iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper); else iwl_power_fill_sleep_cmd(priv, &cmd, priv->hw->conf.dynamic_ps_timeout, priv->hw->conf.max_sleep_period); if (iwl_is_ready_rf(priv) && (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) { if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) set_bit(STATUS_POWER_PMI, &priv->status); ret = iwl_set_power(priv, &cmd); if (!ret) { if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) clear_bit(STATUS_POWER_PMI, &priv->status); if (priv->cfg->ops->lib->update_chain_flags && update_chains) priv->cfg->ops->lib->update_chain_flags(priv); else if (priv->cfg->ops->lib->update_chain_flags) IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " "calibration running: %d\n", priv->chain_noise_data.state); memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)); } else IWL_ERR(priv, "set power fail, ret = %d", ret); } return ret; }