All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy
@ 2026-07-31  3:10 Yang Wang
  2026-07-31  3:10 ` [PATCH 1/4] drm/amd/pm: refactor PPT limits by controller and power source Yang Wang
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Yang Wang @ 2026-07-31  3:10 UTC (permalink / raw)
  To: amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng

PPT limit handling combines controller identity, AC/DC source, immutable
capabilities, PMFW runtime state, and persistent user policy in scalar
state. This prevents the driver from representing PPT0/PPT1 independently
and leaves user limits vulnerable to PMFW reset.

The runtime model requires separate ownership for each class of data:

- PPTable-derived ranges define normal and OD capabilities.
- PMFW messages and tables define the effective runtime limit.
- Common user-profile state defines persistent policy by source and
  controller.

The four patches establish these boundaries:

- Index common ranges by AC/DC source and PPT0/PPT1 controller; pass the
  controller through get and set callbacks.
- Account for PMFW protocols that represent an effective limit as a
  message base plus an OD percentage.
- Save user values and validity masks by source and controller; restore
  them after suspend and live AC/DC transitions.
- Restore the saved PPT policy after GPU reset reinitializes PMFW and the
  platform power table.

The resulting policy preserves explicit user limits without caching
mutable PMFW current values.

Yang Wang (4):
  drm/amd/pm: refactor PPT limits by controller and power source
  drm/amd/pm: account for OD percentage in effective PPT limits
  drm/amd/pm: refactor user PPT policy save and restore
  drm/amd/pm: restore user PPT limits after GPU reset

 drivers/gpu/drm/amd/pm/amdgpu_dpm.c           |   2 +-
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 222 ++++++++++--------
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  63 ++---
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h  |  15 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h  |  11 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h  |  11 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h  |  11 +-
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c |  52 ++--
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   |  78 +++---
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 122 +++++-----
 .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c    |  23 +-
 .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  | 118 ++++------
 .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c    |  93 ++++----
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c    |  23 +-
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 123 ++++++----
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c  | 124 +++++-----
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 123 ++++++----
 .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c    |  23 +-
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  | 123 ++++++----
 .../gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c    |  23 +-
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c  | 122 +++++-----
 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   3 +-
 22 files changed, 792 insertions(+), 716 deletions(-)

-- 
2.54.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] drm/amd/pm: refactor PPT limits by controller and power source
  2026-07-31  3:10 [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Yang Wang
@ 2026-07-31  3:10 ` Yang Wang
  2026-07-31  3:10 ` [PATCH 2/4] drm/amd/pm: account for OD percentage in effective PPT limits Yang Wang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Yang Wang @ 2026-07-31  3:10 UTC (permalink / raw)
  To: amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng

The scalar PPT model has several structural limitations:

- Controller identity, power source, capability, and PMFW state share
  the same fields.
- Combined callbacks cannot address PPT0 and PPT1 independently.
- Cached current limits can become stale after PMFW reset.

Refactor the model around these rules:

- Index ranges by AC/DC source and PPT0/PPT1 controller.
- Store normal and overdrive capabilities separately.
- Pass the controller to get and set callbacks.
- Keep slow and fast names as semantic aliases.

Assign each value to a single owner:

- PPTable or platform initialization supplies constant capabilities.
- PMFW supplies runtime state.
- Common code selects the active source and overdrive range.

Van Gogh defaults are initialized once, while firmware without PPT query
support remains usable. Capable SMU 13.0.6 and SMU 15.0.8 platforms
expose PPT1 through the same interface. A writable controller must also
provide a setter callback.

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
---
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 150 +++++++++---------
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  60 +++----
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h  |  15 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h  |  11 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h  |  11 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h  |  11 +-
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c |  52 +++---
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   |  78 ++++-----
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 122 +++++++-------
 .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c    |  23 +--
 .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  | 118 ++++++--------
 .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c    |  93 +++++------
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c    |  23 +--
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 114 +++++++------
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c  | 124 +++++++--------
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 114 +++++++------
 .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c    |  23 +--
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  | 112 +++++++------
 .../gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c    |  23 +--
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c  | 122 +++++++-------
 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   3 +-
 21 files changed, 707 insertions(+), 695 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 2a771eb5a03f..99d42446cfc8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -70,7 +70,7 @@ static int smu_handle_task(struct smu_context *smu,
 static int smu_reset(struct smu_context *smu);
 static int smu_set_fan_speed_pwm(void *handle, u32 speed);
 static int smu_set_fan_control_mode(void *handle, u32 value);
-static int smu_set_power_limit(void *handle, uint32_t limit_type, uint32_t limit);
+static int smu_set_ppt_limit(void *handle, uint32_t limit_type, uint32_t limit);
 static int smu_set_fan_speed_rpm(void *handle, uint32_t speed);
 static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled);
 static int smu_set_mp1_state(void *handle, enum pp_mp1_state mp1_state);
@@ -493,8 +493,7 @@ static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_
  *
  * @smu:	smu_context pointer
  *
- * Restore the saved user power configurations include power limit,
- * clock frequencies, fan control mode and fan speed.
+ * Restore saved user power limits, clock frequencies and fan settings.
  */
 static void smu_restore_dpm_user_profile(struct smu_context *smu)
 {
@@ -511,13 +510,14 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu)
 	smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE;
 
 	/* set the user dpm power limits */
-	for (int i = SMU_DEFAULT_PPT_LIMIT; i < SMU_LIMIT_TYPE_COUNT; i++) {
-		if (!smu->user_dpm_profile.power_limits[i])
+	for (int i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) {
+		if (!smu->user_dpm_profile.ppt_limits[i])
 			continue;
-		ret = smu_set_power_limit(smu, i,
-					  smu->user_dpm_profile.power_limits[i]);
+		ret = smu_set_ppt_limit(smu, i,
+					    smu->user_dpm_profile.ppt_limits[i]);
 		if (ret)
-			dev_err(smu->adev->dev, "Failed to set %d power limit value\n", i);
+			dev_err(smu->adev->dev,
+				"Failed to set %d PPT limit value\n", i);
 	}
 
 	/* set the user dpm clock configurations */
@@ -687,6 +687,7 @@ static int smu_sys_set_pp_table(void *handle,
 	smu_table->hardcode_pptable = hardcode_pptable;
 	smu_table->power_play_table = smu_table->hardcode_pptable;
 	smu_table->power_play_table_size = size;
+	memset(&smu->ppt_limits, 0, sizeof(smu->ppt_limits));
 
 	/*
 	 * Special hw_fini action(for Navi1x, the DPMs disablement will be
@@ -951,16 +952,6 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block)
 		return ret;
 	}
 
-	ret = smu_get_asic_power_limits(smu,
-					&smu->current_power_limit,
-					&smu->default_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;
-	}
-
 	if (!amdgpu_sriov_vf(adev))
 		smu_get_unique_id(smu);
 
@@ -2904,7 +2895,7 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed)
 }
 
 /**
- * smu_get_power_limit - Request one of the SMU Power Limits
+ * smu_get_ppt_limit - Request one of the SMU PPT limits
  *
  * @handle: pointer to smu context
  * @limit: requested limit is written back to this variable
@@ -2913,13 +2904,13 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed)
  * Return:  0 on success, <0 on error
  *
  */
-int smu_get_power_limit(void *handle,
+int smu_get_ppt_limit(void *handle,
 			uint32_t *limit,
 			enum pp_power_limit_level pp_limit_level,
 			enum pp_power_type pp_power_type)
 {
 	struct smu_context *smu = handle;
-	struct amdgpu_device *adev = smu->adev;
+	enum smu_power_src_type power_source;
 	enum smu_ppt_limit_level limit_level;
 	uint32_t limit_type;
 	int ret = 0;
@@ -2930,9 +2921,12 @@ int smu_get_power_limit(void *handle,
 	if  (!limit)
 		return -EINVAL;
 
+	power_source = smu->adev->pm.ac_power ?
+		SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC;
+
 	switch (pp_power_type) {
 	case PP_PWR_TYPE_SUSTAINED:
-		limit_type = SMU_DEFAULT_PPT_LIMIT;
+		limit_type = SMU_SLOW_PPT_LIMIT;
 		break;
 	case PP_PWR_TYPE_FAST:
 		limit_type = SMU_FAST_PPT_LIMIT;
@@ -2958,77 +2952,77 @@ int smu_get_power_limit(void *handle,
 		return -EOPNOTSUPP;
 	}
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT) {
-		if (smu->ppt_funcs->get_ppt_limit)
-			ret = smu->ppt_funcs->get_ppt_limit(smu, limit, limit_type, limit_level);
-		else
-			return -EOPNOTSUPP;
-	} else {
-		switch (limit_level) {
-		case SMU_PPT_LIMIT_CURRENT:
-			switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
-			case IP_VERSION(13, 0, 2):
-			case IP_VERSION(13, 0, 6):
-			case IP_VERSION(13, 0, 12):
-			case IP_VERSION(13, 0, 14):
-			case IP_VERSION(11, 0, 7):
-			case IP_VERSION(11, 0, 11):
-			case IP_VERSION(11, 0, 12):
-			case IP_VERSION(11, 0, 13):
-			case IP_VERSION(15, 0, 8):
-				ret = smu_get_asic_power_limits(smu,
-								&smu->current_power_limit,
-								NULL, NULL, NULL);
-				break;
-			default:
-				break;
-			}
-			*limit = smu->current_power_limit;
-			break;
-		case SMU_PPT_LIMIT_DEFAULT:
-			*limit = smu->default_power_limit;
-			break;
-		case SMU_PPT_LIMIT_MAX:
-			*limit = smu->max_power_limit;
-			break;
-		case SMU_PPT_LIMIT_MIN:
-			*limit = smu->min_power_limit;
-			break;
-		default:
-			return -EINVAL;
-		}
+	if (!(smu->ppt_limits.supported_mask & BIT(limit_type)))
+		return -EOPNOTSUPP;
+
+	switch (limit_level) {
+	case SMU_PPT_LIMIT_CURRENT:
+		ret = smu_get_asic_ppt_limit(smu, limit_type, limit);
+		break;
+	case SMU_PPT_LIMIT_DEFAULT:
+		*limit = smu->ppt_limits.range[power_source][limit_type].default_value;
+		break;
+	case SMU_PPT_LIMIT_MAX:
+		*limit = smu->od_enabled ?
+			smu->ppt_limits.range[power_source][limit_type].od_max :
+			smu->ppt_limits.range[power_source][limit_type].max;
+		break;
+	case SMU_PPT_LIMIT_MIN:
+		*limit = smu->od_enabled ?
+			smu->ppt_limits.range[power_source][limit_type].od_min :
+			smu->ppt_limits.range[power_source][limit_type].min;
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	return ret;
 }
 
-static int smu_set_power_limit(void *handle, uint32_t limit_type, uint32_t limit)
+static int smu_set_ppt_limit(void *handle, uint32_t limit_type, uint32_t limit)
 {
 	struct smu_context *smu = handle;
+	enum smu_power_src_type power_source;
+	struct smu_ppt_limit_range *range;
+	uint32_t min_limit, max_limit;
 	int ret = 0;
 
 	if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
 		return -EOPNOTSUPP;
+	if (limit_type >= SMU_LIMIT_TYPE_COUNT)
+		return -EINVAL;
 
-	if (limit_type == SMU_DEFAULT_PPT_LIMIT) {
-		if (!limit)
-			limit = smu->current_power_limit;
-		if ((limit > smu->max_power_limit) || (limit < smu->min_power_limit)) {
-			dev_err(smu->adev->dev,
-				"New power limit (%d) is out of range [%d,%d]\n",
-				limit, smu->min_power_limit, smu->max_power_limit);
-			return -EINVAL;
-		}
-	}
+	power_source = smu->adev->pm.ac_power ?
+		SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC;
+	range = &smu->ppt_limits.range[power_source][limit_type];
+	min_limit = smu->od_enabled ? range->od_min : range->min;
+	max_limit = smu->od_enabled ? range->od_max : range->max;
 
-	if (smu->ppt_funcs->set_power_limit) {
-		ret = smu->ppt_funcs->set_power_limit(smu, limit_type, limit);
+	if (!(smu->ppt_limits.supported_mask & BIT(limit_type)))
+		return -EOPNOTSUPP;
+
+	if (limit_type == SMU_DEFAULT_PPT_LIMIT && !limit) {
+		ret = smu_get_asic_ppt_limit(smu, limit_type, &limit);
 		if (ret)
 			return ret;
-		if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
-			smu->user_dpm_profile.power_limits[limit_type] = limit;
 	}
 
+	if (limit > max_limit || limit < min_limit) {
+		dev_err(smu->adev->dev,
+			"New PPT limit (%d) is out of range [%d,%d]\n",
+			limit, min_limit, max_limit);
+		return -EINVAL;
+	}
+
+	if (!smu->ppt_funcs->set_ppt_limit)
+		return -EOPNOTSUPP;
+
+	ret = smu->ppt_funcs->set_ppt_limit(smu, limit_type, limit);
+	if (ret)
+		return ret;
+	if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
+		smu->user_dpm_profile.ppt_limits[limit_type] = limit;
+
 	return 0;
 }
 
@@ -3974,8 +3968,8 @@ static const struct amd_pm_funcs swsmu_pm_funcs = {
 	.dispatch_tasks          = smu_handle_dpm_task,
 	.load_firmware           = smu_load_microcode,
 	.set_powergating_by_smu  = smu_dpm_set_power_gate,
-	.set_power_limit         = smu_set_power_limit,
-	.get_power_limit         = smu_get_power_limit,
+	.set_power_limit         = smu_set_ppt_limit,
+	.get_power_limit         = smu_get_ppt_limit,
 	.get_power_profile_mode  = smu_get_power_profile_mode,
 	.set_power_profile_mode  = smu_set_power_profile_mode,
 	.odn_edit_dpm_table      = smu_od_edit_dpm_table,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index aab7eae1d268..3d32ee723b8e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -212,9 +212,12 @@ enum smu_power_src_type {
 };
 
 enum smu_ppt_limit_type {
-	SMU_DEFAULT_PPT_LIMIT = 0,
-	SMU_FAST_PPT_LIMIT,
+	SMU_PPT_LIMIT_PPT0 = 0,
+	SMU_PPT_LIMIT_PPT1,
 	SMU_LIMIT_TYPE_COUNT,
+	SMU_DEFAULT_PPT_LIMIT = SMU_PPT_LIMIT_PPT0,
+	SMU_SLOW_PPT_LIMIT = SMU_PPT_LIMIT_PPT0,
+	SMU_FAST_PPT_LIMIT = SMU_PPT_LIMIT_PPT1,
 };
 
 enum smu_ppt_limit_level {
@@ -224,6 +227,20 @@ enum smu_ppt_limit_level {
 	SMU_PPT_LIMIT_MAX,
 };
 
+struct smu_ppt_limit_range {
+	uint32_t default_value;
+	uint32_t min;
+	uint32_t max;
+	uint32_t od_min;
+	uint32_t od_max;
+};
+
+struct smu_ppt_limit_context {
+	struct smu_ppt_limit_range
+		range[SMU_POWER_SOURCE_COUNT][SMU_LIMIT_TYPE_COUNT];
+	uint32_t supported_mask;
+};
+
 enum smu_memory_pool_size {
     SMU_MEMORY_POOL_SIZE_ZERO   = 0,
     SMU_MEMORY_POOL_SIZE_256_MB = 0x10000000,
@@ -234,7 +251,7 @@ enum smu_memory_pool_size {
 
 struct smu_user_dpm_profile {
 	uint32_t fan_mode;
-	uint32_t power_limits[SMU_LIMIT_TYPE_COUNT];
+	uint32_t ppt_limits[SMU_LIMIT_TYPE_COUNT];
 	uint32_t fan_speed_pwm;
 	uint32_t fan_speed_rpm;
 	uint32_t flags;
@@ -721,10 +738,7 @@ struct smu_context {
 	uint32_t pstate_mclk;
 
 	bool od_enabled;
-	uint32_t current_power_limit;
-	uint32_t default_power_limit;
-	uint32_t max_power_limit;
-	uint32_t min_power_limit;
+	struct smu_ppt_limit_context ppt_limits;
 
 	/* soft pptable */
 	uint32_t ppt_offset_bytes;
@@ -1047,19 +1061,11 @@ struct pptable_funcs {
 	int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch);
 
 	/**
-	 * @get_power_limit: Get the device's power limits.
-	 */
-	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 *min_power_limit);
-
-	/**
-	 * @get_ppt_limit: Get the device's ppt limits.
+	 * @get_ppt_limit: Get the effective runtime PPT0 or PPT1 limit.
 	 */
-	int (*get_ppt_limit)(struct smu_context *smu, uint32_t *ppt_limit,
-			enum smu_ppt_limit_type limit_type, enum smu_ppt_limit_level limit_level);
+	int (*get_ppt_limit)(struct smu_context *smu,
+			     enum smu_ppt_limit_type limit_type,
+			     uint32_t *current_ppt_limit);
 
 	/**
 	 * @set_df_cstate: Set data fabric cstate.
@@ -1247,11 +1253,11 @@ struct pptable_funcs {
 	int (*notify_display_change)(struct smu_context *smu);
 
 	/**
-	 * @set_power_limit: Set power limit in watts.
+	 * @set_ppt_limit: Set the PPT0 or PPT1 limit in watts.
 	 */
-	int (*set_power_limit)(struct smu_context *smu,
-			       enum smu_ppt_limit_type limit_type,
-			       uint32_t limit);
+	int (*set_ppt_limit)(struct smu_context *smu,
+			     enum smu_ppt_limit_type limit_type,
+			     uint32_t limit);
 
 	/**
 	 * @init_max_sustainable_clocks: Populate max sustainable clock speed
@@ -1917,10 +1923,10 @@ smu_driver_table_update_cache_time(struct smu_context *smu,
 }
 
 #if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && !defined(SWSMU_CODE_LAYER_L4)
-int smu_get_power_limit(void *handle,
-			uint32_t *limit,
-			enum pp_power_limit_level pp_limit_level,
-			enum pp_power_type pp_power_type);
+int smu_get_ppt_limit(void *handle,
+		      uint32_t *limit,
+		      enum pp_power_limit_level pp_limit_level,
+		      enum pp_power_type pp_power_type);
 
 bool smu_mode1_reset_is_support(struct smu_context *smu);
 bool smu_link_reset_is_support(struct smu_context *smu);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
index c0accee9a9c8..9f20c631d2b7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
@@ -108,10 +108,6 @@ struct smu_11_5_power_context {
 	uint32_t	power_source;
 	uint8_t		in_power_limit_boost_mode;
 	enum smu_11_0_power_state power_state;
-
-	uint32_t	current_fast_ppt_limit;
-	uint32_t	default_fast_ppt_limit;
-	uint32_t	max_fast_ppt_limit;
 };
 
 #if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3)
@@ -151,12 +147,13 @@ int smu_v11_0_set_allowed_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_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit);
 
-int smu_v11_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit);
+int smu_v11_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit);
 
 int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu);
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
index 7f21f867d73c..5e7d80e8b26b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
@@ -145,12 +145,13 @@ int smu_v13_0_set_allowed_mask(struct smu_context *smu);
 
 int smu_v13_0_notify_display_change(struct smu_context *smu);
 
-int smu_v13_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit);
+int smu_v13_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit);
 
-int smu_v13_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit);
+int smu_v13_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit);
 
 int smu_v13_0_init_max_sustainable_clocks(struct smu_context *smu);
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
index dc8e13a7c879..dc222f3b3655 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
@@ -132,12 +132,13 @@ int smu_v14_0_set_allowed_mask(struct smu_context *smu);
 
 int smu_v14_0_notify_display_change(struct smu_context *smu);
 
-int smu_v14_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit);
+int smu_v14_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit);
 
-int smu_v14_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit);
+int smu_v14_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit);
 
 int smu_v14_0_gfx_off_control(struct smu_context *smu, bool enable);
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index 38e625cda97d..ec96dc775485 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -142,12 +142,13 @@ int smu_v15_0_set_allowed_mask(struct smu_context *smu);
 
 int smu_v15_0_notify_display_change(struct smu_context *smu);
 
-int smu_v15_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit);
+int smu_v15_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit);
 
-int smu_v15_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit);
+int smu_v15_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit);
 
 int smu_v15_0_gfx_off_control(struct smu_context *smu, bool enable);
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 87e45c700f6b..a40dabe63246 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -67,6 +67,8 @@
 
 #define SMU11_DRIVER_IF_VERSION_ARCT 0x17
 
+static int arcturus_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits arcturus_dpm_features = {
 	.bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_PREFETCHER_BIT),
 		  SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
@@ -544,7 +546,7 @@ static int arcturus_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return ret;
+	return arcturus_init_ppt_limits(smu);
 }
 
 static int arcturus_run_btc(struct smu_context *smu)
@@ -1259,14 +1261,21 @@ static int arcturus_get_fan_parameters(struct smu_context *smu)
 	return 0;
 }
 
-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 *min_power_limit)
+static int arcturus_get_ppt_limit(struct smu_context *smu,
+				 enum smu_ppt_limit_type limit_type,
+				 uint32_t *ppt_limit)
+{
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
+
+	return smu_v11_0_get_ppt_limit(smu, limit_type, ppt_limit);
+}
+
+static int arcturus_init_ppt_limits(struct smu_context *smu)
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
-	uint32_t current_limit, default_limit;
+	uint32_t default_limit;
+	int i;
 
 	if (!pptable) {
 		dev_err(smu->adev->dev,
@@ -1276,21 +1285,18 @@ static int arcturus_get_power_limit(struct smu_context *smu,
 
 	default_limit = pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
 
-	if (smu_v11_0_get_current_power_limit(smu, &current_limit))
-		current_limit = default_limit;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			default_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			default_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min = 0;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			default_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min = 0;
+	}
 
-	if (current_power_limit)
-		*current_power_limit = current_limit;
-	if (default_power_limit)
-		*default_power_limit = default_limit;
-	if (max_power_limit)
-		*max_power_limit = default_limit;
-	/*
-	 * No lower bound is imposed on the limit. Any unreasonable limit set
-	 * will result in frequent throttling.
-	 */
-	if (min_power_limit)
-		*min_power_limit = 0;
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
 
 	return 0;
 }
@@ -1892,7 +1898,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
 	.get_power_profile_mode = arcturus_get_power_profile_mode,
 	.set_power_profile_mode = arcturus_set_power_profile_mode,
 	.set_performance_level = arcturus_set_performance_level,
-	.get_power_limit = arcturus_get_power_limit,
+	.get_ppt_limit = arcturus_get_ppt_limit,
 	.is_dpm_running = arcturus_is_dpm_running,
 	.dpm_set_vcn_enable = arcturus_dpm_set_vcn_enable,
 	.i2c_init = arcturus_i2c_control_init,
@@ -1921,7 +1927,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
 	.feature_is_enabled = smu_cmn_feature_is_enabled,
 	.disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
 	.notify_display_change = NULL,
-	.set_power_limit = smu_v11_0_set_power_limit,
+	.set_ppt_limit = smu_v11_0_set_ppt_limit,
 	.init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
 	.enable_thermal_alert = smu_v11_0_enable_thermal_alert,
 	.disable_thermal_alert = smu_v11_0_disable_thermal_alert,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 09ab2b250287..8a562c08338b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -58,6 +58,8 @@
 #undef pr_info
 #undef pr_debug
 
+static int navi10_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits navi10_dpm_features = {
 	.bits = {
 		SMU_FEATURE_BIT_INIT(FEATURE_DPM_PREFETCHER_BIT),
@@ -488,7 +490,7 @@ static int navi10_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return ret;
+	return navi10_init_ppt_limits(smu);
 }
 
 static int navi10_tables_init(struct smu_context *smu)
@@ -2134,18 +2136,25 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
 	return ret;
 }
 
-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 *min_power_limit)
+static int navi10_get_ppt_limit(struct smu_context *smu,
+				enum smu_ppt_limit_type limit_type,
+				uint32_t *ppt_limit)
+{
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
+
+	return smu_v11_0_get_ppt_limit(smu, limit_type, ppt_limit);
+}
+
+static int navi10_init_ppt_limits(struct smu_context *smu)
 {
 	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 current_limit, default_limit;
+	uint32_t default_limit[SMU_POWER_SOURCE_COUNT];
 	uint32_t od_percent_upper = 0, od_percent_lower = 0;
+	int i;
 
 	if (!pptable) {
 		dev_err(smu->adev->dev,
@@ -2153,41 +2162,34 @@ static int navi10_get_power_limit(struct smu_context *smu,
 		return -EINVAL;
 	}
 
-	default_limit = smu->adev->pm.ac_power ?
-		pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+	default_limit[SMU_POWER_SOURCE_AC] =
+		pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+	default_limit[SMU_POWER_SOURCE_DC] =
 		pptable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
 
-	if (smu_v11_0_get_current_power_limit(smu, &current_limit))
-		current_limit = default_limit;
-
-	if (current_power_limit)
-		*current_power_limit = current_limit;
-	if (default_power_limit)
-		*default_power_limit = default_limit;
-
-	if (powerplay_table) {
-		if (smu->od_enabled &&
-			    navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
-			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 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
-			od_percent_upper = 0;
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
-		}
+	if (powerplay_table &&
+	    navi10_od_feature_is_supported(od_settings,
+					   SMU_11_0_ODCAP_POWER_LIMIT)) {
+		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]);
 	}
 
-	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-		 od_percent_upper, od_percent_lower, default_limit);
-
-	if (max_power_limit) {
-		*max_power_limit = default_limit * (100 + od_percent_upper);
-		*max_power_limit /= 100;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			default_limit[i];
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			default_limit[i];
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
+			default_limit[i] * (100 - od_percent_lower) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			default_limit[i] * (100 + od_percent_upper) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
 	}
 
-	if (min_power_limit) {
-		*min_power_limit = default_limit * (100 - od_percent_lower);
-		*min_power_limit /= 100;
-	}
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
 
 	return 0;
 }
@@ -3305,7 +3307,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
 	.set_performance_level = smu_v11_0_set_performance_level,
 	.get_thermal_temperature_range = navi10_get_thermal_temperature_range,
 	.display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
-	.get_power_limit = navi10_get_power_limit,
+	.get_ppt_limit = navi10_get_ppt_limit,
 	.update_pcie_parameters = navi10_update_pcie_parameters,
 	.init_microcode = smu_v11_0_init_microcode,
 	.load_microcode = smu_v11_0_load_microcode,
@@ -3329,7 +3331,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
 	.feature_is_enabled = smu_cmn_feature_is_enabled,
 	.disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
 	.notify_display_change = smu_v11_0_notify_display_change,
-	.set_power_limit = smu_v11_0_set_power_limit,
+	.set_ppt_limit = smu_v11_0_set_ppt_limit,
 	.init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
 	.enable_thermal_alert = smu_v11_0_enable_thermal_alert,
 	.disable_thermal_alert = smu_v11_0_disable_thermal_alert,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 682f68df64bd..a0f0e858e9de 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -60,6 +60,8 @@
 #undef pr_info
 #undef pr_debug
 
+static int sienna_cichlid_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits sienna_cichlid_dpm_features = {
 	.bits = {
 		SMU_FEATURE_BIT_INIT(FEATURE_DPM_PREFETCHER_BIT),
@@ -524,7 +526,11 @@ static int sienna_cichlid_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return sienna_cichlid_patch_pptable_quirk(smu);
+	ret = sienna_cichlid_patch_pptable_quirk(smu);
+	if (ret)
+		return ret;
+
+	return sienna_cichlid_init_ppt_limits(smu);
 }
 
 static int sienna_cichlid_tables_init(struct smu_context *smu)
@@ -624,57 +630,58 @@ static bool sienna_cichlid_is_od_feature_supported(struct smu_11_0_7_overdrive_t
 	return od_table->cap[cap];
 }
 
-static int sienna_cichlid_get_power_limit(struct smu_context *smu,
-					  uint32_t *current_power_limit,
-					  uint32_t *default_power_limit,
-					  uint32_t *max_power_limit,
-					  uint32_t *min_power_limit)
+static int sienna_cichlid_get_ppt_limit(struct smu_context *smu,
+					enum smu_ppt_limit_type limit_type,
+					uint32_t *ppt_limit)
+{
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
+
+	return smu_v11_0_get_ppt_limit(smu, limit_type, ppt_limit);
+}
+
+static int sienna_cichlid_init_ppt_limits(struct smu_context *smu)
 {
 	struct smu_11_0_7_powerplay_table *powerplay_table =
 		(struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
 	struct smu_11_0_7_overdrive_table *od_settings = smu->od_settings;
-	uint32_t current_limit, default_limit;
+	uint32_t default_limit[SMU_POWER_SOURCE_COUNT];
 	uint32_t od_percent_upper = 0, od_percent_lower = 0;
-	u16 *power_limit_ac, *power_limit_dc;
-
-	GET_PPTABLE_MEMBER(SocketPowerLimitAc, &power_limit_ac);
-	GET_PPTABLE_MEMBER(SocketPowerLimitDc, &power_limit_dc);
-
-	default_limit = smu->adev->pm.ac_power ?
-		power_limit_ac[PPT_THROTTLER_PPT0] :
-		power_limit_dc[PPT_THROTTLER_PPT0];
-
-	if (smu_v11_0_get_current_power_limit(smu, &current_limit))
-		current_limit = default_limit;
-
-	if (current_power_limit)
-		*current_power_limit = current_limit;
-	if (default_power_limit)
-		*default_power_limit = default_limit;
-
-	if (powerplay_table) {
-		if (smu->od_enabled &&
-				sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_POWER_LIMIT)) {
-			od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
-		} else if ((sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_POWER_LIMIT))) {
-			od_percent_upper = 0;
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
-		}
-	}
+	uint16_t *ppt_limit_ac, *ppt_limit_dc;
+	int i;
+
+	GET_PPTABLE_MEMBER(SocketPowerLimitAc, &ppt_limit_ac);
+	GET_PPTABLE_MEMBER(SocketPowerLimitDc, &ppt_limit_dc);
 
-	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-		 od_percent_upper, od_percent_lower, default_limit);
+	default_limit[SMU_POWER_SOURCE_AC] =
+		ppt_limit_ac[PPT_THROTTLER_PPT0];
+	default_limit[SMU_POWER_SOURCE_DC] =
+		ppt_limit_dc[PPT_THROTTLER_PPT0];
 
-	if (max_power_limit) {
-		*max_power_limit = default_limit * (100 + od_percent_upper);
-		*max_power_limit /= 100;
+	if (powerplay_table &&
+	    sienna_cichlid_is_od_feature_supported(od_settings,
+						     SMU_11_0_7_ODCAP_POWER_LIMIT)) {
+		od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[
+			SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
+		od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[
+			SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
 	}
 
-	if (min_power_limit) {
-		*min_power_limit = default_limit * (100 - od_percent_lower);
-		*min_power_limit /= 100;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			default_limit[i];
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			default_limit[i];
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
+			default_limit[i] * (100 - od_percent_lower) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			default_limit[i] * (100 + od_percent_upper) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
 	}
+
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
+
 	return 0;
 }
 
@@ -687,22 +694,29 @@ static void sienna_cichlid_get_smartshift_power_percentage(struct smu_context *s
 		&(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics_V4);
 	uint16_t powerRatio = 0;
 	uint16_t apu_power_limit = 0;
-	uint16_t dgpu_power_limit = 0;
+	uint16_t dgpu_ppt_limit = 0;
 	uint32_t apu_boost = 0;
 	uint32_t dgpu_boost = 0;
-	uint32_t cur_power_limit;
+	uint32_t cur_ppt_limit;
+	enum smu_power_src_type power_source;
 
 	if (metrics_v4->ApuSTAPMSmartShiftLimit != 0) {
-		sienna_cichlid_get_power_limit(smu, &cur_power_limit, NULL, NULL, NULL);
+		if (sienna_cichlid_get_ppt_limit(smu, SMU_PPT_LIMIT_PPT0,
+						 &cur_ppt_limit)) {
+			power_source = smu->adev->pm.ac_power ?
+				SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC;
+			cur_ppt_limit = smu->ppt_limits.range[power_source]
+				[SMU_PPT_LIMIT_PPT0].default_value;
+		}
 		apu_power_limit = metrics_v4->ApuSTAPMLimit;
-		dgpu_power_limit = cur_power_limit;
+		dgpu_ppt_limit = cur_ppt_limit;
 		powerRatio = (((apu_power_limit +
-						  dgpu_power_limit) * 100) /
+						  dgpu_ppt_limit) * 100) /
 						  metrics_v4->ApuSTAPMSmartShiftLimit);
 		if (powerRatio > 100) {
 			apu_power_limit = (apu_power_limit * 100) /
 									 powerRatio;
-			dgpu_power_limit = (dgpu_power_limit * 100) /
+			dgpu_ppt_limit = (dgpu_ppt_limit * 100) /
 									  powerRatio;
 		}
 		if (metrics_v4->AverageApuSocketPower > apu_power_limit &&
@@ -714,11 +728,11 @@ static void sienna_cichlid_get_smartshift_power_percentage(struct smu_context *s
 				apu_boost = 100;
 		}
 
-		if (metrics_v4->AverageSocketPower > dgpu_power_limit &&
-			 dgpu_power_limit != 0) {
+		if (metrics_v4->AverageSocketPower > dgpu_ppt_limit &&
+			 dgpu_ppt_limit != 0) {
 			dgpu_boost = ((metrics_v4->AverageSocketPower -
-							 dgpu_power_limit) * 100) /
-							 dgpu_power_limit;
+							 dgpu_ppt_limit) * 100) /
+							 dgpu_ppt_limit;
 			if (dgpu_boost > 100)
 				dgpu_boost = 100;
 		}
@@ -3113,7 +3127,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
 	.set_performance_level = smu_v11_0_set_performance_level,
 	.get_thermal_temperature_range = sienna_cichlid_get_thermal_temperature_range,
 	.display_disable_memory_clock_switch = sienna_cichlid_display_disable_memory_clock_switch,
-	.get_power_limit = sienna_cichlid_get_power_limit,
+	.get_ppt_limit = sienna_cichlid_get_ppt_limit,
 	.update_pcie_parameters = sienna_cichlid_update_pcie_parameters,
 	.init_microcode = smu_v11_0_init_microcode,
 	.load_microcode = smu_v11_0_load_microcode,
@@ -3137,7 +3151,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
 	.feature_is_enabled = smu_cmn_feature_is_enabled,
 	.disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
 	.notify_display_change = NULL,
-	.set_power_limit = smu_v11_0_set_power_limit,
+	.set_ppt_limit = smu_v11_0_set_ppt_limit,
 	.init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
 	.enable_thermal_alert = smu_v11_0_enable_thermal_alert,
 	.disable_thermal_alert = smu_v11_0_disable_thermal_alert,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index a889d846e9c5..f0b2e7da67b1 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -770,14 +770,17 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
 	return 0;
 }
 
-int smu_v11_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit)
+int smu_v11_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit)
 {
 	int power_src;
 	int ret = 0;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
 		return -EINVAL;
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
 
 	power_src = smu_cmn_to_asic_specific_index(smu,
 					CMN2ASIC_MAPPING_PWR,
@@ -794,26 +797,26 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
 	ret = smu_cmn_send_smc_msg_with_param(smu,
 					  SMU_MSG_GetPptLimit,
 					  (0 << 24) | (power_src << 16),
-					  power_limit);
+					  ppt_limit);
 	if (ret)
 		dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
 
 	return ret;
 }
 
-int smu_v11_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit)
+int smu_v11_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit)
 {
 	int power_src;
 	int ret = 0;
 	uint32_t limit_param;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
-		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
+		dev_err(smu->adev->dev, "Setting new PPT limit is not supported!\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -835,12 +838,10 @@ int smu_v11_0_set_power_limit(struct smu_context *smu,
 	limit_param |= (power_src) << 16;
 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit_param, NULL);
 	if (ret) {
-		dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
+		dev_err(smu->adev->dev, "[%s] Set PPT limit failed!\n", __func__);
 		return ret;
 	}
 
-	smu->current_power_limit = limit;
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index 3e3c68448ba9..b38bc49c43dd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -58,6 +58,8 @@
 #define SMUIO_GFX_MISC_CNTL__SMU_GFX_cold_vs_gfxoff_MASK	0x00000001L
 #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK		0x00000006L
 
+static int vangogh_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits vangogh_dpm_features = {
 	.bits = {
 		SMU_FEATURE_BIT_INIT(FEATURE_CCLK_DPM_BIT),
@@ -2243,6 +2245,10 @@ static int vangogh_post_smu_init(struct smu_context *smu)
 	if (adev->in_s0ix)
 		return 0;
 
+	ret = vangogh_init_ppt_limits(smu);
+	if (ret)
+		return ret;
+
 	/* allow message will be sent after enable message on Vangogh*/
 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
 			(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
@@ -2322,91 +2328,75 @@ static u32 vangogh_get_gfxoff_status(struct smu_context *smu)
 	return gfxoff_status;
 }
 
-static int vangogh_get_power_limit(struct smu_context *smu,
-				   uint32_t *current_power_limit,
-				   uint32_t *default_power_limit,
-				   uint32_t *max_power_limit,
-				   uint32_t *min_power_limit)
+static int vangogh_get_ppt_limit(struct smu_context *smu,
+				 enum smu_ppt_limit_type limit_type,
+				 uint32_t *ppt_limit)
 {
-	struct smu_11_5_power_context *power_context = smu->smu_power.power_context;
-	uint32_t ppt_limit;
-	int ret = 0;
+	enum smu_message_type msg;
+	uint32_t raw_limit;
+	int ret;
 
 	if (smu->adev->pm.fw_version < 0x43f1e00)
-		return ret;
+		return -EOPNOTSUPP;
 
-	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSlowPPTLimit, &ppt_limit);
-	if (ret) {
-		dev_err(smu->adev->dev, "Get slow PPT limit failed!\n");
-		return ret;
-	}
-	/* convert from milliwatt to watt */
-	if (current_power_limit)
-		*current_power_limit = ppt_limit / 1000;
-	if (default_power_limit)
-		*default_power_limit = ppt_limit / 1000;
-	if (max_power_limit)
-		*max_power_limit = 29;
-	if (min_power_limit)
-		*min_power_limit = 0;
-
-	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit);
+	msg = limit_type == SMU_PPT_LIMIT_PPT1 ?
+		SMU_MSG_GetFastPPTLimit : SMU_MSG_GetSlowPPTLimit;
+	ret = smu_cmn_send_smc_msg(smu, msg, &raw_limit);
 	if (ret) {
-		dev_err(smu->adev->dev, "Get fast PPT limit failed!\n");
+		dev_err(smu->adev->dev, "Get PPT%d limit failed!\n",
+			limit_type);
 		return ret;
 	}
-	/* convert from milliwatt to watt */
-	power_context->current_fast_ppt_limit =
-			power_context->default_fast_ppt_limit = ppt_limit / 1000;
-	power_context->max_fast_ppt_limit = 30;
 
-	return ret;
+	*ppt_limit = raw_limit / 1000;
+
+	return 0;
 }
 
-static int vangogh_get_ppt_limit(struct smu_context *smu,
-				 uint32_t *ppt_limit,
-				 enum smu_ppt_limit_type type,
-				 enum smu_ppt_limit_level level)
+static int vangogh_init_ppt_limits(struct smu_context *smu)
 {
-	struct smu_11_5_power_context *power_context = smu->smu_power.power_context;
+	struct smu_ppt_limit_range *range;
+	uint32_t default_limit;
+	int i, j, ret;
 
-	if (!power_context)
-		return -EOPNOTSUPP;
+	if (smu->adev->pm.fw_version < 0x43f1e00)
+		return 0;
 
-	if (type == SMU_FAST_PPT_LIMIT) {
-		switch (level) {
-		case SMU_PPT_LIMIT_MAX:
-			*ppt_limit = power_context->max_fast_ppt_limit;
-			break;
-		case SMU_PPT_LIMIT_CURRENT:
-			*ppt_limit = power_context->current_fast_ppt_limit;
-			break;
-		case SMU_PPT_LIMIT_DEFAULT:
-			*ppt_limit = power_context->default_fast_ppt_limit;
-			break;
-		default:
-			break;
+	for (i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) {
+		if (smu->ppt_limits.supported_mask & BIT(i))
+			continue;
+
+		ret = vangogh_get_ppt_limit(smu, i, &default_limit);
+		if (ret)
+			return ret;
+
+		for (j = SMU_POWER_SOURCE_AC; j < SMU_POWER_SOURCE_COUNT; j++) {
+			range = &smu->ppt_limits.range[j][i];
+			range->default_value = default_limit;
+			range->min = 0;
+			range->max = i == SMU_PPT_LIMIT_PPT1 ? 30 : 29;
+			range->od_min = range->min;
+			range->od_max = range->max;
 		}
+		smu->ppt_limits.supported_mask |= BIT(i);
 	}
 
 	return 0;
 }
 
-static int vangogh_set_power_limit(struct smu_context *smu,
-				   enum smu_ppt_limit_type limit_type,
-				   uint32_t ppt_limit)
+static int vangogh_set_ppt_limit(struct smu_context *smu,
+				 enum smu_ppt_limit_type limit_type,
+				 uint32_t ppt_limit)
 {
-	struct smu_11_5_power_context *power_context =
-			smu->smu_power.power_context;
 	int ret = 0;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
-		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
+		dev_err(smu->adev->dev, "Setting new PPT limit is not supported!\n");
 		return -EOPNOTSUPP;
 	}
 
 	switch (limit_type) {
-	case SMU_DEFAULT_PPT_LIMIT:
+	case SMU_SLOW_PPT_LIMIT:
 		ret = smu_cmn_send_smc_msg_with_param(smu,
 				SMU_MSG_SetSlowPPTLimit,
 				ppt_limit * 1000, /* convert from watt to milliwatt */
@@ -2414,16 +2404,8 @@ static int vangogh_set_power_limit(struct smu_context *smu,
 		if (ret)
 			return ret;
 
-		smu->current_power_limit = ppt_limit;
 		break;
 	case SMU_FAST_PPT_LIMIT:
-		if (ppt_limit > power_context->max_fast_ppt_limit) {
-			dev_err(smu->adev->dev,
-				"New power limit (%d) is over the max allowed %d\n",
-				ppt_limit, power_context->max_fast_ppt_limit);
-			return ret;
-		}
-
 		ret = smu_cmn_send_smc_msg_with_param(smu,
 				SMU_MSG_SetFastPPTLimit,
 				ppt_limit * 1000, /* convert from watt to milliwatt */
@@ -2431,7 +2413,6 @@ static int vangogh_set_power_limit(struct smu_context *smu,
 		if (ret)
 			return ret;
 
-		power_context->current_fast_ppt_limit = ppt_limit;
 		break;
 	default:
 		return -EINVAL;
@@ -2577,8 +2558,7 @@ static const struct pptable_funcs vangogh_ppt_funcs = {
 	.get_gfx_off_residency = vangogh_get_gfxoff_residency,
 	.set_gfx_off_residency = vangogh_set_gfxoff_residency,
 	.get_ppt_limit = vangogh_get_ppt_limit,
-	.get_power_limit = vangogh_get_power_limit,
-	.set_power_limit = vangogh_set_power_limit,
+	.set_ppt_limit = vangogh_set_ppt_limit,
 	.get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
 };
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
index aec46382c264..1aa589bdc301 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -61,6 +61,9 @@
 	[smu_feature] = {1, (aldebaran_feature)}
 
 #define FEATURE_MASK(feature) (1ULL << feature)
+
+static int aldebaran_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits aldebaran_dpm_features = {
 	.bits = {
 		SMU_FEATURE_BIT_INIT(FEATURE_DATA_CALCULATIONS),
@@ -537,7 +540,7 @@ static int aldebaran_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return ret;
+	return aldebaran_init_ppt_limits(smu);
 }
 
 static bool aldebaran_is_primary(struct smu_context *smu)
@@ -1111,28 +1114,17 @@ static int aldebaran_read_sensor(struct smu_context *smu,
 	return ret;
 }
 
-static int aldebaran_get_power_limit(struct smu_context *smu,
-						uint32_t *current_power_limit,
-						uint32_t *default_power_limit,
-						uint32_t *max_power_limit,
-						uint32_t *min_power_limit)
+static int aldebaran_get_ppt_limit(struct smu_context *smu,
+				   enum smu_ppt_limit_type limit_type,
+				   uint32_t *ppt_limit)
 {
-	PPTable_t *pptable = smu->smu_table.driver_pptable;
-	uint32_t power_limit = 0;
 	int ret;
 
-	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
-		if (current_power_limit)
-			*current_power_limit = 0;
-		if (default_power_limit)
-			*default_power_limit = 0;
-		if (max_power_limit)
-			*max_power_limit = 0;
-		if (min_power_limit)
-			*min_power_limit = 0;
-		dev_warn(smu->adev->dev,
-			"PPT feature is not enabled, power values can't be fetched.");
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
 
+	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+		*ppt_limit = 0;
 		return 0;
 	}
 
@@ -1141,46 +1133,47 @@ static int aldebaran_get_power_limit(struct smu_context *smu,
 	 */
 	if (aldebaran_is_primary(smu)) {
 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit,
-					   &power_limit);
-
-		if (ret) {
-			/* 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;
-			}
-			power_limit = pptable->PptLimit;
-		}
+					   ppt_limit);
+		if (ret)
+			return ret;
+	} else {
+		*ppt_limit = 0;
 	}
 
-	if (current_power_limit)
-		*current_power_limit = power_limit;
-	if (default_power_limit) {
-		if (pptable)
-			*default_power_limit = pptable->PptLimit;
-		else
-			*default_power_limit = power_limit;
-	}
+	return 0;
+}
+
+static int aldebaran_init_ppt_limits(struct smu_context *smu)
+{
+	PPTable_t *pptable = smu->smu_table.driver_pptable;
+	int i;
+
+	if (!pptable)
+		return -EINVAL;
 
-	if (max_power_limit) {
-		if (pptable)
-			*max_power_limit = pptable->PptLimit;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			pptable->PptLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min = 0;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			pptable->PptLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min = 0;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			pptable->PptLimit;
 	}
 
-	if (min_power_limit)
-		*min_power_limit = 0;
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
 
 	return 0;
 }
 
-static int aldebaran_set_power_limit(struct smu_context *smu,
-				     enum smu_ppt_limit_type limit_type,
-				     uint32_t limit)
+static int aldebaran_set_ppt_limit(struct smu_context *smu,
+				   enum smu_ppt_limit_type limit_type,
+				   uint32_t limit)
 {
-	/* Power limit can be set only through primary die */
+	/* PPT limit can be set only through primary die */
 	if (aldebaran_is_primary(smu))
-		return smu_v13_0_set_power_limit(smu, limit_type, limit);
+		return smu_v13_0_set_ppt_limit(smu, limit_type, limit);
 
 	return -EINVAL;
 }
@@ -1980,7 +1973,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = {
 	.force_clk_levels = aldebaran_force_clk_levels,
 	.read_sensor = aldebaran_read_sensor,
 	.set_performance_level = aldebaran_set_performance_level,
-	.get_power_limit = aldebaran_get_power_limit,
+	.get_ppt_limit = aldebaran_get_ppt_limit,
 	.is_dpm_running = aldebaran_is_dpm_running,
 	.get_unique_id = aldebaran_get_unique_id,
 	.init_microcode = smu_v13_0_init_microcode,
@@ -2003,7 +1996,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = {
 	.get_enabled_mask = smu_cmn_get_enabled_mask,
 	.feature_is_enabled = smu_cmn_feature_is_enabled,
 	.disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
-	.set_power_limit = aldebaran_set_power_limit,
+	.set_ppt_limit = aldebaran_set_ppt_limit,
 	.init_max_sustainable_clocks = smu_v13_0_init_max_sustainable_clocks,
 	.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
 	.disable_thermal_alert = smu_v13_0_disable_thermal_alert,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index 4f10bce36756..c4b2fe60da62 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -815,14 +815,17 @@ int smu_v13_0_init_max_sustainable_clocks(struct smu_context *smu)
 	return 0;
 }
 
-int smu_v13_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit)
+int smu_v13_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit)
 {
 	int power_src;
 	int ret = 0;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
 		return -EINVAL;
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
 
 	power_src = smu_cmn_to_asic_specific_index(smu,
 						   CMN2ASIC_MAPPING_PWR,
@@ -835,35 +838,33 @@ int smu_v13_0_get_current_power_limit(struct smu_context *smu,
 	ret = smu_cmn_send_smc_msg_with_param(smu,
 					      SMU_MSG_GetPptLimit,
 					      power_src << 16,
-					      power_limit);
+					      ppt_limit);
 	if (ret)
 		dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
 
 	return ret;
 }
 
-int smu_v13_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit)
+int smu_v13_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit)
 {
 	int ret = 0;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
-		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
+		dev_err(smu->adev->dev, "Setting new PPT limit is not supported!\n");
 		return -EOPNOTSUPP;
 	}
 
 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit, NULL);
 	if (ret) {
-		dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
+		dev_err(smu->adev->dev, "[%s] Set PPT limit failed!\n", __func__);
 		return ret;
 	}
 
-	smu->current_power_limit = limit;
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 850db43fe948..95257d5378b8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -62,6 +62,7 @@
 static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
 					      int od_feature_bit,
 					      int32_t *min, int32_t *max);
+static int smu_v13_0_0_init_ppt_limits(struct smu_context *smu);
 
 static const struct smu_feature_bits smu_v13_0_0_dpm_features = {
 	.bits = {
@@ -467,7 +468,7 @@ static int smu_v13_0_0_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return ret;
+	return smu_v13_0_0_init_ppt_limits(smu);
 }
 
 static int smu_v13_0_0_tables_init(struct smu_context *smu)
@@ -2389,58 +2390,65 @@ static int smu_v13_0_0_enable_mgpu_fan_boost(struct smu_context *smu)
 					       NULL);
 }
 
-static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
-				       uint32_t *current_power_limit,
-				       uint32_t *default_power_limit,
-				       uint32_t *max_power_limit,
-				       uint32_t *min_power_limit)
+static int smu_v13_0_0_get_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t *ppt_limit)
+{
+	PPTable_t *pptable = smu->smu_table.driver_pptable;
+	SkuTable_t *skutable = &pptable->SkuTable;
+	uint32_t pp_limit = smu->adev->pm.ac_power ?
+		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
+
+	if (smu_v13_0_get_ppt_limit(smu, limit_type, ppt_limit))
+		*ppt_limit = pp_limit;
+
+	return 0;
+}
+
+static int smu_v13_0_0_init_ppt_limits(struct smu_context *smu)
 {
 	struct smu_table_context *table_context = &smu->smu_table;
 	struct smu_13_0_0_powerplay_table *powerplay_table =
 		(struct smu_13_0_0_powerplay_table *)table_context->power_play_table;
 	PPTable_t *pptable = table_context->driver_pptable;
 	SkuTable_t *skutable = &pptable->SkuTable;
-	uint32_t pp_limit = smu->adev->pm.ac_power ?
-			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-	uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
-	uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
 	uint32_t od_percent_upper = 0, od_percent_lower = 0;
-	int ret;
-
-	if (current_power_limit) {
-		ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
-		if (ret)
-			*current_power_limit = pp_limit;
-	}
+	uint32_t pp_limit, msg_limit, min_limit, max_limit;
+	int i;
 
-	if (default_power_limit)
-		*default_power_limit = pp_limit;
-
-	if (powerplay_table) {
-		if (smu->od_enabled &&
-				smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
-			od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
-		} else if (smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
-			od_percent_upper = 0;
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
-		}
+	if (powerplay_table &&
+	    smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
+		od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[
+			SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
+		od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[
+			SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
 	}
 
-	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-		od_percent_upper, od_percent_lower, pp_limit);
-
-	if (max_power_limit) {
-		*max_power_limit = max_limit * (100 + od_percent_upper);
-		*max_power_limit /= 100;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		pp_limit = i == SMU_POWER_SOURCE_AC ?
+			skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+			skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+		msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][i];
+		min_limit = min(pp_limit, msg_limit);
+		max_limit = max(pp_limit, msg_limit);
+
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			pp_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			max_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
+			min_limit * (100 - od_percent_lower) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			max_limit * (100 + od_percent_upper) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
 	}
 
-	if (min_power_limit) {
-		*min_power_limit = min_limit * (100 - od_percent_lower);
-		*min_power_limit /= 100;
-	}
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
 
 	return 0;
 }
@@ -3031,9 +3039,9 @@ static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu)
 	}
 }
 
-static int smu_v13_0_0_set_power_limit(struct smu_context *smu,
-				       enum smu_ppt_limit_type limit_type,
-				       uint32_t limit)
+static int smu_v13_0_0_set_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t limit)
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
 	SkuTable_t *skutable = &pptable->SkuTable;
@@ -3041,13 +3049,18 @@ static int smu_v13_0_0_set_power_limit(struct smu_context *smu,
 	struct smu_table_context *table_context = &smu->smu_table;
 	OverDriveTableExternal_t *od_table =
 		(OverDriveTableExternal_t *)table_context->overdrive_table;
+	uint32_t current_limit;
 	int ret = 0;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
+	ret = smu_v13_0_0_get_ppt_limit(smu, limit_type, &current_limit);
+	if (ret)
+		return ret;
+
 	if (limit <= msg_limit) {
-		if (smu->current_power_limit > msg_limit) {
+		if (current_limit > msg_limit) {
 			od_table->OverDriveTable.Ppt = 0;
 			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
 
@@ -3057,9 +3070,9 @@ static int smu_v13_0_0_set_power_limit(struct smu_context *smu,
 				return ret;
 			}
 		}
-		return smu_v13_0_set_power_limit(smu, limit_type, limit);
+			return smu_v13_0_set_ppt_limit(smu, limit_type, limit);
 	} else if (smu->od_enabled) {
-		ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit);
+		ret = smu_v13_0_set_ppt_limit(smu, limit_type, msg_limit);
 		if (ret)
 			return ret;
 
@@ -3072,7 +3085,6 @@ static int smu_v13_0_0_set_power_limit(struct smu_context *smu,
 		  return ret;
 		}
 
-		smu->current_power_limit = limit;
 	} else {
 		return -EINVAL;
 	}
@@ -3215,8 +3227,8 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
 	.get_fan_control_mode = smu_v13_0_get_fan_control_mode,
 	.set_fan_control_mode = smu_v13_0_set_fan_control_mode,
 	.enable_mgpu_fan_boost = smu_v13_0_0_enable_mgpu_fan_boost,
-	.get_power_limit = smu_v13_0_0_get_power_limit,
-	.set_power_limit = smu_v13_0_0_set_power_limit,
+	.get_ppt_limit = smu_v13_0_0_get_ppt_limit,
+	.set_ppt_limit = smu_v13_0_0_set_ppt_limit,
 	.set_power_source = smu_v13_0_set_power_source,
 	.get_power_profile_mode = smu_v13_0_0_get_power_profile_mode,
 	.set_power_profile_mode = smu_v13_0_0_set_power_profile_mode,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index a392795aae30..f45b1744868c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -74,6 +74,9 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_14.bin");
 	[smu_feature] = { 1, (smu_13_0_6_feature) }
 
 #define FEATURE_MASK(feature) (1ULL << feature)
+
+static int smu_v13_0_6_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits smu_v13_0_6_dpm_features = {
 	.bits = {
 		SMU_FEATURE_BIT_INIT(FEATURE_DATA_CALCULATION),
@@ -1170,7 +1173,7 @@ static int smu_v13_0_6_set_default_dpm_table(struct smu_context *smu)
 		}
 	}
 
-	return 0;
+	return smu_v13_0_6_init_ppt_limits(smu);
 }
 
 static int smu_v13_0_6_setup_pptable(struct smu_context *smu)
@@ -1719,54 +1722,82 @@ static int smu_v13_0_6_read_sensor(struct smu_context *smu,
 	return ret;
 }
 
-static int smu_v13_0_6_get_power_limit(struct smu_context *smu,
-						uint32_t *current_power_limit,
-						uint32_t *default_power_limit,
-						uint32_t *max_power_limit,
-						uint32_t *min_power_limit)
+static int smu_v13_0_6_get_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t *ppt_limit)
 {
-	struct smu_table_context *smu_table = &smu->smu_table;
-	struct PPTable_t *pptable =
-		(struct PPTable_t *)smu_table->driver_pptable;
-	uint32_t power_limit = 0;
 	int ret;
 
-	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, &power_limit);
-
+	if (limit_type == SMU_PPT_LIMIT_PPT1) {
+		if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(FAST_PPT)))
+			return -EOPNOTSUPP;
+		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPptLimit,
+					       ppt_limit);
+	} else {
+		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit,
+					       ppt_limit);
+	}
 	if (ret) {
 		dev_err(smu->adev->dev, "Couldn't get PPT limit");
 		return -EINVAL;
 	}
 
-	if (current_power_limit)
-		*current_power_limit = power_limit;
-	if (default_power_limit)
-		*default_power_limit = pptable->MaxSocketPowerLimit;
+	return 0;
+}
 
-	if (max_power_limit) {
-		*max_power_limit = pptable->MaxSocketPowerLimit;
+static int smu_v13_0_6_init_ppt_limits(struct smu_context *smu)
+{
+	struct smu_table_context *smu_table = &smu->smu_table;
+	struct PPTable_t *pptable =
+		(struct PPTable_t *)smu_table->driver_pptable;
+	int i;
+
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			pptable->MaxSocketPowerLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			pptable->MaxSocketPowerLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min = 0;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			pptable->MaxSocketPowerLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min = 0;
+	}
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
+
+	if (smu_v13_0_6_cap_supported(smu, SMU_CAP(FAST_PPT))) {
+		for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].default_value =
+				pptable->PPT1Default;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].max =
+				pptable->PPT1Max;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].min =
+				pptable->PPT1Min;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].od_max =
+				pptable->PPT1Max;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].od_min =
+				pptable->PPT1Min;
+		}
+		smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT1);
 	}
 
-	if (min_power_limit)
-		*min_power_limit = 0;
 	return 0;
 }
 
-static int smu_v13_0_6_set_power_limit(struct smu_context *smu,
-				       enum smu_ppt_limit_type limit_type,
-				       uint32_t limit)
+static int smu_v13_0_6_set_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t limit)
 {
 	struct smu_table_context *smu_table = &smu->smu_table;
 	struct PPTable_t *pptable =
 		(struct PPTable_t *)smu_table->driver_pptable;
 	int ret;
 
-	if (limit_type == SMU_FAST_PPT_LIMIT) {
+	if (limit_type == SMU_PPT_LIMIT_PPT1) {
 		if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(FAST_PPT)))
 			return -EOPNOTSUPP;
 		if (limit > pptable->PPT1Max || limit < pptable->PPT1Min) {
 			dev_err(smu->adev->dev,
-				"New power limit (%d) should be between min %d max %d\n",
+				"New PPT limit (%d) should be between min %d max %d\n",
 				limit, pptable->PPT1Min, pptable->PPT1Max);
 			return -EINVAL;
 		}
@@ -1777,43 +1808,7 @@ static int smu_v13_0_6_set_power_limit(struct smu_context *smu,
 		return ret;
 	}
 
-	return smu_v13_0_set_power_limit(smu, limit_type, limit);
-}
-
-static int smu_v13_0_6_get_ppt_limit(struct smu_context *smu,
-				     uint32_t *ppt_limit,
-				     enum smu_ppt_limit_type type,
-				     enum smu_ppt_limit_level level)
-{
-	struct smu_table_context *smu_table = &smu->smu_table;
-	struct PPTable_t *pptable =
-		(struct PPTable_t *)smu_table->driver_pptable;
-	int ret = 0;
-
-	if (type == SMU_FAST_PPT_LIMIT) {
-		if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(FAST_PPT)))
-			return -EOPNOTSUPP;
-		switch (level) {
-		case SMU_PPT_LIMIT_MAX:
-			*ppt_limit = pptable->PPT1Max;
-			break;
-		case SMU_PPT_LIMIT_CURRENT:
-			ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPptLimit, ppt_limit);
-			if (ret)
-				dev_err(smu->adev->dev, "Get fast PPT limit failed!\n");
-			break;
-		case SMU_PPT_LIMIT_DEFAULT:
-			*ppt_limit = pptable->PPT1Default;
-			break;
-		case SMU_PPT_LIMIT_MIN:
-			*ppt_limit = pptable->PPT1Min;
-			break;
-		default:
-			return -EOPNOTSUPP;
-		}
-		return ret;
-	}
-	return -EOPNOTSUPP;
+	return smu_v13_0_set_ppt_limit(smu, limit_type, limit);
 }
 
 static int smu_v13_0_6_irq_process(struct amdgpu_device *adev,
@@ -3312,7 +3307,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = {
 	.force_clk_levels = smu_v13_0_6_force_clk_levels,
 	.read_sensor = smu_v13_0_6_read_sensor,
 	.set_performance_level = smu_v13_0_6_set_performance_level,
-	.get_power_limit = smu_v13_0_6_get_power_limit,
+	.get_ppt_limit = smu_v13_0_6_get_ppt_limit,
 	.is_dpm_running = smu_v13_0_6_is_dpm_running,
 	.get_unique_id = smu_v13_0_6_get_unique_id,
 	.init_microcode = smu_v13_0_6_init_microcode,
@@ -3330,8 +3325,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = {
 	.system_features_control = smu_v13_0_6_system_features_control,
 	.get_enabled_mask = smu_v13_0_6_get_enabled_mask,
 	.feature_is_enabled = smu_cmn_feature_is_enabled,
-	.set_power_limit = smu_v13_0_6_set_power_limit,
-	.get_ppt_limit = smu_v13_0_6_get_ppt_limit,
+	.set_ppt_limit = smu_v13_0_6_set_ppt_limit,
 	.set_xgmi_pstate = smu_v13_0_set_xgmi_pstate,
 	.register_irq_handler = smu_v13_0_6_register_irq_handler,
 	.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index 4deb987e43e0..6e0a27eec610 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -62,6 +62,7 @@
 static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
 					      int od_feature_bit,
 					      int32_t *min, int32_t *max);
+static int smu_v13_0_7_init_ppt_limits(struct smu_context *smu);
 
 static const struct smu_feature_bits smu_v13_0_7_dpm_features = {
 	.bits = {
@@ -503,7 +504,7 @@ static int smu_v13_0_7_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return ret;
+	return smu_v13_0_7_init_ppt_limits(smu);
 }
 
 static int smu_v13_0_7_tables_init(struct smu_context *smu)
@@ -2371,58 +2372,65 @@ static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu)
 					       NULL);
 }
 
-static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
-				       uint32_t *current_power_limit,
-				       uint32_t *default_power_limit,
-				       uint32_t *max_power_limit,
-				       uint32_t *min_power_limit)
+static int smu_v13_0_7_get_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t *ppt_limit)
+{
+	PPTable_t *pptable = smu->smu_table.driver_pptable;
+	SkuTable_t *skutable = &pptable->SkuTable;
+	uint32_t pp_limit = smu->adev->pm.ac_power ?
+		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
+
+	if (smu_v13_0_get_ppt_limit(smu, limit_type, ppt_limit))
+		*ppt_limit = pp_limit;
+
+	return 0;
+}
+
+static int smu_v13_0_7_init_ppt_limits(struct smu_context *smu)
 {
 	struct smu_table_context *table_context = &smu->smu_table;
 	struct smu_13_0_7_powerplay_table *powerplay_table =
 		(struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
 	PPTable_t *pptable = table_context->driver_pptable;
 	SkuTable_t *skutable = &pptable->SkuTable;
-	uint32_t pp_limit = smu->adev->pm.ac_power ?
-			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-	uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
-	uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
 	uint32_t od_percent_upper = 0, od_percent_lower = 0;
-	int ret;
-
-	if (current_power_limit) {
-		ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
-		if (ret)
-			*current_power_limit = pp_limit;
-	}
+	uint32_t pp_limit, msg_limit, min_limit, max_limit;
+	int i;
 
-	if (default_power_limit)
-		*default_power_limit = pp_limit;
-
-	if (powerplay_table) {
-		if (smu->od_enabled &&
-				(smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT))) {
-			od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
-		} else if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
-			od_percent_upper = 0;
-			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
-		}
+	if (powerplay_table &&
+	    smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
+		od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[
+			SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
+		od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[
+			SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
 	}
 
-	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-		od_percent_upper, od_percent_lower, pp_limit);
-
-	if (max_power_limit) {
-		*max_power_limit = max_limit * (100 + od_percent_upper);
-		*max_power_limit /= 100;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		pp_limit = i == SMU_POWER_SOURCE_AC ?
+			skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+			skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+		msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][i];
+		min_limit = min(pp_limit, msg_limit);
+		max_limit = max(pp_limit, msg_limit);
+
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			pp_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			max_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
+			min_limit * (100 - od_percent_lower) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			max_limit * (100 + od_percent_upper) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
 	}
 
-	if (min_power_limit) {
-		*min_power_limit = min_limit * (100 - od_percent_lower);
-		*min_power_limit /= 100;
-	}
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
 
 	return 0;
 }
@@ -2651,9 +2659,9 @@ static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu)
 	return smu->smc_fw_version > 0x00524600;
 }
 
-static int smu_v13_0_7_set_power_limit(struct smu_context *smu,
-				       enum smu_ppt_limit_type limit_type,
-				       uint32_t limit)
+static int smu_v13_0_7_set_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t limit)
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
 	SkuTable_t *skutable = &pptable->SkuTable;
@@ -2661,13 +2669,18 @@ static int smu_v13_0_7_set_power_limit(struct smu_context *smu,
 	struct smu_table_context *table_context = &smu->smu_table;
 	OverDriveTableExternal_t *od_table =
 		(OverDriveTableExternal_t *)table_context->overdrive_table;
+	uint32_t current_limit;
 	int ret = 0;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
+	ret = smu_v13_0_7_get_ppt_limit(smu, limit_type, &current_limit);
+	if (ret)
+		return ret;
+
 	if (limit <= msg_limit) {
-		if (smu->current_power_limit > msg_limit) {
+		if (current_limit > msg_limit) {
 			od_table->OverDriveTable.Ppt = 0;
 			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
 
@@ -2677,9 +2690,9 @@ static int smu_v13_0_7_set_power_limit(struct smu_context *smu,
 				return ret;
 			}
 		}
-		return smu_v13_0_set_power_limit(smu, limit_type, limit);
+		return smu_v13_0_set_ppt_limit(smu, limit_type, limit);
 	} else if (smu->od_enabled) {
-		ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit);
+		ret = smu_v13_0_set_ppt_limit(smu, limit_type, msg_limit);
 		if (ret)
 			return ret;
 
@@ -2692,7 +2705,6 @@ static int smu_v13_0_7_set_power_limit(struct smu_context *smu,
 		  return ret;
 		}
 
-		smu->current_power_limit = limit;
 	} else {
 		return -EINVAL;
 	}
@@ -2861,8 +2873,8 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
 	.get_fan_control_mode = smu_v13_0_get_fan_control_mode,
 	.set_fan_control_mode = smu_v13_0_set_fan_control_mode,
 	.enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost,
-	.get_power_limit = smu_v13_0_7_get_power_limit,
-	.set_power_limit = smu_v13_0_7_set_power_limit,
+	.get_ppt_limit = smu_v13_0_7_get_ppt_limit,
+	.set_ppt_limit = smu_v13_0_7_set_ppt_limit,
 	.set_power_source = smu_v13_0_set_power_source,
 	.get_power_profile_mode = smu_v13_0_7_get_power_profile_mode,
 	.set_power_profile_mode = smu_v13_0_7_set_power_profile_mode,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index 2a0c7cde938d..80dac277d1ae 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@ -667,14 +667,17 @@ int smu_v14_0_notify_display_change(struct smu_context *smu)
 	return ret;
 }
 
-int smu_v14_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit)
+int smu_v14_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit)
 {
 	int power_src;
 	int ret = 0;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
 		return -EINVAL;
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
 
 	power_src = smu_cmn_to_asic_specific_index(smu,
 						   CMN2ASIC_MAPPING_PWR,
@@ -687,35 +690,33 @@ int smu_v14_0_get_current_power_limit(struct smu_context *smu,
 	ret = smu_cmn_send_smc_msg_with_param(smu,
 					      SMU_MSG_GetPptLimit,
 					      power_src << 16,
-					      power_limit);
+					      ppt_limit);
 	if (ret)
 		dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
 
 	return ret;
 }
 
-int smu_v14_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit)
+int smu_v14_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit)
 {
 	int ret = 0;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
-		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
+		dev_err(smu->adev->dev, "Setting new PPT limit is not supported!\n");
 		return -EOPNOTSUPP;
 	}
 
 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit, NULL);
 	if (ret) {
-		dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
+		dev_err(smu->adev->dev, "[%s] Set PPT limit failed!\n", __func__);
 		return ret;
 	}
 
-	smu->current_power_limit = limit;
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index 71a585f4e7d1..f54780e9dba2 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -59,6 +59,7 @@
 static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
 					      int od_feature_bit,
 					      int32_t *min, int32_t *max);
+static int smu_v14_0_2_init_ppt_limits(struct smu_context *smu);
 
 static const struct smu_feature_bits smu_v14_0_2_dpm_features = {
 	.bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
@@ -370,7 +371,7 @@ static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return ret;
+	return smu_v14_0_2_init_ppt_limits(smu);
 }
 
 static int smu_v14_0_2_tables_init(struct smu_context *smu)
@@ -1610,59 +1611,64 @@ static int smu_v14_0_2_get_fan_speed_rpm(struct smu_context *smu,
 						speed);
 }
 
-static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
-				       uint32_t *current_power_limit,
-				       uint32_t *default_power_limit,
-				       uint32_t *max_power_limit,
-				       uint32_t *min_power_limit)
+static int smu_v14_0_2_get_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t *ppt_limit)
 {
-	struct smu_table_context *table_context = &smu->smu_table;
-	struct smu_14_0_2_powerplay_table *powerplay_table =
-		table_context->power_play_table;
-	PPTable_t *pptable = table_context->driver_pptable;
+	PPTable_t *pptable = smu->smu_table.driver_pptable;
 	CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
 	uint32_t pp_limit = smu->adev->pm.ac_power ?
 		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
 		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-	uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
-	uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
-	int16_t od_percent_upper = 0, od_percent_lower = 0;
-	int ret;
 
-	if (current_power_limit) {
-		ret = smu_v14_0_get_current_power_limit(smu, current_power_limit);
-		if (ret)
-			*current_power_limit = pp_limit;
-	}
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
 
-	if (default_power_limit)
-		*default_power_limit = pp_limit;
-
-	if (powerplay_table) {
-		if (smu->od_enabled &&
-		    smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
-			od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
-			od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
-		} else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
-			od_percent_upper = 0;
-			od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
-		}
-	}
+	if (smu_v14_0_get_ppt_limit(smu, limit_type, ppt_limit))
+		*ppt_limit = pp_limit;
 
-	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-					od_percent_upper, od_percent_lower, pp_limit);
+	return 0;
+}
+
+static int smu_v14_0_2_init_ppt_limits(struct smu_context *smu)
+{
+	struct smu_table_context *table_context = &smu->smu_table;
+	struct smu_14_0_2_powerplay_table *powerplay_table =
+		table_context->power_play_table;
+	PPTable_t *pptable = table_context->driver_pptable;
+	CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
+	int16_t od_percent_upper = 0, od_percent_lower = 0;
+	uint32_t pp_limit, msg_limit, min_limit, max_limit;
+	int i;
 
-	if (max_power_limit) {
-		*max_power_limit = max_limit * (100 + od_percent_upper);
-		*max_power_limit /= 100;
+	if (powerplay_table &&
+	    smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
+		od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
+		od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
 	}
 
-	if (min_power_limit) {
-		*min_power_limit = min_limit * (100 + od_percent_lower);
-		*min_power_limit /= 100;
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		pp_limit = i == SMU_POWER_SOURCE_AC ?
+			skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+			skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+		msg_limit = pptable->SkuTable.MsgLimits.Power
+			[PPT_THROTTLER_PPT0][i];
+		min_limit = min(pp_limit, msg_limit);
+		max_limit = max(pp_limit, msg_limit);
+
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			pp_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max = max_limit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
+			min_limit * (100 + od_percent_lower) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			max_limit * (100 + od_percent_upper) / 100;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
 	}
 
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
+
 	return 0;
 }
 
@@ -2789,22 +2795,27 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu,
 	return ret;
 }
 
-static int smu_v14_0_2_set_power_limit(struct smu_context *smu,
-				       enum smu_ppt_limit_type limit_type,
-				       uint32_t limit)
+static int smu_v14_0_2_set_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t limit)
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
 	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
 	struct smu_table_context *table_context = &smu->smu_table;
 	OverDriveTableExternal_t *od_table =
 		(OverDriveTableExternal_t *)table_context->overdrive_table;
+	uint32_t current_limit;
 	int ret = 0;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
+	ret = smu_v14_0_2_get_ppt_limit(smu, limit_type, &current_limit);
+	if (ret)
+		return ret;
+
 	if (limit <= msg_limit) {
-		if (smu->current_power_limit > msg_limit) {
+		if (current_limit > msg_limit) {
 			od_table->OverDriveTable.Ppt = 0;
 			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
 
@@ -2814,9 +2825,9 @@ static int smu_v14_0_2_set_power_limit(struct smu_context *smu,
 				return ret;
 			}
 		}
-		return smu_v14_0_set_power_limit(smu, limit_type, limit);
+		return smu_v14_0_set_ppt_limit(smu, limit_type, limit);
 	} else if (smu->od_enabled) {
-		ret = smu_v14_0_set_power_limit(smu, limit_type, msg_limit);
+		ret = smu_v14_0_set_ppt_limit(smu, limit_type, msg_limit);
 		if (ret)
 			return ret;
 
@@ -2829,7 +2840,6 @@ static int smu_v14_0_2_set_power_limit(struct smu_context *smu,
 		  return ret;
 		}
 
-		smu->current_power_limit = limit;
 	} else {
 		return -EINVAL;
 	}
@@ -2883,8 +2893,8 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
 	.get_unique_id = smu_v14_0_2_get_unique_id,
 	.get_fan_speed_pwm = smu_v14_0_2_get_fan_speed_pwm,
 	.get_fan_speed_rpm = smu_v14_0_2_get_fan_speed_rpm,
-	.get_power_limit = smu_v14_0_2_get_power_limit,
-	.set_power_limit = smu_v14_0_2_set_power_limit,
+	.get_ppt_limit = smu_v14_0_2_get_ppt_limit,
+	.set_ppt_limit = smu_v14_0_2_set_ppt_limit,
 	.get_power_profile_mode = smu_v14_0_2_get_power_profile_mode,
 	.set_power_profile_mode = smu_v14_0_2_set_power_profile_mode,
 	.run_btc = smu_v14_0_run_btc,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
index 046069e93854..14d0eb296a00 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
@@ -618,14 +618,17 @@ int smu_v15_0_notify_display_change(struct smu_context *smu)
 	return ret;
 }
 
-int smu_v15_0_get_current_power_limit(struct smu_context *smu,
-				      uint32_t *power_limit)
+int smu_v15_0_get_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t *ppt_limit)
 {
 	int power_src;
 	int ret = 0;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
 		return -EINVAL;
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
+		return -EOPNOTSUPP;
 
 	power_src = smu_cmn_to_asic_specific_index(smu,
 						   CMN2ASIC_MAPPING_PWR,
@@ -638,35 +641,33 @@ int smu_v15_0_get_current_power_limit(struct smu_context *smu,
 	ret = smu_cmn_send_smc_msg_with_param(smu,
 					      SMU_MSG_GetPptLimit,
 					      power_src << 16,
-					      power_limit);
+					      ppt_limit);
 	if (ret)
 		dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
 
 	return ret;
 }
 
-int smu_v15_0_set_power_limit(struct smu_context *smu,
-			      enum smu_ppt_limit_type limit_type,
-			      uint32_t limit)
+int smu_v15_0_set_ppt_limit(struct smu_context *smu,
+			    enum smu_ppt_limit_type limit_type,
+			    uint32_t limit)
 {
 	int ret = 0;
 
-	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
+	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
-		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
+		dev_err(smu->adev->dev, "Setting new PPT limit is not supported!\n");
 		return -EOPNOTSUPP;
 	}
 
 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit, NULL);
 	if (ret) {
-		dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
+		dev_err(smu->adev->dev, "[%s] Set PPT limit failed!\n", __func__);
 		return ret;
 	}
 
-	smu->current_power_limit = limit;
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 403c35e338cf..c2c84abecc32 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -72,6 +72,8 @@
 
 #define FEATURE_MASK(feature) (1ULL << feature)
 
+static int smu_v15_0_8_init_ppt_limits(struct smu_context *smu);
+
 static const struct smu_feature_bits smu_v15_0_8_dpm_features = {
 	.bits = { SMU_FEATURE_BIT_INIT(FEATURE_ID_DATA_CALCULATION),
 		  SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_GFXCLK),
@@ -1161,7 +1163,7 @@ static int smu_v15_0_8_set_default_dpm_table(struct smu_context *smu)
 	if (ret)
 		return ret;
 
-	return 0;
+	return smu_v15_0_8_init_ppt_limits(smu);
 }
 
 static int smu_v15_0_8_irq_process(struct amdgpu_device *adev,
@@ -1856,34 +1858,59 @@ static void smu_v15_0_8_get_unique_id(struct smu_context *smu)
 	adev->unique_id = pptable->PublicSerialNumberMID;
 }
 
-static int smu_v15_0_8_get_power_limit(struct smu_context *smu,
-				       uint32_t *current_power_limit,
-				       uint32_t *default_power_limit,
-				       uint32_t *max_power_limit,
-				       uint32_t *min_power_limit)
+static int smu_v15_0_8_get_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t *ppt_limit)
 {
-	struct smu_table_context *smu_table = &smu->smu_table;
-	PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
-	uint32_t power_limit = 0;
 	int ret;
 
-	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, &power_limit);
+	if (limit_type == SMU_PPT_LIMIT_PPT1)
+		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPptLimit,
+					       ppt_limit);
+	else
+		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit,
+					       ppt_limit);
 	if (ret) {
 		dev_err(smu->adev->dev, "Couldn't get PPT limit");
 		return -EINVAL;
 	}
 
-	if (current_power_limit)
-		*current_power_limit = power_limit;
-
-	if (default_power_limit)
-		*default_power_limit = pptable->MaxSocketPowerLimit;
-
-	if (max_power_limit)
-		*max_power_limit = pptable->MaxSocketPowerLimit;
+	return 0;
+}
 
-	if (min_power_limit)
-		*min_power_limit = 0;
+static int smu_v15_0_8_init_ppt_limits(struct smu_context *smu)
+{
+	struct smu_table_context *smu_table = &smu->smu_table;
+	PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+	int i;
+
+	for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
+			pptable->MaxSocketPowerLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max =
+			pptable->MaxSocketPowerLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min = 0;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
+			pptable->MaxSocketPowerLimit;
+		smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min = 0;
+	}
+	smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
+
+	if (pptable->PPT1Max) {
+		for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].default_value =
+				pptable->PPT1Default;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].max =
+				pptable->PPT1Max;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].min =
+				pptable->PPT1Min;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].od_max =
+				pptable->PPT1Max;
+			smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT1].od_min =
+				pptable->PPT1Min;
+		}
+		smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT1);
+	}
 
 	return 0;
 }
@@ -2221,15 +2248,15 @@ static int smu_v15_0_8_get_thermal_temperature_range(struct smu_context *smu,
 	return 0;
 }
 
-static int smu_v15_0_8_set_power_limit(struct smu_context *smu,
-				       enum smu_ppt_limit_type limit_type,
-				       uint32_t limit)
+static int smu_v15_0_8_set_ppt_limit(struct smu_context *smu,
+				     enum smu_ppt_limit_type limit_type,
+				     uint32_t limit)
 {
 	struct smu_table_context *smu_table = &smu->smu_table;
 	PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
 	int ret;
 
-	if (limit_type == SMU_FAST_PPT_LIMIT) {
+	if (limit_type == SMU_PPT_LIMIT_PPT1) {
 		if (!pptable->PPT1Max)
 			return -EOPNOTSUPP;
 
@@ -2248,49 +2275,7 @@ static int smu_v15_0_8_set_power_limit(struct smu_context *smu,
 		return ret;
 	}
 
-	return smu_v15_0_set_power_limit(smu, limit_type, limit);
-}
-
-static int smu_v15_0_8_get_ppt_limit(struct smu_context *smu,
-				     uint32_t *ppt_limit,
-				     enum smu_ppt_limit_type type,
-				     enum smu_ppt_limit_level level)
-{
-	struct smu_table_context *smu_table = &smu->smu_table;
-	PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
-	int ret = 0;
-
-	if (!ppt_limit)
-		return -EINVAL;
-
-	if (type == SMU_FAST_PPT_LIMIT) {
-		if (!pptable->PPT1Max)
-			return -EOPNOTSUPP;
-
-		switch (level) {
-		case SMU_PPT_LIMIT_MAX:
-			*ppt_limit = pptable->PPT1Max;
-			break;
-		case SMU_PPT_LIMIT_CURRENT:
-			ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPptLimit,
-						   ppt_limit);
-			if (ret)
-				dev_err(smu->adev->dev,
-					"Get fast PPT limit failed!\n");
-			break;
-		case SMU_PPT_LIMIT_DEFAULT:
-			*ppt_limit = pptable->PPT1Default;
-			break;
-		case SMU_PPT_LIMIT_MIN:
-			*ppt_limit = pptable->PPT1Min;
-			break;
-		default:
-			return -EOPNOTSUPP;
-		}
-		return ret;
-	}
-
-	return -EOPNOTSUPP;
+	return smu_v15_0_set_ppt_limit(smu, limit_type, limit);
 }
 
 static uint32_t smu_v15_0_8_get_throttler_status(struct smu_context *smu)
@@ -2387,9 +2372,8 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
 	.get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
 	.get_gpu_metrics = smu_v15_0_8_get_gpu_metrics,
 	.get_unique_id = smu_v15_0_8_get_unique_id,
-	.get_power_limit = smu_v15_0_8_get_power_limit,
-	.set_power_limit = smu_v15_0_8_set_power_limit,
 	.get_ppt_limit = smu_v15_0_8_get_ppt_limit,
+	.set_ppt_limit = smu_v15_0_8_set_ppt_limit,
 	.emit_clk_levels = smu_v15_0_8_emit_clk_levels,
 	.read_sensor = smu_v15_0_8_read_sensor,
 	.populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index 45e3758e9ed8..6244f8895668 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -82,7 +82,8 @@
 #define smu_i2c_fini(smu)                                               smu_ppt_funcs(i2c_fini, 0, smu)
 #define smu_get_unique_id(smu)						smu_ppt_funcs(get_unique_id, 0, smu)
 #define smu_log_thermal_throttling(smu)					smu_ppt_funcs(log_thermal_throttling_event, 0, smu)
-#define smu_get_asic_power_limits(smu, current, default, max, min)		smu_ppt_funcs(get_power_limit, 0, smu, current, default, max, min)
+#define smu_get_asic_ppt_limit(smu, type, current) \
+	smu_ppt_funcs(get_ppt_limit, -EOPNOTSUPP, smu, type, current)
 #define smu_get_pp_feature_mask(smu, buf)				smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf)
 #define smu_set_pp_feature_mask(smu, new_mask)				smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask)
 #define smu_gfx_ulv_control(smu, enablement)				smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] drm/amd/pm: account for OD percentage in effective PPT limits
  2026-07-31  3:10 [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Yang Wang
  2026-07-31  3:10 ` [PATCH 1/4] drm/amd/pm: refactor PPT limits by controller and power source Yang Wang
