All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/amd/powerplay: support enabled ppfeatures retrieving and setting
@ 2019-01-14 10:01 Evan Quan
       [not found] ` <20190114100142.16922-1-evan.quan-5C7GfCeVMHo@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Evan Quan @ 2019-01-14 10:01 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Alexander.Deucher-5C7GfCeVMHo, Evan Quan

User can use "ppfeatures" sysfs interface to retrieve and set enabled
powerplay features.

Change-Id: I00d5b4931ab426b506e1c187f81a279b00afbb66
Signed-off-by: Evan Quan <evan.quan@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h       |   8 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        |  66 +++++++++++
 .../gpu/drm/amd/include/kgd_pp_interface.h    |   2 +
 drivers/gpu/drm/amd/powerplay/amd_powerplay.c |  42 +++++++
 .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 104 ++++++++++++++++++
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h     |   2 +
 6 files changed, 224 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index f972cd156795..2f61e9edb1c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -364,6 +364,14 @@ enum amdgpu_pcie_gen {
 		((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\
 			(adev)->powerplay.pp_handle))
 
+#define amdgpu_dpm_get_ppfeature_status(adev, buf) \
+		((adev)->powerplay.pp_funcs->get_ppfeature_status(\
+			(adev)->powerplay.pp_handle, (buf)))
+
+#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \
+		((adev)->powerplay.pp_funcs->set_ppfeature_status(\
+			(adev)->powerplay.pp_handle, (ppfeatures)))
+
 struct amdgpu_dpm {
 	struct amdgpu_ps        *ps;
 	/* number of valid power states */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 30ab304eb8b6..db490587464c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -676,6 +676,60 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
 
 }
 
+/**
+ * DOC: ppfeatures
+ *
+ * The amdgpu driver provides a sysfs API for adjusting what powerplay
+ * features to be enabled. The file ppfeatures is used for this.
+ *
+ * Reading back the file will show you the followings:
+ * - Current ppfeature masks
+ * - List of the all supported powerplay features with their naming,
+ *   bitmasks and enablement status('Y'/'N' means "enabled"/"disabled").
+ *
+ * To manually enable or disable a specific feature, just set or clear
+ * the corresponding bit from original ppfeature masks and input the
+ * new ppfeature masks.
+ */
+static ssize_t amdgpu_set_ppfeature_status(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+	uint64_t featuremask;
+	int ret;
+
+	ret = kstrtou64(buf, 0, &featuremask);
+	if (ret)
+		return -EINVAL;
+
+	pr_debug("featuremask = 0x%llx\n", featuremask);
+
+	if (adev->powerplay.pp_funcs->set_ppfeature_status) {
+		ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask);
+		if (ret)
+			return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+	uint32_t size = 0;
+
+	if (adev->powerplay.pp_funcs->get_ppfeature_status)
+		return amdgpu_dpm_get_ppfeature_status(adev, buf);
+
+	return snprintf(buf, PAGE_SIZE, "\n");
+}
+
 /**
  * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
  *
@@ -1102,6 +1156,9 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(gpu_busy_percent, S_IRUGO,
 		amdgpu_get_busy_percent, NULL);
 static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL);
+static DEVICE_ATTR(ppfeatures, S_IRUGO | S_IWUSR,
+		amdgpu_get_ppfeature_status,
+		amdgpu_set_ppfeature_status);
 
 static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
 				      struct device_attribute *attr,
@@ -2294,6 +2351,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 		return ret;
 	}
 
+	ret = device_create_file(adev->dev,
+			&dev_attr_ppfeatures);
+	if (ret) {
+		DRM_ERROR("failed to create device file	"
+				"ppfeatures\n");
+		return ret;
+	}
+
 	adev->pm.sysfs_initialized = true;
 
 	return 0;
@@ -2329,6 +2394,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 	device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
 	if (adev->flags & !AMD_IS_APU)
 		device_remove_file(adev->dev, &dev_attr_pcie_bw);
+	device_remove_file(adev->dev, &dev_attr_ppfeatures);
 }
 
 void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index a2ea4c933360..1130f293c4ee 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -284,6 +284,8 @@ struct amd_pm_funcs {
 	int (*get_asic_baco_capability)(void *handle, bool *cap);
 	int (*get_asic_baco_state)(void *handle, int *state);
 	int (*set_asic_baco_state)(void *handle, int state);
+	int (*get_ppfeature_status)(void *handle, char *buf);
+	int (*set_ppfeature_status)(void *handle, uint64_t ppfeature_masks);
 };
 
 #endif
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index 5d8b5d3c2453..3f73f7cd18b9 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -1455,6 +1455,46 @@ static int pp_set_asic_baco_state(void *handle, int state)
 	return 0;
 }
 
+static int pp_get_ppfeature_status(void *handle, char *buf)
+{
+	struct pp_hwmgr *hwmgr = handle;
+	int ret = 0;
+
+	if (!hwmgr || !hwmgr->pm_en || !buf)
+		return -EINVAL;
+
+	if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {
+		pr_info_ratelimited("%s was not implemented.\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hwmgr->smu_lock);
+	ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);
+	mutex_unlock(&hwmgr->smu_lock);
+
+	return ret;
+}
+
+static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)
+{
+	struct pp_hwmgr *hwmgr = handle;
+	int ret = 0;
+
+	if (!hwmgr || !hwmgr->pm_en)
+		return -EINVAL;
+
+	if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {
+		pr_info_ratelimited("%s was not implemented.\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hwmgr->smu_lock);
+	ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);
+	mutex_unlock(&hwmgr->smu_lock);
+
+	return ret;
+}
+
 static const struct amd_pm_funcs pp_dpm_funcs = {
 	.load_firmware = pp_dpm_load_fw,
 	.wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
@@ -1508,4 +1548,6 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
 	.get_asic_baco_capability = pp_get_asic_baco_capability,
 	.get_asic_baco_state = pp_get_asic_baco_state,
 	.set_asic_baco_state = pp_set_asic_baco_state,
+	.get_ppfeature_status = pp_get_ppfeature_status,
+	.set_ppfeature_status = pp_set_ppfeature_status,
 };
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 82935a3bd950..58b63f864227 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -2775,6 +2775,108 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
 	return 0;
 }
 
+static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
+{
+	static const char *ppfeature_name[] = {
+				"DPM_PREFETCHER",
+				"GFXCLK_DPM",
+				"UCLK_DPM",
+				"SOCCLK_DPM",
+				"UVD_DPM",
+				"VCE_DPM",
+				"ULV",
+				"MP0CLK_DPM",
+				"LINK_DPM",
+				"DCEFCLK_DPM",
+				"GFXCLK_DS",
+				"SOCCLK_DS",
+				"LCLK_DS",
+				"PPT",
+				"TDC",
+				"THERMAL",
+				"GFX_PER_CU_CG",
+				"RM",
+				"DCEFCLK_DS",
+				"ACDC",
+				"VR0HOT",
+				"VR1HOT",
+				"FW_CTF",
+				"LED_DISPLAY",
+				"FAN_CONTROL",
+				"GFX_EDC",
+				"GFXOFF",
+				"CG",
+				"FCLK_DPM",
+				"FCLK_DS",
+				"MP1CLK_DS",
+				"MP0CLK_DS",
+				"XGMI"};
+	static const char *output_title[] = {
+				"FEATURES",
+				"BITMASK",
+				"ENABLEMENT"};
+	uint64_t features_enabled;
+	int i;
+	int ret = 0;
+	int size = 0;
+
+	ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
+	PP_ASSERT_WITH_CODE(!ret,
+			"[EnableAllSmuFeatures] Failed to get enabled smc features!",
+			return ret);
+
+	size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+	size += sprintf(buf + size, "%-19s %-22s %s\n",
+				output_title[0],
+				output_title[1],
+				output_title[2]);
+	for (i = 0; i < GNLD_FEATURES_MAX; i++) {
+		size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+					ppfeature_name[i],
+					1ULL << i,
+					(features_enabled & (1ULL << i)) ? "Y" : "N");
+	}
+
+	return size;
+}
+
+static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
+{
+	uint64_t features_enabled;
+	uint64_t features_to_enable;
+	uint64_t features_to_disable;
+	int ret = 0;
+
+	if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
+		return -EINVAL;
+
+	ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
+	if (ret)
+		return ret;
+
+	features_to_disable =
+		(features_enabled ^ new_ppfeature_masks) & features_enabled;
+	features_to_enable =
+		(features_enabled ^ new_ppfeature_masks) ^ features_to_disable;
+
+	pr_debug("features_to_disable 0x%llx\n", features_to_disable);
+	pr_debug("features_to_enable 0x%llx\n", features_to_enable);
+
+	if (features_to_disable) {
+		ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
+		if (ret)
+			return ret;
+	}
+
+	if (features_to_enable) {
+		ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
 		enum pp_clock_type type, char *buf)
 {
@@ -3571,6 +3673,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
 	.force_clock_level = vega20_force_clock_level,
 	.print_clock_levels = vega20_print_clock_levels,
 	.read_sensor = vega20_read_sensor,
+	.get_ppfeature_status = vega20_get_ppfeature_status,
+	.set_ppfeature_status = vega20_set_ppfeature_status,
 	/* powergate related */
 	.powergate_uvd = vega20_power_gate_uvd,
 	.powergate_vce = vega20_power_gate_vce,
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 577cec90aef1..b1cd70dcd6e7 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -341,6 +341,8 @@ struct pp_hwmgr_func {
 	int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap);
 	int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
 	int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+	int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf);
+	int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks);
 };
 
 struct pp_table_func {
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* [PATCH 2/4] drm/amd/powerplay: support retrieving and adjusting SOC clock power levels
       [not found] ` <20190114100142.16922-1-evan.quan-5C7GfCeVMHo@public.gmane.org>
