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);
}
Exemple #3
0
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)
Exemple #4
0
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);
}
Exemple #5
0
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)
static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
					struct ieee80211_vif *vif, char *buf,
					int bufsz)
{
	struct iwl_mac_power_cmd cmd = {};
	int pos = 0;

	iwl_mvm_power_build_cmd(mvm, vif, &cmd);

	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
		pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
				 (cmd.flags &
				 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
				 0 : 1);
	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
			 iwlmvm_mod_params.power_scheme);
	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
			 le16_to_cpu(cmd.flags));
	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
			 le16_to_cpu(cmd.keep_alive_seconds));

	if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
		pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
				 (cmd.flags &
				 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
				 1 : 0);
		pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
				 cmd.skip_dtim_periods);
		if (!(cmd.flags &
		      cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
			pos += scnprintf(buf+pos, bufsz-pos,
					 "rx_data_timeout = %d\n",
					 le32_to_cpu(cmd.rx_data_timeout));
			pos += scnprintf(buf+pos, bufsz-pos,
					 "tx_data_timeout = %d\n",
					 le32_to_cpu(cmd.tx_data_timeout));
		}
		if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
			pos += scnprintf(buf+pos, bufsz-pos,
					 "lprx_rssi_threshold = %d\n",
					 cmd.lprx_rssi_threshold);
		if (cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
			pos +=
			scnprintf(buf+pos, bufsz-pos,
				  "rx_data_timeout_uapsd = %d\n",
				  le32_to_cpu(cmd.rx_data_timeout_uapsd));
			pos +=
			scnprintf(buf+pos, bufsz-pos,
				  "tx_data_timeout_uapsd = %d\n",
				  le32_to_cpu(cmd.tx_data_timeout_uapsd));
			pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n",
					 cmd.qndp_tid);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "uapsd_ac_flags = 0x%x\n",
					 cmd.uapsd_ac_flags);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "uapsd_max_sp = %d\n",
					 cmd.uapsd_max_sp);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "heavy_tx_thld_packets = %d\n",
					 cmd.heavy_tx_thld_packets);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "heavy_rx_thld_packets = %d\n",
					 cmd.heavy_rx_thld_packets);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "heavy_tx_thld_percentage = %d\n",
					 cmd.heavy_tx_thld_percentage);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "heavy_rx_thld_percentage = %d\n",
					 cmd.heavy_rx_thld_percentage);
			pos +=
			scnprintf(buf+pos, bufsz-pos, "snooze_enable = %d\n",
				  (cmd.flags &
				   cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) ?
				  1 : 0);
		}
		if (cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
			pos += scnprintf(buf+pos, bufsz-pos,
					 "snooze_interval = %d\n",
					 cmd.snooze_interval);
			pos += scnprintf(buf+pos, bufsz-pos,
					 "snooze_window = %d\n",
					 cmd.snooze_window);
		}
	}
	return pos;
}