<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p
        {mso-style-priority:99;
        margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">FWIW, temperature and fan are already exposed via standard hwmon interfaces.  It might be better to use standard interfaces for some of these things if they
 exist.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Alex<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org]
<b>On Behalf Of </b>StDenis, Tom<br>
<b>Sent:</b> Thursday, September 15, 2016 9:32 AM<br>
<b>To:</b> Christian König; amd-gfx@lists.freedesktop.org<br>
<b>Subject:</b> Re: [PATCH] drm/amd/amdgpu: Add sensors debugfs support<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p style="background:white"><span style="font-family:"Calibri","sans-serif";color:black">I don't mind splitting this into pp/headers then amdgpu_device.c. <o:p></o:p></span></p>
<p style="background:white"><span style="font-family:"Calibri","sans-serif";color:black"><o:p> </o:p></span></p>
<p style="background:white"><span style="font-family:"Calibri","sans-serif";color:black">Took a bit to get the userland formatting pretty but it works.  Can --top the PM values.  If we could get temp/watt/etc readings in the kernel I could throw those in userland
 too.  <o:p></o:p></span></p>
<p style="background:white"><span style="font-family:"Calibri","sans-serif";color:black"><o:p> </o:p></span></p>
<p style="background:white"><span style="font-family:"Calibri","sans-serif";color:black">Tom<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:12.0pt;background:white"><span style="font-family:"Calibri","sans-serif";color:black"><o:p> </o:p></span></p>
<div>
<div>
<div class="MsoNormal" align="center" style="text-align:center;background:white">
<span style="font-family:"Calibri","sans-serif";color:black">
<hr size="2" width="98%" align="center">
</span></div>
<div id="x_divRplyFwdMsg">
<p class="MsoNormal" style="background:white"><b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:black">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:black"> Christian König <<a href="mailto:deathsimple@vodafone.de">deathsimple@vodafone.de</a>><br>
<b>Sent:</b> Thursday, September 15, 2016 09:29<br>
<b>To:</b> Tom St Denis; <a href="mailto:amd-gfx@lists.freedesktop.org">amd-gfx@lists.freedesktop.org</a><br>
<b>Cc:</b> StDenis, Tom<br>
<b>Subject:</b> Re: [PATCH] drm/amd/amdgpu: Add sensors debugfs support</span><span style="font-family:"Calibri","sans-serif";color:black">
<o:p></o:p></span></p>
<div>
<p class="MsoNormal" style="background:white"><span style="font-family:"Calibri","sans-serif";color:black"> <o:p></o:p></span></p>
</div>
</div>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt;background:white"><span style="font-size:10.0pt;font-family:"Calibri","sans-serif";color:black">Am 15.09.2016 um 15:22 schrieb Tom St Denis:<br>
> This patch adds a callback to powerplay which<br>
> reads specific PP sensors (vdd/clocks/load) which is then<br>
> accessible via debugfs.  The idea being is it'll be a standard<br>
> interface between different ASICs that userland tools can<br>
> read.<br>
><br>
> Currently only CZ/ST is supported but the others are<br>
> NULL'ed off so they shouldn't cause any sort of oops.<br>
><br>
> Signed-off-by: Tom St Denis <<a href="mailto:tom.stdenis@amd.com">tom.stdenis@amd.com</a>><br>
<br>
Might be a good idea to split this into implementing the <br>
backend/frontend functions, but this way works for me as well.<br>
<br>
Acked-by: Christian König <<a href="mailto:christian.koenig@amd.com">christian.koenig@amd.com</a>>.<br>
<br>
Regards,<br>
Christian.<br>
<br>
> ---<br>
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         | 31 +++++++<br>
>   drivers/gpu/drm/amd/powerplay/amd_powerplay.c      | 20 +++++<br>
>   drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c     | 96 ++++++++++++++++++++++<br>
>   drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c   |  1 +<br>
>   .../gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c    |  1 +<br>
>   .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c  |  1 +<br>
>   drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c  |  1 +<br>
>   drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h  | 10 +++<br>
>   drivers/gpu/drm/amd/powerplay/inc/hwmgr.h          |  1 +<br>
>   9 files changed, 162 insertions(+)<br>
><br>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c<br>
> index 9103e7baf26e..b6a4588c95ee 100644<br>
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c<br>
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c<br>
> @@ -2841,6 +2841,29 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,<br>
>        return result;<br>
>   }<br>
>   <br>
> +static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,<br>
> +                                     size_t size, loff_t *pos)<br>
> +{<br>
> +     struct amdgpu_device *adev = f->f_inode->i_private;<br>
> +     int r;<br>
> +     int32_t value;<br>
> +<br>
> +     if (size != 4 || *pos & 0x3)<br>
> +             return -EINVAL;<br>
> +<br>
> +     /* convert offset to sensor number */<br>
> +     *pos >>= 2;<br>
> +<br>
> +     if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor)<br>
> +             r = adev->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, *pos, &value);<br>
> +     else<br>
> +             r = -EINVAL;<br>
> +<br>
> +     if (!r)<br>
> +             r = put_user(value, (int32_t *)buf);<br>
> +<br>
> +     return !r ? 4 : r;<br>
> +}<br>
>   <br>
>   static const struct file_operations amdgpu_debugfs_regs_fops = {<br>
>        .owner = THIS_MODULE,<br>
> @@ -2873,12 +2896,19 @@ static const struct file_operations amdgpu_debugfs_gca_config_fops = {<br>
>        .llseek = default_llseek<br>
>   };<br>
>   <br>
> +static const struct file_operations amdgpu_debugfs_sensors_fops = {<br>
> +     .owner = THIS_MODULE,<br>
> +     .read = amdgpu_debugfs_sensor_read,<br>
> +     .llseek = default_llseek<br>
> +};<br>
> +<br>
>   static const struct file_operations *debugfs_regs[] = {<br>
>        &amdgpu_debugfs_regs_fops,<br>
>        &amdgpu_debugfs_regs_didt_fops,<br>
>        &amdgpu_debugfs_regs_pcie_fops,<br>
>        &amdgpu_debugfs_regs_smc_fops,<br>
>        &amdgpu_debugfs_gca_config_fops,<br>
> +     &amdgpu_debugfs_sensors_fops,<br>
>   };<br>
>   <br>
>   static const char *debugfs_regs_names[] = {<br>
> @@ -2887,6 +2917,7 @@ static const char *debugfs_regs_names[] = {<br>
>        "amdgpu_regs_pcie",<br>
>        "amdgpu_regs_smc",<br>
>        "amdgpu_gca_config",<br>
> +     "amdgpu_sensors",<br>
>   };<br>
>   <br>
>   static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c<br>
> index b1d19409bf86..ee0368381e82 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c<br>
> +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c<br>
> @@ -894,6 +894,25 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value)<br>
>        return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);<br>
>   }<br>
>   <br>
> +static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value)<br>
> +{<br>
> +     struct pp_hwmgr *hwmgr;<br>
> +<br>
> +     if (!handle)<br>
> +             return -EINVAL;<br>
> +<br>
> +     hwmgr = ((struct pp_instance *)handle)->hwmgr;<br>
> +<br>
> +     PP_CHECK_HW(hwmgr);<br>
> +<br>
> +     if (hwmgr->hwmgr_func->read_sensor == NULL) {<br>
> +             printk(KERN_INFO "%s was not implemented.\n", __func__);<br>
> +             return 0;<br>
> +     }<br>
> +<br>
> +     return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value);<br>
> +}<br>
> +<br>
>   const struct amd_powerplay_funcs pp_dpm_funcs = {<br>
>        .get_temperature = pp_dpm_get_temperature,<br>
>        .load_firmware = pp_dpm_load_fw,<br>
> @@ -920,6 +939,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {<br>
>        .set_sclk_od = pp_dpm_set_sclk_od,<br>
>        .get_mclk_od = pp_dpm_get_mclk_od,<br>
>        .set_mclk_od = pp_dpm_set_mclk_od,<br>
> +     .read_sensor = pp_dpm_read_sensor,<br>
>   };<br>
>   <br>
>   static int amd_pp_instance_init(struct amd_pp_init *pp_init,<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c<br>
> index 5ecef1732e20..9f3c5a8a903c 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c<br>
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c<br>
> @@ -1857,6 +1857,101 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c<br>
>        return 0;<br>
>   }<br>
>   <br>
> +static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)<br>
> +{<br>
> +     struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);<br>
> +<br>
> +     struct phm_clock_voltage_dependency_table *table =<br>
> +                             hwmgr->dyn_state.vddc_dependency_on_sclk;<br>
> +<br>
> +     struct phm_vce_clock_voltage_dependency_table *vce_table =<br>
> +             hwmgr->dyn_state.vce_clock_voltage_dependency_table;<br>
> +<br>
> +     struct phm_uvd_clock_voltage_dependency_table *uvd_table =<br>
> +             hwmgr->dyn_state.uvd_clock_voltage_dependency_table;<br>
> +<br>
> +     uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX),<br>
> +                                     TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);<br>
> +     uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),<br>
> +                                     TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);<br>
> +     uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),<br>
> +                                     TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);<br>
> +<br>
> +     uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent;<br>
> +     uint16_t vddnb, vddgfx;<br>
> +     int result;<br>
> +<br>
> +     switch (idx) {<br>
> +     case AMDGPU_PP_SENSOR_GFX_SCLK:<br>
> +             if (sclk_index < NUM_SCLK_LEVELS) {<br>
> +                     sclk = table->entries[sclk_index].clk;<br>
> +                     *value = sclk;<br>
> +                     return 0;<br>
> +             }<br>
> +             return -EINVAL;<br>
> +     case AMDGPU_PP_SENSOR_VDDNB:<br>
> +             tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) &<br>
> +                     CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;<br>
> +             vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp);<br>
> +             *value = vddnb;<br>
> +             return 0;<br>
> +     case AMDGPU_PP_SENSOR_VDDGFX:<br>
> +             tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) &<br>
> +                     CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;<br>
> +             vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp);<br>
> +             *value = vddgfx;<br>
> +             return 0;<br>
> +     case AMDGPU_PP_SENSOR_UVD_VCLK:<br>
> +             if (!cz_hwmgr->uvd_power_gated) {<br>
> +                     if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {<br>
> +                             return -EINVAL;<br>
> +                     } else {<br>
> +                             vclk = uvd_table->entries[uvd_index].vclk;<br>
> +                             *value = vclk;<br>
> +                             return 0;<br>
> +                     }<br>
> +             }<br>
> +             *value = 0;<br>
> +             return 0;<br>
> +     case AMDGPU_PP_SENSOR_UVD_DCLK:<br>
> +             if (!cz_hwmgr->uvd_power_gated) {<br>
> +                     if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {<br>
> +                             return -EINVAL;<br>
> +                     } else {<br>
> +                             dclk = uvd_table->entries[uvd_index].dclk;<br>
> +                             *value = dclk;<br>
> +                             return 0;<br>
> +                     }<br>
> +             }<br>
> +             *value = 0;<br>
> +             return 0;<br>
> +     case AMDGPU_PP_SENSOR_VCE_ECCLK:<br>
> +             if (!cz_hwmgr->vce_power_gated) {<br>
> +                     if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {<br>
> +                             return -EINVAL;<br>
> +                     } else {<br>
> +                             ecclk = vce_table->entries[vce_index].ecclk;<br>
> +                             *value = ecclk;<br>
> +                             return 0;<br>
> +                     }<br>
> +             }<br>
> +             *value = 0;<br>
> +             return 0;<br>
> +     case AMDGPU_PP_SENSOR_GPU_LOAD:<br>
> +             result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity);<br>
> +             if (0 == result) {<br>
> +                     activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);<br>
> +                     activity_percent = activity_percent > 100 ? 100 : activity_percent;<br>
> +             } else {<br>
> +                     activity_percent = 50;<br>
> +             }<br>
> +             *value = activity_percent;<br>
> +             return 0;<br>
> +     default:<br>
> +             return -EINVAL;<br>
> +     }<br>
> +}<br>
> +<br>
>   static const struct pp_hwmgr_func cz_hwmgr_funcs = {<br>
>        .backend_init = cz_hwmgr_backend_init,<br>
>        .backend_fini = cz_hwmgr_backend_fini,<br>
> @@ -1882,6 +1977,7 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = {<br>
>        .get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks,<br>
>        .get_clock_by_type = cz_get_clock_by_type,<br>
>        .get_max_high_clocks = cz_get_max_high_clocks,<br>
> +     .read_sensor = cz_read_sensor,<br>
>   };<br>
>   <br>
>   int cz_hwmgr_init(struct pp_hwmgr *hwmgr)<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c<br>
> index 0d4c99b9e3f9..c64def1884c9 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c<br>
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c<br>
> @@ -5590,6 +5590,7 @@ static const struct pp_hwmgr_func fiji_hwmgr_funcs = {<br>
>        .set_sclk_od = fiji_set_sclk_od,<br>
>        .get_mclk_od = fiji_get_mclk_od,<br>
>        .set_mclk_od = fiji_set_mclk_od,<br>
> +     .read_sensor = NULL,<br>
>   };<br>
>   <br>
>   int fiji_hwmgr_init(struct pp_hwmgr *hwmgr)<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c<br>
> index 5abe43360ec0..d7a1410402d4 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c<br>
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c<br>
> @@ -5663,6 +5663,7 @@ static const struct pp_hwmgr_func iceland_hwmgr_funcs = {<br>
>        .set_sclk_od = iceland_set_sclk_od,<br>
>        .get_mclk_od = iceland_get_mclk_od,<br>
>        .set_mclk_od = iceland_set_mclk_od,<br>
> +     .read_sensor = NULL,<br>
>   };<br>
>   <br>
>   int iceland_hwmgr_init(struct pp_hwmgr *hwmgr)<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c<br>
> index 970e3930452d..8da1d0f66240 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c<br>
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c<br>
> @@ -5278,6 +5278,7 @@ static const struct pp_hwmgr_func polaris10_hwmgr_funcs = {<br>
>        .set_sclk_od = polaris10_set_sclk_od,<br>
>        .get_mclk_od = polaris10_get_mclk_od,<br>
>        .set_mclk_od = polaris10_set_mclk_od,<br>
> +     .read_sensor = NULL,<br>
>   };<br>
>   <br>
>   int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr)<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c<br>
> index 42783bf7647c..a5175ea5bb46 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c<br>
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c<br>
> @@ -6359,6 +6359,7 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = {<br>
>        .set_sclk_od = tonga_set_sclk_od,<br>
>        .get_mclk_od = tonga_get_mclk_od,<br>
>        .set_mclk_od = tonga_set_mclk_od,<br>
> +     .read_sensor = NULL,<br>
>   };<br>
>   <br>
>   int tonga_hwmgr_init(struct pp_hwmgr *hwmgr)<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h<br>
> index 18f39e89a7aa..bafb593b568a 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h<br>
> +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h<br>
> @@ -29,6 +29,15 @@<br>
>   #include "amd_shared.h"<br>
>   #include "cgs_common.h"<br>
>   <br>
> +enum amd_pp_sensors {<br>
> +     AMDGPU_PP_SENSOR_GFX_SCLK = 0,<br>
> +     AMDGPU_PP_SENSOR_VDDNB,<br>
> +     AMDGPU_PP_SENSOR_VDDGFX,<br>
> +     AMDGPU_PP_SENSOR_UVD_VCLK,<br>
> +     AMDGPU_PP_SENSOR_UVD_DCLK,<br>
> +     AMDGPU_PP_SENSOR_VCE_ECCLK,<br>
> +     AMDGPU_PP_SENSOR_GPU_LOAD,<br>
> +};<br>
>   <br>
>   enum amd_pp_event {<br>
>        AMD_PP_EVENT_INITIALIZE = 0,<br>
> @@ -346,6 +355,7 @@ struct amd_powerplay_funcs {<br>
>        int (*set_sclk_od)(void *handle, uint32_t value);<br>
>        int (*get_mclk_od)(void *handle);<br>
>        int (*set_mclk_od)(void *handle, uint32_t value);<br>
> +     int (*read_sensor)(void *handle, int idx, int32_t *value);<br>
>   };<br>
>   <br>
>   struct amd_powerplay {<br>
> diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h<br>
> index e98748344801..310ba0ce2934 100644<br>
> --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h<br>
> +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h<br>
> @@ -359,6 +359,7 @@ struct pp_hwmgr_func {<br>
>        int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);<br>
>        int (*get_mclk_od)(struct pp_hwmgr *hwmgr);<br>
>        int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);<br>
> +     int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, int32_t *value);<br>
>   };<br>
>   <br>
>   struct pp_table_func {<br>
<br>
<o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>