Commit 19589468 authored by Ma Jun's avatar Ma Jun Committed by Alex Deucher
Browse files

drm/amd/pm: Support for getting power1_cap_min value



Support for getting power1_cap_min value on smu13 and smu11.
For other Asics, we still use 0 as the default value.

Signed-off-by: default avatarMa Jun <Jun.Ma2@amd.com>
Reviewed-by: default avatarKenneth Feng <kenneth.feng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent afcf949c
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -2921,14 +2921,6 @@ static ssize_t amdgpu_hwmon_show_power_input(struct device *dev,
	return sysfs_emit(buf, "%zd\n", val);
}

static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	return sysfs_emit(buf, "%i\n", 0);
}


static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev,
					struct device_attribute *attr,
					char *buf,
@@ -2965,6 +2957,12 @@ static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev,
	return size;
}

static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_MIN);
}

static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
					 struct device_attribute *attr,
+11 −6
Original line number Diff line number Diff line
@@ -849,7 +849,8 @@ static int smu_late_init(void *handle)
	ret = smu_get_asic_power_limits(smu,
					&smu->current_power_limit,
					&smu->default_power_limit,
					&smu->max_power_limit);
					&smu->max_power_limit,
					&smu->min_power_limit);
	if (ret) {
		dev_err(adev->dev, "Failed to get asic power limits!\n");
		return ret;
@@ -2447,6 +2448,8 @@ int smu_get_power_limit(void *handle,
		limit_level = SMU_PPT_LIMIT_MAX;
		break;
	case PP_PWR_LIMIT_MIN:
		limit_level = SMU_PPT_LIMIT_MIN;
		break;
	default:
		return -EOPNOTSUPP;
		break;
@@ -2466,8 +2469,7 @@ int smu_get_power_limit(void *handle,
			case IP_VERSION(11, 0, 13):
				ret = smu_get_asic_power_limits(smu,
								&smu->current_power_limit,
								NULL,
								NULL);
								NULL, NULL, NULL);
				break;
			default:
				break;
@@ -2480,6 +2482,9 @@ int smu_get_power_limit(void *handle,
		case SMU_PPT_LIMIT_MAX:
			*limit = smu->max_power_limit;
			break;
		case SMU_PPT_LIMIT_MIN:
			*limit = smu->min_power_limit;
			break;
		default:
			break;
		}
@@ -2502,10 +2507,10 @@ static int smu_set_power_limit(void *handle, uint32_t limit)
		if (smu->ppt_funcs->set_power_limit)
			return smu->ppt_funcs->set_power_limit(smu, limit_type, limit);

	if (limit > smu->max_power_limit) {
	if ((limit > smu->max_power_limit) || (limit < smu->min_power_limit)) {
		dev_err(smu->adev->dev,
			"New power limit (%d) is over the max allowed %d\n",
			limit, smu->max_power_limit);
			"New power limit (%d) is out of range [%d,%d]\n",
			limit, smu->min_power_limit, smu->max_power_limit);
		return -EINVAL;
	}

+5 −3
Original line number Diff line number Diff line
@@ -500,6 +500,7 @@ struct smu_context {
	uint32_t current_power_limit;
	uint32_t default_power_limit;
	uint32_t max_power_limit;
	uint32_t min_power_limit;

	/* soft pptable */
	uint32_t ppt_offset_bytes;
@@ -823,7 +824,8 @@ struct pptable_funcs {
	int (*get_power_limit)(struct smu_context *smu,
					uint32_t *current_power_limit,
					uint32_t *default_power_limit,
			       uint32_t *max_power_limit);
					uint32_t *max_power_limit,
					uint32_t *min_power_limit);

	/**
	 * @get_ppt_limit: Get the device's ppt limits.
+21 −12
Original line number Diff line number Diff line
@@ -1280,12 +1280,13 @@ static int arcturus_get_fan_parameters(struct smu_context *smu)
static int arcturus_get_power_limit(struct smu_context *smu,
					uint32_t *current_power_limit,
					uint32_t *default_power_limit,
				    uint32_t *max_power_limit)
					uint32_t *max_power_limit,
					uint32_t *min_power_limit)
{
	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 power_limit, od_percent;
	uint32_t power_limit, od_percent_upper, od_percent_lower;

	if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
		/* the last hope to figure out the ppt limit */
@@ -1302,17 +1303,25 @@ static int arcturus_get_power_limit(struct smu_context *smu,
	if (default_power_limit)
		*default_power_limit = power_limit;

	if (max_power_limit) {
	if (smu->od_enabled) {
			od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
		od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
		od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
	} else {
		od_percent_upper = 0;
		od_percent_lower = 100;
	}

			dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
							od_percent_upper, od_percent_lower, power_limit);

			power_limit *= (100 + od_percent);
			power_limit /= 100;
	if (max_power_limit) {
		*max_power_limit = power_limit * (100 + od_percent_upper);
		*max_power_limit /= 100;
	}

		*max_power_limit = power_limit;
	if (min_power_limit) {
		*min_power_limit = power_limit * (100 - od_percent_lower);
		*min_power_limit /= 100;
	}

	return 0;
+21 −12
Original line number Diff line number Diff line
@@ -2332,13 +2332,14 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
static int navi10_get_power_limit(struct smu_context *smu,
					uint32_t *current_power_limit,
					uint32_t *default_power_limit,
				  uint32_t *max_power_limit)
					uint32_t *max_power_limit,
					uint32_t *min_power_limit)
{
	struct smu_11_0_powerplay_table *powerplay_table =
		(struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
	struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
	PPTable_t *pptable = smu->smu_table.driver_pptable;
	uint32_t power_limit, od_percent;
	uint32_t power_limit, od_percent_upper, od_percent_lower;

	if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
		/* the last hope to figure out the ppt limit */
@@ -2355,18 +2356,26 @@ static int navi10_get_power_limit(struct smu_context *smu,
	if (default_power_limit)
		*default_power_limit = power_limit;

	if (max_power_limit) {
	if (smu->od_enabled &&
		    navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
			od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
		od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
		od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
	} else {
		od_percent_upper = 0;
		od_percent_lower = 100;
	}

			dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
					od_percent_upper, od_percent_lower, power_limit);

			power_limit *= (100 + od_percent);
			power_limit /= 100;
	if (max_power_limit) {
		*max_power_limit = power_limit * (100 + od_percent_upper);
		*max_power_limit /= 100;
	}

		*max_power_limit = power_limit;
	if (min_power_limit) {
		*min_power_limit = power_limit * (100 - od_percent_lower);
		*min_power_limit /= 100;
	}

	return 0;
Loading