@ 2026-07-31  3:10 ` Yang Wang
  2026-07-31  3:10 ` [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore Yang Wang
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Yang Wang @ 2026-07-31  3:10 UTC (permalink / raw)
  To: amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng

SMU 13.0.0, SMU 13.0.7, and SMU 14.0.2 represent limits above the
message limit as a base value plus an overdrive percentage. GetPptLimit
returns only the base, which causes two incorrect results:

- hwmon reports the message limit instead of the effective limit.
- Lowering the cap can leave the previous OD percentage active.

Export the active overdrive table from PMFW and combine its PPT
percentage with the message result. Use the exported percentage to clear
OD state before programming a limit within the message range.

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
---
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 35 +++++++++++-------
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 35 +++++++++++-------
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  | 37 ++++++++++++-------
 3 files changed, 65 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 95257d5378b8..81b7c2de45ae 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2394,17 +2394,23 @@ static int smu_v13_0_0_get_ppt_limit(struct smu_context *smu,
 				     enum smu_ppt_limit_type limit_type,
 				     uint32_t *ppt_limit)
 {
-	PPTable_t *pptable = smu->smu_table.driver_pptable;
-	SkuTable_t *skutable = &pptable->SkuTable;
-	uint32_t pp_limit = smu->adev->pm.ac_power ?
-		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+	OverDriveTableExternal_t od_table;
+	int ret;
 
 	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EOPNOTSUPP;
 
-	if (smu_v13_0_get_ppt_limit(smu, limit_type, ppt_limit))
-		*ppt_limit = pp_limit;
+	ret = smu_v13_0_get_ppt_limit(smu, limit_type, ppt_limit);
+	if (ret)
+		return ret;
+
+	ret = smu_v13_0_0_get_overdrive_table(smu, &od_table);
+	if (ret)
+		return ret;
+
+	if (od_table.OverDriveTable.Ppt > 0)
+		*ppt_limit = *ppt_limit *
+			(100 + od_table.OverDriveTable.Ppt) / 100;
 
 	return 0;
 }
@@ -3045,22 +3051,23 @@ static int smu_v13_0_0_set_ppt_limit(struct smu_context *smu,
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
 	SkuTable_t *skutable = &pptable->SkuTable;
-	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+	uint32_t msg_limit = skutable->MsgLimits.Power
+		[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
 	struct smu_table_context *table_context = &smu->smu_table;
 	OverDriveTableExternal_t *od_table =
 		(OverDriveTableExternal_t *)table_context->overdrive_table;
-	uint32_t current_limit;
+	OverDriveTableExternal_t current_od_table;
 	int ret = 0;
 
 	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
-	ret = smu_v13_0_0_get_ppt_limit(smu, limit_type, &current_limit);
-	if (ret)
-		return ret;
-
 	if (limit <= msg_limit) {
-		if (current_limit > msg_limit) {
+		ret = smu_v13_0_0_get_overdrive_table(smu, &current_od_table);
+		if (ret)
+			return ret;
+
+		if (current_od_table.OverDriveTable.Ppt) {
 			od_table->OverDriveTable.Ppt = 0;
 			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index 6e0a27eec610..b94ae43586df 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2376,17 +2376,23 @@ static int smu_v13_0_7_get_ppt_limit(struct smu_context *smu,
 				     enum smu_ppt_limit_type limit_type,
 				     uint32_t *ppt_limit)
 {
-	PPTable_t *pptable = smu->smu_table.driver_pptable;
-	SkuTable_t *skutable = &pptable->SkuTable;
-	uint32_t pp_limit = smu->adev->pm.ac_power ?
-		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+	OverDriveTableExternal_t od_table;
+	int ret;
 
 	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EOPNOTSUPP;
 
-	if (smu_v13_0_get_ppt_limit(smu, limit_type, ppt_limit))
-		*ppt_limit = pp_limit;
+	ret = smu_v13_0_get_ppt_limit(smu, limit_type, ppt_limit);
+	if (ret)
+		return ret;
+
+	ret = smu_v13_0_7_get_overdrive_table(smu, &od_table);
+	if (ret)
+		return ret;
+
+	if (od_table.OverDriveTable.Ppt > 0)
+		*ppt_limit = *ppt_limit *
+			(100 + od_table.OverDriveTable.Ppt) / 100;
 
 	return 0;
 }
@@ -2665,22 +2671,23 @@ static int smu_v13_0_7_set_ppt_limit(struct smu_context *smu,
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
 	SkuTable_t *skutable = &pptable->SkuTable;
-	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+	uint32_t msg_limit = skutable->MsgLimits.Power
+		[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
 	struct smu_table_context *table_context = &smu->smu_table;
 	OverDriveTableExternal_t *od_table =
 		(OverDriveTableExternal_t *)table_context->overdrive_table;
-	uint32_t current_limit;
+	OverDriveTableExternal_t current_od_table;
 	int ret = 0;
 
 	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
-	ret = smu_v13_0_7_get_ppt_limit(smu, limit_type, &current_limit);
-	if (ret)
-		return ret;
-
 	if (limit <= msg_limit) {
-		if (current_limit > msg_limit) {
+		ret = smu_v13_0_7_get_overdrive_table(smu, &current_od_table);
+		if (ret)
+			return ret;
+
+		if (current_od_table.OverDriveTable.Ppt) {
 			od_table->OverDriveTable.Ppt = 0;
 			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index f54780e9dba2..4d8faff364c3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -60,6 +60,8 @@ static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
 					      int od_feature_bit,
 					      int32_t *min, int32_t *max);
 static int smu_v14_0_2_init_ppt_limits(struct smu_context *smu);
+static int smu_v14_0_2_get_overdrive_table(struct smu_context *smu,
+					   OverDriveTableExternal_t *od_table);
 
 static const struct smu_feature_bits smu_v14_0_2_dpm_features = {
 	.bits = { SMU_FEATURE_BIT_INIT(FEATURE_DPM_GFXCLK_BIT),
@@ -1615,17 +1617,23 @@ static int smu_v14_0_2_get_ppt_limit(struct smu_context *smu,
 				     enum smu_ppt_limit_type limit_type,
 				     uint32_t *ppt_limit)
 {
-	PPTable_t *pptable = smu->smu_table.driver_pptable;
-	CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
-	uint32_t pp_limit = smu->adev->pm.ac_power ?
-		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+	OverDriveTableExternal_t od_table;
+	int ret;
 
 	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EOPNOTSUPP;
 
-	if (smu_v14_0_get_ppt_limit(smu, limit_type, ppt_limit))
-		*ppt_limit = pp_limit;
+	ret = smu_v14_0_get_ppt_limit(smu, limit_type, ppt_limit);
+	if (ret)
+		return ret;
+
+	ret = smu_v14_0_2_get_overdrive_table(smu, &od_table);
+	if (ret)
+		return ret;
+
+	if (od_table.OverDriveTable.Ppt > 0)
+		*ppt_limit = *ppt_limit *
+			(100 + od_table.OverDriveTable.Ppt) / 100;
 
 	return 0;
 }
@@ -2800,22 +2808,23 @@ static int smu_v14_0_2_set_ppt_limit(struct smu_context *smu,
 				     uint32_t limit)
 {
 	PPTable_t *pptable = smu->smu_table.driver_pptable;
-	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power
+		[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
 	struct smu_table_context *table_context = &smu->smu_table;
 	OverDriveTableExternal_t *od_table =
 		(OverDriveTableExternal_t *)table_context->overdrive_table;
-	uint32_t current_limit;
+	OverDriveTableExternal_t current_od_table;
 	int ret = 0;
 
 	if (limit_type != SMU_PPT_LIMIT_PPT0)
 		return -EINVAL;
 
-	ret = smu_v14_0_2_get_ppt_limit(smu, limit_type, &current_limit);
-	if (ret)
-		return ret;
-
 	if (limit <= msg_limit) {
-		if (current_limit > msg_limit) {
+		ret = smu_v14_0_2_get_overdrive_table(smu, &current_od_table);
+		if (ret)
+			return ret;
+
+		if (current_od_table.OverDriveTable.Ppt) {
 			od_table->OverDriveTable.Ppt = 0;
 			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
 
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore
  2026-07-31  3:10 [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Yang Wang
  2026-07-31  3:10 ` [PATCH 1/4] drm/amd/pm: refactor PPT limits by controller and power source Yang Wang
  2026-07-31  3:10 ` [PATCH 2/4] drm/amd/pm: account for OD percentage in effective PPT limits Yang Wang
@ 2026-07-31  3:10 ` Yang Wang
  2026-07-31  4:57   ` Lazar, Lijo
  2026-07-31  3:10 ` [PATCH 4/4] drm/amd/pm: restore user PPT limits after GPU reset Yang Wang
  2026-07-31  3:57 ` [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Feng, Kenneth
  4 siblings, 1 reply; 7+ messages in thread
From: Yang Wang @ 2026-07-31  3:10 UTC (permalink / raw)
  To: amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng

The existing user policy representation has three ambiguities:

- A numeric value cannot distinguish explicit zero from an unset policy.
- One value per controller cannot preserve independent AC and DC requests.
- Suspend-only restore misses runtime resume, GPU reset, and table reload.

Refactor policy storage and restore as follows:

- Store values and validity masks by power source and PPT controller.
- Save writes against the active source.
- Restore the active source after default SMU setup.
- Reapply the target policy after live AC/DC transitions.
- Use the target source default when no explicit request exists.

The late-init path now covers system resume, runtime resume, GPU reset,
and custom PPTable reload. Common code owns persistent policy; PMFW
continues to own effective current limits.

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
---
 drivers/gpu/drm/amd/pm/amdgpu_dpm.c           |  2 +-
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 89 +++++++++++++------
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  5 +-
 3 files changed, 68 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index c3688b3b12cc..ce526db4d24a 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -508,7 +508,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
 			amdgpu_dpm_notify_ac_dc(adev);
 
 		if (is_support_sw_smu(adev))
-			smu_set_ac_dc(adev->powerplay.pp_handle);
+			smu_set_ac_dc(adev->powerplay.pp_handle, true);
 
 		mutex_unlock(&adev->pm.mutex);
 	}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 99d42446cfc8..43d5dd7dce7e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -488,12 +488,52 @@ static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_
 		return;
 }
 
+static void smu_restore_ppt_limits(struct smu_context *smu,
+				   bool restore_defaults)
+{
+	enum smu_power_src_type power_source;
+	struct smu_ppt_limit_range *range;
+	uint32_t restore_mask;
+	uint32_t limit;
+	int i, ret;
+
+	power_source = smu->adev->pm.ac_power ?
+		SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC;
+	restore_mask = smu->user_dpm_profile.ppt_limit_user_mask[power_source] &
+		smu->ppt_limits.supported_mask;
+	if (!restore_mask && !restore_defaults)
+		return;
+
+	smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE;
+
+	for (i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) {
+		if (!(smu->ppt_limits.supported_mask & BIT(i)))
+			continue;
+
+		if (restore_mask & BIT(i)) {
+			limit = smu->user_dpm_profile.ppt_limits[power_source][i];
+		} else if (restore_defaults) {
+			range = &smu->ppt_limits.range[power_source][i];
+			limit = range->default_value;
+		} else {
+			continue;
+		}
+
+		ret = smu_set_ppt_limit(smu, i, limit);
+		if (ret)
+			dev_err(smu->adev->dev,
+				"Failed to restore PPT%d limit: %d\n", i, ret);
+	}
+
+	smu->user_dpm_profile.flags &= ~SMU_DPM_USER_PROFILE_RESTORE;
+}
+
 /**
  * smu_restore_dpm_user_profile - reinstate user dpm profile
  *
  * @smu:	smu_context pointer
  *
- * Restore saved user power limits, clock frequencies and fan settings.
+ * Restore saved user clock frequencies and fan settings.
  */
 static void smu_restore_dpm_user_profile(struct smu_context *smu)
 {
@@ -509,17 +549,6 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu)
 	/* Enable restore flag */
 	smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE;
 
-	/* set the user dpm power limits */
-	for (int i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) {
-		if (!smu->user_dpm_profile.ppt_limits[i])
-			continue;
-		ret = smu_set_ppt_limit(smu, i,
-					    smu->user_dpm_profile.ppt_limits[i]);
-		if (ret)
-			dev_err(smu->adev->dev,
-				"Failed to set %d PPT limit value\n", i);
-	}
-
 	/* set the user dpm clock configurations */
 	if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
 		enum smu_clk_type clk_type;
@@ -932,7 +961,7 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block)
 	 * is unnecessary.
 	 */
 	adev->pm.ac_power = power_supply_is_system_supplied() > 0;
-	smu_set_ac_dc(smu);
+	smu_set_ac_dc(smu, false);
 
 	if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 1)) ||
 	    (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 3)))
@@ -967,6 +996,8 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block)
 		return ret;
 	}
 
+	if (adev->in_suspend)
+		smu_restore_ppt_limits(smu, false);
 	smu_restore_dpm_user_profile(smu);
 
 	return 0;
@@ -2746,7 +2777,7 @@ static int smu_set_watermarks_for_clock_ranges(void *handle,
 	return smu_set_watermarks_table(smu, clock_ranges);
 }
 
-int smu_set_ac_dc(struct smu_context *smu)
+int smu_set_ac_dc(struct smu_context *smu, bool restore_ppt_policy)
 {
 	int ret = 0;
 
@@ -2754,17 +2785,22 @@ int smu_set_ac_dc(struct smu_context *smu)
 		return -EOPNOTSUPP;
 
 	/* controlled by firmware */
-	if (smu->dc_controlled_by_gpio)
-		return 0;
+	if (!smu->dc_controlled_by_gpio) {
+		ret = smu_set_power_source(smu,
+					   smu->adev->pm.ac_power ?
+					   SMU_POWER_SOURCE_AC :
+					   SMU_POWER_SOURCE_DC);
+		if (ret) {
+			dev_err(smu->adev->dev, "Failed to switch to %s mode!\n",
+				smu->adev->pm.ac_power ? "AC" : "DC");
+			return ret;
+		}
+	}
 
-	ret = smu_set_power_source(smu,
-				   smu->adev->pm.ac_power ? SMU_POWER_SOURCE_AC :
-				   SMU_POWER_SOURCE_DC);
-	if (ret)
-		dev_err(smu->adev->dev, "Failed to switch to %s mode!\n",
-		       smu->adev->pm.ac_power ? "AC" : "DC");
+	if (restore_ppt_policy)
+		smu_restore_ppt_limits(smu, true);
 
-	return ret;
+	return 0;
 }
 
 const struct amd_ip_funcs smu_ip_funcs = {
@@ -3020,8 +3056,11 @@ static int smu_set_ppt_limit(void *handle, uint32_t limit_type, uint32_t limit)
 	ret = smu->ppt_funcs->set_ppt_limit(smu, limit_type, limit);
 	if (ret)
 		return ret;
-	if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
-		smu->user_dpm_profile.ppt_limits[limit_type] = limit;
+	if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) {
+		smu->user_dpm_profile.ppt_limits[power_source][limit_type] = limit;
+		smu->user_dpm_profile.ppt_limit_user_mask[power_source] |=
+			BIT(limit_type);
+	}
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 3d32ee723b8e..698197a285e3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -251,7 +251,8 @@ enum smu_memory_pool_size {
 
 struct smu_user_dpm_profile {
 	uint32_t fan_mode;
-	uint32_t ppt_limits[SMU_LIMIT_TYPE_COUNT];
+	uint32_t ppt_limits[SMU_POWER_SOURCE_COUNT][SMU_LIMIT_TYPE_COUNT];
+	uint32_t ppt_limit_user_mask[SMU_POWER_SOURCE_COUNT];
 	uint32_t fan_speed_pwm;
 	uint32_t fan_speed_rpm;
 	uint32_t flags;
@@ -1953,7 +1954,7 @@ int smu_set_soft_freq_range(struct smu_context *smu, enum pp_clock_type clk_type
 
 int smu_set_gfx_power_up_by_imu(struct smu_context *smu);
 
-int smu_set_ac_dc(struct smu_context *smu);
+int smu_set_ac_dc(struct smu_context *smu, bool restore_ppt_policy);
 
 int smu_set_xgmi_plpd_mode(struct smu_context *smu,
 			   enum pp_xgmi_plpd_mode mode);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] drm/amd/pm: restore user PPT limits after GPU reset
  2026-07-31  3:10 [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Yang Wang
                   ` (2 preceding siblings ...)
  2026-07-31  3:10 ` [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore Yang Wang
@ 2026-07-31  3:10 ` Yang Wang
  2026-07-31  3:57 ` [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Feng, Kenneth
  4 siblings, 0 replies; 7+ messages in thread
From: Yang Wang @ 2026-07-31  3:10 UTC (permalink / raw)
  To: amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng

GPU reset reinitializes PMFW and reloads the platform power table. The
saved user policy remains valid, but suspend-only restore does not run
because adev->in_suspend is clear.

Restore the active PPT policy from SMU late initialization while the
device is in reset recovery. Route each value through the common range
validation and ASIC setter before updating PMFW.

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
---
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 43d5dd7dce7e..bfe2c0bf426d 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -28,6 +28,7 @@
 #include <linux/reboot.h>
 
 #include "amdgpu.h"
+#include "amdgpu_reset.h"
 #include "amdgpu_smu.h"
 #include "smu_internal.h"
 #include "atom.h"
@@ -996,7 +997,7 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block)
 		return ret;
 	}
 
-	if (adev->in_suspend)
+	if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
 		smu_restore_ppt_limits(smu, false);
 	smu_restore_dpm_user_profile(smu);
 
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy
  2026-07-31  3:10 [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Yang Wang
                   ` (3 preceding siblings ...)
  2026-07-31  3:10 ` [PATCH 4/4] drm/amd/pm: restore user PPT limits after GPU reset Yang Wang
@ 2026-07-31  3:57 ` Feng, Kenneth
  4 siblings, 0 replies; 7+ messages in thread
From: Feng, Kenneth @ 2026-07-31  3:57 UTC (permalink / raw)
  To: Wang, Yang(Kevin), amd-gfx@lists.freedesktop.org
  Cc: Deucher, Alexander, Zhang, Hawking

AMD General

Series is Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>


-----Original Message-----
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Yang Wang
Sent: Friday, July 31, 2026 11:10 AM
To: amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; Zhang, Hawking <Hawking.Zhang@amd.com>; Feng, Kenneth <Kenneth.Feng@amd.com>
Subject: [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy

PPT limit handling combines controller identity, AC/DC source, immutable capabilities, PMFW runtime state, and persistent user policy in scalar state. This prevents the driver from representing PPT0/PPT1 independently and leaves user limits vulnerable to PMFW reset.

The runtime model requires separate ownership for each class of data:

- PPTable-derived ranges define normal and OD capabilities.
- PMFW messages and tables define the effective runtime limit.
- Common user-profile state defines persistent policy by source and
  controller.

The four patches establish these boundaries:

- Index common ranges by AC/DC source and PPT0/PPT1 controller; pass the
  controller through get and set callbacks.
- Account for PMFW protocols that represent an effective limit as a
  message base plus an OD percentage.
- Save user values and validity masks by source and controller; restore
  them after suspend and live AC/DC transitions.
- Restore the saved PPT policy after GPU reset reinitializes PMFW and the
  platform power table.

The resulting policy preserves explicit user limits without caching mutable PMFW current values.

Yang Wang (4):
  drm/amd/pm: refactor PPT limits by controller and power source
  drm/amd/pm: account for OD percentage in effective PPT limits
  drm/amd/pm: refactor user PPT policy save and restore
  drm/amd/pm: restore user PPT limits after GPU reset

 drivers/gpu/drm/amd/pm/amdgpu_dpm.c           |   2 +-
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 222 ++++++++++--------
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  63 ++---  drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h  |  15 +-  drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h  |  11 +-  drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h  |  11 +-  drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h  |  11 +-  .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c |  52 ++--
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   |  78 +++---
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 122 +++++-----
 .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c    |  23 +-
 .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  | 118 ++++------
 .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c    |  93 ++++----
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c    |  23 +-
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 123 ++++++----  .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c  | 124 +++++-----  .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 123 ++++++----
 .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c    |  23 +-
 .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  | 123 ++++++----
 .../gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c    |  23 +-
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c  | 122 +++++-----
 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   3 +-
 22 files changed, 792 insertions(+), 716 deletions(-)

--
2.54.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore
  2026-07-31  3:10 ` [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore Yang Wang
@ 2026-07-31  4:57   ` Lazar, Lijo
  0 siblings, 0 replies; 7+ messages in thread
From: Lazar, Lijo @ 2026-07-31  4:57 UTC (permalink / raw)
  To: Yang Wang, amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng



On 31-Jul-26 8:40 AM, Yang Wang wrote:
> The existing user policy representation has three ambiguities:
> 
> - A numeric value cannot distinguish explicit zero from an unset policy.
> - One value per controller cannot preserve independent AC and DC requests.
> - Suspend-only restore misses runtime resume, GPU reset, and table reload.
> 
> Refactor policy storage and restore as follows:
> 
> - Store values and validity masks by power source and PPT controller.
> - Save writes against the active source.
> - Restore the active source after default SMU setup.
> - Reapply the target policy after live AC/DC transitions.
> - Use the target source default when no explicit request exists.
> 
> The late-init path now covers system resume, runtime resume, GPU reset,
> and custom PPTable reload. Common code owns persistent policy; PMFW
> continues to own effective current limits.
> 
> Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
> ---
>   drivers/gpu/drm/amd/pm/amdgpu_dpm.c           |  2 +-
>   drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 89 +++++++++++++------
>   drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  5 +-
>   3 files changed, 68 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
> index c3688b3b12cc..ce526db4d24a 100644
> --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
> +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
> @@ -508,7 +508,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
>   			amdgpu_dpm_notify_ac_dc(adev);
>   
>   		if (is_support_sw_smu(adev))
> -			smu_set_ac_dc(adev->powerplay.pp_handle);
> +			smu_set_ac_dc(adev->powerplay.pp_handle, true);
>   
>   		mutex_unlock(&adev->pm.mutex);
>   	}
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> index 99d42446cfc8..43d5dd7dce7e 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> @@ -488,12 +488,52 @@ static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_
>   		return;
>   }
>   
> +static void smu_restore_ppt_limits(struct smu_context *smu,
> +				   bool restore_defaults)
> +{
> +	enum smu_power_src_type power_source;
> +	struct smu_ppt_limit_range *range;
> +	uint32_t restore_mask;
> +	uint32_t limit;
> +	int i, ret;
> +
> +	power_source = smu->adev->pm.ac_power ?
> +		SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC;
> +	restore_mask = smu->user_dpm_profile.ppt_limit_user_mask[power_source] &
> +		smu->ppt_limits.supported_mask;
> +	if (!restore_mask && !restore_defaults)
> +		return;
> +
> +	smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE;
> +
> +	for (i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) {
> +		if (!(smu->ppt_limits.supported_mask & BIT(i)))
> +			continue;
> +
> +		if (restore_mask & BIT(i)) {
> +			limit = smu->user_dpm_profile.ppt_limits[power_source][i];
> +		} else if (restore_defaults) {
> +			range = &smu->ppt_limits.range[power_source][i];
> +			limit = range->default_value;

This should be restore the current limit before a suspend/reset and not 
the default limit. The current limit could be set through out of band 
also, user profile values won't reflect that.

Thanks,
Lijo

> +		} else {
> +			continue;
> +		}
> +
> +		ret = smu_set_ppt_limit(smu, i, limit);
> +		if (ret)
> +			dev_err(smu->adev->dev,
> +				"Failed to restore PPT%d limit: %d\n", i, ret);
> +	}
> +
> +	smu->user_dpm_profile.flags &= ~SMU_DPM_USER_PROFILE_RESTORE;
> +}
> +
>   /**
>    * smu_restore_dpm_user_profile - reinstate user dpm profile
>    *
>    * @smu:	smu_context pointer
>    *
> - * Restore saved user power limits, clock frequencies and fan settings.
> + * Restore saved user clock frequencies and fan settings.
>    */
>   static void smu_restore_dpm_user_profile(struct smu_context *smu)
>   {
> @@ -509,17 +549,6 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu)
>   	/* Enable restore flag */
>   	smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE;
>   
> -	/* set the user dpm power limits */
> -	for (int i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) {
> -		if (!smu->user_dpm_profile.ppt_limits[i])
> -			continue;
> -		ret = smu_set_ppt_limit(smu, i,
> -					    smu->user_dpm_profile.ppt_limits[i]);
> -		if (ret)
> -			dev_err(smu->adev->dev,
> -				"Failed to set %d PPT limit value\n", i);
> -	}
> -
>   	/* set the user dpm clock configurations */
>   	if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
>   		enum smu_clk_type clk_type;
> @@ -932,7 +961,7 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block)
>   	 * is unnecessary.
>   	 */
>   	adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> -	smu_set_ac_dc(smu);
> +	smu_set_ac_dc(smu, false);
>   
>   	if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 1)) ||
>   	    (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 3)))
> @@ -967,6 +996,8 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block)
>   		return ret;
>   	}
>   
> +	if (adev->in_suspend)
> +		smu_restore_ppt_limits(smu, false);
>   	smu_restore_dpm_user_profile(smu);
>   
>   	return 0;
> @@ -2746,7 +2777,7 @@ static int smu_set_watermarks_for_clock_ranges(void *handle,
>   	return smu_set_watermarks_table(smu, clock_ranges);
>   }
>   
> -int smu_set_ac_dc(struct smu_context *smu)
> +int smu_set_ac_dc(struct smu_context *smu, bool restore_ppt_policy)
>   {
>   	int ret = 0;
>   
> @@ -2754,17 +2785,22 @@ int smu_set_ac_dc(struct smu_context *smu)
>   		return -EOPNOTSUPP;
>   
>   	/* controlled by firmware */
> -	if (smu->dc_controlled_by_gpio)
> -		return 0;
> +	if (!smu->dc_controlled_by_gpio) {
> +		ret = smu_set_power_source(smu,
> +					   smu->adev->pm.ac_power ?
> +					   SMU_POWER_SOURCE_AC :
> +					   SMU_POWER_SOURCE_DC);
> +		if (ret) {
> +			dev_err(smu->adev->dev, "Failed to switch to %s mode!\n",
> +				smu->adev->pm.ac_power ? "AC" : "DC");
> +			return ret;
> +		}
> +	}
>   
> -	ret = smu_set_power_source(smu,
> -				   smu->adev->pm.ac_power ? SMU_POWER_SOURCE_AC :
> -				   SMU_POWER_SOURCE_DC);
> -	if (ret)
> -		dev_err(smu->adev->dev, "Failed to switch to %s mode!\n",
> -		       smu->adev->pm.ac_power ? "AC" : "DC");
> +	if (restore_ppt_policy)
> +		smu_restore_ppt_limits(smu, true);
>   
> -	return ret;
> +	return 0;
>   }
>   
>   const struct amd_ip_funcs smu_ip_funcs = {
> @@ -3020,8 +3056,11 @@ static int smu_set_ppt_limit(void *handle, uint32_t limit_type, uint32_t limit)
>   	ret = smu->ppt_funcs->set_ppt_limit(smu, limit_type, limit);
>   	if (ret)
>   		return ret;
> -	if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
> -		smu->user_dpm_profile.ppt_limits[limit_type] = limit;
> +	if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) {
> +		smu->user_dpm_profile.ppt_limits[power_source][limit_type] = limit;
> +		smu->user_dpm_profile.ppt_limit_user_mask[power_source] |=
> +			BIT(limit_type);
> +	}
>   
>   	return 0;
>   }
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
> index 3d32ee723b8e..698197a285e3 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
> @@ -251,7 +251,8 @@ enum smu_memory_pool_size {
>   
>   struct smu_user_dpm_profile {
>   	uint32_t fan_mode;
> -	uint32_t ppt_limits[SMU_LIMIT_TYPE_COUNT];
> +	uint32_t ppt_limits[SMU_POWER_SOURCE_COUNT][SMU_LIMIT_TYPE_COUNT];
> +	uint32_t ppt_limit_user_mask[SMU_POWER_SOURCE_COUNT];
>   	uint32_t fan_speed_pwm;
>   	uint32_t fan_speed_rpm;
>   	uint32_t flags;
> @@ -1953,7 +1954,7 @@ int smu_set_soft_freq_range(struct smu_context *smu, enum pp_clock_type clk_type
>   
>   int smu_set_gfx_power_up_by_imu(struct smu_context *smu);
>   
> -int smu_set_ac_dc(struct smu_context *smu);
> +int smu_set_ac_dc(struct smu_context *smu, bool restore_ppt_policy);
>   
>   int smu_set_xgmi_plpd_mode(struct smu_context *smu,
>   			   enum pp_xgmi_plpd_mode mode);


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-31  4:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-31  3:10 [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Yang Wang
2026-07-31  3:10 ` [PATCH 1/4] drm/amd/pm: refactor PPT limits by controller and power source Yang Wang
2026-07-31  3:10 ` [PATCH 2/4] drm/amd/pm: account for OD percentage in effective PPT limits Yang Wang
2026-07-31  3:10 ` [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore Yang Wang
2026-07-31  4:57   ` Lazar, Lijo
2026-07-31  3:10 ` [PATCH 4/4] drm/amd/pm: restore user PPT limits after GPU reset Yang Wang
2026-07-31  3:57 ` [PATCH 0/4] drm/amd/pm: refactor PPT limit runtime policy Feng, Kenneth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.