@ 2019-01-14 10:01   ` Evan Quan
  2019-01-14 10:01   ` [PATCH 3/4] drm/amd/powerplay: support retrieving and adjusting fclock " Evan Quan
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Evan Quan @ 2019-01-14 10:01 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Alexander.Deucher-5C7GfCeVMHo, Evan Quan

User can use "pp_dpm_socclk" to retrieve and adjust SOC clock power
levels.

Change-Id: I24d2f1df2dcf6b8dfa188f82767b36624610406f
Signed-off-by: Evan Quan <evan.quan@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 49 ++++++++++++++++++-
 .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
 .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 45 +++++++++++++++++
 3 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index db490587464c..f735118a6070 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -731,11 +731,11 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
 }
 
 /**
- * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
+ * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_pcie
  *
  * The amdgpu driver provides a sysfs API for adjusting what power levels
  * are enabled for a given power state.  The files pp_dpm_sclk, pp_dpm_mclk,
- * and pp_dpm_pcie are used for this.
+ * pp_dpm_socclk and pp_dpm_pcie are used for this.
  *
  * Reading back the files will show you the available power levels within
  * the power state and the clock information for those levels.
@@ -855,6 +855,42 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
 	return count;
 }
 
+static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+
+	if (adev->powerplay.pp_funcs->print_clock_levels)
+		return amdgpu_dpm_print_clock_levels(adev, PP_SOCCLK, buf);
+	else
+		return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+	int ret;
+	uint32_t mask = 0;
+
+	ret = amdgpu_read_mask(buf, count, &mask);
+	if (ret)
+		return ret;
+
+	if (adev->powerplay.pp_funcs->force_clock_level)
+		ret = amdgpu_dpm_force_clock_level(adev, PP_SOCCLK, mask);
+
+	if (ret)
+		return -EINVAL;
+
+	return count;
+}
+
 static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
@@ -1138,6 +1174,9 @@ static DEVICE_ATTR(pp_dpm_sclk, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR,
 		amdgpu_get_pp_dpm_mclk,
 		amdgpu_set_pp_dpm_mclk);
+static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
+		amdgpu_get_pp_dpm_socclk,
+		amdgpu_set_pp_dpm_socclk);
 static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
 		amdgpu_get_pp_dpm_pcie,
 		amdgpu_set_pp_dpm_pcie);
@@ -2299,6 +2338,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 		DRM_ERROR("failed to create device file pp_dpm_mclk\n");
 		return ret;
 	}
+	ret = device_create_file(adev->dev, &dev_attr_pp_dpm_socclk);
+	if (ret) {
+		DRM_ERROR("failed to create device file pp_dpm_socclk\n");
+		return ret;
+	}
 	ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
 	if (ret) {
 		DRM_ERROR("failed to create device file pp_dpm_pcie\n");
@@ -2383,6 +2427,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk);
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
+	device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
 	device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
 	device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 1130f293c4ee..f5ec25a6ab54 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -92,6 +92,7 @@ enum pp_clock_type {
 	PP_SCLK,
 	PP_MCLK,
 	PP_PCIE,
+	PP_SOCCLK,
 	OD_SCLK,
 	OD_MCLK,
 	OD_VDDC_CURVE,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 58b63f864227..61583d6fc20e 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -2295,6 +2295,34 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
 
 		break;
 
+	case PP_SOCCLK:
+		soft_min_level = mask ? (ffs(mask) - 1) : 0;
+		soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+		if (soft_max_level >= data->dpm_table.soc_table.count) {
+			pr_err("Clock level specified %d is over max allowed %d\n",
+					soft_max_level,
+					data->dpm_table.soc_table.count - 1);
+			return -EINVAL;
+		}
+
+		data->dpm_table.soc_table.dpm_state.soft_min_level =
+			data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+		data->dpm_table.soc_table.dpm_state.soft_max_level =
+			data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
+		ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
+		PP_ASSERT_WITH_CODE(!ret,
+			"Failed to upload boot level to lowest!",
+			return ret);
+
+		ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
+		PP_ASSERT_WITH_CODE(!ret,
+			"Failed to upload dpm max level to highest!",
+			return ret);
+
+		break;
+
 	case PP_PCIE:
 		soft_min_level = mask ? (ffs(mask) - 1) : 0;
 		soft_max_level = mask ? (fls(mask) - 1) : 0;
@@ -2930,6 +2958,23 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
 				(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
 		break;
 
+	case PP_SOCCLK:
+		ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now);
+		PP_ASSERT_WITH_CODE(!ret,
+				"Attempt to get current socclk freq Failed!",
+				return ret);
+
+		ret = vega20_get_socclocks(hwmgr, &clocks);
+		PP_ASSERT_WITH_CODE(!ret,
+				"Attempt to get soc clk levels Failed!",
+				return ret);
+
+		for (i = 0; i < clocks.num_levels; i++)
+			size += sprintf(buf + size, "%d: %uMhz %s\n",
+				i, clocks.data[i].clocks_in_khz / 1000,
+				(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
+		break;
+
 	case PP_PCIE:
 		gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
 			     PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* [PATCH 3/4] drm/amd/powerplay: support retrieving and adjusting fclock power levels
       [not found] ` <20190114100142.16922-1-evan.quan-5C7GfCeVMHo@public.gmane.org>
  2019-01-14 10:01   ` [PATCH 2/4] drm/amd/powerplay: support retrieving and adjusting SOC clock power levels Evan Quan
@ 2019-01-14 10:01   ` Evan Quan
  2019-01-14 10:01   ` [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock " Evan Quan
  2019-01-29 21:59   ` [PATCH 1/4] drm/amd/powerplay: support enabled ppfeatures retrieving and setting Kuehling, Felix
  3 siblings, 0 replies; 9+ messages in thread
From: Evan Quan @ 2019-01-14 10:01 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Alexander.Deucher-5C7GfCeVMHo, Evan Quan

User can use "pp_dpm_fclk" to retrieve and adjust fclock power
levels.

Change-Id: Ib5325a9533b5fe8c125738a2f26e7b976d3ec991
Signed-off-by: Evan Quan <evan.quan@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 49 +++++++++++++-
 .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
 .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 64 +++++++++++++++++++
 3 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index f735118a6070..f6646a522c06 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -731,11 +731,11 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
 }
 
 /**
- * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_pcie
+ * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_pcie
  *
  * The amdgpu driver provides a sysfs API for adjusting what power levels
  * are enabled for a given power state.  The files pp_dpm_sclk, pp_dpm_mclk,
- * pp_dpm_socclk and pp_dpm_pcie are used for this.
+ * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
  *
  * Reading back the files will show you the available power levels within
  * the power state and the clock information for those levels.
@@ -891,6 +891,42 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
 	return count;
 }
 
+static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+
+	if (adev->powerplay.pp_funcs->print_clock_levels)
+		return amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf);
+	else
+		return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+	int ret;
+	uint32_t mask = 0;
+
+	ret = amdgpu_read_mask(buf, count, &mask);
+	if (ret)
+		return ret;
+
+	if (adev->powerplay.pp_funcs->force_clock_level)
+		ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask);
+
+	if (ret)
+		return -EINVAL;
+
+	return count;
+}
+
 static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
@@ -1177,6 +1213,9 @@ static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
 		amdgpu_get_pp_dpm_socclk,
 		amdgpu_set_pp_dpm_socclk);
+static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
+		amdgpu_get_pp_dpm_fclk,
+		amdgpu_set_pp_dpm_fclk);
 static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
 		amdgpu_get_pp_dpm_pcie,
 		amdgpu_set_pp_dpm_pcie);
@@ -2343,6 +2382,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 		DRM_ERROR("failed to create device file pp_dpm_socclk\n");
 		return ret;
 	}
+	ret = device_create_file(adev->dev, &dev_attr_pp_dpm_fclk);
+	if (ret) {
+		DRM_ERROR("failed to create device file pp_dpm_fclk\n");
+		return ret;
+	}
 	ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
 	if (ret) {
 		DRM_ERROR("failed to create device file pp_dpm_pcie\n");
@@ -2429,6 +2473,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
+	device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
 	device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
 	device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
 	device_remove_file(adev->dev,
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index f5ec25a6ab54..f82de14f6560 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -93,6 +93,7 @@ enum pp_clock_type {
 	PP_MCLK,
 	PP_PCIE,
 	PP_SOCCLK,
+	PP_FCLK,
 	OD_SCLK,
 	OD_MCLK,
 	OD_VDDC_CURVE,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 61583d6fc20e..1832dcb965b1 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -1735,6 +1735,17 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
 					return ret);
 	}
 
+	if (data->smu_features[GNLD_DPM_FCLK].enabled &&
+	   (feature_mask & FEATURE_DPM_FCLK_MASK)) {
+		min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level;
+
+		PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+					hwmgr, PPSMC_MSG_SetSoftMinByFreq,
+					(PPCLK_FCLK << 16) | (min_freq & 0xffff))),
+					"Failed to set soft min fclk!",
+					return ret);
+	}
+
 	return ret;
 }
 
@@ -1807,6 +1818,17 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_
 					return ret);
 	}
 
+	if (data->smu_features[GNLD_DPM_FCLK].enabled &&
+	   (feature_mask & FEATURE_DPM_FCLK_MASK)) {
+		max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level;
+
+		PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+					hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
+					(PPCLK_FCLK << 16) | (max_freq & 0xffff))),
+					"Failed to set soft max fclk!",
+					return ret);
+	}
+
 	return ret;
 }
 
@@ -2323,6 +2345,34 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
 
 		break;
 
+	case PP_FCLK:
+		soft_min_level = mask ? (ffs(mask) - 1) : 0;
+		soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+		if (soft_max_level >= data->dpm_table.fclk_table.count) {
+			pr_err("Clock level specified %d is over max allowed %d\n",
+					soft_max_level,
+					data->dpm_table.fclk_table.count - 1);
+			return -EINVAL;
+		}
+
+		data->dpm_table.fclk_table.dpm_state.soft_min_level =
+			data->dpm_table.fclk_table.dpm_levels[soft_min_level].value;
+		data->dpm_table.fclk_table.dpm_state.soft_max_level =
+			data->dpm_table.fclk_table.dpm_levels[soft_max_level].value;
+
+		ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK);
+		PP_ASSERT_WITH_CODE(!ret,
+			"Failed to upload boot level to lowest!",
+			return ret);
+
+		ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK);
+		PP_ASSERT_WITH_CODE(!ret,
+			"Failed to upload dpm max level to highest!",
+			return ret);
+
+		break;
+
 	case PP_PCIE:
 		soft_min_level = mask ? (ffs(mask) - 1) : 0;
 		soft_max_level = mask ? (fls(mask) - 1) : 0;
@@ -2919,6 +2969,8 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
 	PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
 	struct amdgpu_device *adev = hwmgr->adev;
 	struct pp_clock_levels_with_latency clocks;
+	struct vega20_single_dpm_table *fclk_dpm_table =
+			&(data->dpm_table.fclk_table);
 	int i, now, size = 0;
 	int ret = 0;
 	uint32_t gen_speed, lane_width;
@@ -2975,6 +3027,18 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
 				(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
 		break;
 
+	case PP_FCLK:
+		ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
+		PP_ASSERT_WITH_CODE(!ret,
+				"Attempt to get current fclk freq Failed!",
+				return ret);
+
+		for (i = 0; i < fclk_dpm_table->count; i++)
+			size += sprintf(buf + size, "%d: %uMhz %s\n",
+				i, fclk_dpm_table->dpm_levels[i].value,
+				fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
+		break;
+
 	case PP_PCIE:
 		gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
 			     PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels
       [not found] ` <20190114100142.16922-1-evan.quan-5C7GfCeVMHo@public.gmane.org>
  2019-01-14 10:01   ` [PATCH 2/4] drm/amd/powerplay: support retrieving and adjusting SOC clock power levels Evan Quan
  2019-01-14 10:01   ` [PATCH 3/4] drm/amd/powerplay: support retrieving and adjusting fclock " Evan Quan
@ 2019-01-14 10:01   ` Evan Quan
       [not found]     ` <20190114100142.16922-4-evan.quan-5C7GfCeVMHo@public.gmane.org>
  2019-01-29 21:59   ` [PATCH 1/4] drm/amd/powerplay: support enabled ppfeatures retrieving and setting Kuehling, Felix
  3 siblings, 1 reply; 9+ messages in thread
From: Evan Quan @ 2019-01-14 10:01 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Alexander.Deucher-5C7GfCeVMHo, Evan Quan

User can use "pp_dpm_dcefclk" to retrieve and adjust dcefclock power
levels.

Change-Id: Ia3f61558ca96104c88d129ba5194103b2fe702ec
Signed-off-by: Evan Quan <evan.quan@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 53 ++++++++++++++++++-
 .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
 .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 52 +++++++++++++++++-
 3 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index f6646a522c06..b7b70f590236 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -731,11 +731,13 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
 }
 
 /**
- * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_pcie
+ * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk
+ * pp_dpm_pcie
  *
  * The amdgpu driver provides a sysfs API for adjusting what power levels
  * are enabled for a given power state.  The files pp_dpm_sclk, pp_dpm_mclk,
- * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
+ * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for
+ * this.
  *
  * Reading back the files will show you the available power levels within
  * the power state and the clock information for those levels.
@@ -745,6 +747,8 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
  * Secondly,Enter a new value for each level by inputing a string that
  * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
  * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
+ *
+ * NOTE: change to the dcefclk max dpm level is not supported now
  */
 
 static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
