diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 71 |
1 files changed, 71 insertions, 0 deletions
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 | */ | ||
644 | static 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 | |||
669 | static 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, | |||
1051 | static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, | 1105 | static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, |
1052 | amdgpu_get_busy_percent, NULL); | 1106 | amdgpu_get_busy_percent, NULL); |
1053 | static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); | 1107 | static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); |
1108 | static DEVICE_ATTR(ppfeatures, S_IRUGO | S_IWUSR, | ||
1109 | amdgpu_get_ppfeature_status, | ||
1110 | amdgpu_set_ppfeature_status); | ||
1054 | 1111 | ||
1055 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, | 1112 | static 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 | ||
2281 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | 2352 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) |