Commit 1e239fdd authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

drm/amd/powerplay: maximize code sharing around power limit



Also cache the current and max power limits.

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f3bc9aec
Loading
Loading
Loading
Loading
+21 −28
Original line number Diff line number Diff line
@@ -1413,40 +1413,33 @@ static int arcturus_get_power_limit(struct smu_context *smu,
				     uint32_t *limit,
				     bool cap)
{
	struct smu_11_0_powerplay_table *powerplay_table =
		(struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
	PPTable_t *pptable = smu->smu_table.driver_pptable;
	uint32_t asic_default_power_limit = 0;
	int ret = 0;
	int power_src;

	if (!smu->power_limit) {
		if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
			power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
			if (power_src < 0)
				return -EINVAL;
	uint32_t power_limit, od_percent;

			ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
				power_src << 16, &asic_default_power_limit);
			if (ret) {
				dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
				return ret;
			}
		} else {
	if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
		/* the last hope to figure out the ppt limit */
		if (!pptable) {
			dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
			return -EINVAL;
		}
			asic_default_power_limit =
		power_limit =
			pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
	}
	smu->current_power_limit = power_limit;

	if (smu->od_enabled) {
		od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);

		dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);

		smu->power_limit = asic_default_power_limit;
		power_limit *= (100 + od_percent);
		power_limit /= 100;
	}
	smu->max_power_limit = power_limit;

	if (cap)
		*limit = smu_get_max_power_limit(smu);
	else
		*limit = smu->power_limit;
	*limit = (cap ? smu->max_power_limit : smu->current_power_limit);

	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -382,6 +382,8 @@ struct smu_context
	bool od_enabled;
	uint32_t power_limit;
	uint32_t default_power_limit;
	uint32_t current_power_limit;
	uint32_t max_power_limit;

	/* soft pptable */
	uint32_t ppt_offset_bytes;
+3 −0
Original line number Diff line number Diff line
@@ -196,6 +196,9 @@ int smu_v11_0_get_enabled_mask(struct smu_context *smu,

int smu_v11_0_notify_display_change(struct smu_context *smu);

int smu_v11_0_get_current_power_limit(struct smu_context *smu,
				      uint32_t *power_limit);

int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n);

int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
+23 −30
Original line number Diff line number Diff line
@@ -1926,40 +1926,33 @@ static int navi10_get_power_limit(struct smu_context *smu,
				  uint32_t *limit,
				  bool cap)
{
	struct smu_11_0_powerplay_table *powerplay_table =
		(struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
	PPTable_t *pptable = smu->smu_table.driver_pptable;
	uint32_t asic_default_power_limit = 0;
	int ret = 0;
	int power_src;

	if (!smu->power_limit) {
		if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
			power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
			if (power_src < 0)
				return -EINVAL;
	uint32_t power_limit, od_percent;

			ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
				power_src << 16, &asic_default_power_limit);
			if (ret) {
				dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
				return ret;
			}
		} else {
	if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
		/* the last hope to figure out the ppt limit */
		if (!pptable) {
			dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
			return -EINVAL;
		}
			asic_default_power_limit =
		power_limit =
			pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
	}
	smu->current_power_limit = power_limit;

	if (smu->od_enabled) {
		od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);

		dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);

		smu->power_limit = asic_default_power_limit;
		power_limit *= (100 + od_percent);
		power_limit /= 100;
	}
	smu->max_power_limit = power_limit;

	if (cap)
		*limit = smu_get_max_power_limit(smu);
	else
		*limit = smu->power_limit;
	*limit = (cap ? smu->max_power_limit : smu->current_power_limit);

	return 0;
}
+22 −29
Original line number Diff line number Diff line
@@ -1747,40 +1747,33 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
				     uint32_t *limit,
				     bool cap)
{
	struct smu_11_0_7_powerplay_table *powerplay_table =
		(struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
	PPTable_t *pptable = smu->smu_table.driver_pptable;
	uint32_t asic_default_power_limit = 0;
	int ret = 0;
	int power_src;

	if (!smu->power_limit) {
		if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
			power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
			if (power_src < 0)
				return -EINVAL;
	uint32_t power_limit, od_percent;

			ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
							  power_src << 16, &asic_default_power_limit);
			if (ret) {
				dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
				return ret;
			}
		} else {
	if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
		/* the last hope to figure out the ppt limit */
		if (!pptable) {
			dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
			return -EINVAL;
		}
			asic_default_power_limit =
		power_limit =
			pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
	}
	smu->current_power_limit = power_limit;

	if (smu->od_enabled) {
		od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);

		dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);

		smu->power_limit = asic_default_power_limit;
		power_limit *= (100 + od_percent);
		power_limit /= 100;
	}
	smu->max_power_limit = power_limit;

	if (cap)
		*limit = smu_get_max_power_limit(smu);
	else
		*limit = smu->power_limit;
	*limit = (cap ? smu->max_power_limit : smu->current_power_limit);

	return 0;
}
Loading