> -----Original Message----- > From: Alex Deucher <alexdeucher at gmail.com> > Sent: Friday, August 24, 2018 11:48 PM > To: Quan, Evan <Evan.Quan at amd.com> > Cc: amd-gfx list <amd-gfx at lists.freedesktop.org>; Xu, Feifei > <Feifei.Xu at amd.com>; Kuehling, Felix <Felix.Kuehling at amd.com>; Deucher, > Alexander <Alexander.Deucher at amd.com>; Zhu, Rex <Rex.Zhu at amd.com>; > Zhang, Hawking <Hawking.Zhang at amd.com> > Subject: Re: [PATCH] drm/amd/powerplay: expose vega20 OD features > > On Fri, Aug 24, 2018 at 3:45 AM Evan Quan <evan.quan at amd.com> wrote: > > > > Vega20 simplifies the OD logics and it can not fit old OD interfaces. > > Thus we design new OD interfaces for vega20. > > Please split this into two patches, one to add the internal od8_settings API, > and one to wire it up to sysfs. A few more comments below. > > > > > Change-Id: I888faec46a81287ae24f452ce16b42c1f6d06d7d > > Signed-off-by: Evan Quan <evan.quan at amd.com> > > --- > > drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 8 + > > drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 125 ++++++++++++ > > .../gpu/drm/amd/include/kgd_pp_interface.h | 2 + > > drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 37 ++++ > > .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 191 > +++++++++++++++++- > > drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 + > > 6 files changed, 362 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > > index ff24e1cc5b65..84b3e6f87abf 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > > @@ -357,6 +357,14 @@ enum amdgpu_pcie_gen { > > ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ > > (adev)->powerplay.pp_handle, type, parameter, > > size)) > > > > +#define amdgpu_dpm_get_od8_settings(adev, buf) \ > > + ((adev)->powerplay.pp_funcs->get_od8_settings(\ > > + (adev)->powerplay.pp_handle, buf)) > > + > > +#define amdgpu_dpm_set_od8_settings(adev, parameter, size) \ > > + ((adev)->powerplay.pp_funcs->set_od8_settings(\ > > + (adev)->powerplay.pp_handle, parameter, size)) > > + > > struct amdgpu_dpm { > > struct amdgpu_ps *ps; > > /* 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 daa55fb06171..94cd7c503372 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c > > @@ -934,6 +934,121 @@ static ssize_t amdgpu_get_busy_percent(struct > device *dev, > > return snprintf(buf, PAGE_SIZE, "%d\n", value); } > > > > +/** > > + * DOC: pp_od8_settings > > + * > > + * The amdgpu driver provides a sysfs API for adjusting the clocks, > > +voltages, > > + * power limit, fan speed and temperature. The pp_od8_settings is > > +used for > > + * this. > > + * > > + * Reading the file will display: > > + * > > + * - a name list of the features that are able to be adjusted > > + * > > + * - the mininum and maximum allowed value for each supported > > + * feature labeled in format of "[mininum - maximum]" > > + * > > + * - the current value for each supported feature labeled after > > + * ":" > > + * > > + * To manually adjust these settings: > > + * > > + * - write a string that contains the new value for each supported > > + * feature. For those which do not need to be changed, just enter > > + * their old value > > + * > > + * - make sure the new value is within the allowed ranges between > > + * the minimum and maximum > > We should probably also make it a set and commit model like we do for > previous asics for consistency. That way you can see the changes, and then > apply them. > > > + * > > + * All the possible supported features: > > + * > > + * - Gfx clock > > + * The min and max frequency can be specified by GfxclkFmin > > + * and GfxclkFmax(both in Mhz). Intermediate levels are > > + * stretched/shrunk according to ratio in original table. > > + * > > + * - Gfx voltage > > + * With three pairs of gfx clk(in Mhz) and offset voltage(in mV) > > + * combinations specified, smu fw can calibrate the voltage > > + * curve automatically. > > + * - GfxclkFreq1 <-> GfxclkOffsetVolt1 > > + * - GfxclkFreq2 <-> GfxclkOffsetVolt2 > > + * - GfxclkFreq3 <-> GfxclkOffsetVolt3 > > + * > > + * - Uclk > > + * The max memory clock can be specified by UclkFmax(in Mhz). > > + * > > + * - Power limit > > + * The power limit can be increased or descreased by > > + * OverDrivePct(in percent). > > We already expose the power limit via hwmon. Do we still need it here? > > > + * > > + * - Fan spped > > spped -> speed > > > + * The max fan speed can be set by FanMaxinumRpm and the > > FanMaxinumRpm -> FanMaximumRpm > > > + * min fan speed by FanMinimumPwm. Also zero rpm enablement > > + * is specified by FanZeroRpmEnable. > > + * > > + * - Temperature > > + * The fan target temperature can be set by FanTargetTemperature > > + * and max Tj temperature by MaxOpTemp. > > The fan and temp stuff might be a better fit for the hwmon interfaces: > https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface > > > + * > > + */ > > + > > +static ssize_t amdgpu_get_pp_od8_settings(struct device *dev, > > + struct device_attribute *attr, > > + char *buf) > > +{ > > + struct drm_device *ddev = dev_get_drvdata(dev); > > + struct amdgpu_device *adev = ddev->dev_private; > > + > > + if (adev->powerplay.pp_funcs->get_od8_settings) > > + return amdgpu_dpm_get_od8_settings(adev, buf); > > + > > + return snprintf(buf, PAGE_SIZE, "\n"); } > > + > > +static ssize_t amdgpu_set_pp_od8_settings(struct device *dev, > > + struct device_attribute *attr, > > + const char *buf, > > + size_t count) > > +{ > > + struct drm_device *ddev = dev_get_drvdata(dev); > > + struct amdgpu_device *adev = ddev->dev_private; > > + char *sub_str, *tmp_str, buf_cpy[128]; > > + const char delimiter[3] = {' ', '\n', '\0'}; > > + uint32_t parameter_size = 0; > > + long parameter[64]; > > + int ret = 0xff; > > + > > + if (count >= sizeof(buf_cpy) / sizeof(buf_cpy[0])) > > + return -EINVAL; > > + > > + memcpy(buf_cpy, buf, count); > > + buf_cpy[count] = '\0'; > > + > > + tmp_str = buf_cpy; > > + > > + while (isspace(*tmp_str)) tmp_str++; > > + > > + while (tmp_str[0]) { > > + sub_str = strsep(&tmp_str, delimiter); > > + ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); > > + if (ret) > > + return -EINVAL; > > + parameter_size++; > > + > > + while (isspace(*tmp_str)) > > + tmp_str++; > > + } > > + > > + if (adev->powerplay.pp_funcs->set_od8_settings) > > + ret = amdgpu_dpm_set_od8_settings(adev, parameter, > > + parameter_size); > > + > > + if (ret) > > + return -EINVAL; > > + > > + return count; > > +} > > + > > static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, > > amdgpu_get_dpm_state, amdgpu_set_dpm_state); static > DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, > > amdgpu_get_dpm_forced_performance_level, > > @@ -969,6 +1084,9 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO > | S_IWUSR, > > amdgpu_set_pp_od_clk_voltage); static > > DEVICE_ATTR(gpu_busy_percent, S_IRUGO, > > amdgpu_get_busy_percent, NULL); > > +static DEVICE_ATTR(pp_od8_settings, S_IRUGO | S_IWUSR, > > + amdgpu_get_pp_od8_settings, > > + amdgpu_set_pp_od8_settings); > > Rather than adding a new file, would it make more sense to expose this new > API on the same file we use for older asics? Otherwise, every time the > interface changes, we'll need to add a new file. We already handle asic > specific differences in the power profile sysfs files. > > > > > static ssize_t amdgpu_hwmon_show_temp(struct device *dev, > > struct device_attribute *attr, > > @@ -1879,6 +1997,13 @@ int amdgpu_pm_sysfs_init(struct > amdgpu_device *adev) > > "gpu_busy_level\n"); > > return ret; > > } > > + ret = device_create_file(adev->dev, > > + &dev_attr_pp_od8_settings); > > + if (ret) { > > + DRM_ERROR("failed to create device file " > > + "pp_od8_settings\n"); > > + return ret; > > + } > > ret = amdgpu_debugfs_pm_init(adev); > > if (ret) { > > DRM_ERROR("Failed to register debugfs file for > > dpm!\n"); diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h > > b/drivers/gpu/drm/amd/include/kgd_pp_interface.h > > index 6a41b81c7325..e23746ba53bf 100644 > > --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h > > +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h > > @@ -269,6 +269,8 @@ struct amd_pm_funcs { > > int (*get_display_mode_validation_clocks)(void *handle, > > struct amd_pp_simple_clock_info *clocks); > > int (*notify_smu_enable_pwe)(void *handle); > > + int (*get_od8_settings)(void *handle, char *buf); > > + int (*set_od8_settings)(void *handle, long *input, uint32_t > > + size); > > }; > > > > #endif > > diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > > b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > > index da4ebff5b74d..4bcd06306698 100644 > > --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > > +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c > > @@ -883,6 +883,41 @@ static int pp_odn_edit_dpm_table(void *handle, > uint32_t type, long *input, uint3 > > return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, > > input, size); } > > > > +static int pp_get_od8_settings(void *handle, char *buf) { > > + struct pp_hwmgr *hwmgr = handle; > > + > > + if (!hwmgr || !hwmgr->pm_en || !buf) > > + return -EINVAL; > > + > > + if (hwmgr->hwmgr_func->get_od8_settings == NULL) { > > + pr_info("%s was not implemented.\n", __func__); > > + return snprintf(buf, PAGE_SIZE, "\n"); > > + } > > + > > + return hwmgr->hwmgr_func->get_od8_settings(hwmgr, buf); } > > + > > +static int pp_set_od8_settings(void *handle, long *input, uint32_t > > +size) { > > + struct pp_hwmgr *hwmgr = handle; > > + int ret = -EINVAL; > > + > > + if (!hwmgr || !hwmgr->pm_en) > > + return ret; > > + > > + if (hwmgr->hwmgr_func->set_od8_settings == NULL) { > > + pr_info("%s was not implemented.\n", __func__); > > + return ret; > > + } > > + > > + mutex_lock(&hwmgr->smu_lock); > > + ret = hwmgr->hwmgr_func->set_od8_settings(hwmgr, input, size); > > + mutex_unlock(&hwmgr->smu_lock); > > + > > + return ret; > > +} > > + > > static int pp_dpm_switch_power_profile(void *handle, > > enum PP_SMC_POWER_PROFILE type, bool en) { @@ -1272,6 > > +1307,8 @@ static const struct amd_pm_funcs pp_dpm_funcs = { > > .get_power_profile_mode = pp_get_power_profile_mode, > > .set_power_profile_mode = pp_set_power_profile_mode, > > .odn_edit_dpm_table = pp_odn_edit_dpm_table, > > + .get_od8_settings = pp_get_od8_settings, > > + .set_od8_settings = pp_set_od8_settings, > > .set_power_limit = pp_set_power_limit, > > .get_power_limit = pp_get_power_limit, > > /* export to DC */ > > diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c > > b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c > > index fb32b28afa66..ececa2f7fe5f 100644 > > --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c > > +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c > > @@ -1099,7 +1099,188 @@ static int > vega20_od8_initialize_default_settings( > > return 0; > > } > > > > -static int vega20_od8_set_settings( > > +static int vega20_get_od8_settings( > > + struct pp_hwmgr *hwmgr, > > + char *buf) > > +{ > > + struct vega20_hwmgr *data = > > + (struct vega20_hwmgr *)(hwmgr->backend); > > + struct vega20_od8_single_setting *od8_settings = > > + data->od8_settings.od8_settings_array; > > + OverDriveTable_t od_table; > > + uint32_t size = 0; > > + int ret = 0; > > + > > + if (!buf) > > + return -EINVAL; > > + > > + ret = vega20_copy_table_from_smc(hwmgr, > > + (uint8_t *)(&od_table), > > + TABLE_OVERDRIVE); > > + PP_ASSERT_WITH_CODE(!ret, > > + "Failed to export over drive table!", > > + return ret); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFmin", > > + od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, > > + od8_settings[OD8_SETTING_GFXCLK_FMIN].max_value, > > + od_table.GfxclkFmin); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFmax", > > + od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value, > > + od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value, > > + od_table.GfxclkFmax); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFreq1", > > + od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, > > + od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value, > > + od_table.GfxclkFreq1); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "GfxclkOffsetVolt1", > > + > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, > > + > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value, > > + od_table.GfxclkOffsetVolt1); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFreq2", > > + od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, > > + od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value, > > + od_table.GfxclkFreq2); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "GfxclkOffsetVolt2", > > + > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, > > + > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value, > > + od_table.GfxclkOffsetVolt2); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "GfxclkFreq3", > > + od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, > > + od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value, > > + od_table.GfxclkFreq3); > > + > > + if (od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "GfxclkOffsetVolt3", > > + > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, > > + > od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value, > > + od_table.GfxclkOffsetVolt3); > > + > > + if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "UclkFmax", > > + od8_settings[OD8_SETTING_UCLK_FMAX].min_value, > > + od8_settings[OD8_SETTING_UCLK_FMAX].max_value, > > + od_table.UclkFmax); > > + > > + if (od8_settings[OD8_SETTING_POWER_PERCENTAGE].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "OverDrivePct", > > + > od8_settings[OD8_SETTING_POWER_PERCENTAGE].min_value, > > + > od8_settings[OD8_SETTING_POWER_PERCENTAGE].max_value, > > + od_table.OverDrivePct); > > + > > + if (od8_settings[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "FanMaximumRpm", > > + > od8_settings[OD8_SETTING_FAN_ACOUSTIC_LIMIT].min_value, > > + > od8_settings[OD8_SETTING_FAN_ACOUSTIC_LIMIT].max_value, > > + od_table.FanMaximumRpm); > > + > > + if (od8_settings[OD8_SETTING_FAN_MIN_SPEED].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "FanMinimumPwm", > > + > od8_settings[OD8_SETTING_FAN_MIN_SPEED].min_value, > > + > od8_settings[OD8_SETTING_FAN_MIN_SPEED].max_value, > > + od_table.FanMinimumPwm); > > + > > + if (od8_settings[OD8_SETTING_FAN_TARGET_TEMP].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "FanTargetTemperautre", > > + > od8_settings[OD8_SETTING_FAN_TARGET_TEMP].min_value, > > + > od8_settings[OD8_SETTING_FAN_TARGET_TEMP].max_value, > > + od_table.FanTargetTemperature); > > + > > + if (od8_settings[OD8_SETTING_OPERATING_TEMP_MAX].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", "MaxOpTemp", > > + > od8_settings[OD8_SETTING_OPERATING_TEMP_MAX].min_value, > > + > od8_settings[OD8_SETTING_OPERATING_TEMP_MAX].max_value, > > + od_table.MaxOpTemp); > > + > > + if (od8_settings[OD8_SETTING_FAN_ZERO_RPM_CONTROL].feature_id) > > + size += sprintf(buf + size, "%22s[%d - %d]: %u\n", > "FanZeroRpmEnable", > > + > od8_settings[OD8_SETTING_FAN_ZERO_RPM_CONTROL].min_value, > > + > od8_settings[OD8_SETTING_FAN_ZERO_RPM_CONTROL].max_value, > > + od_table.FanZeroRpmEnable); > > + > > + return size; > > +} > > + > > +static int vega20_set_od8_settings( > > + struct pp_hwmgr *hwmgr, > > + long *input, > > + uint32_t size) > > +{ > > + struct vega20_hwmgr *data = > > + (struct vega20_hwmgr *)(hwmgr->backend); > > + struct vega20_od8_single_setting *od8_settings = > > + data->od8_settings.od8_settings_array; > > + OverDriveTable_t od_table; > > + uint16_t *buf = (uint16_t *)(&od_table); > > + uint32_t i, j = 0, k; > > + int ret = 0; > > + > > + /* retrieve current overdrive settings */ > > + ret = vega20_copy_table_from_smc(hwmgr, > > + (uint8_t *)(&od_table), > > + TABLE_OVERDRIVE); > > + PP_ASSERT_WITH_CODE(!ret, > > + "Failed to export over drive table!", > > + return ret); > > + > > + for (i = 0; > > + i < (sizeof(OverDriveTable_t) / sizeof(uint16_t)) - 1; > > + i++) { > > + /* overdrive table supports no dram timing setting */ > > + k = (i == OD8_SETTING_AC_TIMING) ? > > + OD8_SETTING_FAN_ZERO_RPM_CONTROL : i; > > + /* > > + * Not all OD settings are supported and exported > > + * to user. > > + * So, updated only those which are supported and > > + * exported to user. > > + */ > > + if (od8_settings[k].feature_id) { > > + if (input[j] < od8_settings[k].min_value || > > + input[j] > od8_settings[k].max_value) > > + return -EINVAL; > > + > > + buf[i] = input[j]; > > + if (j++ >= size - 1) > > + break; > > + } > > + } > > + > > + /* enable the new overdrive settings */ > > + ret = vega20_copy_table_to_smc(hwmgr, > > + (uint8_t *)(&od_table), > > + TABLE_OVERDRIVE); > > + PP_ASSERT_WITH_CODE(!ret, > > + "Failed to import over drive table!", > > + return ret); > > + > > + /* update the current_value of overdrive settings */ > > + for (i = 0; > > + i < (sizeof(OverDriveTable_t) / sizeof(uint16_t)) - 1; > > + i++) { > > + k = (i == OD8_SETTING_AC_TIMING) ? > > + OD8_SETTING_FAN_ZERO_RPM_CONTROL : i; > > + if (od8_settings[k].feature_id) > > + od8_settings[k].current_value = buf[i]; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_od8_set_single_setting( > > struct pp_hwmgr *hwmgr, > > uint32_t index, > > uint32_t value) > > @@ -1198,7 +1379,7 @@ static int vega20_set_sclk_od( > > do_div(od_sclk, 100); > > od_sclk += > > golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; > > > > - ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, > od_sclk); > > + ret = vega20_od8_set_single_setting(hwmgr, > > + OD8_SETTING_GFXCLK_FMAX, od_sclk); > > PP_ASSERT_WITH_CODE(!ret, > > "[SetSclkOD] failed to set od gfxclk!", > > return ret); > > @@ -1245,7 +1426,7 @@ static int vega20_set_mclk_od( > > do_div(od_mclk, 100); > > od_mclk += > > golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; > > > > - ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, > od_mclk); > > + ret = vega20_od8_set_single_setting(hwmgr, > > + OD8_SETTING_UCLK_FMAX, od_mclk); > > PP_ASSERT_WITH_CODE(!ret, > > "[SetMclkOD] failed to set od memclk!", > > return ret); > > @@ -2966,6 +3147,10 @@ static const struct pp_hwmgr_func > vega20_hwmgr_funcs = { > > vega20_get_power_profile_mode, > > .set_power_profile_mode = > > vega20_set_power_profile_mode, > > + .get_od8_settings = > > + vega20_get_od8_settings, > > + .set_od8_settings = > > + vega20_set_od8_settings, > > /* od related */ > > .set_power_limit = > > vega20_set_power_limit, diff --git > > a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h > > b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h > > index a6d92128b19c..285af1728e2e 100644 > > --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h > > +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h > > @@ -328,6 +328,8 @@ struct pp_hwmgr_func { > > int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n); > > int (*powergate_mmhub)(struct pp_hwmgr *hwmgr); > > int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); > > + int (*get_od8_settings)(struct pp_hwmgr *hwmgr, char *buf); > > + int (*set_od8_settings)(struct pp_hwmgr *hwmgr, long *input, > > + uint32_t size); Those new added interfaces for OD parameters get/set seems have no difference with the old interface. int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, enum PP_OD_DPM_TABLE_COMMAND type, long *input, uint32_t size); Regards Rex > > }; > > > > struct pp_table_func { > > -- > > 2.18.0 > > > > _______________________________________________ > > amd-gfx mailing list > > amd-gfx at lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/amd-gfx