Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd4ace2a authored by Alexander Bondar's avatar Alexander Bondar Committed by Johannes Berg
Browse files

iwlwifi: mvm: Add support for Low Power RX



To improve power consumption in idle associated mode FW may lower
RX power. This low linearity mode is acceptable for listening low rate
RX such as beacons and groupcast. The driver enables LPRX only if PM
is enabled and associated AP's beacon TX rate is 1Mbps or 6Mbps.
LPRX RSSI threshold is used to limit a range where LPRX is applied.

Signed-off-by: default avatarAlexander Bondar <alexander.bondar@intel.com>
Reviewed-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9277326e
Loading
Loading
Loading
Loading
+23 −1
Original line number Original line Diff line number Diff line
@@ -344,6 +344,13 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
	case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
	case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
		IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
		IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
		dbgfs_pm->disable_power_off = val;
		dbgfs_pm->disable_power_off = val;
	case MVM_DEBUGFS_PM_LPRX_ENA:
		IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
		dbgfs_pm->lprx_ena = val;
		break;
	case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
		IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
		dbgfs_pm->lprx_rssi_threshold = val;
		break;
		break;
	}
	}
}
}
@@ -387,6 +394,17 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
		if (sscanf(buf + 18, "%d", &val) != 1)
		if (sscanf(buf + 18, "%d", &val) != 1)
			return -EINVAL;
			return -EINVAL;
		param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
		param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
	} else if (!strncmp("lprx=", buf, 5)) {
		if (sscanf(buf + 5, "%d", &val) != 1)
			return -EINVAL;
		param = MVM_DEBUGFS_PM_LPRX_ENA;
	} else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
		if (sscanf(buf + 20, "%d", &val) != 1)
			return -EINVAL;
		if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
		    POWER_LPRX_RSSI_THRESHOLD_MIN)
			return -EINVAL;
		param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
	} else {
	} else {
		return -EINVAL;
		return -EINVAL;
	}
	}
@@ -421,7 +439,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
			 le32_to_cpu(cmd.skip_dtim_periods));
			 le32_to_cpu(cmd.skip_dtim_periods));
	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
			 iwlmvm_mod_params.power_scheme);
			 iwlmvm_mod_params.power_scheme);
	pos += scnprintf(buf+pos, bufsz-pos, "flags = %d\n",
	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
			 le16_to_cpu(cmd.flags));
			 le16_to_cpu(cmd.flags));
	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
			 cmd.keep_alive_seconds);
			 cmd.keep_alive_seconds);
@@ -435,6 +453,10 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
				 le32_to_cpu(cmd.rx_data_timeout));
				 le32_to_cpu(cmd.rx_data_timeout));
		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
				 le32_to_cpu(cmd.tx_data_timeout));
				 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",
					 le32_to_cpu(cmd.lprx_rssi_threshold));
	}
	}


	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+5 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,11 @@


/* Power Management Commands, Responses, Notifications */
/* Power Management Commands, Responses, Notifications */


/* Radio LP RX Energy Threshold measured in dBm */
#define POWER_LPRX_RSSI_THRESHOLD	75
#define POWER_LPRX_RSSI_THRESHOLD_MAX	94
#define POWER_LPRX_RSSI_THRESHOLD_MIN	30

/**
/**
 * enum iwl_scan_flags - masks for power table command flags
 * enum iwl_scan_flags - masks for power table command flags
 * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
 * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
+4 −0
Original line number Original line Diff line number Diff line
@@ -158,6 +158,8 @@ enum iwl_dbgfs_pm_mask {
	MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3),
	MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3),
	MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4),
	MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4),
	MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
	MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
	MVM_DEBUGFS_PM_LPRX_ENA = BIT(6),
	MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
};
};


struct iwl_dbgfs_pm {
struct iwl_dbgfs_pm {
@@ -167,6 +169,8 @@ struct iwl_dbgfs_pm {
	bool skip_over_dtim;
	bool skip_over_dtim;
	u8 skip_dtim_periods;
	u8 skip_dtim_periods;
	bool disable_power_off;
	bool disable_power_off;
	bool lprx_ena;
	u32 lprx_rssi_threshold;
	int mask;
	int mask;
};
};


+20 −2
Original line number Original line Diff line number Diff line
@@ -137,11 +137,12 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
				le32_to_cpu(cmd->rx_data_timeout));
				le32_to_cpu(cmd->rx_data_timeout));
		IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
		IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
				le32_to_cpu(cmd->tx_data_timeout));
				le32_to_cpu(cmd->tx_data_timeout));
		IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
				cmd->lprx_rssi_threshold);
		if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
		if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
			IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
			IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
					le32_to_cpu(cmd->skip_dtim_periods));
					le32_to_cpu(cmd->skip_dtim_periods));
		if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
			IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
					le32_to_cpu(cmd->lprx_rssi_threshold));
	}
	}
}
}


@@ -181,6 +182,14 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,


	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);


	if (vif->bss_conf.beacon_rate &&
	    (vif->bss_conf.beacon_rate->bitrate == 10 ||
	     vif->bss_conf.beacon_rate->bitrate == 60)) {
		cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
		cmd->lprx_rssi_threshold =
			cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
	}

	dtimper = hw->conf.ps_dtim_period ?: 1;
	dtimper = hw->conf.ps_dtim_period ?: 1;


	/* Check if radar detection is required on current channel */
	/* Check if radar detection is required on current channel */
@@ -236,6 +245,15 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
		cmd->skip_dtim_periods =
		cmd->skip_dtim_periods =
			cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
			cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
		if (mvmvif->dbgfs_pm.lprx_ena)
			cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
		else
			cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
	}
	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
		cmd->lprx_rssi_threshold =
			cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#endif /* CONFIG_IWLWIFI_DEBUGFS */
}
}