From f33647b9e1b098181fb7c6a95afe8043285bfea8 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 16 Aug 2023 09:07:42 +0530 Subject: Documentation/gpu: Update amdgpu documentation 7957ec80ef97 ("drm/amdgpu: Add FRU sysfs nodes only if needed") moved the documentation for some of the sysfs nodes to amdgpu_fru_eeprom.c. Update the documentation accordingly. Signed-off-by: Lijo Lazar Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/driver-misc.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/driver-misc.rst b/Documentation/gpu/amdgpu/driver-misc.rst index be131e963d87..4321c38fef21 100644 --- a/Documentation/gpu/amdgpu/driver-misc.rst +++ b/Documentation/gpu/amdgpu/driver-misc.rst @@ -11,19 +11,19 @@ via sysfs product_name ------------ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c :doc: product_name product_number -------------- -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c - :doc: product_name +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c + :doc: product_number serial_number ------------- -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c :doc: serial_number unique_id -- cgit v1.2.3 From d7bf1b556fcceaa81c0a18d7828258e7a6c383c2 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 11 Aug 2023 16:13:59 +0800 Subject: drm/amd/pm: add fan temperature/pwm curve OD setting support for SMU13 Add SMU13 fan temperature/pwm curve OD setting support. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/thermal.rst | 6 + drivers/gpu/drm/amd/include/kgd_pp_interface.h | 4 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 210 ++++++++++++++++++++- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 + .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 102 +++++++++- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 102 +++++++++- 8 files changed, 423 insertions(+), 8 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst index 5e27e4eb3959..08ee33b2acb6 100644 --- a/Documentation/gpu/amdgpu/thermal.rst +++ b/Documentation/gpu/amdgpu/thermal.rst @@ -64,6 +64,12 @@ gpu_metrics .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: gpu_metrics +fan_curve +--------- + +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c + :doc: fan_curve + GFXOFF ====== diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 84c5224d994c..7bdd2bdab970 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -113,6 +113,7 @@ enum pp_clock_type { OD_RANGE, OD_VDDGFX_OFFSET, OD_CCLK, + OD_FAN_CURVE, }; enum amd_pp_sensors { @@ -186,7 +187,8 @@ enum PP_OD_DPM_TABLE_COMMAND { PP_OD_EDIT_VDDC_CURVE, PP_OD_RESTORE_DEFAULT_TABLE, PP_OD_COMMIT_DPM_TABLE, - PP_OD_EDIT_VDDGFX_OFFSET + PP_OD_EDIT_VDDGFX_OFFSET, + PP_OD_EDIT_FAN_CURVE, }; struct pp_states_info { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index edb52697c489..1008d43e9c3f 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3383,7 +3383,215 @@ static const struct attribute_group *hwmon_groups[] = { NULL }; -static struct od_feature_set amdgpu_od_set; +static int amdgpu_retrieve_od_settings(struct amdgpu_device *adev, + enum pp_clock_type od_type, + char *buf) +{ + int size = 0; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + if (adev->in_suspend && !adev->in_runpm) + return -EPERM; + + ret = pm_runtime_get_sync(adev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(adev->dev); + return ret; + } + + size = amdgpu_dpm_print_clock_levels(adev, od_type, buf); + if (size == 0) + size = sysfs_emit(buf, "\n"); + + pm_runtime_mark_last_busy(adev->dev); + pm_runtime_put_autosuspend(adev->dev); + + return size; +} + +static int parse_input_od_command_lines(const char *buf, + size_t count, + u32 *type, + long *params, + uint32_t *num_of_params) +{ + const char delimiter[3] = {' ', '\n', '\0'}; + uint32_t parameter_size = 0; + char buf_cpy[128] = {0}; + char *tmp_str, *sub_str; + int ret; + + if (count > sizeof(buf_cpy) - 1) + return -EINVAL; + + memcpy(buf_cpy, buf, count); + tmp_str = buf_cpy; + + /* skip heading spaces */ + while (isspace(*tmp_str)) + tmp_str++; + + switch (*tmp_str) { + case 'c': + *type = PP_OD_COMMIT_DPM_TABLE; + return 0; + default: + break; + } + + while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { + if (strlen(sub_str) == 0) + continue; + + ret = kstrtol(sub_str, 0, ¶ms[parameter_size]); + if (ret) + return -EINVAL; + parameter_size++; + + while (isspace(*tmp_str)) + tmp_str++; + } + + *num_of_params = parameter_size; + + return 0; +} + +static int +amdgpu_distribute_custom_od_settings(struct amdgpu_device *adev, + enum PP_OD_DPM_TABLE_COMMAND cmd_type, + const char *in_buf, + size_t count) +{ + uint32_t parameter_size = 0; + long parameter[64]; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + if (adev->in_suspend && !adev->in_runpm) + return -EPERM; + + ret = parse_input_od_command_lines(in_buf, + count, + &cmd_type, + parameter, + ¶meter_size); + if (ret) + return ret; + + ret = pm_runtime_get_sync(adev->dev); + if (ret < 0) + goto err_out0; + + ret = amdgpu_dpm_odn_edit_dpm_table(adev, + cmd_type, + parameter, + parameter_size); + if (ret) + goto err_out1; + + if (cmd_type == PP_OD_COMMIT_DPM_TABLE) { + ret = amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_READJUST_POWER_STATE, + NULL); + if (ret) + goto err_out1; + } + + pm_runtime_mark_last_busy(adev->dev); + pm_runtime_put_autosuspend(adev->dev); + + return count; + +err_out1: + pm_runtime_mark_last_busy(adev->dev); +err_out0: + pm_runtime_put_autosuspend(adev->dev); + + return ret; +} + +/** + * DOC: fan_curve + * + * The amdgpu driver provides a sysfs API for checking and adjusting the fan + * control curve line. + * + * Reading back the file shows you the current settings(temperature in Celsius + * degree and fan speed in pwm) applied to every anchor point of the curve line + * and their permitted ranges if changable. + * + * Writing a desired string(with the format like "anchor_point_index temperature + * fan_speed_in_pwm") to the file, change the settings for the specific anchor + * point accordingly. + * + * When you have finished the editing, write "c" (commit) to the file to commit + * your changes. + * + * There are two fan control modes supported: auto and manual. With auto mode, + * PMFW handles the fan speed control(how fan speed reacts to ASIC temperature). + * While with manual mode, users can set their own fan curve line as what + * described here. Normally the ASIC is booted up with auto mode. Any + * settings via this interface will switch the fan control to manual mode + * implicitly. + */ +static ssize_t fan_curve_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_CURVE, buf); +} + +static ssize_t fan_curve_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_distribute_custom_od_settings(adev, + PP_OD_EDIT_FAN_CURVE, + buf, + count); +} + +static umode_t fan_curve_visible(struct amdgpu_device *adev) +{ + umode_t umode = 0000; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE) + umode |= S_IRUSR | S_IRGRP | S_IROTH; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_CURVE_SET) + umode |= S_IWUSR; + + return umode; +} + +static struct od_feature_set amdgpu_od_set = { + .containers = { + [0] = { + .name = "fan_ctrl", + .sub_feature = { + [0] = { + .name = "fan_curve", + .ops = { + .is_visible = fan_curve_visible, + .show = fan_curve_show, + .store = fan_curve_store, + }, + }, + }, + }, + }, +}; static void od_kobj_release(struct kobject *kobj) { diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 4cab6a2efb63..90544a8f450c 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -314,6 +314,9 @@ struct config_table_setting uint16_t fclk_average_tau; }; +#define OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE BIT(0) +#define OD_OPS_SUPPORT_FAN_CURVE_SET BIT(1) + struct amdgpu_pm { struct mutex mutex; u32 current_sclk; @@ -368,6 +371,7 @@ struct amdgpu_pm { enum amdgpu_runpm_mode rpm_mode; struct list_head od_kobj_list; + uint32_t od_feature_mask; }; int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index f005a90c35af..2d73a63813de 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2481,6 +2481,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type) clk_type = SMU_OD_VDDGFX_OFFSET; break; case OD_CCLK: clk_type = SMU_OD_CCLK; break; + case OD_FAN_CURVE: + clk_type = SMU_OD_FAN_CURVE; break; default: clk_type = SMU_CLK_COUNT; break; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index e57265cf637c..83e1d43efd2b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -280,6 +280,7 @@ enum smu_clk_type { SMU_OD_VDDC_CURVE, SMU_OD_RANGE, SMU_OD_VDDGFX_OFFSET, + SMU_OD_FAN_CURVE, SMU_CLK_COUNT, }; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 5fdb2b3c042a..09297dbcbdf1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -101,6 +101,8 @@ #define PP_OD_FEATURE_UCLK_FMIN 2 #define PP_OD_FEATURE_UCLK_FMAX 3 #define PP_OD_FEATURE_GFX_VF_CURVE 4 +#define PP_OD_FEATURE_FAN_CURVE_TEMP 5 +#define PP_OD_FEATURE_FAN_CURVE_PWM 6 #define LINK_SPEED_MAX 3 @@ -1122,6 +1124,14 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary; od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary; break; + case PP_OD_FEATURE_FAN_CURVE_TEMP: + od_min_setting = overdrive_lowerlimits->FanLinearTempPoints; + od_max_setting = overdrive_upperlimits->FanLinearTempPoints; + break; + case PP_OD_FEATURE_FAN_CURVE_PWM: + od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints; + od_max_setting = overdrive_upperlimits->FanLinearPwmPoints; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1341,6 +1351,35 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[0]); break; + case SMU_OD_FAN_CURVE: + if (!smu_v13_0_0_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "OD_FAN_CURVE:\n"); + for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) + size += sysfs_emit_at(buf, size, "%d: %dC %d%%\n", + i, + (int)od_table->OverDriveTable.FanLinearTempPoints[i], + (int)od_table->OverDriveTable.FanLinearPwmPoints[i]); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_TEMP, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "FAN_CURVE(hotspot temp): %uC %uC\n", + min_value, max_value); + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_PWM, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "FAN_CURVE(fan speed): %u%% %u%%\n", + min_value, max_value); + + break; + case SMU_OD_RANGE: if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1551,6 +1590,44 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT); break; + case PP_OD_EDIT_FAN_CURVE: + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + if (input[0] >= NUM_OD_FAN_MAX_POINTS - 1 || + input[0] < 0) + return -EINVAL; + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_TEMP, + &minimum, + &maximum); + if (input[1] < minimum || + input[1] > maximum) { + dev_info(adev->dev, "Fan curve temp setting(%ld) must be within [%d, %d]!\n", + input[1], minimum, maximum); + return -EINVAL; + } + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_PWM, + &minimum, + &maximum); + if (input[2] < minimum || + input[2] > maximum) { + dev_info(adev->dev, "Fan curve pwm setting(%ld) must be within [%d, %d]!\n", + input[2], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanLinearTempPoints[input[0]] = input[1]; + od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2]; + od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1801,6 +1878,16 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_3); } +static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + if (smu_v13_0_0_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | + OD_OPS_SUPPORT_FAN_CURVE_SET; +} + static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) { OverDriveTableExternal_t *od_table = @@ -1850,8 +1937,16 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++) user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i]; + for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) { + user_od_table->OverDriveTable.FanLinearTempPoints[i] = + user_od_table_bak.OverDriveTable.FanLinearTempPoints[i]; + user_od_table->OverDriveTable.FanLinearPwmPoints[i] = + user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i]; + } } + smu_v13_0_0_set_supported_od_feature_mask(smu); + return 0; } @@ -1862,9 +1957,10 @@ static int smu_v13_0_0_restore_user_od_settings(struct smu_context *smu) OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table; int res; - user_od_table->OverDriveTable.FeatureCtrlMask = 1U << PP_OD_FEATURE_GFXCLK_BIT | - 1U << PP_OD_FEATURE_UCLK_BIT | - 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT; + user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | + BIT(PP_OD_FEATURE_UCLK_BIT) | + BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | + BIT(PP_OD_FEATURE_FAN_CURVE_BIT); res = smu_v13_0_0_upload_overdrive_table(smu, user_od_table); user_od_table->OverDriveTable.FeatureCtrlMask = 0; if (res == 0) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 12949928e285..3e852bf6177e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -77,6 +77,8 @@ #define PP_OD_FEATURE_UCLK_FMIN 2 #define PP_OD_FEATURE_UCLK_FMAX 3 #define PP_OD_FEATURE_GFX_VF_CURVE 4 +#define PP_OD_FEATURE_FAN_CURVE_TEMP 5 +#define PP_OD_FEATURE_FAN_CURVE_PWM 6 #define LINK_SPEED_MAX 3 @@ -1102,6 +1104,14 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary; od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary; break; + case PP_OD_FEATURE_FAN_CURVE_TEMP: + od_min_setting = overdrive_lowerlimits->FanLinearTempPoints; + od_max_setting = overdrive_upperlimits->FanLinearTempPoints; + break; + case PP_OD_FEATURE_FAN_CURVE_PWM: + od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints; + od_max_setting = overdrive_upperlimits->FanLinearPwmPoints; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1321,6 +1331,35 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu, od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[0]); break; + case SMU_OD_FAN_CURVE: + if (!smu_v13_0_7_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "OD_FAN_CURVE:\n"); + for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) + size += sysfs_emit_at(buf, size, "%d: %dC %d%%\n", + i, + (int)od_table->OverDriveTable.FanLinearTempPoints[i], + (int)od_table->OverDriveTable.FanLinearPwmPoints[i]); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_TEMP, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "FAN_CURVE(hotspot temp): %uC %uC\n", + min_value, max_value); + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_PWM, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "FAN_CURVE(fan speed): %u%% %u%%\n", + min_value, max_value); + + break; + case SMU_OD_RANGE: if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1531,6 +1570,44 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT); break; + case PP_OD_EDIT_FAN_CURVE: + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + if (input[0] >= NUM_OD_FAN_MAX_POINTS - 1 || + input[0] < 0) + return -EINVAL; + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_TEMP, + &minimum, + &maximum); + if (input[1] < minimum || + input[1] > maximum) { + dev_info(adev->dev, "Fan curve temp setting(%ld) must be within [%d, %d]!\n", + input[1], minimum, maximum); + return -EINVAL; + } + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_CURVE_PWM, + &minimum, + &maximum); + if (input[2] < minimum || + input[2] > maximum) { + dev_info(adev->dev, "Fan curve pwm setting(%ld) must be within [%d, %d]!\n", + input[2], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanLinearTempPoints[input[0]] = input[1]; + od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2]; + od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1776,6 +1853,16 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_3); } +static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + if (smu_v13_0_7_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | + OD_OPS_SUPPORT_FAN_CURVE_SET; +} + static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) { OverDriveTableExternal_t *od_table = @@ -1825,8 +1912,16 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++) user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i]; + for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) { + user_od_table->OverDriveTable.FanLinearTempPoints[i] = + user_od_table_bak.OverDriveTable.FanLinearTempPoints[i]; + user_od_table->OverDriveTable.FanLinearPwmPoints[i] = + user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i]; + } } + smu_v13_0_7_set_supported_od_feature_mask(smu); + return 0; } @@ -1837,9 +1932,10 @@ static int smu_v13_0_7_restore_user_od_settings(struct smu_context *smu) OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table; int res; - user_od_table->OverDriveTable.FeatureCtrlMask = 1U << PP_OD_FEATURE_GFXCLK_BIT | - 1U << PP_OD_FEATURE_UCLK_BIT | - 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT; + user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | + BIT(PP_OD_FEATURE_UCLK_BIT) | + BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | + BIT(PP_OD_FEATURE_FAN_CURVE_BIT); res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table); user_od_table->OverDriveTable.FeatureCtrlMask = 0; if (res == 0) -- cgit v1.2.3 From 548009ad1c9a8e7dedf3c50730214c2e33f03865 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 11 Aug 2023 17:53:08 +0800 Subject: drm/amd/pm: add fan acoustic limit OD setting support for SMU13 Add SMU13 fan acoustic limit OD setting support. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/thermal.rst | 6 +++ drivers/gpu/drm/amd/include/kgd_pp_interface.h | 2 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 63 ++++++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 + .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 51 +++++++++++++++++- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 51 +++++++++++++++++- 8 files changed, 176 insertions(+), 2 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst index 08ee33b2acb6..8ed888f81d2c 100644 --- a/Documentation/gpu/amdgpu/thermal.rst +++ b/Documentation/gpu/amdgpu/thermal.rst @@ -70,6 +70,12 @@ fan_curve .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: fan_curve +acoustic_limit_rpm_threshold +---------------------------- + +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c + :doc: acoustic_limit_rpm_threshold + GFXOFF ====== diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 7bdd2bdab970..e3dcef8c4ab7 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -114,6 +114,7 @@ enum pp_clock_type { OD_VDDGFX_OFFSET, OD_CCLK, OD_FAN_CURVE, + OD_ACOUSTIC_LIMIT, }; enum amd_pp_sensors { @@ -189,6 +190,7 @@ enum PP_OD_DPM_TABLE_COMMAND { PP_OD_COMMIT_DPM_TABLE, PP_OD_EDIT_VDDGFX_OFFSET, PP_OD_EDIT_FAN_CURVE, + PP_OD_EDIT_ACOUSTIC_LIMIT, }; struct pp_states_info { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 1008d43e9c3f..1ec8a8c4016a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3575,6 +3575,61 @@ static umode_t fan_curve_visible(struct amdgpu_device *adev) return umode; } +/** + * DOC: acoustic_limit_rpm_threshold + * + * The amdgpu driver provides a sysfs API for checking and adjusting the + * acoustic limit in RPM for fan control. + * + * Reading back the file shows you the current setting and the permitted + * ranges if changable. + * + * Writing an integer to the file, change the setting accordingly. + * + * When you have finished the editing, write "c" (commit) to the file to commit + * your changes. + * + * This setting works under auto fan control mode only. It adjusts the PMFW's + * behavior about the maximum speed in RPM the fan can spin. Setting via this + * interface will switch the fan control to auto mode implicitly. + */ +static ssize_t acoustic_limit_threshold_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_ACOUSTIC_LIMIT, buf); +} + +static ssize_t acoustic_limit_threshold_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_distribute_custom_od_settings(adev, + PP_OD_EDIT_ACOUSTIC_LIMIT, + buf, + count); +} + +static umode_t acoustic_limit_threshold_visible(struct amdgpu_device *adev) +{ + umode_t umode = 0000; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE) + umode |= S_IRUSR | S_IRGRP | S_IROTH; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET) + umode |= S_IWUSR; + + return umode; +} + static struct od_feature_set amdgpu_od_set = { .containers = { [0] = { @@ -3588,6 +3643,14 @@ static struct od_feature_set amdgpu_od_set = { .store = fan_curve_store, }, }, + [1] = { + .name = "acoustic_limit_rpm_threshold", + .ops = { + .is_visible = acoustic_limit_threshold_visible, + .show = acoustic_limit_threshold_show, + .store = acoustic_limit_threshold_store, + }, + }, }, }, }, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 90544a8f450c..984fda278f1a 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -316,6 +316,8 @@ struct config_table_setting #define OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE BIT(0) #define OD_OPS_SUPPORT_FAN_CURVE_SET BIT(1) +#define OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE BIT(2) +#define OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET BIT(3) struct amdgpu_pm { struct mutex mutex; diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 2d73a63813de..ca41cfd57d89 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2483,6 +2483,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type) clk_type = SMU_OD_CCLK; break; case OD_FAN_CURVE: clk_type = SMU_OD_FAN_CURVE; break; + case OD_ACOUSTIC_LIMIT: + clk_type = SMU_OD_ACOUSTIC_LIMIT; break; default: clk_type = SMU_CLK_COUNT; break; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index 83e1d43efd2b..76bb1cba9b83 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -281,6 +281,7 @@ enum smu_clk_type { SMU_OD_RANGE, SMU_OD_VDDGFX_OFFSET, SMU_OD_FAN_CURVE, + SMU_OD_ACOUSTIC_LIMIT, SMU_CLK_COUNT, }; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 09297dbcbdf1..021cff1995da 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -103,6 +103,7 @@ #define PP_OD_FEATURE_GFX_VF_CURVE 4 #define PP_OD_FEATURE_FAN_CURVE_TEMP 5 #define PP_OD_FEATURE_FAN_CURVE_PWM 6 +#define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 #define LINK_SPEED_MAX 3 @@ -1132,6 +1133,10 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints; od_max_setting = overdrive_upperlimits->FanLinearPwmPoints; break; + case PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT: + od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold; + od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1380,6 +1385,24 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, break; + case SMU_OD_ACOUSTIC_LIMIT: + if (!smu_v13_0_0_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_LIMIT:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.AcousticLimitRpmThreshold); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "ACOUSTIC_LIMIT: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1628,6 +1651,28 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_ACOUSTIC_LIMIT: + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "acoustic limit threshold setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.AcousticLimitRpmThreshold = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1885,7 +1930,9 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu) if (smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | - OD_OPS_SUPPORT_FAN_CURVE_SET; + OD_OPS_SUPPORT_FAN_CURVE_SET | + OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | + OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET; } static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) @@ -1943,6 +1990,8 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) user_od_table->OverDriveTable.FanLinearPwmPoints[i] = user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i]; } + user_od_table->OverDriveTable.AcousticLimitRpmThreshold = + user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; } smu_v13_0_0_set_supported_od_feature_mask(smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 3e852bf6177e..f9486c7e26bf 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -79,6 +79,7 @@ #define PP_OD_FEATURE_GFX_VF_CURVE 4 #define PP_OD_FEATURE_FAN_CURVE_TEMP 5 #define PP_OD_FEATURE_FAN_CURVE_PWM 6 +#define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 #define LINK_SPEED_MAX 3 @@ -1112,6 +1113,10 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints; od_max_setting = overdrive_upperlimits->FanLinearPwmPoints; break; + case PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT: + od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold; + od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1360,6 +1365,24 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu, break; + case SMU_OD_ACOUSTIC_LIMIT: + if (!smu_v13_0_7_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_LIMIT:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.AcousticLimitRpmThreshold); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "ACOUSTIC_LIMIT: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1608,6 +1631,28 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_ACOUSTIC_LIMIT: + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "acoustic limit threshold setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.AcousticLimitRpmThreshold = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1860,7 +1905,9 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu) if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | - OD_OPS_SUPPORT_FAN_CURVE_SET; + OD_OPS_SUPPORT_FAN_CURVE_SET | + OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | + OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET; } static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) @@ -1918,6 +1965,8 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) user_od_table->OverDriveTable.FanLinearPwmPoints[i] = user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i]; } + user_od_table->OverDriveTable.AcousticLimitRpmThreshold = + user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; } smu_v13_0_7_set_supported_od_feature_mask(smu); -- cgit v1.2.3 From 47cf6fcb88d2b46018a5dc9b1b369518f5588ae4 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 11 Aug 2023 18:09:14 +0800 Subject: drm/amd/pm: add fan acoustic target OD setting support for SMU13 Add SMU13 fan acoustic target OD setting support. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/thermal.rst | 6 ++ drivers/gpu/drm/amd/include/kgd_pp_interface.h | 2 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 + .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 51 ++++++++++++++++- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 51 ++++++++++++++++- 8 files changed, 178 insertions(+), 2 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst index 8ed888f81d2c..26ca4812b9f6 100644 --- a/Documentation/gpu/amdgpu/thermal.rst +++ b/Documentation/gpu/amdgpu/thermal.rst @@ -76,6 +76,12 @@ acoustic_limit_rpm_threshold .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: acoustic_limit_rpm_threshold +acoustic_target_rpm_threshold +----------------------------- + +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c + :doc: acoustic_target_rpm_threshold + GFXOFF ====== diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index e3dcef8c4ab7..a7bc81a0a36e 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -115,6 +115,7 @@ enum pp_clock_type { OD_CCLK, OD_FAN_CURVE, OD_ACOUSTIC_LIMIT, + OD_ACOUSTIC_TARGET, }; enum amd_pp_sensors { @@ -191,6 +192,7 @@ enum PP_OD_DPM_TABLE_COMMAND { PP_OD_EDIT_VDDGFX_OFFSET, PP_OD_EDIT_FAN_CURVE, PP_OD_EDIT_ACOUSTIC_LIMIT, + PP_OD_EDIT_ACOUSTIC_TARGET, }; struct pp_states_info { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 1ec8a8c4016a..0d63d31b05d3 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3630,6 +3630,63 @@ static umode_t acoustic_limit_threshold_visible(struct amdgpu_device *adev) return umode; } +/** + * DOC: acoustic_target_rpm_threshold + * + * The amdgpu driver provides a sysfs API for checking and adjusting the + * acoustic target in RPM for fan control. + * + * Reading back the file shows you the current setting and the permitted + * ranges if changable. + * + * Writing an integer to the file, change the setting accordingly. + * + * When you have finished the editing, write "c" (commit) to the file to commit + * your changes. + * + * This setting works under auto fan control mode only. It can co-exist with + * other settings which can work also under auto mode. It adjusts the PMFW's + * behavior about the maximum speed in RPM the fan can spin when ASIC + * temperature is not greater than target temperature. Setting via this + * interface will switch the fan control to auto mode implicitly. + */ +static ssize_t acoustic_target_threshold_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_ACOUSTIC_TARGET, buf); +} + +static ssize_t acoustic_target_threshold_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_distribute_custom_od_settings(adev, + PP_OD_EDIT_ACOUSTIC_TARGET, + buf, + count); +} + +static umode_t acoustic_target_threshold_visible(struct amdgpu_device *adev) +{ + umode_t umode = 0000; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE) + umode |= S_IRUSR | S_IRGRP | S_IROTH; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET) + umode |= S_IWUSR; + + return umode; +} + static struct od_feature_set amdgpu_od_set = { .containers = { [0] = { @@ -3651,6 +3708,14 @@ static struct od_feature_set amdgpu_od_set = { .store = acoustic_limit_threshold_store, }, }, + [2] = { + .name = "acoustic_target_rpm_threshold", + .ops = { + .is_visible = acoustic_target_threshold_visible, + .show = acoustic_target_threshold_show, + .store = acoustic_target_threshold_store, + }, + }, }, }, }, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 984fda278f1a..bcb37ba8db58 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -318,6 +318,8 @@ struct config_table_setting #define OD_OPS_SUPPORT_FAN_CURVE_SET BIT(1) #define OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE BIT(2) #define OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET BIT(3) +#define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE BIT(4) +#define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET BIT(5) struct amdgpu_pm { struct mutex mutex; diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index ca41cfd57d89..0f1e805e166c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2485,6 +2485,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type) clk_type = SMU_OD_FAN_CURVE; break; case OD_ACOUSTIC_LIMIT: clk_type = SMU_OD_ACOUSTIC_LIMIT; break; + case OD_ACOUSTIC_TARGET: + clk_type = SMU_OD_ACOUSTIC_TARGET; break; default: clk_type = SMU_CLK_COUNT; break; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index 76bb1cba9b83..b2e9874f4a0e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -282,6 +282,7 @@ enum smu_clk_type { SMU_OD_VDDGFX_OFFSET, SMU_OD_FAN_CURVE, SMU_OD_ACOUSTIC_LIMIT, + SMU_OD_ACOUSTIC_TARGET, SMU_CLK_COUNT, }; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 021cff1995da..c5f958d7057f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -104,6 +104,7 @@ #define PP_OD_FEATURE_FAN_CURVE_TEMP 5 #define PP_OD_FEATURE_FAN_CURVE_PWM 6 #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 +#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 #define LINK_SPEED_MAX 3 @@ -1137,6 +1138,10 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold; od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold; break; + case PP_OD_FEATURE_FAN_ACOUSTIC_TARGET: + od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold; + od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1403,6 +1408,24 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_ACOUSTIC_TARGET: + if (!smu_v13_0_0_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_TARGET:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.AcousticTargetRpmThreshold); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_TARGET, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "ACOUSTIC_TARGET: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1673,6 +1696,28 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_ACOUSTIC_TARGET: + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_TARGET, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "acoustic target threshold setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.AcousticTargetRpmThreshold = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1932,7 +1977,9 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu) adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | OD_OPS_SUPPORT_FAN_CURVE_SET | OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | - OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET; + OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET | + OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | + OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET; } static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) @@ -1992,6 +2039,8 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) } user_od_table->OverDriveTable.AcousticLimitRpmThreshold = user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; + user_od_table->OverDriveTable.AcousticTargetRpmThreshold = + user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; } smu_v13_0_0_set_supported_od_feature_mask(smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index f9486c7e26bf..55571dee19a0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -80,6 +80,7 @@ #define PP_OD_FEATURE_FAN_CURVE_TEMP 5 #define PP_OD_FEATURE_FAN_CURVE_PWM 6 #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 +#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 #define LINK_SPEED_MAX 3 @@ -1117,6 +1118,10 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold; od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold; break; + case PP_OD_FEATURE_FAN_ACOUSTIC_TARGET: + od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold; + od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1383,6 +1388,24 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_ACOUSTIC_TARGET: + if (!smu_v13_0_7_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_TARGET:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.AcousticTargetRpmThreshold); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_TARGET, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "ACOUSTIC_TARGET: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1653,6 +1676,28 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_ACOUSTIC_TARGET: + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ACOUSTIC_TARGET, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "acoustic target threshold setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.AcousticTargetRpmThreshold = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1907,7 +1952,9 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu) adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | OD_OPS_SUPPORT_FAN_CURVE_SET | OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | - OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET; + OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET | + OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | + OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET; } static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) @@ -1967,6 +2014,8 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) } user_od_table->OverDriveTable.AcousticLimitRpmThreshold = user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; + user_od_table->OverDriveTable.AcousticTargetRpmThreshold = + user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; } smu_v13_0_7_set_supported_od_feature_mask(smu); -- cgit v1.2.3 From eedd5a343d2294c1593a492edfd5514d4d2c9220 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 11 Aug 2023 19:33:23 +0800 Subject: drm/amd/pm: add fan target temperature OD setting support for SMU13 Add SMU13 fan target temperature OD setting support. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/thermal.rst | 6 ++ drivers/gpu/drm/amd/include/kgd_pp_interface.h | 2 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 66 ++++++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 + .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 51 ++++++++++++++++- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 51 ++++++++++++++++- 8 files changed, 179 insertions(+), 2 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst index 26ca4812b9f6..aa2d15706cda 100644 --- a/Documentation/gpu/amdgpu/thermal.rst +++ b/Documentation/gpu/amdgpu/thermal.rst @@ -82,6 +82,12 @@ acoustic_target_rpm_threshold .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: acoustic_target_rpm_threshold +fan_target_temperature +---------------------- + +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c + :doc: fan_target_temperature + GFXOFF ====== diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a7bc81a0a36e..0501d174dbd8 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -116,6 +116,7 @@ enum pp_clock_type { OD_FAN_CURVE, OD_ACOUSTIC_LIMIT, OD_ACOUSTIC_TARGET, + OD_FAN_TARGET_TEMPERATURE, }; enum amd_pp_sensors { @@ -193,6 +194,7 @@ enum PP_OD_DPM_TABLE_COMMAND { PP_OD_EDIT_FAN_CURVE, PP_OD_EDIT_ACOUSTIC_LIMIT, PP_OD_EDIT_ACOUSTIC_TARGET, + PP_OD_EDIT_FAN_TARGET_TEMPERATURE, }; struct pp_states_info { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 0d63d31b05d3..060a38e30878 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3687,6 +3687,64 @@ static umode_t acoustic_target_threshold_visible(struct amdgpu_device *adev) return umode; } +/** + * DOC: fan_target_temperature + * + * The amdgpu driver provides a sysfs API for checking and adjusting the + * target tempeature in Celsius degree for fan control. + * + * Reading back the file shows you the current setting and the permitted + * ranges if changable. + * + * Writing an integer to the file, change the setting accordingly. + * + * When you have finished the editing, write "c" (commit) to the file to commit + * your changes. + * + * This setting works under auto fan control mode only. It can co-exist with + * other settings which can work also under auto mode. Paring with the + * acoustic_target_rpm_threshold setting, they define the maximum speed in + * RPM the fan can spin when ASIC temperature is not greater than target + * temperature. Setting via this interface will switch the fan control to + * auto mode implicitly. + */ +static ssize_t fan_target_temperature_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_TARGET_TEMPERATURE, buf); +} + +static ssize_t fan_target_temperature_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_distribute_custom_od_settings(adev, + PP_OD_EDIT_FAN_TARGET_TEMPERATURE, + buf, + count); +} + +static umode_t fan_target_temperature_visible(struct amdgpu_device *adev) +{ + umode_t umode = 0000; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE) + umode |= S_IRUSR | S_IRGRP | S_IROTH; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET) + umode |= S_IWUSR; + + return umode; +} + static struct od_feature_set amdgpu_od_set = { .containers = { [0] = { @@ -3716,6 +3774,14 @@ static struct od_feature_set amdgpu_od_set = { .store = acoustic_target_threshold_store, }, }, + [3] = { + .name = "fan_target_temperature", + .ops = { + .is_visible = fan_target_temperature_visible, + .show = fan_target_temperature_show, + .store = fan_target_temperature_store, + }, + }, }, }, }, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index bcb37ba8db58..486036632ab7 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -320,6 +320,8 @@ struct config_table_setting #define OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET BIT(3) #define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE BIT(4) #define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET BIT(5) +#define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE BIT(6) +#define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET BIT(7) struct amdgpu_pm { struct mutex mutex; diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 0f1e805e166c..60feffd8b221 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2487,6 +2487,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type) clk_type = SMU_OD_ACOUSTIC_LIMIT; break; case OD_ACOUSTIC_TARGET: clk_type = SMU_OD_ACOUSTIC_TARGET; break; + case OD_FAN_TARGET_TEMPERATURE: + clk_type = SMU_OD_FAN_TARGET_TEMPERATURE; break; default: clk_type = SMU_CLK_COUNT; break; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index b2e9874f4a0e..5a129e7162a9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -283,6 +283,7 @@ enum smu_clk_type { SMU_OD_FAN_CURVE, SMU_OD_ACOUSTIC_LIMIT, SMU_OD_ACOUSTIC_TARGET, + SMU_OD_FAN_TARGET_TEMPERATURE, SMU_CLK_COUNT, }; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index c5f958d7057f..b377aee4b1f0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -105,6 +105,7 @@ #define PP_OD_FEATURE_FAN_CURVE_PWM 6 #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 +#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 #define LINK_SPEED_MAX 3 @@ -1142,6 +1143,10 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold; od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold; break; + case PP_OD_FEATURE_FAN_TARGET_TEMPERATURE: + od_min_setting = overdrive_lowerlimits->FanTargetTemperature; + od_max_setting = overdrive_upperlimits->FanTargetTemperature; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1426,6 +1431,24 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_FAN_TARGET_TEMPERATURE: + if (!smu_v13_0_0_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "FAN_TARGET_TEMPERATURE:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.FanTargetTemperature); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_TARGET_TEMPERATURE, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1718,6 +1741,28 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_FAN_TARGET_TEMPERATURE: + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_TARGET_TEMPERATURE, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "fan target temperature setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanTargetTemperature = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1979,7 +2024,9 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu) OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET | OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | - OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET; + OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET; } static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) @@ -2041,6 +2088,8 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; user_od_table->OverDriveTable.AcousticTargetRpmThreshold = user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; + user_od_table->OverDriveTable.FanTargetTemperature = + user_od_table_bak.OverDriveTable.FanTargetTemperature; } smu_v13_0_0_set_supported_od_feature_mask(smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 55571dee19a0..c12ff7c1a339 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -81,6 +81,7 @@ #define PP_OD_FEATURE_FAN_CURVE_PWM 6 #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 +#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 #define LINK_SPEED_MAX 3 @@ -1122,6 +1123,10 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold; od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold; break; + case PP_OD_FEATURE_FAN_TARGET_TEMPERATURE: + od_min_setting = overdrive_lowerlimits->FanTargetTemperature; + od_max_setting = overdrive_upperlimits->FanTargetTemperature; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1406,6 +1411,24 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_FAN_TARGET_TEMPERATURE: + if (!smu_v13_0_7_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "FAN_TARGET_TEMPERATURE:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.FanTargetTemperature); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_TARGET_TEMPERATURE, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1698,6 +1721,28 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_FAN_TARGET_TEMPERATURE: + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_TARGET_TEMPERATURE, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "fan target temperature setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanTargetTemperature = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -1954,7 +1999,9 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu) OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET | OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | - OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET; + OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET; } static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) @@ -2016,6 +2063,8 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; user_od_table->OverDriveTable.AcousticTargetRpmThreshold = user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; + user_od_table->OverDriveTable.FanTargetTemperature = + user_od_table_bak.OverDriveTable.FanTargetTemperature; } smu_v13_0_7_set_supported_od_feature_mask(smu); -- cgit v1.2.3 From 9df5d00870ea628c3c6310aea859e5c06d378a12 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 11 Aug 2023 19:52:12 +0800 Subject: drm/amd/pm: add fan minimum pwm OD setting support for SMU13 Add SMU13 fan minimum pwm OD setting support. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/thermal.rst | 6 ++ drivers/gpu/drm/amd/include/kgd_pp_interface.h | 2 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 64 ++++++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 + .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 51 ++++++++++++++++- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 51 ++++++++++++++++- 8 files changed, 177 insertions(+), 2 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst index aa2d15706cda..2f6166f81e6a 100644 --- a/Documentation/gpu/amdgpu/thermal.rst +++ b/Documentation/gpu/amdgpu/thermal.rst @@ -88,6 +88,12 @@ fan_target_temperature .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: fan_target_temperature +fan_minimum_pwm +--------------- + +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c + :doc: fan_minimum_pwm + GFXOFF ====== diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 0501d174dbd8..5a889f733462 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -117,6 +117,7 @@ enum pp_clock_type { OD_ACOUSTIC_LIMIT, OD_ACOUSTIC_TARGET, OD_FAN_TARGET_TEMPERATURE, + OD_FAN_MINIMUM_PWM, }; enum amd_pp_sensors { @@ -195,6 +196,7 @@ enum PP_OD_DPM_TABLE_COMMAND { PP_OD_EDIT_ACOUSTIC_LIMIT, PP_OD_EDIT_ACOUSTIC_TARGET, PP_OD_EDIT_FAN_TARGET_TEMPERATURE, + PP_OD_EDIT_FAN_MINIMUM_PWM, }; struct pp_states_info { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 060a38e30878..84e1af6a6ce7 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3745,6 +3745,62 @@ static umode_t fan_target_temperature_visible(struct amdgpu_device *adev) return umode; } +/** + * DOC: fan_minimum_pwm + * + * The amdgpu driver provides a sysfs API for checking and adjusting the + * minimum fan speed in PWM. + * + * Reading back the file shows you the current setting and the permitted + * ranges if changable. + * + * Writing an integer to the file, change the setting accordingly. + * + * When you have finished the editing, write "c" (commit) to the file to commit + * your changes. + * + * This setting works under auto fan control mode only. It can co-exist with + * other settings which can work also under auto mode. It adjusts the PMFW's + * behavior about the minimum fan speed in PWM the fan should spin. Setting + * via this interface will switch the fan control to auto mode implicitly. + */ +static ssize_t fan_minimum_pwm_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_MINIMUM_PWM, buf); +} + +static ssize_t fan_minimum_pwm_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; + + return (ssize_t)amdgpu_distribute_custom_od_settings(adev, + PP_OD_EDIT_FAN_MINIMUM_PWM, + buf, + count); +} + +static umode_t fan_minimum_pwm_visible(struct amdgpu_device *adev) +{ + umode_t umode = 0000; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE) + umode |= S_IRUSR | S_IRGRP | S_IROTH; + + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET) + umode |= S_IWUSR; + + return umode; +} + static struct od_feature_set amdgpu_od_set = { .containers = { [0] = { @@ -3782,6 +3838,14 @@ static struct od_feature_set amdgpu_od_set = { .store = fan_target_temperature_store, }, }, + [4] = { + .name = "fan_minimum_pwm", + .ops = { + .is_visible = fan_minimum_pwm_visible, + .show = fan_minimum_pwm_show, + .store = fan_minimum_pwm_store, + }, + }, }, }, }, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 486036632ab7..5efdba6e358f 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -322,6 +322,8 @@ struct config_table_setting #define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET BIT(5) #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE BIT(6) #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET BIT(7) +#define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE BIT(8) +#define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET BIT(9) struct amdgpu_pm { struct mutex mutex; diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 60feffd8b221..206e233826b5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2489,6 +2489,8 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type) clk_type = SMU_OD_ACOUSTIC_TARGET; break; case OD_FAN_TARGET_TEMPERATURE: clk_type = SMU_OD_FAN_TARGET_TEMPERATURE; break; + case OD_FAN_MINIMUM_PWM: + clk_type = SMU_OD_FAN_MINIMUM_PWM; break; default: clk_type = SMU_CLK_COUNT; break; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index 5a129e7162a9..ebc789e7a289 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -284,6 +284,7 @@ enum smu_clk_type { SMU_OD_ACOUSTIC_LIMIT, SMU_OD_ACOUSTIC_TARGET, SMU_OD_FAN_TARGET_TEMPERATURE, + SMU_OD_FAN_MINIMUM_PWM, SMU_CLK_COUNT, }; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index b377aee4b1f0..93fb56200a14 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -106,6 +106,7 @@ #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 +#define PP_OD_FEATURE_FAN_MINIMUM_PWM 10 #define LINK_SPEED_MAX 3 @@ -1147,6 +1148,10 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->FanTargetTemperature; od_max_setting = overdrive_upperlimits->FanTargetTemperature; break; + case PP_OD_FEATURE_FAN_MINIMUM_PWM: + od_min_setting = overdrive_lowerlimits->FanMinimumPwm; + od_max_setting = overdrive_upperlimits->FanMinimumPwm; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1449,6 +1454,24 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_FAN_MINIMUM_PWM: + if (!smu_v13_0_0_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.FanMinimumPwm); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_MINIMUM_PWM, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1763,6 +1786,28 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_FAN_MINIMUM_PWM: + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_0_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_MINIMUM_PWM, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanMinimumPwm = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -2026,7 +2071,9 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu) OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | - OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET; + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET | + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE | + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET; } static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) @@ -2090,6 +2137,8 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; user_od_table->OverDriveTable.FanTargetTemperature = user_od_table_bak.OverDriveTable.FanTargetTemperature; + user_od_table->OverDriveTable.FanMinimumPwm = + user_od_table_bak.OverDriveTable.FanMinimumPwm; } smu_v13_0_0_set_supported_od_feature_mask(smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index c12ff7c1a339..99bc449799a6 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -82,6 +82,7 @@ #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 +#define PP_OD_FEATURE_FAN_MINIMUM_PWM 10 #define LINK_SPEED_MAX 3 @@ -1127,6 +1128,10 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->FanTargetTemperature; od_max_setting = overdrive_upperlimits->FanTargetTemperature; break; + case PP_OD_FEATURE_FAN_MINIMUM_PWM: + od_min_setting = overdrive_lowerlimits->FanMinimumPwm; + od_max_setting = overdrive_upperlimits->FanMinimumPwm; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1429,6 +1434,24 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_FAN_MINIMUM_PWM: + if (!smu_v13_0_7_is_od_feature_supported(smu, + PP_OD_FEATURE_FAN_CURVE_BIT)) + break; + + size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.FanMinimumPwm); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_MINIMUM_PWM, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -1743,6 +1766,28 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_FAN_MINIMUM_PWM: + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + dev_warn(adev->dev, "Fan curve setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v13_0_7_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_MINIMUM_PWM, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanMinimumPwm = input[0]; + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; memcpy(od_table, @@ -2001,7 +2046,9 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu) OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | - OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET; + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET | + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE | + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET; } static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) @@ -2065,6 +2112,8 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; user_od_table->OverDriveTable.FanTargetTemperature = user_od_table_bak.OverDriveTable.FanTargetTemperature; + user_od_table->OverDriveTable.FanMinimumPwm = + user_od_table_bak.OverDriveTable.FanMinimumPwm; } smu_v13_0_7_set_supported_od_feature_mask(smu); -- cgit v1.2.3 From 4798db85b76a0e2bebe8bb51251c2688b1e8ab93 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 28 Sep 2023 09:04:11 +0530 Subject: Documentation/amdgpu: Add board info details Add documentation for board info sysfs attribute. Signed-off-by: Lijo Lazar Reviewed-by: Alex Deucher Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/driver-misc.rst | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/driver-misc.rst b/Documentation/gpu/amdgpu/driver-misc.rst index 4321c38fef21..82b47f1818ac 100644 --- a/Documentation/gpu/amdgpu/driver-misc.rst +++ b/Documentation/gpu/amdgpu/driver-misc.rst @@ -32,6 +32,12 @@ unique_id .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: unique_id +board_info +---------- + +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c + :doc: board_info + Accelerated Processing Units (APU) Info --------------------------------------- diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 10f1641aede9..27c95bb02411 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -162,6 +162,22 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev, static DEVICE_ATTR(pcie_replay_count, 0444, amdgpu_device_get_pcie_replay_count, NULL); +/** + * DOC: board_info + * + * The amdgpu driver provides a sysfs API for giving board related information. + * It provides the form factor information in the format + * + * type : form factor + * + * Possible form factor values + * + * - "cem" - PCIE CEM card + * - "oam" - Open Compute Accelerator Module + * - "unknown" - Not known + * + */ + static ssize_t amdgpu_device_get_board_info(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3 From b3e73b5a8f8ae3f585abd756416b089f82578ef2 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 4 Oct 2023 18:46:06 +0530 Subject: Documentation/amdgpu: Add FRU attribute details Add documentation for the newly added manufacturer and fru_id attributes in sysfs. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/driver-misc.rst | 12 ++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/amdgpu/driver-misc.rst b/Documentation/gpu/amdgpu/driver-misc.rst index 82b47f1818ac..e40e15f89fd3 100644 --- a/Documentation/gpu/amdgpu/driver-misc.rst +++ b/Documentation/gpu/amdgpu/driver-misc.rst @@ -26,6 +26,18 @@ serial_number .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c :doc: serial_number +fru_id +------------- + +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c + :doc: fru_id + +manufacturer +------------- + +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c + :doc: manufacturer + unique_id --------- diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 5d627d0e19a4..d635e61805ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -321,6 +321,16 @@ static ssize_t amdgpu_fru_serial_number_show(struct device *dev, static DEVICE_ATTR(serial_number, 0444, amdgpu_fru_serial_number_show, NULL); +/** + * DOC: fru_id + * + * The amdgpu driver provides a sysfs API for reporting FRU File Id + * for the device. + * The file fru_id is used for this and returns the File Id value + * as returned from the FRU. + * NOTE: This is only available for certain server cards + */ + static ssize_t amdgpu_fru_id_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -332,6 +342,15 @@ static ssize_t amdgpu_fru_id_show(struct device *dev, static DEVICE_ATTR(fru_id, 0444, amdgpu_fru_id_show, NULL); +/** + * DOC: manufacturer + * + * The amdgpu driver provides a sysfs API for reporting manufacturer name from + * FRU information. + * The file manufacturer returns the value as returned from the FRU. + * NOTE: This is only available for certain server cards + */ + static ssize_t amdgpu_fru_manufacturer_name_show(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3