Thanks for adding these. Some comments inline. > -----Original Message----- > From: amd-gfx <amd-gfx-bounces@xxxxxxxxxxxxxxxxxxxxx> On Behalf Of Matt > Coffin > Sent: Friday, November 8, 2019 2:34 AM > To: amd-gfx@xxxxxxxxxxxxxxxxxxxxx > Cc: Matt Coffin <mcoffin13@xxxxxxxxx> > Subject: [PATCH 1/3] drm/amdgpu/navi10: implement sclk/mclk OD via > pp_od_clk_voltage > > [Why] > Before this patch, there was no way to use pp_od_clk_voltage on navi > > [How] > Similar to the vega20 implementation, but using the common smc_v11_0 > headers, implemented the pp_od_clk_voltage API for navi10's pptable > implementation > --- > drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 1 + > drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 185 ++++++++++++++++++ > drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 27 +++ > 3 files changed, 213 insertions(+) > > diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h > b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h > index 5bda8539447a..133a53da6785 100644 > --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h > +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h > @@ -130,6 +130,7 @@ enum smu_v11_0_baco_seq { > BACO_SEQ_COUNT, > }; > > +int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool > +initialize, size_t overdrive_table_size); > void smu_v11_0_set_smu_funcs(struct smu_context *smu); > > #endif > diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > index 0b461404af6b..6d0e511ad093 100644 > --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > @@ -1591,6 +1591,189 @@ static int navi10_get_power_limit(struct > smu_context *smu, > return 0; > } > > +static inline void navi10_dump_od_table(OverDriveTable_t *od_table) { > + pr_debug("OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table- > >GfxclkFmax); > + pr_debug("OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table- > >GfxclkVolt1); > + pr_debug("OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table- > >GfxclkVolt2); > + pr_debug("OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table- > >GfxclkVolt3); > + pr_debug("OD: UclkFmax: %d\n", od_table->UclkFmax); > + pr_debug("OD: OverDrivePct: %d\n", od_table->OverDrivePct); } > + > +static inline bool navi10_od_feature_is_supported(struct > +smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_ID > feature) { > + return od_table->cap[feature]; > +} > + > +static int navi10_od_setting_check_range(struct > +smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODSETTING_ID > setting, uint32_t value) { > + if (value < od_table->min[setting]) { > + pr_warn("OD setting (%d, %d) is less than the minimum > allowed (%d)\n", setting, value, od_table->min[setting]); > + return -EINVAL; > + } > + if (value > od_table->max[setting]) { > + pr_warn("OD setting (%d, %d) is greater than the maximum > allowed (%d)\n", setting, value, od_table->max[setting]); > + return -EINVAL; > + } > + return 0; > +} > + > +static int navi10_setup_od_limits(struct smu_context *smu) { > + struct smu_11_0_overdrive_table *overdrive_table = NULL; > + struct smu_11_0_powerplay_table *powerplay_table = NULL; > + > + if (!smu->smu_table.power_play_table) { > + pr_err("powerplay table uninitialized!\n"); > + return -ENOENT; > + } > + powerplay_table = (struct smu_11_0_powerplay_table *)smu- > >smu_table.power_play_table; > + overdrive_table = &powerplay_table->overdrive_table; > + if (!smu->od_settings) { > + smu->od_settings = kmemdup(overdrive_table, sizeof(struct > smu_11_0_overdrive_table), GFP_KERNEL); > + } else { > + memcpy(smu->od_settings, overdrive_table, sizeof(struct > smu_11_0_overdrive_table)); > + } > + return 0; > +} > + > +static int navi10_set_default_od_settings(struct smu_context *smu, bool > initialize) { > + OverDriveTable_t *od_table; > + int ret = 0; > + > + ret = smu_v11_0_set_default_od_settings(smu, initialize, > sizeof(OverDriveTable_t)); > + if (ret) > + return ret; > + > + if (initialize) { > + ret = navi10_setup_od_limits(smu); > + if (ret) { > + pr_err("Failed to retrieve board OD limits\n"); > + return ret; > + } > + > + } > + > + od_table = (OverDriveTable_t *)smu->smu_table.overdrive_table; > + if (od_table) { > + navi10_dump_od_table(od_table); > + } > + > + return ret; > +} > + > +static int navi10_od_edit_dpm_table(struct smu_context *smu, enum > PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) { > + int i; > + int ret = 0; > + struct smu_table_context *table_context = &smu->smu_table; > + OverDriveTable_t *od_table; > + struct smu_11_0_overdrive_table *od_settings; > + od_table = (OverDriveTable_t *)table_context->overdrive_table; > + > + if (!smu->od_enabled) { > + pr_warn("OverDrive is not enabled!\n"); > + return -EINVAL; > + } > + > + if (!smu->od_settings) { > + pr_err("OD board limits are not set!\n"); > + return -ENOENT; > + } > + > + od_settings = smu->od_settings; > + > + switch (type) { > + case PP_OD_EDIT_SCLK_VDDC_TABLE: > + if (!navi10_od_feature_is_supported(od_settings, > SMU_11_0_ODFEATURE_GFXCLK_LIMITS)) { > + pr_warn("GFXCLK_LIMITS not supported!\n"); > + return -ENOTSUPP; > + } > + if (!table_context->overdrive_table) { > + pr_err("Overdrive is not initialized\n"); > + return -EINVAL; > + } > + if (input[0] > input[1]) { > + pr_info("GfxclkFmin must be less than GfxclkFmax\n"); > + return -EINVAL; > + } [Quan, Evan] This judgement is a little weird. As input[0] is feature id while input[1] is the actual requested frequency. > + for (i = 0; i < size; i += 2) { > + if (i + 2 > size) { > + pr_info("invalid number of input > parameters %d\n", size); > + return -EINVAL; > + } > + switch (input[i]) { > + case 0: > + freq_setting = > SMU_11_0_ODSETTING_GFXCLKFMIN; > + freq_ptr = &od_table->GfxclkFmin; > + if (input[i + 1] > od_table->GfxclkFmax) { > + pr_info("GfxclkFmin (%ld) must be <= > GfxclkFmax (%u)!\n", > + input[i + 1], > + od_table->GfxclkFmin); > + return -EINVAL; > + } > + break; > + case 1: > + freq_setting = > SMU_11_0_ODSETTING_GFXCLKFMAX; > + freq_ptr = &od_table->GfxclkFmax; > + if (input[i + 1] < od_table->GfxclkFmin) { > + pr_info("GfxclkFmax (%ld) must be >= > GfxclkFmin (%u)!\n", > + input[i + 1], > + od_table->GfxclkFmax); > + return -EINVAL; > + } > + break; > + default: > + pr_info("Invalid SCLK_VDDC_TABLE > index: %ld\n", input[i]); > + pr_info("Supported indices: [0:min,1:max]\n"); > + return -EINVAL; > + } > + ret = navi10_od_setting_check_range(od_settings, > freq_setting, input[i + 1]); > + if (ret) > + return ret; > + *freq_ptr = input[i + 1]; > + } > + break; > + case PP_OD_EDIT_MCLK_VDDC_TABLE: > + if (!navi10_od_feature_is_supported(od_settings, > SMU_11_0_ODFEATURE_UCLK_MAX)) { > + pr_warn("UCLK_MAX not supported!\n"); > + return -ENOTSUPP; > + } > + if (size < 2) { > + pr_info("invalid number of parameters: %d\n", size); > + return -EINVAL; > + } > + if (input[0] != 1) { > + pr_info("Invalid MCLK_VDDC_TABLE index: %ld\n", > input[0]); > + pr_info("Supported indices: [1:max]\n"); > + return -EINVAL; > + } > + ret = navi10_od_setting_check_range(od_settings, > SMU_11_0_ODSETTING_UCLKFMAX, input[1]); > + if (ret) > + return ret; > + od_table->UclkFmax = input[1]; > + break; > + case PP_OD_COMMIT_DPM_TABLE: > + navi10_dump_od_table(od_table); > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, > (void *)od_table, true); > + if (ret) { > + pr_err("Failed to import overdrive table!\n"); > + return ret; > + } > + mutex_lock(&(smu->mutex)); > + ret = smu_handle_task(smu, smu->smu_dpm.dpm_level, > AMD_PP_TASK_READJUST_POWER_STATE); > + mutex_unlock(&(smu->mutex)); [Quan, Evan] This may be not based on the latest source code. As with the latest source code, there is already lock protection in smu_od_edit_dpm_table(). Then trying to get the lock again will dead lock. > + if (ret) { > + return ret; > + } > + break; > + case PP_OD_EDIT_VDDC_CURVE: > + // TODO: implement > + return -ENOSYS; > + default: > + return -ENOSYS; > + } > + return ret; > +} > + > static const struct pptable_funcs navi10_ppt_funcs = { > .tables_init = navi10_tables_init, > .alloc_dpm_context = navi10_allocate_dpm_context, @@ -1629,6 > +1812,8 @@ static const struct pptable_funcs navi10_ppt_funcs = { > .get_thermal_temperature_range = > navi10_get_thermal_temperature_range, > .display_disable_memory_clock_switch = > navi10_display_disable_memory_clock_switch, > .get_power_limit = navi10_get_power_limit, > + .set_default_od_settings = navi10_set_default_od_settings, > + .od_edit_dpm_table = navi10_od_edit_dpm_table, > }; > > void navi10_set_ppt_funcs(struct smu_context *smu) diff --git > a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c > b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c > index c5257ae3188a..029f0896146a 100644 > --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c > +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c > @@ -1828,3 +1828,30 @@ void smu_v11_0_set_smu_funcs(struct smu_context > *smu) > pr_warn("Unknown asic for smu11\n"); > } > } > + > +int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool > +initialize, size_t overdrive_table_size) { > + struct smu_table_context *table_context = &smu->smu_table; > + int ret = 0; > + > + if (initialize) { > + if (table_context->overdrive_table) { > + return -EINVAL; > + } > + table_context->overdrive_table = kzalloc(overdrive_table_size, > GFP_KERNEL); > + if (!table_context->overdrive_table) { > + return -ENOMEM; > + } > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, > table_context->overdrive_table, false); > + if (ret) { > + pr_err("Failed to export overdrive table!\n"); > + return ret; > + } > + } > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, > table_context->overdrive_table, true); > + if (ret) { > + pr_err("Failed to import overdrive table!\n"); > + return ret; > + } > + return ret; > +} > -- > 2.23.0 > > > From 7bc07e0b053381ce7409d8251be18380fb6b3c43 Mon Sep 17 00:00:00 > 2001 > Message-Id: > <7bc07e0b053381ce7409d8251be18380fb6b3c43.1573151434.git.mcoffin13@g > mail.com> > In-Reply-To: <cover.1573151434.git.mcoffin13@xxxxxxxxx> > References: <cover.1573151434.git.mcoffin13@xxxxxxxxx> > From: Matt Coffin <mcoffin13@xxxxxxxxx> > Date: Tue, 5 Nov 2019 12:39:27 -0700 > Subject: [PATCH 2/3] drm/amdgpu/navi10: implement GFXCLK_CURVE > overdrive > To: amd-gfx@xxxxxxxxxxxxxxxxxxxxx > > [Why] > Before this patch, there was no way to set the gfxclk voltage curve in > the overdrive settings for navi10 through pp_od_clk_voltage > > [How] > Add the required implementation to navi10's ppt dpm table editing > implementation, similar to the vega20 implementation and interface. > --- > drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 55 +++++++++++++++++++++- > drivers/gpu/drm/amd/powerplay/navi10_ppt.h | 2 + > 2 files changed, 55 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > index 6d0e511ad093..e717328f93ce 100644 > --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > @@ -1667,6 +1667,8 @@ static int navi10_od_edit_dpm_table(struct > smu_context *smu, enum PP_OD_DPM_TABL > struct smu_table_context *table_context = &smu->smu_table; > OverDriveTable_t *od_table; > struct smu_11_0_overdrive_table *od_settings; > + enum SMU_11_0_ODSETTING_ID freq_setting, voltage_setting; > + uint16_t *freq_ptr, *voltage_ptr; > od_table = (OverDriveTable_t *)table_context->overdrive_table; > > if (!smu->od_enabled) { > @@ -1766,8 +1768,57 @@ static int navi10_od_edit_dpm_table(struct > smu_context *smu, enum PP_OD_DPM_TABL > } > break; > case PP_OD_EDIT_VDDC_CURVE: > - // TODO: implement > - return -ENOSYS; > + if (!navi10_od_feature_is_supported(od_settings, > SMU_11_0_ODFEATURE_GFXCLK_CURVE)) { > + pr_warn("GFXCLK_CURVE not supported!\n"); > + return -ENOTSUPP; > + } > + if (size < 3) { > + pr_info("invalid number of parameters: %d\n", size); > + return -EINVAL; > + } > + if (!od_table) { > + pr_info("Overdrive is not initialized\n"); > + return -EINVAL; > + } > + > + switch (input[0]) { > + case 0: > + freq_setting = > SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1; > + voltage_setting = > SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1; > + freq_ptr = &od_table->GfxclkFreq1; > + voltage_ptr = &od_table->GfxclkVolt1; > + break; > + case 1: > + freq_setting = > SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2; > + voltage_setting = > SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2; > + freq_ptr = &od_table->GfxclkFreq2; > + voltage_ptr = &od_table->GfxclkVolt2; > + break; > + case 2: > + freq_setting = > SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3; > + voltage_setting = > SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3; > + freq_ptr = &od_table->GfxclkFreq3; > + voltage_ptr = &od_table->GfxclkVolt3; > + break; > + default: > + pr_info("Invalid VDDC_CURVE index: %ld\n", input[0]); > + pr_info("Supported indices: [0, 1, 2]\n"); > + return -EINVAL; > + } > + ret = navi10_od_setting_check_range(od_settings, freq_setting, > input[1]); > + if (ret) > + return ret; > + // Allow setting zero to disable the OverDrive VDDC curve > + if (input[2] != 0) { > + ret = navi10_od_setting_check_range(od_settings, > voltage_setting, input[2]); > + if (ret) > + return ret; > + } > + *freq_ptr = input[1]; > + *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE; > + pr_debug("OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, > *voltage_ptr); > + navi10_dump_od_table(od_table); > + break; > default: > return -ENOSYS; > } > diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > index 620ff17c2fef..484d2c58fc06 100644 > --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > @@ -27,6 +27,8 @@ > #define NAVI10_PEAK_SCLK_XT (1755) > #define NAVI10_PEAK_SCLK_XL (1625) > > +#define NAVI10_VOLTAGE_SCALE (4) > + > extern void navi10_set_ppt_funcs(struct smu_context *smu); > > #endif > -- > 2.23.0 > > > From e091c4085ecc669ea907fe5d8515f14586863f9b Mon Sep 17 00:00:00 > 2001 > Message-Id: > <e091c4085ecc669ea907fe5d8515f14586863f9b.1573151434.git.mcoffin13@g > mail.com> > In-Reply-To: <cover.1573151434.git.mcoffin13@xxxxxxxxx> > References: <cover.1573151434.git.mcoffin13@xxxxxxxxx> > From: Matt Coffin <mcoffin13@xxxxxxxxx> > Date: Wed, 6 Nov 2019 12:05:28 -0700 > Subject: [PATCH 3/3] drm/amdgpu/navi10: Implement od clk printing > To: amd-gfx@xxxxxxxxxxxxxxxxxxxxx > > [Why] > Before this patch, navi10 overdrive settings could not be printed via > pp_od_clk_voltage > > [How] > Implement printing for the overdrive settings for the following clocks > in navi10's ppt print_clk_levels implementation: > > * SMU_OD_SCLK > * SMU_OD_MCLK > * SMU_OD_VDDC_CURVE > --- > drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 56 ++++++++++++++++++++-- > 1 file changed, 51 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > index e717328f93ce..506af59ff45f 100644 > --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > @@ -677,13 +677,25 @@ static bool > navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu > return dpm_desc->SnapToDiscrete == 0 ? true : false; > } > > +static inline bool navi10_od_feature_is_supported(struct > smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_ID > feature) > +{ > + return od_table->cap[feature]; > +} > + > + > static int navi10_print_clk_levels(struct smu_context *smu, > enum smu_clk_type clk_type, char *buf) > { > + OverDriveTable_t *od_table; > + struct smu_11_0_overdrive_table *od_settings; > + uint16_t *curve_settings; > int i, size = 0, ret = 0; > uint32_t cur_value = 0, value = 0, count = 0; > uint32_t freq_values[3] = {0}; > uint32_t mark_index = 0; > + struct smu_table_context *table_context = &smu->smu_table; > + od_table = (OverDriveTable_t *)table_context->overdrive_table; > + od_settings = smu->od_settings; > > switch (clk_type) { > case SMU_GFXCLK: > @@ -734,6 +746,45 @@ static int navi10_print_clk_levels(struct smu_context > *smu, > > } > break; > + case SMU_OD_SCLK: > + if (!smu->od_enabled || !od_table || !od_settings) > + break; > + if (!navi10_od_feature_is_supported(od_settings, > SMU_11_0_ODFEATURE_GFXCLK_LIMITS)) > + break; > + size += sprintf(buf + size, "OD_SCLK:\n"); > + size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table- > >GfxclkFmin, od_table->GfxclkFmax); > + break; > + case SMU_OD_MCLK: > + if (!smu->od_enabled || !od_table || !od_settings) > + break; > + if (!navi10_od_feature_is_supported(od_settings, > SMU_11_0_ODFEATURE_UCLK_MAX)) > + break; > + size += sprintf(buf + size, "OD_MCLK:\n"); > + size += sprintf(buf + size, "0: %uMHz\n", od_table->UclkFmax); > + break; > + case SMU_OD_VDDC_CURVE: > + if (!smu->od_enabled || !od_table || !od_settings) > + break; > + if (!navi10_od_feature_is_supported(od_settings, > SMU_11_0_ODFEATURE_GFXCLK_CURVE)) > + break; > + size += sprintf(buf + size, "OD_VDDC_CURVE:\n"); > + for (i = 0; i < 3; i++) { > + switch (i) { > + case 0: > + curve_settings = &od_table->GfxclkFreq1; > + break; > + case 1: > + curve_settings = &od_table->GfxclkFreq2; > + break; > + case 2: > + curve_settings = &od_table->GfxclkFreq3; > + break; > + default: > + break; > + } > + size += sprintf(buf + size, "%d: %uMHz @ %umV\n", i, > curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); > + } > + break; > default: > break; > } > @@ -1600,11 +1651,6 @@ static inline void > navi10_dump_od_table(OverDriveTable_t *od_table) { > pr_debug("OD: OverDrivePct: %d\n", od_table->OverDrivePct); > } > > -static inline bool navi10_od_feature_is_supported(struct > smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_ID > feature) > -{ > - return od_table->cap[feature]; > -} > - > static int navi10_od_setting_check_range(struct smu_11_0_overdrive_table > *od_table, enum SMU_11_0_ODSETTING_ID setting, uint32_t value) > { > if (value < od_table->min[setting]) { > -- > 2.23.0 > > _______________________________________________ > amd-gfx mailing list > amd-gfx@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/amd-gfx _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx