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 d38d753da7f7c9c4739e3e9ca3c986fa2c1b8c98 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 26 Sep 2023 12:51:06 -0400 Subject: drm/i915: Add missing CCS documentation Let's introduce the basic documentation about CCS. While doing that, also removed the legacy execution flag name. That flag simply doesn't exist for CCS and it is not needed on current context submission. Those flag names are only needed on legacy context, while on new ones we only need to pass the engine ID. It is worth mention that this documentation should probably live with the engine definitions rather than in the i915.rst file directly and that more updates are likely need in this section. But this should come later. v2: Overall improvements from Matt and Tvrtko. Fixes: 944823c94639 ("drm/i915/xehp: Define compute class and engine") Cc: Matt Roper Cc: Sushma Venkatesh Reddy Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Signed-off-by: Rodrigo Vivi Acked-by: Tvrtko Ursulin Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20230926165107.23440-1-rodrigo.vivi@intel.com --- Documentation/gpu/i915.rst | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 378e825754d5..13de8bcaaa29 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -267,19 +267,18 @@ i915 driver. Intel GPU Basics ---------------- -An Intel GPU has multiple engines. There are several engine types. - -- RCS engine is for rendering 3D and performing compute, this is named - `I915_EXEC_RENDER` in user space. -- BCS is a blitting (copy) engine, this is named `I915_EXEC_BLT` in user - space. -- VCS is a video encode and decode engine, this is named `I915_EXEC_BSD` - in user space -- VECS is video enhancement engine, this is named `I915_EXEC_VEBOX` in user - space. -- The enumeration `I915_EXEC_DEFAULT` does not refer to specific engine; - instead it is to be used by user space to specify a default rendering - engine (for 3D) that may or may not be the same as RCS. +An Intel GPU has multiple engines. There are several engine types: + +- Render Command Streamer (RCS). An engine for rendering 3D and + performing compute. +- Blitting Command Streamer (BCS). An engine for performing blitting and/or + copying operations. +- Video Command Streamer. An engine used for video encoding and decoding. Also + sometimes called 'BSD' in hardware documentation. +- Video Enhancement Command Streamer (VECS). An engine for video enhancement. + Also sometimes called 'VEBOX' in hardware documentation. +- Compute Command Streamer (CCS). An engine that has access to the media and + GPGPU pipelines, but not the 3D pipeline. The Intel GPU family is a family of integrated GPU's using Unified Memory Access. For having the GPU "do work", user space will feed the -- cgit v1.2.3 From 587e80dc1cb5f1f3f41b38356d3e3563c01d9d8e Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 26 Sep 2023 13:55:54 -0400 Subject: drm/i915: Add missing GSCCS documentation Introduce the basic documentation about GSC CS. This "GPU Basics" section is focused on explaining the hardware rather than the driver/uapi, so let's make sure GSC is also properly documented here. v2: Fixes from Matt: typos and acronym. Fixes: 5fd974d164b4 ("drm/i915/mtl: add initial definitions for GSC CS") Suggested-by: Matt Roper Cc: Daniele Ceraolo Spurio Cc: Tvrtko Ursulin Signed-off-by: Rodrigo Vivi Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20230926175554.25968-1-rodrigo.vivi@intel.com --- Documentation/gpu/i915.rst | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Documentation/gpu') diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 13de8bcaaa29..0ca1550fd9dc 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -279,6 +279,10 @@ An Intel GPU has multiple engines. There are several engine types: Also sometimes called 'VEBOX' in hardware documentation. - Compute Command Streamer (CCS). An engine that has access to the media and GPGPU pipelines, but not the 3D pipeline. +- Graphics Security Controller (GSCCS). A dedicated engine for internal + communication with GSC controller on security related tasks like + High-bandwidth Digital Content Protection (HDCP), Protected Xe Path (PXP), + and HuC firmware authentication. The Intel GPU family is a family of integrated GPU's using Unified Memory Access. For having the GPU "do work", user space will feed the -- 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