@@ -927,6 +931,42 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
 	return count;
 }
 
+static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+
+	if (adev->powerplay.pp_funcs->print_clock_levels)
+		return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
+	else
+		return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = ddev->dev_private;
+	int ret;
+	uint32_t mask = 0;
+
+	ret = amdgpu_read_mask(buf, count, &mask);
+	if (ret)
+		return ret;
+
+	if (adev->powerplay.pp_funcs->force_clock_level)
+		ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask);
+
+	if (ret)
+		return -EINVAL;
+
+	return count;
+}
+
 static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
@@ -1216,6 +1256,9 @@ static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
 		amdgpu_get_pp_dpm_fclk,
 		amdgpu_set_pp_dpm_fclk);
+static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
+		amdgpu_get_pp_dpm_dcefclk,
+		amdgpu_set_pp_dpm_dcefclk);
 static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
 		amdgpu_get_pp_dpm_pcie,
 		amdgpu_set_pp_dpm_pcie);
@@ -2387,6 +2430,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 		DRM_ERROR("failed to create device file pp_dpm_fclk\n");
 		return ret;
 	}
+	ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
+	if (ret) {
+		DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
+		return ret;
+	}
 	ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
 	if (ret) {
 		DRM_ERROR("failed to create device file pp_dpm_pcie\n");
@@ -2474,6 +2522,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
 	device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
+	device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
 	device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
 	device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
 	device_remove_file(adev->dev,
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index f82de14f6560..2b579ba9b685 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -94,6 +94,7 @@ enum pp_clock_type {
 	PP_PCIE,
 	PP_SOCCLK,
 	PP_FCLK,
+	PP_DCEFCLK,
 	OD_SCLK,
 	OD_MCLK,
 	OD_VDDC_CURVE,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 1832dcb965b1..585046c24925 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -1746,6 +1746,17 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
 					return ret);
 	}
 
+	if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
+	   (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
+		min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
+
+		PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+					hwmgr, PPSMC_MSG_SetHardMinByFreq,
+					(PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
+					"Failed to set hard min dcefclk!",
+					return ret);
+	}
+
 	return ret;
 }
 
