diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 113edffb5960..fdb399821915 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
@@ -918,6 +918,36 @@ fail: | |||
918 | return -EINVAL; | 918 | return -EINVAL; |
919 | } | 919 | } |
920 | 920 | ||
921 | /** | ||
922 | * DOC: busy_percent | ||
923 | * | ||
924 | * The amdgpu driver provides a sysfs API for reading how busy the GPU | ||
925 | * is as a percentage. The file gpu_busy_percent is used for this. | ||
926 | * The SMU firmware computes a percentage of load based on the | ||
927 | * aggregate activity level in the IP cores. | ||
928 | */ | ||
929 | static ssize_t amdgpu_get_busy_percent(struct device *dev, | ||
930 | struct device_attribute *attr, | ||
931 | char *buf) | ||
932 | { | ||
933 | struct drm_device *ddev = dev_get_drvdata(dev); | ||
934 | struct amdgpu_device *adev = ddev->dev_private; | ||
935 | int r, value, size = sizeof(value); | ||
936 | |||
937 | /* sanity check PP is enabled */ | ||
938 | if (!(adev->powerplay.pp_funcs && | ||
939 | adev->powerplay.pp_funcs->read_sensor)) | ||
940 | return -EINVAL; | ||
941 | |||
942 | /* read the IP busy sensor */ | ||
943 | r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, | ||
944 | (void *)&value, &size); | ||
945 | if (r) | ||
946 | return r; | ||
947 | |||
948 | return snprintf(buf, PAGE_SIZE, "%d\n", value); | ||
949 | } | ||
950 | |||
921 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); | 951 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); |
922 | static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, | 952 | static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, |
923 | amdgpu_get_dpm_forced_performance_level, | 953 | amdgpu_get_dpm_forced_performance_level, |
@@ -951,6 +981,8 @@ static DEVICE_ATTR(pp_power_profile_mode, S_IRUGO | S_IWUSR, | |||
951 | static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, | 981 | static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, |
952 | amdgpu_get_pp_od_clk_voltage, | 982 | amdgpu_get_pp_od_clk_voltage, |
953 | amdgpu_set_pp_od_clk_voltage); | 983 | amdgpu_set_pp_od_clk_voltage); |
984 | static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, | ||
985 | amdgpu_get_busy_percent, NULL); | ||
954 | 986 | ||
955 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, | 987 | static ssize_t amdgpu_hwmon_show_temp(struct device *dev, |
956 | struct device_attribute *attr, | 988 | struct device_attribute *attr, |
@@ -1854,6 +1886,13 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) | |||
1854 | "pp_od_clk_voltage\n"); | 1886 | "pp_od_clk_voltage\n"); |
1855 | return ret; | 1887 | return ret; |
1856 | } | 1888 | } |
1889 | ret = device_create_file(adev->dev, | ||
1890 | &dev_attr_gpu_busy_percent); | ||
1891 | if (ret) { | ||
1892 | DRM_ERROR("failed to create device file " | ||
1893 | "gpu_busy_level\n"); | ||
1894 | return ret; | ||
1895 | } | ||
1857 | ret = amdgpu_debugfs_pm_init(adev); | 1896 | ret = amdgpu_debugfs_pm_init(adev); |
1858 | if (ret) { | 1897 | if (ret) { |
1859 | DRM_ERROR("Failed to register debugfs file for dpm!\n"); | 1898 | DRM_ERROR("Failed to register debugfs file for dpm!\n"); |
@@ -1889,6 +1928,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) | |||
1889 | &dev_attr_pp_power_profile_mode); | 1928 | &dev_attr_pp_power_profile_mode); |
1890 | device_remove_file(adev->dev, | 1929 | device_remove_file(adev->dev, |
1891 | &dev_attr_pp_od_clk_voltage); | 1930 | &dev_attr_pp_od_clk_voltage); |
1931 | device_remove_file(adev->dev, &dev_attr_gpu_busy_percent); | ||
1892 | } | 1932 | } |
1893 | 1933 | ||
1894 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) | 1934 | void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) |