diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1053-drm-amdgpu-expose-sclk-and-mclk-via-hwmon.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/1053-drm-amdgpu-expose-sclk-and-mclk-via-hwmon.patch | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1053-drm-amdgpu-expose-sclk-and-mclk-via-hwmon.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1053-drm-amdgpu-expose-sclk-and-mclk-via-hwmon.patch new file mode 100644 index 00000000..49ec3e85 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1053-drm-amdgpu-expose-sclk-and-mclk-via-hwmon.patch @@ -0,0 +1,162 @@ +From 06ca134cca5414ab41d4dfc47226a755c46a64e4 Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexander.deucher@amd.com> +Date: Mon, 10 Dec 2018 16:04:15 -0500 +Subject: [PATCH 1053/2940] drm/amdgpu: expose sclk and mclk via hwmon + +Expose sclk (gfx clock) and mclk (memory clock) via +hwmon compatible interface. hwmon does not actually +formally specify a frequency type attribute, but these +are compatible with the format of the other attributes +exposed via hwmon. Units are hertz. + +freq1_input - GPU gfx/compute clock in hertz +freq2_input - GPU memory clock in hertz (dGPU only) + +Reviewed-by: Evan Quan <evan.quan@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 93 ++++++++++++++++++++++++++ + 1 file changed, 93 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +index b38c06f0196e..51eb2cf42b81 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +@@ -1542,6 +1542,75 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, + return count; + } + ++static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct amdgpu_device *adev = dev_get_drvdata(dev); ++ struct drm_device *ddev = adev->ddev; ++ uint32_t sclk; ++ int r, size = sizeof(sclk); ++ ++ /* Can't get voltage when the card is off */ ++ if ((adev->flags & AMD_IS_PX) && ++ (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) ++ return -EINVAL; ++ ++ /* sanity check PP is enabled */ ++ if (!(adev->powerplay.pp_funcs && ++ adev->powerplay.pp_funcs->read_sensor)) ++ return -EINVAL; ++ ++ /* get the sclk */ ++ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, ++ (void *)&sclk, &size); ++ if (r) ++ return r; ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000); ++} ++ ++static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "sclk\n"); ++} ++ ++static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct amdgpu_device *adev = dev_get_drvdata(dev); ++ struct drm_device *ddev = adev->ddev; ++ uint32_t mclk; ++ int r, size = sizeof(mclk); ++ ++ /* Can't get voltage when the card is off */ ++ if ((adev->flags & AMD_IS_PX) && ++ (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) ++ return -EINVAL; ++ ++ /* sanity check PP is enabled */ ++ if (!(adev->powerplay.pp_funcs && ++ adev->powerplay.pp_funcs->read_sensor)) ++ return -EINVAL; ++ ++ /* get the sclk */ ++ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, ++ (void *)&mclk, &size); ++ if (r) ++ return r; ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000); ++} ++ ++static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "mclk\n"); ++} + + /** + * DOC: hwmon +@@ -1558,6 +1627,10 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, + * + * - GPU fan + * ++ * - GPU gfx/compute engine clock ++ * ++ * - GPU memory clock (dGPU only) ++ * + * hwmon interfaces for GPU temperature: + * + * - temp1_input: the on die GPU temperature in millidegrees Celsius +@@ -1602,6 +1675,12 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, + * + * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable + * ++ * hwmon interfaces for GPU clocks: ++ * ++ * - freq1_input: the gfx/compute clock in hertz ++ * ++ * - freq2_input: the memory clock in hertz ++ * + * You can use hwmon tools like sensors to view this information on your system. + * + */ +@@ -1626,6 +1705,10 @@ static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg, + static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0); + static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0); + static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0); ++static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0); ++static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0); ++static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, amdgpu_hwmon_show_mclk, NULL, 0); ++static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, amdgpu_hwmon_show_mclk_label, NULL, 0); + + static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, +@@ -1648,6 +1731,10 @@ static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_power1_cap_max.dev_attr.attr, + &sensor_dev_attr_power1_cap_min.dev_attr.attr, + &sensor_dev_attr_power1_cap.dev_attr.attr, ++ &sensor_dev_attr_freq1_input.dev_attr.attr, ++ &sensor_dev_attr_freq1_label.dev_attr.attr, ++ &sensor_dev_attr_freq2_input.dev_attr.attr, ++ &sensor_dev_attr_freq2_label.dev_attr.attr, + NULL + }; + +@@ -1738,6 +1825,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, + attr == &sensor_dev_attr_in1_label.dev_attr.attr)) + return 0; + ++ /* no mclk on APUs */ ++ if ((adev->flags & AMD_IS_APU) && ++ (attr == &sensor_dev_attr_freq2_input.dev_attr.attr || ++ attr == &sensor_dev_attr_freq2_label.dev_attr.attr)) ++ return 0; ++ + return effective_mode; + } + +-- +2.17.1 + |