@@ -2258,7 +2269,7 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
 		enum pp_clock_type type, uint32_t mask)
 {
 	struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
-	uint32_t soft_min_level, soft_max_level;
+	uint32_t soft_min_level, soft_max_level, hard_min_level;
 	int ret = 0;
 
 	switch (type) {
@@ -2373,6 +2384,28 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
 
 		break;
 
+	case PP_DCEFCLK:
+		hard_min_level = mask ? (ffs(mask) - 1) : 0;
+
+		if (hard_min_level >= data->dpm_table.dcef_table.count) {
+			pr_err("Clock level specified %d is over max allowed %d\n",
+					hard_min_level,
+					data->dpm_table.dcef_table.count - 1);
+			return -EINVAL;
+		}
+
+		data->dpm_table.dcef_table.dpm_state.hard_min_level =
+			data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
+
+		ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
+		PP_ASSERT_WITH_CODE(!ret,
+			"Failed to upload boot level to lowest!",
+			return ret);
+
+		//TODO: Setting DCEFCLK max dpm level is not supported
+
+		break;
+
 	case PP_PCIE:
 		soft_min_level = mask ? (ffs(mask) - 1) : 0;
 		soft_max_level = mask ? (fls(mask) - 1) : 0;
@@ -3039,6 +3072,23 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
 				fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
 		break;
 
+	case PP_DCEFCLK:
+		ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
+		PP_ASSERT_WITH_CODE(!ret,
+				"Attempt to get current dcefclk freq Failed!",
+				return ret);
+
+		ret = vega20_get_dcefclocks(hwmgr, &clocks);
+		PP_ASSERT_WITH_CODE(!ret,
+				"Attempt to get dcefclk levels Failed!",
+				return ret);
+
+		for (i = 0; i < clocks.num_levels; i++)
+			size += sprintf(buf + size, "%d: %uMhz %s\n",
+				i, clocks.data[i].clocks_in_khz / 1000,
+				(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
+		break;
+
 	case PP_PCIE:
 		gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
 			     PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels
       [not found]     ` <20190114100142.16922-4-evan.quan-5C7GfCeVMHo@public.gmane.org>
@ 2019-01-14 16:59       ` Alex Deucher
       [not found]         ` <CADnq5_MQg0z6FCH-3UQCXtLEOdtsS2vQ-YXvgWDNBGoyOSaFbw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Alex Deucher @ 2019-01-14 16:59 UTC (permalink / raw)
  To: Evan Quan; +Cc: Deucher, Alexander, amd-gfx list

On Mon, Jan 14, 2019 at 5:02 AM Evan Quan <evan.quan@amd.com> wrote:
>
> User can use "pp_dpm_dcefclk" to retrieve and adjust dcefclock power
> levels.
>
> Change-Id: Ia3f61558ca96104c88d129ba5194103b2fe702ec
> Signed-off-by: Evan Quan <evan.quan@amd.com>

We should probably find a way to hide these new files on asics which
don't support them.  Other than that, the series looks good to me.

Alex

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 53 ++++++++++++++++++-
>  .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
>  .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 52 +++++++++++++++++-
>  3 files changed, 103 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> index f6646a522c06..b7b70f590236 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> @@ -731,11 +731,13 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
>  }
>
>  /**
> - * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_pcie
> + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk
> + * pp_dpm_pcie
>   *
>   * The amdgpu driver provides a sysfs API for adjusting what power levels
>   * are enabled for a given power state.  The files pp_dpm_sclk, pp_dpm_mclk,
> - * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
> + * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for
> + * this.
>   *
>   * Reading back the files will show you the available power levels within
>   * the power state and the clock information for those levels.
> @@ -745,6 +747,8 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
>   * Secondly,Enter a new value for each level by inputing a string that
>   * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
>   * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
> + *
> + * NOTE: change to the dcefclk max dpm level is not supported now
>   */
>
>  static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
> @@ -927,6 +931,42 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
>         return count;
>  }
>
> +static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
> +               struct device_attribute *attr,
> +               char *buf)
> +{
> +       struct drm_device *ddev = dev_get_drvdata(dev);
> +       struct amdgpu_device *adev = ddev->dev_private;
> +
> +       if (adev->powerplay.pp_funcs->print_clock_levels)
> +               return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
> +       else
> +               return snprintf(buf, PAGE_SIZE, "\n");
> +}
> +
> +static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
> +               struct device_attribute *attr,
> +               const char *buf,
> +               size_t count)
> +{
> +       struct drm_device *ddev = dev_get_drvdata(dev);
> +       struct amdgpu_device *adev = ddev->dev_private;
> +       int ret;
> +       uint32_t mask = 0;
> +
> +       ret = amdgpu_read_mask(buf, count, &mask);
> +       if (ret)
> +               return ret;
> +
> +       if (adev->powerplay.pp_funcs->force_clock_level)
> +               ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask);
> +
> +       if (ret)
> +               return -EINVAL;
> +
> +       return count;
> +}
> +
>  static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
>                 struct device_attribute *attr,
>                 char *buf)
> @@ -1216,6 +1256,9 @@ static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
>  static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
>                 amdgpu_get_pp_dpm_fclk,
>                 amdgpu_set_pp_dpm_fclk);
> +static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
> +               amdgpu_get_pp_dpm_dcefclk,
> +               amdgpu_set_pp_dpm_dcefclk);
>  static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
>                 amdgpu_get_pp_dpm_pcie,
>                 amdgpu_set_pp_dpm_pcie);
> @@ -2387,6 +2430,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
>                 DRM_ERROR("failed to create device file pp_dpm_fclk\n");
>                 return ret;
>         }
> +       ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> +       if (ret) {
> +               DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
> +               return ret;
> +       }
>         ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
>         if (ret) {
>                 DRM_ERROR("failed to create device file pp_dpm_pcie\n");
> @@ -2474,6 +2522,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
>         device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
>         device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
>         device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
> +       device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
>         device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
>         device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
>         device_remove_file(adev->dev,
> diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> index f82de14f6560..2b579ba9b685 100644
> --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> @@ -94,6 +94,7 @@ enum pp_clock_type {
>         PP_PCIE,
>         PP_SOCCLK,
>         PP_FCLK,
> +       PP_DCEFCLK,
>         OD_SCLK,
>         OD_MCLK,
>         OD_VDDC_CURVE,
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> index 1832dcb965b1..585046c24925 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> @@ -1746,6 +1746,17 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
>                                         return ret);
>         }
>
> +       if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
> +          (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
> +               min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
> +
> +               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
> +                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
> +                                       (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
> +                                       "Failed to set hard min dcefclk!",
> +                                       return ret);
> +       }
> +
>         return ret;
>  }
>
> @@ -2258,7 +2269,7 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
>                 enum pp_clock_type type, uint32_t mask)
>  {
>         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
> -       uint32_t soft_min_level, soft_max_level;
> +       uint32_t soft_min_level, soft_max_level, hard_min_level;
>         int ret = 0;
>
>         switch (type) {
> @@ -2373,6 +2384,28 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
>
>                 break;
>
> +       case PP_DCEFCLK:
> +               hard_min_level = mask ? (ffs(mask) - 1) : 0;
> +
> +               if (hard_min_level >= data->dpm_table.dcef_table.count) {
> +                       pr_err("Clock level specified %d is over max allowed %d\n",
> +                                       hard_min_level,
> +                                       data->dpm_table.dcef_table.count - 1);
> +                       return -EINVAL;
> +               }
> +
> +               data->dpm_table.dcef_table.dpm_state.hard_min_level =
> +                       data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
> +
> +               ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
> +               PP_ASSERT_WITH_CODE(!ret,
> +                       "Failed to upload boot level to lowest!",
> +                       return ret);
> +
> +               //TODO: Setting DCEFCLK max dpm level is not supported
> +
> +               break;
> +
>         case PP_PCIE:
>                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
>                 soft_max_level = mask ? (fls(mask) - 1) : 0;
> @@ -3039,6 +3072,23 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
>                                 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
>                 break;
>
> +       case PP_DCEFCLK:
> +               ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
> +               PP_ASSERT_WITH_CODE(!ret,
> +                               "Attempt to get current dcefclk freq Failed!",
> +                               return ret);
> +
> +               ret = vega20_get_dcefclocks(hwmgr, &clocks);
> +               PP_ASSERT_WITH_CODE(!ret,
> +                               "Attempt to get dcefclk levels Failed!",
> +                               return ret);
> +
> +               for (i = 0; i < clocks.num_levels; i++)
> +                       size += sprintf(buf + size, "%d: %uMhz %s\n",
> +                               i, clocks.data[i].clocks_in_khz / 1000,
> +                               (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
> +               break;
> +
>         case PP_PCIE:
>                 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
>                              PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
> --
> 2.20.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* RE: [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels
       [not found]         ` <CADnq5_MQg0z6FCH-3UQCXtLEOdtsS2vQ-YXvgWDNBGoyOSaFbw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2019-01-15  6:44           ` Quan, Evan
       [not found]             ` <SN6PR12MB265648F3ACAE6F52278858D3E4810-kxOKjb6HO/FeL/N0e1LXkAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Quan, Evan @ 2019-01-15  6:44 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Deucher, Alexander, amd-gfx list

I think we can use asic_type to determine whether to expose these new interfaces.
If (adev->asic_type >= CHIP_VEGA10), socclk and dcefclk are OK to expose
If (adev->asic_type >= CHIP_VEGA20), fclk is OK to expose

Regards,
Evan
> -----Original Message-----
> From: Alex Deucher <alexdeucher@gmail.com>
> Sent: Tuesday, January 15, 2019 1:00 AM
> To: Quan, Evan <Evan.Quan@amd.com>
> Cc: amd-gfx list <amd-gfx@lists.freedesktop.org>; Deucher, Alexander
> <Alexander.Deucher@amd.com>
> Subject: Re: [PATCH 4/4] drm/amd/powerplay: support retrieving and
> adjusting dcefclock power levels
> 
> On Mon, Jan 14, 2019 at 5:02 AM Evan Quan <evan.quan@amd.com> wrote:
> >
> > User can use "pp_dpm_dcefclk" to retrieve and adjust dcefclock power
> > levels.
> >
> > Change-Id: Ia3f61558ca96104c88d129ba5194103b2fe702ec
> > Signed-off-by: Evan Quan <evan.quan@amd.com>
> 
> We should probably find a way to hide these new files on asics which don't
> support them.  Other than that, the series looks good to me.
> 
> Alex
> 
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 53
> ++++++++++++++++++-
> >  .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
> >  .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 52
> +++++++++++++++++-
> >  3 files changed, 103 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > index f6646a522c06..b7b70f590236 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > @@ -731,11 +731,13 @@ static ssize_t
> > amdgpu_get_ppfeature_status(struct device *dev,  }
> >
> >  /**
> > - * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk
> pp_dpm_pcie
> > + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk
> > + pp_dpm_dcefclk
> > + * pp_dpm_pcie
> >   *
> >   * The amdgpu driver provides a sysfs API for adjusting what power levels
> >   * are enabled for a given power state.  The files pp_dpm_sclk,
> > pp_dpm_mclk,
> > - * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
> > + * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are
> > + used for
> > + * this.
> >   *
> >   * Reading back the files will show you the available power levels within
> >   * the power state and the clock information for those levels.
> > @@ -745,6 +747,8 @@ static ssize_t amdgpu_get_ppfeature_status(struct
> device *dev,
> >   * Secondly,Enter a new value for each level by inputing a string that
> >   * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
> >   * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
> > + *
> > + * NOTE: change to the dcefclk max dpm level is not supported now
> >   */
> >
> >  static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, @@ -927,6
> > +931,42 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
> >         return count;
> >  }
> >
> > +static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
> > +               struct device_attribute *attr,
> > +               char *buf)
> > +{
> > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > +       struct amdgpu_device *adev = ddev->dev_private;
> > +
> > +       if (adev->powerplay.pp_funcs->print_clock_levels)
> > +               return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
> > +       else
> > +               return snprintf(buf, PAGE_SIZE, "\n"); }
> > +
> > +static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
> > +               struct device_attribute *attr,
> > +               const char *buf,
> > +               size_t count)
> > +{
> > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > +       struct amdgpu_device *adev = ddev->dev_private;
> > +       int ret;
> > +       uint32_t mask = 0;
> > +
> > +       ret = amdgpu_read_mask(buf, count, &mask);
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (adev->powerplay.pp_funcs->force_clock_level)
> > +               ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK,
> > + mask);
> > +
> > +       if (ret)
> > +               return -EINVAL;
> > +
> > +       return count;
> > +}
> > +
> >  static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
> >                 struct device_attribute *attr,
> >                 char *buf)
> > @@ -1216,6 +1256,9 @@ static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO |
> > S_IWUSR,  static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
> >                 amdgpu_get_pp_dpm_fclk,
> >                 amdgpu_set_pp_dpm_fclk);
> > +static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
> > +               amdgpu_get_pp_dpm_dcefclk,
> > +               amdgpu_set_pp_dpm_dcefclk);
> >  static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
> >                 amdgpu_get_pp_dpm_pcie,
> >                 amdgpu_set_pp_dpm_pcie); @@ -2387,6 +2430,11 @@ int
> > amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
> >                 DRM_ERROR("failed to create device file pp_dpm_fclk\n");
> >                 return ret;
> >         }
> > +       ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> > +       if (ret) {
> > +               DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
> > +               return ret;
> > +       }
> >         ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
> >         if (ret) {
> >                 DRM_ERROR("failed to create device file
> > pp_dpm_pcie\n"); @@ -2474,6 +2522,7 @@ void
> amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
> >         device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
> >         device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
> >         device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
> > +       device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> >         device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
> >         device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
> >         device_remove_file(adev->dev,
> > diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > index f82de14f6560..2b579ba9b685 100644
> > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > @@ -94,6 +94,7 @@ enum pp_clock_type {
> >         PP_PCIE,
> >         PP_SOCCLK,
> >         PP_FCLK,
> > +       PP_DCEFCLK,
> >         OD_SCLK,
> >         OD_MCLK,
> >         OD_VDDC_CURVE,
> > diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > index 1832dcb965b1..585046c24925 100644
> > --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > @@ -1746,6 +1746,17 @@ static int vega20_upload_dpm_min_level(struct
> pp_hwmgr *hwmgr, uint32_t feature_
> >                                         return ret);
> >         }
> >
> > +       if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
> > +          (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
> > +               min_freq =
> > + data->dpm_table.dcef_table.dpm_state.hard_min_level;
> > +
> > +               PP_ASSERT_WITH_CODE(!(ret =
> smum_send_msg_to_smc_with_parameter(
> > +                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
> > +                                       (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
> > +                                       "Failed to set hard min dcefclk!",
> > +                                       return ret);
> > +       }
> > +
> >         return ret;
> >  }
> >
> > @@ -2258,7 +2269,7 @@ static int vega20_force_clock_level(struct
> pp_hwmgr *hwmgr,
> >                 enum pp_clock_type type, uint32_t mask)  {
> >         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr-
> >backend);
> > -       uint32_t soft_min_level, soft_max_level;
> > +       uint32_t soft_min_level, soft_max_level, hard_min_level;
> >         int ret = 0;
> >
> >         switch (type) {
> > @@ -2373,6 +2384,28 @@ static int vega20_force_clock_level(struct
> > pp_hwmgr *hwmgr,
> >
> >                 break;
> >
> > +       case PP_DCEFCLK:
> > +               hard_min_level = mask ? (ffs(mask) - 1) : 0;
> > +
> > +               if (hard_min_level >= data->dpm_table.dcef_table.count) {
> > +                       pr_err("Clock level specified %d is over max allowed %d\n",
> > +                                       hard_min_level,
> > +                                       data->dpm_table.dcef_table.count - 1);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               data->dpm_table.dcef_table.dpm_state.hard_min_level =
> > +
> > + data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
> > +
> > +               ret = vega20_upload_dpm_min_level(hwmgr,
> FEATURE_DPM_DCEFCLK_MASK);
> > +               PP_ASSERT_WITH_CODE(!ret,
> > +                       "Failed to upload boot level to lowest!",
> > +                       return ret);
> > +
> > +               //TODO: Setting DCEFCLK max dpm level is not supported
> > +
> > +               break;
> > +
> >         case PP_PCIE:
> >                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
> >                 soft_max_level = mask ? (fls(mask) - 1) : 0; @@
> > -3039,6 +3072,23 @@ static int vega20_print_clock_levels(struct pp_hwmgr
> *hwmgr,
> >                                 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" :
> "");
> >                 break;
> >
> > +       case PP_DCEFCLK:
> > +               ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK,
> &now);
> > +               PP_ASSERT_WITH_CODE(!ret,
> > +                               "Attempt to get current dcefclk freq Failed!",
> > +                               return ret);
> > +
> > +               ret = vega20_get_dcefclocks(hwmgr, &clocks);
> > +               PP_ASSERT_WITH_CODE(!ret,
> > +                               "Attempt to get dcefclk levels Failed!",
> > +                               return ret);
> > +
> > +               for (i = 0; i < clocks.num_levels; i++)
> > +                       size += sprintf(buf + size, "%d: %uMhz %s\n",
> > +                               i, clocks.data[i].clocks_in_khz / 1000,
> > +                               (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
> > +               break;
> > +
> >         case PP_PCIE:
> >                 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
> >
> > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
> > --
> > 2.20.1
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* RE: [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels
       [not found]             ` <SN6PR12MB265648F3ACAE6F52278858D3E4810-kxOKjb6HO/FeL/N0e1LXkAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2019-01-15  6:59               ` Quan, Evan
       [not found]                 ` <SN6PR12MB26560F7F273E30EBFECE50EFE4810-kxOKjb6HO/FeL/N0e1LXkAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Quan, Evan @ 2019-01-15  6:59 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Deucher, Alexander, amd-gfx list

For ppfeatures, it will be seen only if (adev->asic_type >= CHIP_VEGA10 && !APU).

Regards,
Evan
> -----Original Message-----
> From: Quan, Evan
> Sent: Tuesday, January 15, 2019 2:44 PM
> To: Alex Deucher <alexdeucher@gmail.com>
> Cc: amd-gfx list <amd-gfx@lists.freedesktop.org>; Deucher, Alexander
> <Alexander.Deucher@amd.com>
> Subject: RE: [PATCH 4/4] drm/amd/powerplay: support retrieving and
> adjusting dcefclock power levels
> 
> I think we can use asic_type to determine whether to expose these new
> interfaces.
> If (adev->asic_type >= CHIP_VEGA10), socclk and dcefclk are OK to expose If
> (adev->asic_type >= CHIP_VEGA20), fclk is OK to expose
> 
> Regards,
> Evan
> > -----Original Message-----
> > From: Alex Deucher <alexdeucher@gmail.com>
> > Sent: Tuesday, January 15, 2019 1:00 AM
> > To: Quan, Evan <Evan.Quan@amd.com>
> > Cc: amd-gfx list <amd-gfx@lists.freedesktop.org>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>
> > Subject: Re: [PATCH 4/4] drm/amd/powerplay: support retrieving and
> > adjusting dcefclock power levels
> >
> > On Mon, Jan 14, 2019 at 5:02 AM Evan Quan <evan.quan@amd.com> wrote:
> > >
> > > User can use "pp_dpm_dcefclk" to retrieve and adjust dcefclock power
> > > levels.
> > >
> > > Change-Id: Ia3f61558ca96104c88d129ba5194103b2fe702ec
> > > Signed-off-by: Evan Quan <evan.quan@amd.com>
> >
> > We should probably find a way to hide these new files on asics which
> > don't support them.  Other than that, the series looks good to me.
> >
> > Alex
> >
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 53
> > ++++++++++++++++++-
> > >  .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
> > >  .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 52
> > +++++++++++++++++-
> > >  3 files changed, 103 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > index f6646a522c06..b7b70f590236 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > @@ -731,11 +731,13 @@ static ssize_t
> > > amdgpu_get_ppfeature_status(struct device *dev,  }
> > >
> > >  /**
> > > - * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk
> > pp_dpm_pcie
> > > + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk
> > > + pp_dpm_dcefclk
> > > + * pp_dpm_pcie
> > >   *
> > >   * The amdgpu driver provides a sysfs API for adjusting what power
> levels
> > >   * are enabled for a given power state.  The files pp_dpm_sclk,
> > > pp_dpm_mclk,
> > > - * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
> > > + * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie
> are
> > > + used for
> > > + * this.
> > >   *
> > >   * Reading back the files will show you the available power levels within
> > >   * the power state and the clock information for those levels.
> > > @@ -745,6 +747,8 @@ static ssize_t
> > > amdgpu_get_ppfeature_status(struct
> > device *dev,
> > >   * Secondly,Enter a new value for each level by inputing a string that
> > >   * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
> > >   * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
> > > + *
> > > + * NOTE: change to the dcefclk max dpm level is not supported now
> > >   */
> > >
> > >  static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, @@ -927,6
> > > +931,42 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
> > >         return count;
> > >  }
> > >
> > > +static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
> > > +               struct device_attribute *attr,
> > > +               char *buf)
> > > +{
> > > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > > +       struct amdgpu_device *adev = ddev->dev_private;
> > > +
> > > +       if (adev->powerplay.pp_funcs->print_clock_levels)
> > > +               return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK,
> buf);
> > > +       else
> > > +               return snprintf(buf, PAGE_SIZE, "\n"); }
> > > +
> > > +static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
> > > +               struct device_attribute *attr,
> > > +               const char *buf,
> > > +               size_t count)
> > > +{
> > > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > > +       struct amdgpu_device *adev = ddev->dev_private;
> > > +       int ret;
> > > +       uint32_t mask = 0;
> > > +
> > > +       ret = amdgpu_read_mask(buf, count, &mask);
> > > +       if (ret)
> > > +               return ret;
> > > +
> > > +       if (adev->powerplay.pp_funcs->force_clock_level)
> > > +               ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK,
> > > + mask);
> > > +
> > > +       if (ret)
> > > +               return -EINVAL;
> > > +
> > > +       return count;
> > > +}
> > > +
> > >  static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
> > >                 struct device_attribute *attr,
> > >                 char *buf)
> > > @@ -1216,6 +1256,9 @@ static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO |
> > > S_IWUSR,  static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
> > >                 amdgpu_get_pp_dpm_fclk,
> > >                 amdgpu_set_pp_dpm_fclk);
> > > +static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
> > > +               amdgpu_get_pp_dpm_dcefclk,
> > > +               amdgpu_set_pp_dpm_dcefclk);
> > >  static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
> > >                 amdgpu_get_pp_dpm_pcie,
> > >                 amdgpu_set_pp_dpm_pcie); @@ -2387,6 +2430,11 @@ int
> > > amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
> > >                 DRM_ERROR("failed to create device file pp_dpm_fclk\n");
> > >                 return ret;
> > >         }
> > > +       ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> > > +       if (ret) {
> > > +               DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
> > > +               return ret;
> > > +       }
> > >         ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
> > >         if (ret) {
> > >                 DRM_ERROR("failed to create device file
> > > pp_dpm_pcie\n"); @@ -2474,6 +2522,7 @@ void
> > amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
> > >         device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
> > >         device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
> > >         device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
> > > +       device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> > >         device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
> > >         device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
> > >         device_remove_file(adev->dev, diff --git
> > > a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > index f82de14f6560..2b579ba9b685 100644
> > > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > @@ -94,6 +94,7 @@ enum pp_clock_type {
> > >         PP_PCIE,
> > >         PP_SOCCLK,
> > >         PP_FCLK,
> > > +       PP_DCEFCLK,
> > >         OD_SCLK,
> > >         OD_MCLK,
> > >         OD_VDDC_CURVE,
> > > diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > index 1832dcb965b1..585046c24925 100644
> > > --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > @@ -1746,6 +1746,17 @@ static int
> vega20_upload_dpm_min_level(struct
> > pp_hwmgr *hwmgr, uint32_t feature_
> > >                                         return ret);
> > >         }
> > >
> > > +       if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
> > > +          (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
> > > +               min_freq =
> > > + data->dpm_table.dcef_table.dpm_state.hard_min_level;
> > > +
> > > +               PP_ASSERT_WITH_CODE(!(ret =
> > smum_send_msg_to_smc_with_parameter(
> > > +                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
> > > +                                       (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
> > > +                                       "Failed to set hard min dcefclk!",
> > > +                                       return ret);
> > > +       }
> > > +
> > >         return ret;
> > >  }
> > >
> > > @@ -2258,7 +2269,7 @@ static int vega20_force_clock_level(struct
> > pp_hwmgr *hwmgr,
> > >                 enum pp_clock_type type, uint32_t mask)  {
> > >         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr-
> > >backend);
> > > -       uint32_t soft_min_level, soft_max_level;
> > > +       uint32_t soft_min_level, soft_max_level, hard_min_level;
> > >         int ret = 0;
> > >
> > >         switch (type) {
> > > @@ -2373,6 +2384,28 @@ static int vega20_force_clock_level(struct
> > > pp_hwmgr *hwmgr,
> > >
> > >                 break;
> > >
> > > +       case PP_DCEFCLK:
> > > +               hard_min_level = mask ? (ffs(mask) - 1) : 0;
> > > +
> > > +               if (hard_min_level >= data->dpm_table.dcef_table.count) {
> > > +                       pr_err("Clock level specified %d is over max allowed %d\n",
> > > +                                       hard_min_level,
> > > +                                       data->dpm_table.dcef_table.count - 1);
> > > +                       return -EINVAL;
> > > +               }
> > > +
> > > +               data->dpm_table.dcef_table.dpm_state.hard_min_level
> > > + =
> > > +
> > > + data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
> > > +
> > > +               ret = vega20_upload_dpm_min_level(hwmgr,
> > FEATURE_DPM_DCEFCLK_MASK);
> > > +               PP_ASSERT_WITH_CODE(!ret,
> > > +                       "Failed to upload boot level to lowest!",
> > > +                       return ret);
> > > +
> > > +               //TODO: Setting DCEFCLK max dpm level is not
> > > + supported
> > > +
> > > +               break;
> > > +
> > >         case PP_PCIE:
> > >                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
> > >                 soft_max_level = mask ? (fls(mask) - 1) : 0; @@
> > > -3039,6 +3072,23 @@ static int vega20_print_clock_levels(struct
> > > pp_hwmgr
> > *hwmgr,
> > >                                 fclk_dpm_table->dpm_levels[i].value == (now / 100) ?
> "*" :
> > "");
> > >                 break;
> > >
> > > +       case PP_DCEFCLK:
> > > +               ret = vega20_get_current_clk_freq(hwmgr,
> > > + PPCLK_DCEFCLK,
> > &now);
> > > +               PP_ASSERT_WITH_CODE(!ret,
> > > +                               "Attempt to get current dcefclk freq Failed!",
> > > +                               return ret);
> > > +
> > > +               ret = vega20_get_dcefclocks(hwmgr, &clocks);
> > > +               PP_ASSERT_WITH_CODE(!ret,
> > > +                               "Attempt to get dcefclk levels Failed!",
> > > +                               return ret);
> > > +
> > > +               for (i = 0; i < clocks.num_levels; i++)
> > > +                       size += sprintf(buf + size, "%d: %uMhz %s\n",
> > > +                               i, clocks.data[i].clocks_in_khz / 1000,
> > > +                               (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
> > > +               break;
> > > +
> > >         case PP_PCIE:
> > >                 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
> > >
> > > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
> > > --
> > > 2.20.1
> > >
> > > _______________________________________________
> > > amd-gfx mailing list
> > > amd-gfx@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels
       [not found]                 ` <SN6PR12MB26560F7F273E30EBFECE50EFE4810-kxOKjb6HO/FeL/N0e1LXkAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2019-01-15 15:19                   ` Deucher, Alexander
  0 siblings, 0 replies; 9+ messages in thread
From: Deucher, Alexander @ 2019-01-15 15:19 UTC (permalink / raw)
  To: Quan, Evan, Alex Deucher; +Cc: amd-gfx list


[-- Attachment #1.1: Type: text/plain, Size: 12628 bytes --]

Seems reasonable to me.  With those changes,

Reviewed-by: Alex Deucher <alexander.deucher-5C7GfCeVMHo@public.gmane.org>

________________________________
From: Quan, Evan
Sent: Tuesday, January 15, 2019 1:59:42 AM
To: Alex Deucher
Cc: amd-gfx list; Deucher, Alexander
Subject: RE: [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels

For ppfeatures, it will be seen only if (adev->asic_type >= CHIP_VEGA10 && !APU).

Regards,
Evan
> -----Original Message-----
> From: Quan, Evan
> Sent: Tuesday, January 15, 2019 2:44 PM
> To: Alex Deucher <alexdeucher-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: amd-gfx list <amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>; Deucher, Alexander
> <Alexander.Deucher-5C7GfCeVMHo@public.gmane.org>
> Subject: RE: [PATCH 4/4] drm/amd/powerplay: support retrieving and
> adjusting dcefclock power levels
>
> I think we can use asic_type to determine whether to expose these new
> interfaces.
> If (adev->asic_type >= CHIP_VEGA10), socclk and dcefclk are OK to expose If
> (adev->asic_type >= CHIP_VEGA20), fclk is OK to expose
>
> Regards,
> Evan
> > -----Original Message-----
> > From: Alex Deucher <alexdeucher-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > Sent: Tuesday, January 15, 2019 1:00 AM
> > To: Quan, Evan <Evan.Quan-5C7GfCeVMHo@public.gmane.org>
> > Cc: amd-gfx list <amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>; Deucher, Alexander
> > <Alexander.Deucher-5C7GfCeVMHo@public.gmane.org>
> > Subject: Re: [PATCH 4/4] drm/amd/powerplay: support retrieving and
> > adjusting dcefclock power levels
> >
> > On Mon, Jan 14, 2019 at 5:02 AM Evan Quan <evan.quan-5C7GfCeVMHo@public.gmane.org> wrote:
> > >
> > > User can use "pp_dpm_dcefclk" to retrieve and adjust dcefclock power
> > > levels.
> > >
> > > Change-Id: Ia3f61558ca96104c88d129ba5194103b2fe702ec
> > > Signed-off-by: Evan Quan <evan.quan-5C7GfCeVMHo@public.gmane.org>
> >
> > We should probably find a way to hide these new files on asics which
> > don't support them.  Other than that, the series looks good to me.
> >
> > Alex
> >
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 53
> > ++++++++++++++++++-
> > >  .../gpu/drm/amd/include/kgd_pp_interface.h    |  1 +
> > >  .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 52
> > +++++++++++++++++-
> > >  3 files changed, 103 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > index f6646a522c06..b7b70f590236 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > > @@ -731,11 +731,13 @@ static ssize_t
> > > amdgpu_get_ppfeature_status(struct device *dev,  }
> > >
> > >  /**
> > > - * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk
> > pp_dpm_pcie
> > > + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk
> > > + pp_dpm_dcefclk
> > > + * pp_dpm_pcie
> > >   *
> > >   * The amdgpu driver provides a sysfs API for adjusting what power
> levels
> > >   * are enabled for a given power state.  The files pp_dpm_sclk,
> > > pp_dpm_mclk,
> > > - * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
> > > + * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie
> are
> > > + used for
> > > + * this.
> > >   *
> > >   * Reading back the files will show you the available power levels within
> > >   * the power state and the clock information for those levels.
> > > @@ -745,6 +747,8 @@ static ssize_t
> > > amdgpu_get_ppfeature_status(struct
> > device *dev,
> > >   * Secondly,Enter a new value for each level by inputing a string that
> > >   * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
> > >   * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
> > > + *
> > > + * NOTE: change to the dcefclk max dpm level is not supported now
> > >   */
> > >
> > >  static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, @@ -927,6
> > > +931,42 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
> > >         return count;
> > >  }
> > >
> > > +static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
> > > +               struct device_attribute *attr,
> > > +               char *buf)
> > > +{
> > > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > > +       struct amdgpu_device *adev = ddev->dev_private;
> > > +
> > > +       if (adev->powerplay.pp_funcs->print_clock_levels)
> > > +               return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK,
> buf);
> > > +       else
> > > +               return snprintf(buf, PAGE_SIZE, "\n"); }
> > > +
> > > +static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
> > > +               struct device_attribute *attr,
> > > +               const char *buf,
> > > +               size_t count)
> > > +{
> > > +       struct drm_device *ddev = dev_get_drvdata(dev);
> > > +       struct amdgpu_device *adev = ddev->dev_private;
> > > +       int ret;
> > > +       uint32_t mask = 0;
> > > +
> > > +       ret = amdgpu_read_mask(buf, count, &mask);
> > > +       if (ret)
> > > +               return ret;
> > > +
> > > +       if (adev->powerplay.pp_funcs->force_clock_level)
> > > +               ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK,
> > > + mask);
> > > +
> > > +       if (ret)
> > > +               return -EINVAL;
> > > +
> > > +       return count;
> > > +}
> > > +
> > >  static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
> > >                 struct device_attribute *attr,
> > >                 char *buf)
> > > @@ -1216,6 +1256,9 @@ static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO |
> > > S_IWUSR,  static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
> > >                 amdgpu_get_pp_dpm_fclk,
> > >                 amdgpu_set_pp_dpm_fclk);
> > > +static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
> > > +               amdgpu_get_pp_dpm_dcefclk,
> > > +               amdgpu_set_pp_dpm_dcefclk);
> > >  static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
> > >                 amdgpu_get_pp_dpm_pcie,
> > >                 amdgpu_set_pp_dpm_pcie); @@ -2387,6 +2430,11 @@ int
> > > amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
> > >                 DRM_ERROR("failed to create device file pp_dpm_fclk\n");
> > >                 return ret;
> > >         }
> > > +       ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> > > +       if (ret) {
> > > +               DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
> > > +               return ret;
> > > +       }
> > >         ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
> > >         if (ret) {
> > >                 DRM_ERROR("failed to create device file
> > > pp_dpm_pcie\n"); @@ -2474,6 +2522,7 @@ void
> > amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
> > >         device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
> > >         device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
> > >         device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
> > > +       device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> > >         device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
> > >         device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
> > >         device_remove_file(adev->dev, diff --git
> > > a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > index f82de14f6560..2b579ba9b685 100644
> > > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> > > @@ -94,6 +94,7 @@ enum pp_clock_type {
> > >         PP_PCIE,
> > >         PP_SOCCLK,
> > >         PP_FCLK,
> > > +       PP_DCEFCLK,
> > >         OD_SCLK,
> > >         OD_MCLK,
> > >         OD_VDDC_CURVE,
> > > diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > index 1832dcb965b1..585046c24925 100644
> > > --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> > > @@ -1746,6 +1746,17 @@ static int
> vega20_upload_dpm_min_level(struct
> > pp_hwmgr *hwmgr, uint32_t feature_
> > >                                         return ret);
> > >         }
> > >
> > > +       if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
> > > +          (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
> > > +               min_freq =
> > > + data->dpm_table.dcef_table.dpm_state.hard_min_level;
> > > +
> > > +               PP_ASSERT_WITH_CODE(!(ret =
> > smum_send_msg_to_smc_with_parameter(
> > > +                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
> > > +                                       (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
> > > +                                       "Failed to set hard min dcefclk!",
> > > +                                       return ret);
> > > +       }
> > > +
> > >         return ret;
> > >  }
> > >
> > > @@ -2258,7 +2269,7 @@ static int vega20_force_clock_level(struct
> > pp_hwmgr *hwmgr,
> > >                 enum pp_clock_type type, uint32_t mask)  {
> > >         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr-
> > >backend);
> > > -       uint32_t soft_min_level, soft_max_level;
> > > +       uint32_t soft_min_level, soft_max_level, hard_min_level;
> > >         int ret = 0;
> > >
> > >         switch (type) {
> > > @@ -2373,6 +2384,28 @@ static int vega20_force_clock_level(struct
> > > pp_hwmgr *hwmgr,
> > >
> > >                 break;
> > >
> > > +       case PP_DCEFCLK:
> > > +               hard_min_level = mask ? (ffs(mask) - 1) : 0;
> > > +
> > > +               if (hard_min_level >= data->dpm_table.dcef_table.count) {
> > > +                       pr_err("Clock level specified %d is over max allowed %d\n",
> > > +                                       hard_min_level,
> > > +                                       data->dpm_table.dcef_table.count - 1);
> > > +                       return -EINVAL;
> > > +               }
> > > +
> > > +               data->dpm_table.dcef_table.dpm_state.hard_min_level
> > > + =
> > > +
> > > + data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
> > > +
> > > +               ret = vega20_upload_dpm_min_level(hwmgr,
> > FEATURE_DPM_DCEFCLK_MASK);
> > > +               PP_ASSERT_WITH_CODE(!ret,
> > > +                       "Failed to upload boot level to lowest!",
> > > +                       return ret);
> > > +
> > > +               //TODO: Setting DCEFCLK max dpm level is not
> > > + supported
> > > +
> > > +               break;
> > > +
> > >         case PP_PCIE:
> > >                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
> > >                 soft_max_level = mask ? (fls(mask) - 1) : 0; @@
> > > -3039,6 +3072,23 @@ static int vega20_print_clock_levels(struct
> > > pp_hwmgr
> > *hwmgr,
> > >                                 fclk_dpm_table->dpm_levels[i].value == (now / 100) ?
> "*" :
> > "");
> > >                 break;
> > >
> > > +       case PP_DCEFCLK:
> > > +               ret = vega20_get_current_clk_freq(hwmgr,
> > > + PPCLK_DCEFCLK,
> > &now);
> > > +               PP_ASSERT_WITH_CODE(!ret,
> > > +                               "Attempt to get current dcefclk freq Failed!",
> > > +                               return ret);
> > > +
> > > +               ret = vega20_get_dcefclocks(hwmgr, &clocks);
> > > +               PP_ASSERT_WITH_CODE(!ret,
> > > +                               "Attempt to get dcefclk levels Failed!",
> > > +                               return ret);
> > > +
> > > +               for (i = 0; i < clocks.num_levels; i++)
> > > +                       size += sprintf(buf + size, "%d: %uMhz %s\n",
> > > +                               i, clocks.data[i].clocks_in_khz / 1000,
> > > +                               (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
> > > +               break;
> > > +
> > >         case PP_PCIE:
> > >                 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
> > >
> > > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
> > > --
> > > 2.20.1
> > >
> > > _______________________________________________
> > > amd-gfx mailing list
> > > amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
> > > https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[-- Attachment #1.2: Type: text/html, Size: 26211 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/4] drm/amd/powerplay: support enabled ppfeatures retrieving and setting
       [not found] ` <20190114100142.16922-1-evan.quan-5C7GfCeVMHo@public.gmane.org>
                     ` (2 preceding siblings ...)
  2019-01-14 10:01   ` [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock " Evan Quan
@ 2019-01-29 21:59   ` Kuehling, Felix
  3 siblings, 0 replies; 9+ messages in thread
From: Kuehling, Felix @ 2019-01-29 21:59 UTC (permalink / raw)
  To: Quan, Evan, amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Deucher, Alexander


On 2019-01-14 5:01 a.m., Evan Quan wrote:
> +	features_to_disable =
> +		(features_enabled ^ new_ppfeature_masks) & features_enabled;
> +	features_to_enable =
> +		(features_enabled ^ new_ppfeature_masks) ^ features_to_disable;

This is confusing and unnecessarily complicated. I think you can achieve
the same thing in a more obvious way like this:

    features_to_disable = features_enabled & ~new_pp_feature_masks;
    features_to_enable = ~features_enabled & new_pp_feature_masks;

Regards,
  Felix

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

end of thread, other threads:[~2019-01-29 21:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-14 10:01 [PATCH 1/4] drm/amd/powerplay: support enabled ppfeatures retrieving and setting Evan Quan
     [not found] ` <20190114100142.16922-1-evan.quan-5C7GfCeVMHo@public.gmane.org>
2019-01-14 10:01   ` [PATCH 2/4] drm/amd/powerplay: support retrieving and adjusting SOC clock power levels Evan Quan
2019-01-14 10:01   ` [PATCH 3/4] drm/amd/powerplay: support retrieving and adjusting fclock " Evan Quan
2019-01-14 10:01   ` [PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock " Evan Quan
     [not found]     ` <20190114100142.16922-4-evan.quan-5C7GfCeVMHo@public.gmane.org>
2019-01-14 16:59       ` Alex Deucher
     [not found]         ` <CADnq5_MQg0z6FCH-3UQCXtLEOdtsS2vQ-YXvgWDNBGoyOSaFbw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2019-01-15  6:44           ` Quan, Evan
     [not found]             ` <SN6PR12MB265648F3ACAE6F52278858D3E4810-kxOKjb6HO/FeL/N0e1LXkAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2019-01-15  6:59               ` Quan, Evan
     [not found]                 ` <SN6PR12MB26560F7F273E30EBFECE50EFE4810-kxOKjb6HO/FeL/N0e1LXkAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2019-01-15 15:19                   ` Deucher, Alexander
2019-01-29 21:59   ` [PATCH 1/4] drm/amd/powerplay: support enabled ppfeatures retrieving and setting Kuehling, Felix

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.