aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2019-01-14 01:06:54 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-01-25 16:15:34 -0500
commit7ca881a8651bdeffd99ba8e0010160f9bf60673e (patch)
tree2eae8b802c105eac32ca7d4027eb7dd7d52115b1 /drivers/gpu
parentb61857b5e365889d67a6296c413df396032d374d (diff)
drm/amd/powerplay: support enabled ppfeatures retrieving and setting V3
User can use "ppfeatures" sysfs interface to retrieve and set enabled powerplay features. V2: expose this feature for Vega10 and later dGPUs V3: squash in removal of unused variable (Alex) Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c71
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c42
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c104
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h2
6 files changed, 229 insertions, 0 deletions
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 {
364 ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\ 364 ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\
365 (adev)->powerplay.pp_handle)) 365 (adev)->powerplay.pp_handle))
366 366
367#define amdgpu_dpm_get_ppfeature_status(adev, buf) \
368 ((adev)->powerplay.pp_funcs->get_ppfeature_status(\
369 (adev)->powerplay.pp_handle, (buf)))
370
371#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \
372 ((adev)->powerplay.pp_funcs->set_ppfeature_status(\
373 (adev)->powerplay.pp_handle, (ppfeatures)))
374
367struct amdgpu_dpm { 375struct amdgpu_dpm {
368 struct amdgpu_ps *ps; 376 struct amdgpu_ps *ps;
369 /* number of valid power states */ 377 /* 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 51eb2cf42b81..f21f294e6735 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -626,6 +626,60 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
626} 626}
627 627
628/** 628/**
629 * DOC: ppfeatures
630 *
631 * The amdgpu driver provides a sysfs API for adjusting what powerplay
632 * features to be enabled. The file ppfeatures is used for this. And
633 * this is only available for Vega10 and later dGPUs.
634 *
635 * Reading back the file will show you the followings:
636 * - Current ppfeature masks
637 * - List of the all supported powerplay features with their naming,
638 * bitmasks and enablement status('Y'/'N' means "enabled"/"disabled").
639 *
640 * To manually enable or disable a specific feature, just set or clear
641 * the corresponding bit from original ppfeature masks and input the
642 * new ppfeature masks.
643 */
644static ssize_t amdgpu_set_ppfeature_status(struct device *dev,
645 struct device_attribute *attr,
646 const char *buf,
647 size_t count)
648{
649 struct drm_device *ddev = dev_get_drvdata(dev);
650 struct amdgpu_device *adev = ddev->dev_private;
651 uint64_t featuremask;
652 int ret;
653
654 ret = kstrtou64(buf, 0, &featuremask);
655 if (ret)
656 return -EINVAL;
657
658 pr_debug("featuremask = 0x%llx\n", featuremask);
659
660 if (adev->powerplay.pp_funcs->set_ppfeature_status) {
661 ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask);
662 if (ret)
663 return -EINVAL;
664 }
665
666 return count;
667}
668
669static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
670 struct device_attribute *attr,
671 char *buf)
672{
673 struct drm_device *ddev = dev_get_drvdata(dev);
674 struct amdgpu_device *adev = ddev->dev_private;
675
676 if (adev->powerplay.pp_funcs->get_ppfeature_status)
677 return amdgpu_dpm_get_ppfeature_status(adev, buf);
678
679 return snprintf(buf, PAGE_SIZE, "\n");
680}
681
682/**
629 * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie 683 * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
630 * 684 *
631 * The amdgpu driver provides a sysfs API for adjusting what power levels 685 * The amdgpu driver provides a sysfs API for adjusting what power levels
@@ -1051,6 +1105,9 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR,
1051static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, 1105static DEVICE_ATTR(gpu_busy_percent, S_IRUGO,
1052 amdgpu_get_busy_percent, NULL); 1106 amdgpu_get_busy_percent, NULL);
1053static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); 1107static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL);
1108static DEVICE_ATTR(ppfeatures, S_IRUGO | S_IWUSR,
1109 amdgpu_get_ppfeature_status,
1110 amdgpu_set_ppfeature_status);
1054 1111
1055static ssize_t amdgpu_hwmon_show_temp(struct device *dev, 1112static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
1056 struct device_attribute *attr, 1113 struct device_attribute *attr,
@@ -2241,6 +2298,17 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
2241 return ret; 2298 return ret;
2242 } 2299 }
2243 2300
2301 if ((adev->asic_type >= CHIP_VEGA10) &&
2302 !(adev->flags & AMD_IS_APU)) {
2303 ret = device_create_file(adev->dev,
2304 &dev_attr_ppfeatures);
2305 if (ret) {
2306 DRM_ERROR("failed to create device file "
2307 "ppfeatures\n");
2308 return ret;
2309 }
2310 }
2311
2244 adev->pm.sysfs_initialized = true; 2312 adev->pm.sysfs_initialized = true;
2245 2313
2246 return 0; 2314 return 0;
@@ -2276,6 +2344,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
2276 device_remove_file(adev->dev, &dev_attr_gpu_busy_percent); 2344 device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
2277 if (adev->flags & !AMD_IS_APU) 2345 if (adev->flags & !AMD_IS_APU)
2278 device_remove_file(adev->dev, &dev_attr_pcie_bw); 2346 device_remove_file(adev->dev, &dev_attr_pcie_bw);
2347 if ((adev->asic_type >= CHIP_VEGA10) &&
2348 !(adev->flags & AMD_IS_APU))
2349 device_remove_file(adev->dev, &dev_attr_ppfeatures);
2279} 2350}
2280 2351
2281void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) 2352void 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 {
284 int (*get_asic_baco_capability)(void *handle, bool *cap); 284 int (*get_asic_baco_capability)(void *handle, bool *cap);
285 int (*get_asic_baco_state)(void *handle, int *state); 285 int (*get_asic_baco_state)(void *handle, int *state);
286 int (*set_asic_baco_state)(void *handle, int state); 286 int (*set_asic_baco_state)(void *handle, int state);
287 int (*get_ppfeature_status)(void *handle, char *buf);
288 int (*set_ppfeature_status)(void *handle, uint64_t ppfeature_masks);
287}; 289};
288 290
289#endif 291#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)
1455 return 0; 1455 return 0;
1456} 1456}
1457 1457
1458static int pp_get_ppfeature_status(void *handle, char *buf)
1459{
1460 struct pp_hwmgr *hwmgr = handle;
1461 int ret = 0;
1462
1463 if (!hwmgr || !hwmgr->pm_en || !buf)
1464 return -EINVAL;
1465
1466 if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {
1467 pr_info_ratelimited("%s was not implemented.\n", __func__);
1468 return -EINVAL;
1469 }
1470
1471 mutex_lock(&hwmgr->smu_lock);
1472 ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);
1473 mutex_unlock(&hwmgr->smu_lock);
1474
1475 return ret;
1476}
1477
1478static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)
1479{
1480 struct pp_hwmgr *hwmgr = handle;
1481 int ret = 0;
1482
1483 if (!hwmgr || !hwmgr->pm_en)
1484 return -EINVAL;
1485
1486 if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {
1487 pr_info_ratelimited("%s was not implemented.\n", __func__);
1488 return -EINVAL;
1489 }
1490
1491 mutex_lock(&hwmgr->smu_lock);
1492 ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);
1493 mutex_unlock(&hwmgr->smu_lock);
1494
1495 return ret;
1496}
1497
1458static const struct amd_pm_funcs pp_dpm_funcs = { 1498static const struct amd_pm_funcs pp_dpm_funcs = {
1459 .load_firmware = pp_dpm_load_fw, 1499 .load_firmware = pp_dpm_load_fw,
1460 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, 1500 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
@@ -1508,4 +1548,6 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
1508 .get_asic_baco_capability = pp_get_asic_baco_capability, 1548 .get_asic_baco_capability = pp_get_asic_baco_capability,
1509 .get_asic_baco_state = pp_get_asic_baco_state, 1549 .get_asic_baco_state = pp_get_asic_baco_state,
1510 .set_asic_baco_state = pp_set_asic_baco_state, 1550 .set_asic_baco_state = pp_set_asic_baco_state,
1551 .get_ppfeature_status = pp_get_ppfeature_status,
1552 .set_ppfeature_status = pp_set_ppfeature_status,
1511}; 1553};
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 2ba387b0f27c..3e97b9d6f450 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -2776,6 +2776,108 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
2776 return 0; 2776 return 0;
2777} 2777}
2778 2778
2779static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
2780{
2781 static const char *ppfeature_name[] = {
2782 "DPM_PREFETCHER",
2783 "GFXCLK_DPM",
2784 "UCLK_DPM",
2785 "SOCCLK_DPM",
2786 "UVD_DPM",
2787 "VCE_DPM",
2788 "ULV",
2789 "MP0CLK_DPM",
2790 "LINK_DPM",
2791 "DCEFCLK_DPM",
2792 "GFXCLK_DS",
2793 "SOCCLK_DS",
2794 "LCLK_DS",
2795 "PPT",
2796 "TDC",
2797 "THERMAL",
2798 "GFX_PER_CU_CG",
2799 "RM",
2800 "DCEFCLK_DS",
2801 "ACDC",
2802 "VR0HOT",
2803 "VR1HOT",
2804 "FW_CTF",
2805 "LED_DISPLAY",
2806 "FAN_CONTROL",
2807 "GFX_EDC",
2808 "GFXOFF",
2809 "CG",
2810 "FCLK_DPM",
2811 "FCLK_DS",
2812 "MP1CLK_DS",
2813 "MP0CLK_DS",
2814 "XGMI"};
2815 static const char *output_title[] = {
2816 "FEATURES",
2817 "BITMASK",
2818 "ENABLEMENT"};
2819 uint64_t features_enabled;
2820 int i;
2821 int ret = 0;
2822 int size = 0;
2823
2824 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
2825 PP_ASSERT_WITH_CODE(!ret,
2826 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
2827 return ret);
2828
2829 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
2830 size += sprintf(buf + size, "%-19s %-22s %s\n",
2831 output_title[0],
2832 output_title[1],
2833 output_title[2]);
2834 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
2835 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
2836 ppfeature_name[i],
2837 1ULL << i,
2838 (features_enabled & (1ULL << i)) ? "Y" : "N");
2839 }
2840
2841 return size;
2842}
2843
2844static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
2845{
2846 uint64_t features_enabled;
2847 uint64_t features_to_enable;
2848 uint64_t features_to_disable;
2849 int ret = 0;
2850
2851 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
2852 return -EINVAL;
2853
2854 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
2855 if (ret)
2856 return ret;
2857
2858 features_to_disable =
2859 (features_enabled ^ new_ppfeature_masks) & features_enabled;
2860 features_to_enable =
2861 (features_enabled ^ new_ppfeature_masks) ^ features_to_disable;
2862
2863 pr_debug("features_to_disable 0x%llx\n", features_to_disable);
2864 pr_debug("features_to_enable 0x%llx\n", features_to_enable);
2865
2866 if (features_to_disable) {
2867 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
2868 if (ret)
2869 return ret;
2870 }
2871
2872 if (features_to_enable) {
2873 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
2874 if (ret)
2875 return ret;
2876 }
2877
2878 return 0;
2879}
2880
2779static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, 2881static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
2780 enum pp_clock_type type, char *buf) 2882 enum pp_clock_type type, char *buf)
2781{ 2883{
@@ -3572,6 +3674,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
3572 .force_clock_level = vega20_force_clock_level, 3674 .force_clock_level = vega20_force_clock_level,
3573 .print_clock_levels = vega20_print_clock_levels, 3675 .print_clock_levels = vega20_print_clock_levels,
3574 .read_sensor = vega20_read_sensor, 3676 .read_sensor = vega20_read_sensor,
3677 .get_ppfeature_status = vega20_get_ppfeature_status,
3678 .set_ppfeature_status = vega20_set_ppfeature_status,
3575 /* powergate related */ 3679 /* powergate related */
3576 .powergate_uvd = vega20_power_gate_uvd, 3680 .powergate_uvd = vega20_power_gate_uvd,
3577 .powergate_vce = vega20_power_gate_vce, 3681 .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 {
341 int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); 341 int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap);
342 int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); 342 int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
343 int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); 343 int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
344 int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf);
345 int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks);
344}; 346};
345 347
346struct pp_table_func { 348struct pp_table_func {