示例#1
0
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;
}
示例#2
0
/*
 * 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;
}
示例#3
0
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;
}