From 79c65f3fcbb1288b84473d45e6d001820a971d54 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 22 Nov 2021 11:05:22 +0800 Subject: drm/amd/pm: do not expose power implementation details to amdgpu_pm.c amdgpu_pm.c holds all the user sysfs/hwmon interfaces. It's another client of our power APIs. It's not proper to spike into power implementation details there. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 519 +++++++++++++------------------------ 1 file changed, 182 insertions(+), 337 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index e2cae97f4ff1..b16bb67b93f1 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -34,7 +34,6 @@ #include #include #include -#include "hwmgr.h" static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"}, @@ -132,7 +131,6 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_pm_state_type pm; int ret; @@ -147,11 +145,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, return ret; } - if (pp_funcs->get_current_power_state) { - pm = amdgpu_dpm_get_current_power_state(adev); - } else { - pm = adev->pm.dpm.user_state; - } + amdgpu_dpm_get_current_power_state(adev, &pm); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -191,19 +185,8 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.user_state = state; - mutex_unlock(&adev->pm.mutex); - } else if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state); - } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.user_state = state; - mutex_unlock(&adev->pm.mutex); + amdgpu_dpm_set_power_state(adev, state); - amdgpu_pm_compute_clocks(adev); - } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -290,10 +273,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_performance_level) - level = amdgpu_dpm_get_performance_level(adev); - else - level = adev->pm.dpm.forced_level; + level = amdgpu_dpm_get_performance_level(adev); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -318,7 +298,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_dpm_forced_level level; enum amd_dpm_forced_level current_level; int ret = 0; @@ -358,11 +337,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } - if (pp_funcs->get_performance_level) - current_level = amdgpu_dpm_get_performance_level(adev); - else - current_level = adev->pm.dpm.forced_level; - + current_level = amdgpu_dpm_get_performance_level(adev); if (current_level == level) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -390,25 +365,12 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return -EINVAL; } - if (pp_funcs->force_performance_level) { - mutex_lock(&adev->pm.mutex); - if (adev->pm.dpm.thermal_active) { - mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - ret = amdgpu_dpm_force_performance_level(adev, level); - if (ret) { - mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } else { - adev->pm.dpm.forced_level = level; - } - mutex_unlock(&adev->pm.mutex); + if (amdgpu_dpm_force_performance_level(adev, level)) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; } + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -421,7 +383,6 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_states_info data; uint32_t i; int buf_len, ret; @@ -437,11 +398,8 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, return ret; } - if (pp_funcs->get_pp_num_states) { - amdgpu_dpm_get_pp_num_states(adev, &data); - } else { + if (amdgpu_dpm_get_pp_num_states(adev, &data)) memset(&data, 0, sizeof(data)); - } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -463,7 +421,6 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_states_info data = {0}; enum amd_pm_state_type pm = 0; int i = 0, ret = 0; @@ -479,15 +436,16 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, return ret; } - if (pp_funcs->get_current_power_state - && pp_funcs->get_pp_num_states) { - pm = amdgpu_dpm_get_current_power_state(adev); - amdgpu_dpm_get_pp_num_states(adev, &data); - } + amdgpu_dpm_get_current_power_state(adev, &pm); + + ret = amdgpu_dpm_get_pp_num_states(adev, &data); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + if (ret) + return ret; + for (i = 0; i < data.nums; i++) { if (pm == data.states[i]) break; @@ -525,6 +483,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type state = 0; + struct pp_states_info data; unsigned long idx; int ret; @@ -533,41 +492,49 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if (strlen(buf) == 1) - adev->pp_force_state_enabled = false; - else if (is_support_sw_smu(adev)) - adev->pp_force_state_enabled = false; - else if (adev->powerplay.pp_funcs->dispatch_tasks && - adev->powerplay.pp_funcs->get_pp_num_states) { - struct pp_states_info data; - - ret = kstrtoul(buf, 0, &idx); - if (ret || idx >= ARRAY_SIZE(data.states)) - return -EINVAL; + adev->pp_force_state_enabled = false; - idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); + if (strlen(buf) == 1) + return count; - amdgpu_dpm_get_pp_num_states(adev, &data); - state = data.states[idx]; + ret = kstrtoul(buf, 0, &idx); + if (ret || idx >= ARRAY_SIZE(data.states)) + return -EINVAL; - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } + idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); - /* only set user selected power states */ - if (state != POWER_STATE_TYPE_INTERNAL_BOOT && - state != POWER_STATE_TYPE_DEFAULT) { - amdgpu_dpm_dispatch_task(adev, - AMD_PP_TASK_ENABLE_USER_STATE, &state); - adev->pp_force_state_enabled = true; - } - pm_runtime_mark_last_busy(ddev->dev); + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + ret = amdgpu_dpm_get_pp_num_states(adev, &data); + if (ret) + goto err_out; + + state = data.states[idx]; + + /* only set user selected power states */ + if (state != POWER_STATE_TYPE_INTERNAL_BOOT && + state != POWER_STATE_TYPE_DEFAULT) { + ret = amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_ENABLE_USER_STATE, &state); + if (ret) + goto err_out; + + adev->pp_force_state_enabled = true; } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return count; + +err_out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return ret; } /** @@ -601,17 +568,13 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_pp_table) { - size = amdgpu_dpm_get_pp_table(adev, &table); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - if (size < 0) - return size; - } else { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return 0; - } + size = amdgpu_dpm_get_pp_table(adev, &table); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (size <= 0) + return size; if (size >= PAGE_SIZE) size = PAGE_SIZE - 1; @@ -642,15 +605,13 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, } ret = amdgpu_dpm_set_pp_table(adev, buf, count); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + if (ret) + return ret; + return count; } @@ -866,46 +827,32 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->set_fine_grain_clk_vol) { - ret = amdgpu_dpm_set_fine_grain_clk_vol(adev, type, - parameter, - parameter_size); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } + if (amdgpu_dpm_set_fine_grain_clk_vol(adev, + type, + parameter, + parameter_size)) + goto err_out; - if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { - ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, - parameter, parameter_size); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } + if (amdgpu_dpm_odn_edit_dpm_table(adev, type, + parameter, parameter_size)) + goto err_out; if (type == PP_OD_COMMIT_DPM_TABLE) { - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, - AMD_PP_TASK_READJUST_POWER_STATE, - NULL); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return count; - } else { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } + if (amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_READJUST_POWER_STATE, + NULL)) + goto err_out; } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); return count; + +err_out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; } static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, @@ -928,8 +875,8 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->print_clock_levels) { - size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + if (size > 0) { size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size); size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf+size); @@ -985,17 +932,14 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->set_ppfeature_status) { - ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } + ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + if (ret) + return -EINVAL; + return count; } @@ -1019,9 +963,8 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_ppfeature_status) - size = amdgpu_dpm_get_ppfeature_status(adev, buf); - else + size = amdgpu_dpm_get_ppfeature_status(adev, buf); + if (size <= 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -1080,9 +1023,8 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->print_clock_levels) - size = amdgpu_dpm_print_clock_levels(adev, type, buf); - else + size = amdgpu_dpm_print_clock_levels(adev, type, buf); + if (size <= 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -1151,10 +1093,7 @@ static ssize_t amdgpu_set_pp_dpm_clock(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->force_clock_level) - ret = amdgpu_dpm_force_clock_level(adev, type, mask); - else - ret = 0; + ret = amdgpu_dpm_force_clock_level(adev, type, mask); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1305,10 +1244,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) - value = 0; - else if (adev->powerplay.pp_funcs->get_sclk_od) - value = amdgpu_dpm_get_sclk_od(adev); + value = amdgpu_dpm_get_sclk_od(adev); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1342,19 +1278,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) { - value = 0; - } else { - if (adev->powerplay.pp_funcs->set_sclk_od) - amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); - - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); - } - } + amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1382,10 +1306,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) - value = 0; - else if (adev->powerplay.pp_funcs->get_mclk_od) - value = amdgpu_dpm_get_mclk_od(adev); + value = amdgpu_dpm_get_mclk_od(adev); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1419,19 +1340,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) { - value = 0; - } else { - if (adev->powerplay.pp_funcs->set_mclk_od) - amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); - - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); - } - } + amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1479,9 +1388,8 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_power_profile_mode) - size = amdgpu_dpm_get_power_profile_mode(adev, buf); - else + size = amdgpu_dpm_get_power_profile_mode(adev, buf); + if (size <= 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -1545,8 +1453,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->set_power_profile_mode) - ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); + ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1812,9 +1719,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_gpu_metrics) - size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); - + size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); if (size <= 0) goto out; @@ -2053,7 +1958,6 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ { struct device_attribute *dev_attr = &attr->dev_attr; const char *attr_name = dev_attr->attr.name; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; enum amd_asic_type asic_type = adev->asic_type; if (!(attr->flags & mask)) { @@ -2076,9 +1980,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { *states = ATTR_STATE_UNSUPPORTED; - if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || - (is_support_sw_smu(adev) && adev->smu.is_apu) || - (!is_support_sw_smu(adev) && hwmgr->od_enabled)) + if (amdgpu_dpm_is_overdrive_supported(adev)) *states = ATTR_STATE_SUPPORTED; } else if (DEVICE_ATTR_IS(mem_busy_percent)) { if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) @@ -2106,8 +2008,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { - if (!adev->powerplay.pp_funcs->get_power_profile_mode || - amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) + if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; } @@ -2396,17 +2297,14 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, return ret; } - if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + ret = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (ret) + return -EINVAL; + return sysfs_emit(buf, "%u\n", pwm_mode); } @@ -2434,17 +2332,14 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, return ret; } - if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - amdgpu_dpm_set_fan_control_mode(adev, value); + ret = amdgpu_dpm_set_fan_control_mode(adev, value); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (ret) + return -EINVAL; + return count; } @@ -2476,32 +2371,29 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; + err = kstrtou32(buf, 10, &value); + if (err) + return err; + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + err = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); + if (err) + goto out; + if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; + err = -EINVAL; + goto out; } - err = kstrtou32(buf, 10, &value); - if (err) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return err; - } - - if (adev->powerplay.pp_funcs->set_fan_speed_pwm) - err = amdgpu_dpm_set_fan_speed_pwm(adev, value); - else - err = -EINVAL; + err = amdgpu_dpm_set_fan_speed_pwm(adev, value); +out: pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2530,10 +2422,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, return err; } - if (adev->powerplay.pp_funcs->get_fan_speed_pwm) - err = amdgpu_dpm_get_fan_speed_pwm(adev, &speed); - else - err = -EINVAL; + err = amdgpu_dpm_get_fan_speed_pwm(adev, &speed); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2563,10 +2452,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, return err; } - if (adev->powerplay.pp_funcs->get_fan_speed_rpm) - err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); - else - err = -EINVAL; + err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2660,10 +2546,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, return err; } - if (adev->powerplay.pp_funcs->get_fan_speed_rpm) - err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); - else - err = -EINVAL; + err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2688,32 +2571,28 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; + err = kstrtou32(buf, 10, &value); + if (err) + return err; + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + err = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); + if (err) + goto out; if (pwm_mode != AMD_FAN_CTRL_MANUAL) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -ENODATA; - } - - err = kstrtou32(buf, 10, &value); - if (err) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return err; + err = -ENODATA; + goto out; } - if (adev->powerplay.pp_funcs->set_fan_speed_rpm) - err = amdgpu_dpm_set_fan_speed_rpm(adev, value); - else - err = -EINVAL; + err = amdgpu_dpm_set_fan_speed_rpm(adev, value); +out: pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2742,17 +2621,14 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, return ret; } - if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + ret = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (ret) + return -EINVAL; + return sysfs_emit(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); } @@ -2788,16 +2664,14 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, return err; } - if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); + err = amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (err) + return -EINVAL; + return count; } @@ -2933,7 +2807,6 @@ static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev, enum pp_power_limit_level pp_limit_level) { struct amdgpu_device *adev = dev_get_drvdata(dev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum pp_power_type power_type = to_sensor_dev_attr(attr)->index; uint32_t limit; ssize_t size; @@ -2944,16 +2817,13 @@ static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if ( !(pp_funcs && pp_funcs->get_power_limit)) - return -ENODATA; - r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } - r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, + r = amdgpu_dpm_get_power_limit(adev, &limit, pp_limit_level, power_type); if (!r) @@ -3008,7 +2878,6 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, size_t count) { struct amdgpu_device *adev = dev_get_drvdata(dev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int limit_type = to_sensor_dev_attr(attr)->index; int err; u32 value; @@ -3034,10 +2903,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, return err; } - if (pp_funcs && pp_funcs->set_power_limit) - err = pp_funcs->set_power_limit(adev->powerplay.pp_handle, value); - else - err = -EINVAL; + err = amdgpu_dpm_set_power_limit(adev, value); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -3310,6 +3176,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; + uint32_t speed = 0; /* under multi-vf mode, the hwmon attributes are all not supported */ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) @@ -3374,20 +3241,18 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) return 0; - if (!is_support_sw_smu(adev)) { - /* mask fan attributes if we have no bindings for this asic to expose */ - if ((!adev->powerplay.pp_funcs->get_fan_speed_pwm && - attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ - (!adev->powerplay.pp_funcs->get_fan_control_mode && - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ - effective_mode &= ~S_IRUGO; + /* mask fan attributes if we have no bindings for this asic to expose */ + if (((amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ + ((amdgpu_dpm_get_fan_control_mode(adev, &speed) == -EOPNOTSUPP) && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ + effective_mode &= ~S_IRUGO; - if ((!adev->powerplay.pp_funcs->set_fan_speed_pwm && - attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ - (!adev->powerplay.pp_funcs->set_fan_control_mode && - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ - effective_mode &= ~S_IWUSR; - } + if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ + ((amdgpu_dpm_set_fan_control_mode(adev, speed) == -EOPNOTSUPP) && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ + effective_mode &= ~S_IWUSR; if (((adev->family == AMDGPU_FAMILY_SI) || ((adev->flags & AMD_IS_APU) && @@ -3404,22 +3269,20 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, (attr == &sensor_dev_attr_power1_average.dev_attr.attr)) return 0; - if (!is_support_sw_smu(adev)) { - /* hide max/min values if we can't both query and manage the fan */ - if ((!adev->powerplay.pp_funcs->set_fan_speed_pwm && - !adev->powerplay.pp_funcs->get_fan_speed_pwm) && - (!adev->powerplay.pp_funcs->set_fan_speed_rpm && - !adev->powerplay.pp_funcs->get_fan_speed_rpm) && - (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) - return 0; + /* hide max/min values if we can't both query and manage the fan */ + if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && + (amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && + (amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && + (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL)) && + (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) + return 0; - if ((!adev->powerplay.pp_funcs->set_fan_speed_rpm && - !adev->powerplay.pp_funcs->get_fan_speed_rpm) && - (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) - return 0; - } + if ((amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && + (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL) && + (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) + return 0; if ((adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ @@ -3549,14 +3412,15 @@ static void amdgpu_debugfs_prints_cpu_info(struct seq_file *m, uint16_t *p_val; uint32_t size; int i; + uint32_t num_cpu_cores = amdgpu_dpm_get_num_cpu_cores(adev); - if (is_support_cclk_dpm(adev)) { - p_val = kcalloc(adev->smu.cpu_core_num, sizeof(uint16_t), + if (amdgpu_dpm_is_cclk_dpm_supported(adev)) { + p_val = kcalloc(num_cpu_cores, sizeof(uint16_t), GFP_KERNEL); if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_CPU_CLK, (void *)p_val, &size)) { - for (i = 0; i < adev->smu.cpu_core_num; i++) + for (i = 0; i < num_cpu_cores; i++) seq_printf(m, "\t%u MHz (CPU%d)\n", *(p_val + i), i); } @@ -3684,27 +3548,11 @@ static int amdgpu_debugfs_pm_info_show(struct seq_file *m, void *unused) return r; } - if (!adev->pm.dpm_enabled) { - seq_printf(m, "dpm not enabled\n"); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); - return 0; - } - - if (!is_support_sw_smu(adev) && - adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { - mutex_lock(&adev->pm.mutex); - if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) - adev->powerplay.pp_funcs->debugfs_print_current_performance_level(adev, m); - else - seq_printf(m, "Debugfs support not implemented for this asic\n"); - mutex_unlock(&adev->pm.mutex); - r = 0; - } else { + if (amdgpu_dpm_debugfs_print_current_performance_level(adev, m)) { r = amdgpu_debugfs_pm_info_pp(m, adev); + if (r) + goto out; } - if (r) - goto out; amdgpu_device_ip_get_clockgating_state(adev, &flags); @@ -3730,21 +3578,18 @@ static ssize_t amdgpu_pm_prv_buffer_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { struct amdgpu_device *adev = file_inode(f)->i_private; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; size_t smu_prv_buf_size; void *smu_prv_buf; + int ret = 0; if (amdgpu_in_reset(adev)) return -EPERM; if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if (pp_funcs && pp_funcs->get_smu_prv_buf_details) - pp_funcs->get_smu_prv_buf_details(pp_handle, &smu_prv_buf, - &smu_prv_buf_size); - else - return -ENOSYS; + ret = amdgpu_dpm_get_smu_prv_buf_details(adev, &smu_prv_buf, &smu_prv_buf_size); + if (ret) + return ret; if (!smu_prv_buf || !smu_prv_buf_size) return -EINVAL; @@ -3777,6 +3622,6 @@ void amdgpu_debugfs_pm_init(struct amdgpu_device *adev) &amdgpu_debugfs_pm_prv_buffer_fops, adev->pm.smu_prv_buffer_size); - amdgpu_smu_stb_debug_fs_init(adev); + amdgpu_dpm_stb_debug_fs_init(adev); #endif } -- cgit From d698a2c4859de2d4d42d2f3c3806d6dce821d663 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 15 Nov 2021 15:24:05 +0800 Subject: drm/amd/pm: move pp_force_state_enabled member to amdgpu_pm structure As it lables an internal pm state and amdgpu_pm structure is the more proper place than amdgpu_device structure for it. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +++--- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 182d673103ed..d6dff14e7a2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -949,7 +949,6 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; - bool pp_force_state_enabled; /* smu */ struct smu_context smu; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index b16bb67b93f1..cd32f4ed373e 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -469,7 +469,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if (adev->pp_force_state_enabled) + if (adev->pm.pp_force_state_enabled) return amdgpu_get_pp_cur_state(dev, attr, buf); else return sysfs_emit(buf, "\n"); @@ -492,7 +492,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - adev->pp_force_state_enabled = false; + adev->pm.pp_force_state_enabled = false; if (strlen(buf) == 1) return count; @@ -523,7 +523,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (ret) goto err_out; - adev->pp_force_state_enabled = true; + adev->pm.pp_force_state_enabled = true; } pm_runtime_mark_last_busy(ddev->dev); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 1958e0e488b0..7afff23305a5 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -343,6 +343,8 @@ struct amdgpu_pm { * 0 = disabled (default), otherwise enable corresponding debug mode */ uint32_t smu_debug_mask; + + bool pp_force_state_enabled; }; #define R600_SSTU_DFLT 0 -- cgit From ebfc253335af81db2e40e6e8ed17cd76edf9080f Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 22 Nov 2021 13:11:06 +0800 Subject: drm/amd/pm: do not expose the smu_context structure used internally in power This can cover the power implementation details. And as what did for powerplay framework, we hook the smu_context to adev->powerplay.pp_handle. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 3 ++ drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 50 +++++++++++++++------- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 2 +- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 4 -- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 48 +++++++++++++-------- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 9 ++-- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 9 ++-- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 9 ++-- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 4 +- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 9 ++-- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 8 ++-- 12 files changed, 94 insertions(+), 67 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d6dff14e7a2d..f0132a5cc58d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -99,7 +99,6 @@ #include "amdgpu_gem.h" #include "amdgpu_doorbell.h" #include "amdgpu_amdkfd.h" -#include "amdgpu_smu.h" #include "amdgpu_discovery.h" #include "amdgpu_mes.h" #include "amdgpu_umc.h" @@ -949,11 +948,6 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; - - /* smu */ - struct smu_context smu; - - /* dpm */ struct amdgpu_pm pm; u32 cg_flags; u32 pg_flags; diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 7919e96e772b..a8eec91c0995 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -25,6 +25,9 @@ #define __KGD_PP_INTERFACE_H__ extern const struct amdgpu_ip_block_version pp_smu_ip_block; +extern const struct amdgpu_ip_block_version smu_v11_0_ip_block; +extern const struct amdgpu_ip_block_version smu_v12_0_ip_block; +extern const struct amdgpu_ip_block_version smu_v13_0_ip_block; enum smu_event_type { SMU_EVENT_RESET_COMPLETE = 0, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 88909b7c40db..2756f52b74c1 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -31,6 +31,7 @@ #include "amdgpu_display.h" #include "hwmgr.h" #include +#include "amdgpu_smu.h" #define amdgpu_dpm_enable_bapm(adev, e) \ ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) @@ -213,7 +214,7 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (is_support_sw_smu(adev)) return smu_mode1_reset_is_support(smu); @@ -223,7 +224,7 @@ bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (is_support_sw_smu(adev)) return smu_mode1_reset(smu); @@ -276,7 +277,7 @@ int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (is_support_sw_smu(adev)) return smu_allow_xgmi_power_down(smu, en); @@ -341,7 +342,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) mutex_unlock(&adev->pm.mutex); if (is_support_sw_smu(adev)) - smu_set_ac_dc(&adev->smu); + smu_set_ac_dc(adev->powerplay.pp_handle); } } @@ -426,12 +427,14 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) { - return smu_handle_passthrough_sbr(&adev->smu, enable); + return smu_handle_passthrough_sbr(adev->powerplay.pp_handle, enable); } int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) { - return smu_send_hbm_bad_pages_num(&adev->smu, size); + struct smu_context *smu = adev->powerplay.pp_handle; + + return smu_send_hbm_bad_pages_num(smu, size); } int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, @@ -444,7 +447,7 @@ int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, switch (type) { case PP_SCLK: - return smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, min, max); + return smu_get_dpm_freq_range(adev->powerplay.pp_handle, SMU_SCLK, min, max); default: return -EINVAL; } @@ -455,12 +458,14 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, uint32_t min, uint32_t max) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; switch (type) { case PP_SCLK: - return smu_set_soft_freq_range(&adev->smu, SMU_SCLK, min, max); + return smu_set_soft_freq_range(smu, SMU_SCLK, min, max); default: return -EINVAL; } @@ -468,33 +473,41 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return 0; - return smu_write_watermarks_table(&adev->smu); + return smu_write_watermarks_table(smu); } int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, uint64_t event_arg) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_wait_for_event(&adev->smu, event, event_arg); + return smu_wait_for_event(smu, event, event_arg); } int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_get_status_gfxoff(&adev->smu, value); + return smu_get_status_gfxoff(smu, value); } uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) { - return atomic64_read(&adev->smu.throttle_int_counter); + struct smu_context *smu = adev->powerplay.pp_handle; + + return atomic64_read(&smu->throttle_int_counter); } /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set @@ -516,10 +529,12 @@ void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, void *umc_ecc) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_get_ecc_info(&adev->smu, umc_ecc); + return smu_get_ecc_info(smu, umc_ecc); } struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, @@ -943,9 +958,10 @@ int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) { struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + struct smu_context *smu = adev->powerplay.pp_handle; - if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || - (is_support_sw_smu(adev) && adev->smu.is_apu) || + if ((is_support_sw_smu(adev) && smu->od_enabled) || + (is_support_sw_smu(adev) && smu->is_apu) || (!is_support_sw_smu(adev) && hwmgr->od_enabled)) return true; @@ -968,7 +984,9 @@ int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) { - return adev->smu.cpu_core_num; + struct smu_context *smu = adev->powerplay.pp_handle; + + return smu->cpu_core_num; } void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index cd32f4ed373e..b14b004577e5 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2869,7 +2869,7 @@ static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, int limit_type = to_sensor_dev_attr(attr)->index; return sysfs_emit(buf, "%s\n", - limit_type == SMU_FAST_PPT_LIMIT ? "fastPPT" : "slowPPT"); + limit_type == PP_PWR_TYPE_FAST ? "fastPPT" : "slowPPT"); } static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index b90ed0ec9322..8a689baeaf82 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -1390,10 +1390,6 @@ int smu_mode1_reset(struct smu_context *smu); extern const struct amd_ip_funcs smu_ip_funcs; -extern const struct amdgpu_ip_block_version smu_v11_0_ip_block; -extern const struct amdgpu_ip_block_version smu_v12_0_ip_block; -extern const struct amdgpu_ip_block_version smu_v13_0_ip_block; - bool is_support_sw_smu(struct amdgpu_device *adev); bool is_support_cclk_dpm(struct amdgpu_device *adev); int smu_write_watermarks_table(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7191b3928e8e..c898ea67354a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -468,7 +468,7 @@ bool is_support_sw_smu(struct amdgpu_device *adev) bool is_support_cclk_dpm(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (!smu_feature_is_enabled(smu, SMU_FEATURE_CCLK_DPM_BIT)) return false; @@ -572,7 +572,7 @@ static int smu_get_driver_allowed_feature_mask(struct smu_context *smu) static int smu_set_funcs(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (adev->pm.pp_feature & PP_OVERDRIVE_MASK) smu->od_enabled = true; @@ -624,7 +624,11 @@ static int smu_set_funcs(struct amdgpu_device *adev) static int smu_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu; + + smu = kzalloc(sizeof(struct smu_context), GFP_KERNEL); + if (!smu) + return -ENOMEM; smu->adev = adev; smu->pm_enabled = !!amdgpu_dpm; @@ -684,7 +688,7 @@ err0_out: static int smu_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret = 0; smu_set_fine_grain_gfx_freq_parameters(smu); @@ -730,7 +734,7 @@ static int smu_late_init(void *handle) smu_get_fan_parameters(smu); - smu_handle_task(&adev->smu, + smu_handle_task(smu, smu->smu_dpm.dpm_level, AMD_PP_TASK_COMPLETE_INIT, false); @@ -1020,7 +1024,7 @@ static void smu_interrupt_work_fn(struct work_struct *work) static int smu_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret; smu->pool_size = adev->pm.smu_prv_buffer_size; @@ -1095,7 +1099,7 @@ static int smu_sw_init(void *handle) static int smu_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret; ret = smu_smc_table_sw_fini(smu); @@ -1330,7 +1334,7 @@ static int smu_hw_init(void *handle) { int ret; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) { smu->pm_enabled = false; @@ -1346,7 +1350,7 @@ static int smu_hw_init(void *handle) if (smu->is_apu) { smu_dpm_set_vcn_enable(smu, true); smu_dpm_set_jpeg_enable(smu, true); - smu_set_gfx_cgpg(&adev->smu, true); + smu_set_gfx_cgpg(smu, true); } if (!smu->pm_enabled) @@ -1506,7 +1510,7 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) static int smu_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1525,6 +1529,14 @@ static int smu_hw_fini(void *handle) return smu_smc_hw_cleanup(smu); } +static void smu_late_fini(void *handle) +{ + struct amdgpu_device *adev = handle; + struct smu_context *smu = adev->powerplay.pp_handle; + + kfree(smu); +} + static int smu_reset(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -1552,7 +1564,7 @@ static int smu_reset(struct smu_context *smu) static int smu_suspend(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) @@ -1569,7 +1581,7 @@ static int smu_suspend(void *handle) smu->watermarks_bitmap &= ~(WATERMARKS_LOADED); - smu_set_gfx_cgpg(&adev->smu, false); + smu_set_gfx_cgpg(smu, false); return 0; } @@ -1578,7 +1590,7 @@ static int smu_resume(void *handle) { int ret; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1600,7 +1612,7 @@ static int smu_resume(void *handle) return ret; } - smu_set_gfx_cgpg(&adev->smu, true); + smu_set_gfx_cgpg(smu, true); smu->disable_uclk_switch = 0; @@ -2132,6 +2144,7 @@ const struct amd_ip_funcs smu_ip_funcs = { .sw_fini = smu_sw_fini, .hw_init = smu_hw_init, .hw_fini = smu_hw_fini, + .late_fini = smu_late_fini, .suspend = smu_suspend, .resume = smu_resume, .is_idle = NULL, @@ -3196,7 +3209,7 @@ int smu_stb_collect_info(struct smu_context *smu, void *buf, uint32_t size) static int smu_stb_debugfs_open(struct inode *inode, struct file *filp) { struct amdgpu_device *adev = filp->f_inode->i_private; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; unsigned char *buf; int r; @@ -3221,7 +3234,7 @@ static ssize_t smu_stb_debugfs_read(struct file *filp, char __user *buf, size_t loff_t *pos) { struct amdgpu_device *adev = filp->f_inode->i_private; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (!filp->private_data) @@ -3262,7 +3275,7 @@ void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev) { #if defined(CONFIG_DEBUG_FS) - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (!smu->stb_context.stb_buf_size) return; @@ -3274,7 +3287,6 @@ void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev) &smu_stb_debugfs_fops, smu->stb_context.stb_buf_size); #endif - } int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 505d2fb94fd9..0a1547c27305 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2072,7 +2072,8 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -2118,9 +2119,9 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 2bb7816b245a..37e11716e919 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2779,7 +2779,8 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -2825,9 +2826,9 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index d8c57b780bca..efe6b2eff6a0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3459,7 +3459,8 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -3505,9 +3506,9 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 4e9e2cf39859..e176e6a74f44 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1372,7 +1372,7 @@ static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, unsigned tyep, enum amdgpu_interrupt_state state) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t low, high; uint32_t val = 0; @@ -1441,7 +1441,7 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t client_id = entry->client_id; uint32_t src_id = entry->src_id; /* diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 4885c4ae78b7..a4d46f7069bc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1475,7 +1475,8 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -1521,9 +1522,9 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index b54790d3483e..f1d7b4900aa1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -1200,7 +1200,7 @@ static int smu_v13_0_set_irq_state(struct amdgpu_device *adev, unsigned tyep, enum amdgpu_interrupt_state state) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t low, high; uint32_t val = 0; @@ -1275,7 +1275,7 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t client_id = entry->client_id; uint32_t src_id = entry->src_id; /* @@ -1321,11 +1321,11 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev, switch (ctxid) { case 0x3: dev_dbg(adev->dev, "Switched to AC mode!\n"); - smu_v13_0_ack_ac_dc_interrupt(&adev->smu); + smu_v13_0_ack_ac_dc_interrupt(smu); break; case 0x4: dev_dbg(adev->dev, "Switched to DC mode!\n"); - smu_v13_0_ack_ac_dc_interrupt(&adev->smu); + smu_v13_0_ack_ac_dc_interrupt(smu); break; case 0x7: /* -- cgit From 61d7d0d5adc705f833d8a5dbb596253842486220 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 25 Nov 2021 11:15:46 +0800 Subject: drm/amd/pm: revise the performance level setting APIs Avoid cross callings which make lock protection enforcement on amdgpu_dpm_force_performance_level() impossible. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/amd_shared.h | 2 -- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 29 ++++++++++++++++++++---- drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c | 17 +++++++------- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 12 ---------- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 ------------ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - 6 files changed, 34 insertions(+), 42 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index f57a1478f0fe..fb6ad56ad6f1 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -268,7 +268,6 @@ enum amd_dpm_forced_level; * @set_clockgating_state: enable/disable cg for the IP block * @set_powergating_state: enable/disable pg for the IP block * @get_clockgating_state: get current clockgating status - * @enable_umd_pstate: enable UMD powerstate * * These hooks provide an interface for controlling the operational state * of IP blocks. After acquiring a list of IP blocks for the GPU in use, @@ -299,7 +298,6 @@ struct amd_ip_funcs { int (*set_powergating_state)(void *handle, enum amd_powergating_state state); void (*get_clockgating_state)(void *handle, u32 *flags); - int (*enable_umd_pstate)(void *handle, enum amd_dpm_forced_level *level); }; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index b14b004577e5..d3eab245e0fe 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -300,6 +300,10 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level; enum amd_dpm_forced_level current_level; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; int ret = 0; if (amdgpu_in_reset(adev)) @@ -354,10 +358,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, } /* profile_exit setting is valid only when current mode is in profile mode */ - if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) && + if (!(current_level & profile_mode_mask) && (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { pr_err("Currently not in any profile mode!\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -365,6 +366,26 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return -EINVAL; } + if (!(current_level & profile_mode_mask) && + (level & profile_mode_mask)) { + /* enter UMD Pstate */ + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } else if ((current_level & profile_mode_mask) && + !(level & profile_mode_mask)) { + /* exit UMD Pstate */ + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + if (amdgpu_dpm_force_performance_level(adev, level)) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c index 3c6ee493e410..9613c6181c17 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c @@ -953,6 +953,7 @@ restart_search: static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) { + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct amdgpu_ps *ps; enum amd_pm_state_type dpm_state; int ret; @@ -976,7 +977,7 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) else return -EINVAL; - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { + if (amdgpu_dpm == 1 && pp_funcs->print_power_state) { printk("switching from power state:\n"); amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); printk("switching to power state:\n"); @@ -985,14 +986,14 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) /* update whether vce is active */ ps->vce_active = adev->pm.dpm.vce_active; - if (adev->powerplay.pp_funcs->display_configuration_changed) + if (pp_funcs->display_configuration_changed) amdgpu_dpm_display_configuration_changed(adev); ret = amdgpu_dpm_pre_set_power_state(adev); if (ret) return ret; - if (adev->powerplay.pp_funcs->check_state_equal) { + if (pp_funcs->check_state_equal) { if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) equal = false; } @@ -1000,24 +1001,24 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) if (equal) return 0; - if (adev->powerplay.pp_funcs->set_power_state) - adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); + if (pp_funcs->set_power_state) + pp_funcs->set_power_state(adev->powerplay.pp_handle); amdgpu_dpm_post_set_power_state(adev); adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - if (adev->powerplay.pp_funcs->force_performance_level) { + if (pp_funcs->force_performance_level) { if (adev->pm.dpm.thermal_active) { enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; /* force low perf level for thermal */ - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); + pp_funcs->force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); /* save the user's level */ adev->pm.dpm.forced_level = level; } else { /* otherwise, user selected level */ - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); + pp_funcs->force_performance_level(adev, adev->pm.dpm.forced_level); } } diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 6a06a1f0b79b..89341729744d 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -323,12 +323,6 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, if (*level & profile_mode_mask) { hwmgr->saved_dpm_level = hwmgr->dpm_level; hwmgr->en_umd_pstate = true; - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -336,12 +330,6 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = hwmgr->saved_dpm_level; hwmgr->en_umd_pstate = false; - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); } } } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8895b2b595a4..c374c3067496 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1677,14 +1677,7 @@ static int smu_enable_umd_pstate(void *handle, /* enter umd pstate, save current level, disable gfx cg*/ if (*level & profile_mode_mask) { smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level; - smu_dpm_ctx->enable_umd_pstate = true; smu_gpo_control(smu, false); - amdgpu_device_ip_set_powergating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); smu_gfx_ulv_control(smu, false); smu_deep_sleep_control(smu, false); amdgpu_asic_update_umd_stable_pstate(smu->adev, true); @@ -1694,16 +1687,9 @@ static int smu_enable_umd_pstate(void *handle, if (!(*level & profile_mode_mask)) { if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = smu_dpm_ctx->saved_dpm_level; - smu_dpm_ctx->enable_umd_pstate = false; amdgpu_asic_update_umd_stable_pstate(smu->adev, false); smu_deep_sleep_control(smu, true); smu_gfx_ulv_control(smu, true); - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); smu_gpo_control(smu, true); } } @@ -2149,7 +2135,6 @@ const struct amd_ip_funcs smu_ip_funcs = { .soft_reset = NULL, .set_clockgating_state = smu_set_clockgating_state, .set_powergating_state = smu_set_powergating_state, - .enable_umd_pstate = smu_enable_umd_pstate, }; const struct amdgpu_ip_block_version smu_v11_0_ip_block = diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 8a689baeaf82..3fdab6a44901 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -363,7 +363,6 @@ struct smu_dpm_context { uint32_t dpm_context_size; void *dpm_context; void *golden_dpm_context; - bool enable_umd_pstate; enum amd_dpm_forced_level dpm_level; enum amd_dpm_forced_level saved_dpm_level; enum amd_dpm_forced_level requested_dpm_level; -- cgit From 54c73b51df2958f564b144ce86f15a85e227db90 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Jan 2022 18:14:22 -0500 Subject: drm/amdgpu/pm: move additional logic into amdgpu_dpm_force_performance_level This is part of the forced performance level. Move it from the sysfs handler into amdgpu_dpm_force_performance_level. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 61 +++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 50 ------------------------------ 2 files changed, 59 insertions(+), 52 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 68d2e80a673b..728b6e10f302 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -692,16 +692,25 @@ void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, amdgpu_dpm_compute_clocks(adev); } -enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) +static enum amd_dpm_forced_level amdgpu_dpm_get_performance_level_locked(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_dpm_forced_level level; - mutex_lock(&adev->pm.mutex); if (pp_funcs->get_performance_level) level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); else level = adev->pm.dpm.forced_level; + + return level; +} + +enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) +{ + enum amd_dpm_forced_level level; + + mutex_lock(&adev->pm.mutex); + level = amdgpu_dpm_get_performance_level_locked(adev); mutex_unlock(&adev->pm.mutex); return level; @@ -711,6 +720,11 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, enum amd_dpm_forced_level level) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + enum amd_dpm_forced_level current_level; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; int ret = 0; if (!pp_funcs->force_performance_level) @@ -723,6 +737,49 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, goto out; } + current_level = amdgpu_dpm_get_performance_level_locked(adev); + if (current_level == level) { + ret = 0; + goto out; + } + + if (adev->asic_type == CHIP_RAVEN) { + if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { + if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && + level == AMD_DPM_FORCED_LEVEL_MANUAL) + amdgpu_gfx_off_ctrl(adev, false); + else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && + level != AMD_DPM_FORCED_LEVEL_MANUAL) + amdgpu_gfx_off_ctrl(adev, true); + } + } + + if (!(current_level & profile_mode_mask) && + (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { + ret = -EINVAL; + goto out; + } + + if (!(current_level & profile_mode_mask) && + (level & profile_mode_mask)) { + /* enter UMD Pstate */ + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } else if ((current_level & profile_mode_mask) && + !(level & profile_mode_mask)) { + /* exit UMD Pstate */ + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, level)) ret = -EINVAL; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d3eab245e0fe..d2823aaeca09 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -299,11 +299,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level; - enum amd_dpm_forced_level current_level; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; int ret = 0; if (amdgpu_in_reset(adev)) @@ -341,51 +336,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } - current_level = amdgpu_dpm_get_performance_level(adev); - if (current_level == level) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return count; - } - - if (adev->asic_type == CHIP_RAVEN) { - if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { - if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && level == AMD_DPM_FORCED_LEVEL_MANUAL) - amdgpu_gfx_off_ctrl(adev, false); - else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && level != AMD_DPM_FORCED_LEVEL_MANUAL) - amdgpu_gfx_off_ctrl(adev, true); - } - } - - /* profile_exit setting is valid only when current mode is in profile mode */ - if (!(current_level & profile_mode_mask) && - (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { - pr_err("Currently not in any profile mode!\n"); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - - if (!(current_level & profile_mode_mask) && - (level & profile_mode_mask)) { - /* enter UMD Pstate */ - amdgpu_device_ip_set_powergating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } else if ((current_level & profile_mode_mask) && - !(level & profile_mode_mask)) { - /* exit UMD Pstate */ - amdgpu_device_ip_set_clockgating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); - } - if (amdgpu_dpm_force_performance_level(adev, level)) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); -- cgit From 685fae24d94fd615b7058832fcb437eb588f4860 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 11 Jan 2022 15:02:19 +0800 Subject: drm/amd/pm: correct the checks for fan attributes support On functionality unsupported, -EOPNOTSUPP will be returned. And we rely on that to determine the fan attributes support. Fixes: 79c65f3fcbb128 ("drm/amd/pm: do not expose power implementation details to amdgpu_pm.c") Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 4 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 21 ++-- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 21 ++-- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 19 +++- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 71 +++++++----- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 133 +++++++++++++---------- 6 files changed, 160 insertions(+), 109 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a8eec91c0995..387120099493 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -315,8 +315,8 @@ struct amd_pm_funcs { void *rps, bool *equal); /* export for sysfs */ - void (*set_fan_control_mode)(void *handle, u32 mode); - u32 (*get_fan_control_mode)(void *handle); + int (*set_fan_control_mode)(void *handle, u32 mode); + int (*get_fan_control_mode)(void *handle, u32 *fan_mode); int (*set_fan_speed_pwm)(void *handle, u32 speed); int (*get_fan_speed_pwm)(void *handle, u32 *speed); int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 728b6e10f302..f0daa66f5b3d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1087,15 +1087,17 @@ int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, uint32_t *fan_mode) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_fan_control_mode) return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); - *fan_mode = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle); + ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, + fan_mode); mutex_unlock(&adev->pm.mutex); - return 0; + return ret; } int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, @@ -1105,7 +1107,7 @@ int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->set_fan_speed_pwm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, @@ -1122,7 +1124,7 @@ int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->get_fan_speed_pwm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, @@ -1139,7 +1141,7 @@ int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->get_fan_speed_rpm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, @@ -1156,7 +1158,7 @@ int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->set_fan_speed_rpm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, @@ -1170,16 +1172,17 @@ int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, uint32_t mode) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_fan_control_mode) return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); - pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, - mode); + ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, + mode); mutex_unlock(&adev->pm.mutex); - return 0; + return ret; } int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d2823aaeca09..1b03ad7a21ad 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3147,7 +3147,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; - uint32_t speed = 0; /* under multi-vf mode, the hwmon attributes are all not supported */ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) @@ -3213,15 +3212,15 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* mask fan attributes if we have no bindings for this asic to expose */ - if (((amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && + if (((amdgpu_dpm_get_fan_speed_pwm(adev, NULL) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ - ((amdgpu_dpm_get_fan_control_mode(adev, &speed) == -EOPNOTSUPP) && + ((amdgpu_dpm_get_fan_control_mode(adev, NULL) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ effective_mode &= ~S_IRUGO; - if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && + if (((amdgpu_dpm_set_fan_speed_pwm(adev, U32_MAX) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ - ((amdgpu_dpm_set_fan_control_mode(adev, speed) == -EOPNOTSUPP) && + ((amdgpu_dpm_set_fan_control_mode(adev, U32_MAX) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ effective_mode &= ~S_IWUSR; @@ -3241,16 +3240,16 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* hide max/min values if we can't both query and manage the fan */ - if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && - (amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && - (amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && - (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL)) && + if (((amdgpu_dpm_set_fan_speed_pwm(adev, U32_MAX) == -EOPNOTSUPP) && + (amdgpu_dpm_get_fan_speed_pwm(adev, NULL) == -EOPNOTSUPP) && + (amdgpu_dpm_set_fan_speed_rpm(adev, U32_MAX) == -EOPNOTSUPP) && + (amdgpu_dpm_get_fan_speed_rpm(adev, NULL) == -EOPNOTSUPP)) && (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; - if ((amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && - (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL) && + if ((amdgpu_dpm_set_fan_speed_rpm(adev, U32_MAX) == -EOPNOTSUPP) && + (amdgpu_dpm_get_fan_speed_rpm(adev, NULL) == -EOPNOTSUPP) && (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) return 0; diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index 92b987fb31d4..23ff0d812e4b 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -6619,6 +6619,9 @@ static int si_dpm_get_fan_speed_pwm(void *handle, u64 tmp64; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (!speed) + return -EINVAL; + if (adev->pm.no_fan) return -ENOENT; @@ -6669,10 +6672,13 @@ static int si_dpm_set_fan_speed_pwm(void *handle, return 0; } -static void si_dpm_set_fan_control_mode(void *handle, u32 mode) +static int si_dpm_set_fan_control_mode(void *handle, u32 mode) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (mode == U32_MAX) + return -EINVAL; + if (mode) { /* stop auto-manage */ if (adev->pm.dpm.fan.ucode_fan_control) @@ -6685,19 +6691,26 @@ static void si_dpm_set_fan_control_mode(void *handle, u32 mode) else si_fan_ctrl_set_default_mode(adev); } + + return 0; } -static u32 si_dpm_get_fan_control_mode(void *handle) +static int si_dpm_get_fan_control_mode(void *handle, u32 *fan_mode) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct si_power_info *si_pi = si_get_pi(adev); u32 tmp; + if (!fan_mode) + return -EINVAL; + if (si_pi->fan_is_controlled_by_smc) return 0; tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; - return (tmp >> FDO_PWM_MODE_SHIFT); + *fan_mode = (tmp >> FDO_PWM_MODE_SHIFT); + + return 0; } #if 0 diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 89341729744d..76c26ae368f9 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -488,38 +488,43 @@ static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) return pm_type; } -static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) +static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) { struct pp_hwmgr *hwmgr = handle; if (!hwmgr || !hwmgr->pm_en) - return; + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) + return -EOPNOTSUPP; + + if (mode == U32_MAX) + return -EINVAL; - if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); mutex_unlock(&hwmgr->smu_lock); + + return 0; } -static uint32_t pp_dpm_get_fan_control_mode(void *handle) +static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode) { struct pp_hwmgr *hwmgr = handle; - uint32_t mode = 0; if (!hwmgr || !hwmgr->pm_en) - return 0; + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) + return -EOPNOTSUPP; + + if (!fan_mode) + return -EINVAL; - if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } mutex_lock(&hwmgr->smu_lock); - mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); + *fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); mutex_unlock(&hwmgr->smu_lock); - return mode; + return 0; } static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed) @@ -528,12 +533,14 @@ static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed) int ret = 0; if (!hwmgr || !hwmgr->pm_en) + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL) + return -EOPNOTSUPP; + + if (speed == U32_MAX) return -EINVAL; - if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } mutex_lock(&hwmgr->smu_lock); ret = hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed); mutex_unlock(&hwmgr->smu_lock); @@ -546,12 +553,13 @@ static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed) int ret = 0; if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; + return -EOPNOTSUPP; - if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } + if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL) + return -EOPNOTSUPP; + + if (!speed) + return -EINVAL; mutex_lock(&hwmgr->smu_lock); ret = hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed); @@ -565,9 +573,12 @@ static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) int ret = 0; if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; + return -EOPNOTSUPP; if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL) + return -EOPNOTSUPP; + + if (!rpm) return -EINVAL; mutex_lock(&hwmgr->smu_lock); @@ -582,12 +593,14 @@ static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm) int ret = 0; if (!hwmgr || !hwmgr->pm_en) + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) + return -EOPNOTSUPP; + + if (rpm == U32_MAX) return -EINVAL; - if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } mutex_lock(&hwmgr->smu_lock); ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm); mutex_unlock(&hwmgr->smu_lock); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index c374c3067496..828cb932f6a9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -59,7 +59,7 @@ static int smu_handle_task(struct smu_context *smu, bool lock_needed); static int smu_reset(struct smu_context *smu); static int smu_set_fan_speed_pwm(void *handle, u32 speed); -static int smu_set_fan_control_mode(struct smu_context *smu, int value); +static int smu_set_fan_control_mode(void *handle, u32 value); static int smu_set_power_limit(void *handle, uint32_t limit); static int smu_set_fan_speed_rpm(void *handle, uint32_t speed); static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled); @@ -407,7 +407,7 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) if (smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_MANUAL || smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_NONE) { ret = smu_set_fan_control_mode(smu, smu->user_dpm_profile.fan_mode); - if (ret) { + if (ret != -EOPNOTSUPP) { smu->user_dpm_profile.fan_speed_pwm = 0; smu->user_dpm_profile.fan_speed_rpm = 0; smu->user_dpm_profile.fan_mode = AMD_FAN_CTRL_AUTO; @@ -416,13 +416,13 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) if (smu->user_dpm_profile.fan_speed_pwm) { ret = smu_set_fan_speed_pwm(smu, smu->user_dpm_profile.fan_speed_pwm); - if (ret) + if (ret != -EOPNOTSUPP) dev_err(smu->adev->dev, "Failed to set manual fan speed in pwm\n"); } if (smu->user_dpm_profile.fan_speed_rpm) { ret = smu_set_fan_speed_rpm(smu, smu->user_dpm_profile.fan_speed_rpm); - if (ret) + if (ret != -EOPNOTSUPP) dev_err(smu->adev->dev, "Failed to set manual fan speed in rpm\n"); } } @@ -2218,18 +2218,22 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->set_fan_speed_rpm) + return -EOPNOTSUPP; + + if (speed == U32_MAX) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_speed_rpm) { - ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); - if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { - smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_RPM; - smu->user_dpm_profile.fan_speed_rpm = speed; + ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_RPM; + smu->user_dpm_profile.fan_speed_rpm = speed; - /* Override custom PWM setting as they cannot co-exist */ - smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_PWM; - smu->user_dpm_profile.fan_speed_pwm = 0; - } + /* Override custom PWM setting as they cannot co-exist */ + smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_PWM; + smu->user_dpm_profile.fan_speed_pwm = 0; } mutex_unlock(&smu->mutex); @@ -2562,60 +2566,65 @@ static int smu_set_power_profile_mode(void *handle, } -static u32 smu_get_fan_control_mode(void *handle) +static int smu_get_fan_control_mode(void *handle, u32 *fan_mode) { struct smu_context *smu = handle; - u32 ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return AMD_FAN_CTRL_NONE; + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->get_fan_control_mode) + return -EOPNOTSUPP; + + if (!fan_mode) + return -EINVAL; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_control_mode) - ret = smu->ppt_funcs->get_fan_control_mode(smu); + *fan_mode = smu->ppt_funcs->get_fan_control_mode(smu); mutex_unlock(&smu->mutex); - return ret; + return 0; } -static int smu_set_fan_control_mode(struct smu_context *smu, int value) +static int smu_set_fan_control_mode(void *handle, u32 value) { + struct smu_context *smu = handle; int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->set_fan_control_mode) + return -EOPNOTSUPP; + + if (value == U32_MAX) + return -EINVAL; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_control_mode) { - ret = smu->ppt_funcs->set_fan_control_mode(smu, value); - if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) - smu->user_dpm_profile.fan_mode = value; - } + ret = smu->ppt_funcs->set_fan_control_mode(smu, value); + if (ret) + goto out; - mutex_unlock(&smu->mutex); + if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.fan_mode = value; - /* reset user dpm fan speed */ - if (!ret && value != AMD_FAN_CTRL_MANUAL && - !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { - smu->user_dpm_profile.fan_speed_pwm = 0; - smu->user_dpm_profile.fan_speed_rpm = 0; - smu->user_dpm_profile.flags &= ~(SMU_CUSTOM_FAN_SPEED_RPM | SMU_CUSTOM_FAN_SPEED_PWM); + /* reset user dpm fan speed */ + if (value != AMD_FAN_CTRL_MANUAL) { + smu->user_dpm_profile.fan_speed_pwm = 0; + smu->user_dpm_profile.fan_speed_rpm = 0; + smu->user_dpm_profile.flags &= ~(SMU_CUSTOM_FAN_SPEED_RPM | SMU_CUSTOM_FAN_SPEED_PWM); + } } - return ret; -} - -static void smu_pp_set_fan_control_mode(void *handle, u32 value) -{ - struct smu_context *smu = handle; +out: + mutex_unlock(&smu->mutex); - smu_set_fan_control_mode(smu, value); + return ret; } - static int smu_get_fan_speed_pwm(void *handle, u32 *speed) { struct smu_context *smu = handle; @@ -2624,10 +2633,15 @@ static int smu_get_fan_speed_pwm(void *handle, u32 *speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->get_fan_speed_pwm) + return -EOPNOTSUPP; + + if (!speed) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_speed_pwm) - ret = smu->ppt_funcs->get_fan_speed_pwm(smu, speed); + ret = smu->ppt_funcs->get_fan_speed_pwm(smu, speed); mutex_unlock(&smu->mutex); @@ -2642,18 +2656,22 @@ static int smu_set_fan_speed_pwm(void *handle, u32 speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->set_fan_speed_pwm) + return -EOPNOTSUPP; + + if (speed == U32_MAX) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_speed_pwm) { - ret = smu->ppt_funcs->set_fan_speed_pwm(smu, speed); - if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { - smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_PWM; - smu->user_dpm_profile.fan_speed_pwm = speed; + ret = smu->ppt_funcs->set_fan_speed_pwm(smu, speed); + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_PWM; + smu->user_dpm_profile.fan_speed_pwm = speed; - /* Override custom RPM setting as they cannot co-exist */ - smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_RPM; - smu->user_dpm_profile.fan_speed_rpm = 0; - } + /* Override custom RPM setting as they cannot co-exist */ + smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_RPM; + smu->user_dpm_profile.fan_speed_rpm = 0; } mutex_unlock(&smu->mutex); @@ -2669,10 +2687,15 @@ static int smu_get_fan_speed_rpm(void *handle, uint32_t *speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->get_fan_speed_rpm) + return -EOPNOTSUPP; + + if (!speed) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_speed_rpm) - ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); + ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); mutex_unlock(&smu->mutex); @@ -3101,7 +3124,7 @@ static int smu_get_prv_buffer_details(void *handle, void **addr, size_t *size) static const struct amd_pm_funcs swsmu_pm_funcs = { /* export for sysfs */ - .set_fan_control_mode = smu_pp_set_fan_control_mode, + .set_fan_control_mode = smu_set_fan_control_mode, .get_fan_control_mode = smu_get_fan_control_mode, .set_fan_speed_pwm = smu_set_fan_speed_pwm, .get_fan_speed_pwm = smu_get_fan_speed_pwm, -- cgit From 1613f346f86b25121aceb941d03ca927e57af20c Mon Sep 17 00:00:00 2001 From: Flora Cui Date: Thu, 13 Jan 2022 14:55:24 +0800 Subject: drm/amd/pm: fix null ptr access check null ptr first before access its element v2: check adev->pm.dpm_enabled early in amdgpu_debugfs_pm_init() Signed-off-by: Flora Cui Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index f0daa66f5b3d..5fc33893a68c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -463,7 +463,7 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int r = 0; - if (!pp_funcs->load_firmware) + if (!pp_funcs || !pp_funcs->load_firmware) return 0; mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 1b03ad7a21ad..49a9c6375343 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3583,6 +3583,9 @@ void amdgpu_debugfs_pm_init(struct amdgpu_device *adev) struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; + if (!adev->pm.dpm_enabled) + return; + debugfs_create_file("amdgpu_pm_info", 0444, root, adev, &amdgpu_debugfs_pm_info_fops); -- cgit From f3527a6483fbccbf569f91d9ee9c561b14d86a9f Mon Sep 17 00:00:00 2001 From: Marina Nikolic Date: Fri, 14 Jan 2022 00:46:33 +0800 Subject: drm/amd/pm: Enable sysfs required by rocm-smi tool for One VF mode Enable power level, power limit and fan speed information retrieval in one VF mode. This is required so that tool ROCM-SMI can provide this information to users. Signed-off-by: Marina Nikolic Acked-by: Evan Quan Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 17 ++--------------- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 49a9c6375343..837a31a46596 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1903,8 +1903,8 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_sclk_od, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_mclk_od, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_power_profile_mode, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), @@ -3152,19 +3152,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return 0; - /* there is no fan under pp one vf mode */ - if (amdgpu_sriov_is_pp_one_vf(adev) && - (attr == &sensor_dev_attr_pwm1.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_input.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_target.dev_attr.attr || - attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) - return 0; - /* Skip fan attributes if fan is not present */ if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index eb47d490ee9d..c29353e05fd2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -141,7 +141,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), - MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), -- cgit From 8cda7a4f96e435be2fd074009d69521d973d7d31 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Jan 2022 17:57:33 -0500 Subject: drm/amdgpu/UAPI: add new CTX OP to get/set stable pstates Add a new CTX ioctl operation to set stable pstates for profiling. When creating traces for tools like RGP or using SPM or doing performance profiling, it's required to enable a special stable profiling power state on the GPU. These profiling states set fixed clocks and disable certain other power features like powergating which may impact the results. Historically, these profiling pstates were enabled via sysfs, but this adds an interface to enable it via the CTX ioctl from the application. Since the power state is global only one application can set it at a time, so if multiple applications try and use it only the first will get it, the ioctl will return -EBUSY for others. The sysfs interface will override whatever has been set by this interface. Mesa MR: https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/207 v2: don't default r = 0; v3: rebase on Evan's PM cleanup Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 129 ++++++++++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 5 ++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 3 + include/uapi/drm/amdgpu_drm.h | 17 +++- 6 files changed, 153 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 468003583b2a..2c929fa40379 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -237,6 +237,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter); ctx->init_priority = priority; ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET; + ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE; return 0; } @@ -255,6 +256,86 @@ static void amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity) kfree(entity); } +static int amdgpu_ctx_get_stable_pstate(struct amdgpu_ctx *ctx, + u32 *stable_pstate) +{ + struct amdgpu_device *adev = ctx->adev; + enum amd_dpm_forced_level current_level; + + if (!ctx) + return -EINVAL; + + current_level = amdgpu_dpm_get_performance_level(adev); + + switch (current_level) { + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_STANDARD; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_PEAK; + break; + default: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE; + break; + } + return 0; +} + +static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, + u32 stable_pstate) +{ + struct amdgpu_device *adev = ctx->adev; + enum amd_dpm_forced_level level; + int r; + + if (!ctx) + return -EINVAL; + + mutex_lock(&adev->pm.stable_pstate_ctx_lock); + if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) { + r = -EBUSY; + goto done; + } + + switch (stable_pstate) { + case AMDGPU_CTX_STABLE_PSTATE_NONE: + level = AMD_DPM_FORCED_LEVEL_AUTO; + break; + case AMDGPU_CTX_STABLE_PSTATE_STANDARD: + level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD; + break; + case AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK: + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK; + break; + case AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK: + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK; + break; + case AMDGPU_CTX_STABLE_PSTATE_PEAK: + level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + break; + default: + r = -EINVAL; + goto done; + } + + r = amdgpu_dpm_force_performance_level(adev, level); + + if (level == AMD_DPM_FORCED_LEVEL_AUTO) + adev->pm.stable_pstate_ctx = NULL; + else + adev->pm.stable_pstate_ctx = ctx; +done: + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + + return r; +} + static void amdgpu_ctx_fini(struct kref *ref) { struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount); @@ -270,7 +351,7 @@ static void amdgpu_ctx_fini(struct kref *ref) ctx->entities[i][j] = NULL; } } - + amdgpu_ctx_set_stable_pstate(ctx, AMDGPU_CTX_STABLE_PSTATE_NONE); mutex_destroy(&ctx->lock); kfree(ctx); } @@ -467,11 +548,41 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, return 0; } + + +static int amdgpu_ctx_stable_pstate(struct amdgpu_device *adev, + struct amdgpu_fpriv *fpriv, uint32_t id, + bool set, u32 *stable_pstate) +{ + struct amdgpu_ctx *ctx; + struct amdgpu_ctx_mgr *mgr; + int r; + + if (!fpriv) + return -EINVAL; + + mgr = &fpriv->ctx_mgr; + mutex_lock(&mgr->lock); + ctx = idr_find(&mgr->ctx_handles, id); + if (!ctx) { + mutex_unlock(&mgr->lock); + return -EINVAL; + } + + if (set) + r = amdgpu_ctx_set_stable_pstate(ctx, *stable_pstate); + else + r = amdgpu_ctx_get_stable_pstate(ctx, stable_pstate); + + mutex_unlock(&mgr->lock); + return r; +} + int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { int r; - uint32_t id; + uint32_t id, stable_pstate; int32_t priority; union drm_amdgpu_ctx *args = data; @@ -500,6 +611,20 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, case AMDGPU_CTX_OP_QUERY_STATE2: r = amdgpu_ctx_query2(adev, fpriv, id, &args->out); break; + case AMDGPU_CTX_OP_GET_STABLE_PSTATE: + if (args->in.flags) + return -EINVAL; + r = amdgpu_ctx_stable_pstate(adev, fpriv, id, false, &stable_pstate); + args->out.pstate.flags = stable_pstate; + break; + case AMDGPU_CTX_OP_SET_STABLE_PSTATE: + if (args->in.flags & ~AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK) + return -EINVAL; + stable_pstate = args->in.flags & AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK; + if (stable_pstate > AMDGPU_CTX_STABLE_PSTATE_PEAK) + return -EINVAL; + r = amdgpu_ctx_stable_pstate(adev, fpriv, id, true, &stable_pstate); + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h index a44b8b8ed39c..142f2f87d44c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h @@ -53,6 +53,7 @@ struct amdgpu_ctx { atomic_t guilty; unsigned long ras_counter_ce; unsigned long ras_counter_ue; + uint32_t stable_pstate; }; struct amdgpu_ctx_mgr { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6ba57ad88640..660fb4085c97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3510,6 +3510,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, init_rwsem(&adev->reset_sem); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); + mutex_init(&adev->pm.stable_pstate_ctx_lock); amdgpu_device_init_apu_flags(adev); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 837a31a46596..d68e7132da2c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -336,11 +336,16 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } + mutex_lock(&adev->pm.stable_pstate_ctx_lock); if (amdgpu_dpm_force_performance_level(adev, level)) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); return -EINVAL; } + /* override whatever a user ctx may have set */ + adev->pm.stable_pstate_ctx = NULL; + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 2766b88ecf96..5cc05110cdae 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -338,6 +338,9 @@ struct amdgpu_pm { uint32_t smu_debug_mask; bool pp_force_state_enabled; + + struct mutex stable_pstate_ctx_lock; + struct amdgpu_ctx *stable_pstate_ctx; }; u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index be4f9111f478..76b580d10a52 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -206,6 +206,8 @@ union drm_amdgpu_bo_list { #define AMDGPU_CTX_OP_FREE_CTX 2 #define AMDGPU_CTX_OP_QUERY_STATE 3 #define AMDGPU_CTX_OP_QUERY_STATE2 4 +#define AMDGPU_CTX_OP_GET_STABLE_PSTATE 5 +#define AMDGPU_CTX_OP_SET_STABLE_PSTATE 6 /* GPU reset status */ #define AMDGPU_CTX_NO_RESET 0 @@ -238,10 +240,18 @@ union drm_amdgpu_bo_list { #define AMDGPU_CTX_PRIORITY_HIGH 512 #define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023 +/* select a stable profiling pstate for perfmon tools */ +#define AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK 0xf +#define AMDGPU_CTX_STABLE_PSTATE_NONE 0 +#define AMDGPU_CTX_STABLE_PSTATE_STANDARD 1 +#define AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK 2 +#define AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK 3 +#define AMDGPU_CTX_STABLE_PSTATE_PEAK 4 + struct drm_amdgpu_ctx_in { /** AMDGPU_CTX_OP_* */ __u32 op; - /** For future use, no flags defined so far */ + /** Flags */ __u32 flags; __u32 ctx_id; /** AMDGPU_CTX_PRIORITY_* */ @@ -262,6 +272,11 @@ union drm_amdgpu_ctx_out { /** Reset status since the last call of the ioctl. */ __u32 reset_status; } state; + + struct { + __u32 flags; + __u32 _pad; + } pstate; }; union drm_amdgpu_ctx { -- cgit From de7fbd020d959708282ac0916be3e5498086d9aa Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 8 Feb 2022 14:23:55 +0800 Subject: drm/amd/pm: fix hwmon node of power1_label create issue it will cause hwmon node of power1_label is not created. v2: the hwmon node of "power1_label" is always needed for all ASICs. and the patch will remove ASIC type check for "power1_label". Fixes: ae07970a0621d6 ("drm/amd/pm: add support for hwmon control of slow and fast PPT limit on vangogh") Signed-off-by: Yang Wang Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d68e7132da2c..426e00112c91 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3287,8 +3287,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr || attr == &sensor_dev_attr_power2_cap.dev_attr.attr || attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || - attr == &sensor_dev_attr_power2_label.dev_attr.attr || - attr == &sensor_dev_attr_power1_label.dev_attr.attr)) + attr == &sensor_dev_attr_power2_label.dev_attr.attr)) return 0; return effective_mode; -- cgit From 3b99e8e37d0ffaa0ef95598b9b83c49c89bc0ea2 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 8 Feb 2022 15:36:50 +0800 Subject: drm/amd/pm: correct hwmon power label name only vangogh has 2 types of hwmon power node: "fastPPT" and "slowPPT", the other asic only has 1 type of hwmon power node: "PPT". Signed-off-by: Yang Wang Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 426e00112c91..ad5da252228b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2842,10 +2842,14 @@ static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, struct device_attribute *attr, char *buf) { - int limit_type = to_sensor_dev_attr(attr)->index; + struct amdgpu_device *adev = dev_get_drvdata(dev); - return sysfs_emit(buf, "%s\n", - limit_type == PP_PWR_TYPE_FAST ? "fastPPT" : "slowPPT"); + if (adev->asic_type == CHIP_VANGOGH) + return sysfs_emit(buf, "%s\n", + to_sensor_dev_attr(attr)->index == PP_PWR_TYPE_FAST ? + "fastPPT" : "slowPPT"); + else + return sysfs_emit(buf, "PPT\n"); } static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, -- cgit From c8cb19c7b26d78434ec563088d5d377ec2caf616 Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Tue, 25 Jan 2022 18:57:56 -0500 Subject: amdgpu/pm: Add emit_clock_levels calls (v4) Modifications to satisfy checkpatch --strict (v3) Rewrote patchset to order patches as (API, hw impl, usecase) - modified amdgpu_get_pp_od_clk_voltage to try amdgpu_dpm_emit_clock_levels and fallback to amdgpu_dpm_print_clock_levels if emit is not implemented. - modified amdgpu_get_pp_dpm_clock to try amdgpu_dpm_emit_clock_levels and fallback to amdgpu_dpm_print_clock_levels if emit is not implemented. - Newline is printed to buf if no output produced == Test == LOGFILE=pp_clk.test.log AMDGPU_PCI_ADDR=`lspci -nn | grep "VGA\|Display" | cut -d " " -f 1` AMDGPU_HWMON=`ls -la /sys/class/hwmon | grep $AMDGPU_PCI_ADDR | awk '{print $9}'` HWMON_DIR=/sys/class/hwmon/${AMDGPU_HWMON} lspci -nn | grep "VGA\|Display" > $LOGFILE FILES="pp_od_clk_voltage pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_vclk pp_dpm_dclk " for f in $FILES do echo === $f === >> $LOGFILE cat $HWMON_DIR/device/$f >> $LOGFILE done cat $LOGFILE Signed-off-by: Darren Powell Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 49 +++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index ad5da252228b..b0243068212b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -837,8 +837,17 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - ssize_t size; + int size = 0; int ret; + enum pp_clock_type od_clocks[6] = { + OD_SCLK, + OD_MCLK, + OD_VDDC_CURVE, + OD_RANGE, + OD_VDDGFX_OFFSET, + OD_CCLK, + }; + uint clk_index; if (amdgpu_in_reset(adev)) return -EPERM; @@ -851,16 +860,25 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, return ret; } - size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); - if (size > 0) { - size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf+size); - } else { - size = sysfs_emit(buf, "\n"); + for (clk_index = 0 ; clk_index < 6 ; clk_index++) { + ret = amdgpu_dpm_emit_clock_levels(adev, od_clocks[clk_index], buf, &size); + if (ret) + break; + } + if (ret == -ENOENT) { + size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + if (size > 0) { + size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size); + } } + + if (size == 0) + size = sysfs_emit(buf, "\n"); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -985,8 +1003,8 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - ssize_t size; - int ret; + int size = 0; + int ret = 0; if (amdgpu_in_reset(adev)) return -EPERM; @@ -999,8 +1017,11 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev, return ret; } - size = amdgpu_dpm_print_clock_levels(adev, type, buf); - if (size <= 0) + ret = amdgpu_dpm_emit_clock_levels(adev, type, buf, &size); + if (ret == -ENOENT) + size = amdgpu_dpm_print_clock_levels(adev, type, buf); + + if (size == 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); -- cgit From e610941c45bad75aa839af015c27d236ab6749e5 Mon Sep 17 00:00:00 2001 From: Yiqing Yao Date: Mon, 24 Jan 2022 16:11:20 +0800 Subject: drm/amd/pm: enable pm sysfs write for one VF mode [why] pm sysfs should be writable in one VF mode as is in passthrough [how] do not remove write access on pm sysfs if device is in one VF mode Fixes: 11c9cc95f818 ("amdgpu/pm: Make sysfs pm attributes as read-only for VFs") Signed-off-by: Yiqing Yao Reviewed-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index b0243068212b..541c9f237e9c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2032,8 +2032,8 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } } - /* setting should not be allowed from VF */ - if (amdgpu_sriov_vf(adev)) { + /* setting should not be allowed from VF if not in one VF mode */ + if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) { dev_attr->attr.mode &= ~S_IWUGO; dev_attr->store = NULL; } -- cgit From 4f0f1b58fbacc3d4f60e0cf17b01a6273df1d415 Mon Sep 17 00:00:00 2001 From: Danijel Slivka Date: Fri, 11 Feb 2022 02:06:01 +0100 Subject: amdgpu/pm: Disable managing hwmon sysfs attributes for ONEVF mode This patch prohibits performing of set commands on all hwmon attributes through sysfs in ONEVF mode. Signed-off-by: Danijel Slivka Acked-by: Harish Kasiviswanathan Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 541c9f237e9c..cbbbd4079249 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3182,6 +3182,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return 0; + /* under pp one vf mode manage of hwmon attributes is not supported */ + if (amdgpu_sriov_is_pp_one_vf(adev)) + effective_mode &= ~S_IWUSR; + /* Skip fan attributes if fan is not present */ if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || -- cgit From bd4b9bb77956639e6d9618ed306cb2264c69ba49 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 14 Mar 2022 12:53:25 +0100 Subject: drm/amd/pm: fix typos in comments Various spelling mistakes in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index cbbbd4079249..5cd67ddf8495 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1870,7 +1870,7 @@ static ssize_t amdgpu_set_smartshift_bias(struct device *dev, amdgpu_smartshift_bias = bias; r = count; - /* TODO: upadte bias level with SMU message */ + /* TODO: update bias level with SMU message */ out: pm_runtime_mark_last_busy(ddev->dev); -- cgit From 8ecad8d66d7f03ccc8fa7b4921d45041e9b77680 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 25 Mar 2022 13:19:36 +0530 Subject: drm/amd/pm: Check feature support using IP version Instead of ASIC type, use GC and MP1 IP versions for feature support checks. Signed-off-by: Lijo Lazar Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 73 +++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 5cd67ddf8495..9ce597ded31d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1954,8 +1954,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ uint32_t mask, enum amdgpu_device_attr_states *states) { struct device_attribute *dev_attr = &attr->dev_attr; + uint32_t mp1_ver = adev->ip_versions[MP1_HWIP][0]; + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; const char *attr_name = dev_attr->attr.name; - enum amd_asic_type asic_type = adev->asic_type; if (!(attr->flags & mask)) { *states = ATTR_STATE_UNSUPPORTED; @@ -1965,53 +1966,55 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ #define DEVICE_ATTR_IS(_name) (!strcmp(attr_name, #_name)) if (DEVICE_ATTR_IS(pp_dpm_socclk)) { - if (asic_type < CHIP_VEGA10) + if (gc_ver < IP_VERSION(9, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) { - if (asic_type < CHIP_VEGA10 || - asic_type == CHIP_ARCTURUS || - asic_type == CHIP_ALDEBARAN) + if (gc_ver < IP_VERSION(9, 0, 0) || + gc_ver == IP_VERSION(9, 4, 1) || + gc_ver == IP_VERSION(9, 4, 2)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_fclk)) { - if (asic_type < CHIP_VEGA20) + if (mp1_ver < IP_VERSION(10, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { *states = ATTR_STATE_UNSUPPORTED; if (amdgpu_dpm_is_overdrive_supported(adev)) *states = ATTR_STATE_SUPPORTED; } else if (DEVICE_ATTR_IS(mem_busy_percent)) { - if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) + if (adev->flags & AMD_IS_APU || gc_ver == IP_VERSION(9, 0, 1)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pcie_bw)) { /* PCIe Perf counters won't work on APU nodes */ if (adev->flags & AMD_IS_APU) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(unique_id)) { - if (asic_type != CHIP_VEGA10 && - asic_type != CHIP_VEGA20 && - asic_type != CHIP_ARCTURUS && - asic_type != CHIP_ALDEBARAN) + if (gc_ver != IP_VERSION(9, 0, 1) && + gc_ver != IP_VERSION(9, 4, 0) && + gc_ver != IP_VERSION(9, 4, 1) && + gc_ver != IP_VERSION(9, 4, 2)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_features)) { - if (adev->flags & AMD_IS_APU || asic_type < CHIP_VEGA10) + if (adev->flags & AMD_IS_APU || gc_ver < IP_VERSION(9, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(gpu_metrics)) { - if (asic_type < CHIP_VEGA12) + if (gc_ver < IP_VERSION(9, 1, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { - if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 0))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { - if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 0))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; } - switch (asic_type) { - case CHIP_ARCTURUS: - case CHIP_ALDEBARAN: + switch (gc_ver) { + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): /* the Mi series card does not support standalone mclk/socclk/fclk level setting */ if (DEVICE_ATTR_IS(pp_dpm_mclk) || DEVICE_ATTR_IS(pp_dpm_socclk) || @@ -2026,7 +2029,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) { /* SMU MP1 does not support dcefclk level setting */ - if (asic_type >= CHIP_NAVI10) { + if (gc_ver >= IP_VERSION(10, 0, 0)) { dev_attr->attr.mode &= ~S_IWUGO; dev_attr->store = NULL; } @@ -2864,8 +2867,9 @@ static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, char *buf) { struct amdgpu_device *adev = dev_get_drvdata(dev); + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; - if (adev->asic_type == CHIP_VANGOGH) + if (gc_ver == IP_VERSION(10, 3, 1)) return sysfs_emit(buf, "%s\n", to_sensor_dev_attr(attr)->index == PP_PWR_TYPE_FAST ? "fastPPT" : "slowPPT"); @@ -3177,6 +3181,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; /* under multi-vf mode, the hwmon attributes are all not supported */ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) @@ -3245,18 +3250,18 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ effective_mode &= ~S_IWUSR; + /* not implemented yet for GC 10.3.1 APUs */ if (((adev->family == AMDGPU_FAMILY_SI) || - ((adev->flags & AMD_IS_APU) && - (adev->asic_type != CHIP_VANGOGH))) && /* not implemented yet */ + ((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(10, 3, 1)))) && (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || - attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| + attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr || attr == &sensor_dev_attr_power1_cap.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_default.dev_attr.attr)) return 0; + /* not implemented yet for APUs having <= GC 9.3.0 */ if (((adev->family == AMDGPU_FAMILY_SI) || - ((adev->flags & AMD_IS_APU) && - (adev->asic_type < CHIP_RENOIR))) && /* not implemented yet */ + ((adev->flags & AMD_IS_APU) && (gc_ver < IP_VERSION(9, 3, 0)))) && (attr == &sensor_dev_attr_power1_average.dev_attr.attr)) return 0; @@ -3294,8 +3299,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* only SOC15 dGPUs support hotspot and mem temperatures */ - if (((adev->flags & AMD_IS_APU) || - adev->asic_type < CHIP_VEGA10) && + if (((adev->flags & AMD_IS_APU) || gc_ver < IP_VERSION(9, 0, 0)) && (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr || attr == &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr || attr == &sensor_dev_attr_temp3_crit.dev_attr.attr || @@ -3310,13 +3314,13 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* only Vangogh has fast PPT limit and power labels */ - if (!(adev->asic_type == CHIP_VANGOGH) && + if (!(gc_ver == IP_VERSION(10, 3, 1)) && (attr == &sensor_dev_attr_power2_average.dev_attr.attr || - attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr || + attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr || - attr == &sensor_dev_attr_power2_cap.dev_attr.attr || - attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || - attr == &sensor_dev_attr_power2_label.dev_attr.attr)) + attr == &sensor_dev_attr_power2_cap.dev_attr.attr || + attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || + attr == &sensor_dev_attr_power2_label.dev_attr.attr)) return 0; return effective_mode; @@ -3421,6 +3425,8 @@ static void amdgpu_debugfs_prints_cpu_info(struct seq_file *m, static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) { + uint32_t mp1_ver = adev->ip_versions[MP1_HWIP][0]; + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; uint32_t value; uint64_t value64 = 0; uint32_t query = 0; @@ -3467,7 +3473,8 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK, (void *)&value64, &size)) seq_printf(m, "SMC Feature Mask: 0x%016llx\n", value64); - if (adev->asic_type > CHIP_VEGA20) { + /* ASICs greater than CHIP_VEGA20 supports these sensors */ + if (gc_ver != IP_VERSION(9, 4, 0) && mp1_ver > IP_VERSION(9, 0, 0)) { /* VCN clocks */ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_POWER_STATE, (void *)&value, &size)) { if (!value) { -- cgit From 60044748f2c816aad2b5f95c46774ce0aaccf4ca Mon Sep 17 00:00:00 2001 From: Kent Russell Date: Fri, 25 Mar 2022 10:11:36 -0400 Subject: drm/amdgpu: Use switch case for unique_id To ease readability, use switch to set unique_id as supported for the supported IP_VERSIONs, and set it to unsupported by default for all other ASICs. This makes it easier to add IP_VERSIONs later on, and makes it obvious that it is not supported by default, instead of the current logic that assumes that it is supported unless it is not one of the specified IP_VERSIONs. v2: Rebase onto previous IP_VERSION change Signed-off-by: Kent Russell Reviewed-by: Alex Deucher Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 9ce597ded31d..4151db2678fb 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1988,11 +1988,16 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (adev->flags & AMD_IS_APU) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(unique_id)) { - if (gc_ver != IP_VERSION(9, 0, 1) && - gc_ver != IP_VERSION(9, 4, 0) && - gc_ver != IP_VERSION(9, 4, 1) && - gc_ver != IP_VERSION(9, 4, 2)) + switch (gc_ver) { + case IP_VERSION(9, 0, 1): + case IP_VERSION(9, 4, 0): + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): + *states = ATTR_STATE_SUPPORTED; + break; + default: *states = ATTR_STATE_UNSUPPORTED; + } } else if (DEVICE_ATTR_IS(pp_features)) { if (adev->flags & AMD_IS_APU || gc_ver < IP_VERSION(9, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; -- cgit From ebd9c071d29e56b21ef5155757e0da9926d8d814 Mon Sep 17 00:00:00 2001 From: Kent Russell Date: Wed, 9 Feb 2022 19:56:46 -0500 Subject: drm/amdgpu: Add unique_id support for sienna cichlid This is being added to SMU Metrics, so add the required tie-ins in the kernel. Also create the corresponding unique_id sysfs file. v2: Add FW version check, remove SMU mutex v3: Fix style warning v4: Add MP1 IP_VERSION check to FW version check Signed-off-by: Kent Russell Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 1 + .../inc/pmfw_if/smu11_driver_if_sienna_cichlid.h | 13 +++++++-- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 33 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 4151db2678fb..4a9aabc16fbc 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1993,6 +1993,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ case IP_VERSION(9, 4, 0): case IP_VERSION(9, 4, 1): case IP_VERSION(9, 4, 2): + case IP_VERSION(10, 3, 0): *states = ATTR_STATE_SUPPORTED; break; default: diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h index 3e4a314ef925..5831145646e6 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h @@ -1419,8 +1419,11 @@ typedef struct { uint8_t PcieRate ; uint8_t PcieWidth ; uint16_t AverageGfxclkFrequencyTarget; - uint16_t Padding16_2; + uint32_t PublicSerialNumLower32; + uint32_t PublicSerialNumUpper32; + + uint16_t Padding16_2; } SmuMetrics_t; typedef struct { @@ -1476,8 +1479,11 @@ typedef struct { uint8_t PcieRate ; uint8_t PcieWidth ; uint16_t AverageGfxclkFrequencyTarget; - uint16_t Padding16_2; + uint32_t PublicSerialNumLower32; + uint32_t PublicSerialNumUpper32; + + uint16_t Padding16_2; } SmuMetrics_V2_t; typedef struct { @@ -1535,6 +1541,9 @@ typedef struct { uint8_t PcieWidth; uint16_t AverageGfxclkFrequencyTarget; + uint32_t PublicSerialNumLower32; + uint32_t PublicSerialNumUpper32; + } SmuMetrics_V3_t; typedef struct { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 38f04836c82f..b2f3d80e5945 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -715,6 +715,16 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, *value = use_metrics_v3 ? metrics_v3->CurrFanSpeed : use_metrics_v2 ? metrics_v2->CurrFanSpeed : metrics->CurrFanSpeed; break; + case METRICS_UNIQUE_ID_UPPER32: + *value = use_metrics_v3 ? metrics_v3->PublicSerialNumUpper32 : + use_metrics_v2 ? metrics_v2->PublicSerialNumUpper32 : + metrics->PublicSerialNumUpper32; + break; + case METRICS_UNIQUE_ID_LOWER32: + *value = use_metrics_v3 ? metrics_v3->PublicSerialNumLower32 : + use_metrics_v2 ? metrics_v2->PublicSerialNumLower32 : + metrics->PublicSerialNumLower32; + break; default: *value = UINT_MAX; break; @@ -1773,6 +1783,28 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu, return ret; } +static void sienna_cichlid_get_unique_id(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t upper32 = 0, lower32 = 0; + + /* Only supported as of version 0.58.83.0 and only on Sienna Cichlid */ + if (smu->smc_fw_version < 0x3A5300 || + smu->adev->ip_versions[MP1_HWIP][0] != IP_VERSION(11, 0, 7)) + return; + + if (sienna_cichlid_get_smu_metrics_data(smu, METRICS_UNIQUE_ID_UPPER32, &upper32)) + goto out; + if (sienna_cichlid_get_smu_metrics_data(smu, METRICS_UNIQUE_ID_LOWER32, &lower32)) + goto out; + +out: + + adev->unique_id = ((uint64_t)upper32 << 32) | lower32; + if (adev->serial[0] == '\0') + sprintf(adev->serial, "%016llx", adev->unique_id); +} + static int sienna_cichlid_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states) { uint32_t num_discrete_levels = 0; @@ -4182,6 +4214,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_ecc_info = sienna_cichlid_get_ecc_info, .get_default_config_table_settings = sienna_cichlid_get_default_config_table_settings, .set_config_table = sienna_cichlid_set_config_table, + .get_unique_id = sienna_cichlid_get_unique_id, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- cgit From a68bec2ce7d6d89136b91160c3428caf683acb91 Mon Sep 17 00:00:00 2001 From: Marko Zekovic Date: Mon, 28 Mar 2022 12:37:30 +0200 Subject: amdgpu/pm: Enable sysfs nodes for vclk and dclk for NAVI12 SMI clock measure API is failing on NAVI12, because sysfs node for pp_dpm_vclk is not existing. Enable sysfs node for pp_dpm_vclk for NAVI12. v2: Also enable sysfs node for pp_dpm_dclk. Reviewed-by: Lijo Lazar Signed-off-by: Marko Zekovic Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 4a9aabc16fbc..ec4ea141bfda 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2007,11 +2007,13 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { if (!(gc_ver == IP_VERSION(10, 3, 1) || - gc_ver == IP_VERSION(10, 3, 0))) + gc_ver == IP_VERSION(10, 3, 0) || + gc_ver == IP_VERSION(10, 1, 2))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { if (!(gc_ver == IP_VERSION(10, 3, 1) || - gc_ver == IP_VERSION(10, 3, 0))) + gc_ver == IP_VERSION(10, 3, 0) || + gc_ver == IP_VERSION(10, 1, 2))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) -- cgit From 25faeddcf3c3f31f9f43de5c55f7cbdd13d3ebc7 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 25 Mar 2022 18:00:02 +0800 Subject: drm/amdgpu: expand cg_flags from u32 to u64 With this, we can support more CG flags. Signed-off-by: Evan Quan Acked-by: Alex Deucher Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 5 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_df.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h | 2 +- drivers/gpu/drm/amd/amdgpu/athub_v1_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/athub_v1_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/athub_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/athub_v2_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/athub_v2_1.c | 2 +- drivers/gpu/drm/amd/amdgpu/athub_v2_1.h | 2 +- drivers/gpu/drm/amd/amdgpu/df_v1_7.c | 2 +- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 2 +- drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 2 +- drivers/gpu/drm/amd/amdgpu/nv.c | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 2 +- drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/smuio_v11_0_6.c | 2 +- drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/smuio_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vi.c | 2 +- drivers/gpu/drm/amd/include/amd_shared.h | 66 ++++++++++++++--------------- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-- drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h | 2 +- 53 files changed, 95 insertions(+), 92 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index cdf0818088b3..bffd24845765 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -179,7 +179,7 @@ extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern uint amdgpu_pcie_gen_cap; extern uint amdgpu_pcie_lane_cap; -extern uint amdgpu_cg_mask; +extern u64 amdgpu_cg_mask; extern uint amdgpu_pg_mask; extern uint amdgpu_sdma_phase_quantum; extern char *amdgpu_disable_cu; @@ -322,7 +322,7 @@ int amdgpu_device_ip_set_powergating_state(void *dev, enum amd_ip_block_type block_type, enum amd_powergating_state state); void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags); + u64 *flags); int amdgpu_device_ip_wait_for_idle(struct amdgpu_device *adev, enum amd_ip_block_type block_type); bool amdgpu_device_ip_is_idle(struct amdgpu_device *adev, @@ -860,7 +860,7 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; struct amdgpu_pm pm; - u32 cg_flags; + u64 cg_flags; u32 pg_flags; /* nbio */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 5d04d24a0d5f..1db48dc58ae9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -758,7 +758,7 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, /* rev==1 */ config[no_regs++] = adev->rev_id; config[no_regs++] = adev->pg_flags; - config[no_regs++] = adev->cg_flags; + config[no_regs++] = lower_32_bits(adev->cg_flags); /* rev==2 */ config[no_regs++] = adev->family; @@ -773,6 +773,9 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, /* rev==4 APU flag */ config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0; + /* rev==5 CG flag upper 32bit */ + config[no_regs++] = upper_32_bits(adev->cg_flags); + while (size && (*pos < no_regs * 4)) { uint32_t value; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 49f734137f15..fb69b4188c8a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1703,7 +1703,7 @@ int amdgpu_device_ip_set_powergating_state(void *dev, * clockgating is enabled. */ void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int i; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h index 6b25837955c4..1538b2dbfff1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h @@ -40,7 +40,7 @@ struct amdgpu_df_funcs { void (*update_medium_grain_clock_gating)(struct amdgpu_device *adev, bool enable); void (*get_clockgating_state)(struct amdgpu_device *adev, - u32 *flags); + u64 *flags); void (*enable_ecc_force_par_wr_rmw)(struct amdgpu_device *adev, bool enable); int (*pmc_start)(struct amdgpu_device *adev, uint64_t config, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 29e9419a914b..4efaa183abcd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -136,7 +136,7 @@ int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; uint amdgpu_pcie_gen_cap; uint amdgpu_pcie_lane_cap; -uint amdgpu_cg_mask = 0xffffffff; +u64 amdgpu_cg_mask = 0xffffffffffffffff; uint amdgpu_pg_mask = 0xffffffff; uint amdgpu_sdma_phase_quantum = 32; char *amdgpu_disable_cu = NULL; @@ -454,12 +454,12 @@ MODULE_PARM_DESC(pcie_lane_cap, "PCIE Lane Caps (0: autodetect (default))"); module_param_named(pcie_lane_cap, amdgpu_pcie_lane_cap, uint, 0444); /** - * DOC: cg_mask (uint) + * DOC: cg_mask (ullong) * Override Clockgating features enabled on GPU (0 = disable clock gating). See the AMD_CG_SUPPORT flags in - * drivers/gpu/drm/amd/include/amd_shared.h. The default is 0xffffffff (all enabled). + * drivers/gpu/drm/amd/include/amd_shared.h. The default is 0xffffffffffffffff (all enabled). */ MODULE_PARM_DESC(cg_mask, "Clockgating flags mask (0 = disable clock gating)"); -module_param_named(cg_mask, amdgpu_cg_mask, uint, 0444); +module_param_named(cg_mask, amdgpu_cg_mask, ullong, 0444); /** * DOC: pg_mask (uint) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h index 9181c7bef7c6..ac5c61d3de2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h @@ -33,7 +33,7 @@ struct amdgpu_hdp_funcs { void (*invalidate_hdp)(struct amdgpu_device *adev, struct amdgpu_ring *ring); void (*update_clock_gating)(struct amdgpu_device *adev, bool enable); - void (*get_clock_gating_state)(struct amdgpu_device *adev, u32 *flags); + void (*get_clock_gating_state)(struct amdgpu_device *adev, u64 *flags); void (*init_registers)(struct amdgpu_device *adev); }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h index 9f1540f0ebf9..f939395c5914 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h @@ -34,7 +34,7 @@ struct amdgpu_mmhub_funcs { void (*gart_disable)(struct amdgpu_device *adev); int (*set_clockgating)(struct amdgpu_device *adev, enum amd_clockgating_state state); - void (*get_clockgating)(struct amdgpu_device *adev, u32 *flags); + void (*get_clockgating)(struct amdgpu_device *adev, u64 *flags); void (*setup_vm_pt_regs)(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base); void (*update_power_gating)(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h index 3d13e601fc35..03439083182a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h @@ -83,7 +83,7 @@ struct amdgpu_nbio_funcs { void (*update_medium_grain_light_sleep)(struct amdgpu_device *adev, bool enable); void (*get_clockgating_state)(struct amdgpu_device *adev, - u32 *flags); + u64 *flags); void (*ih_control)(struct amdgpu_device *adev); void (*init_registers)(struct amdgpu_device *adev); void (*remap_hdp_registers)(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h index 484bb3dcec47..c7a823f3f2c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h @@ -27,7 +27,7 @@ struct amdgpu_smuio_funcs { u32 (*get_rom_index_offset)(struct amdgpu_device *adev); u32 (*get_rom_data_offset)(struct amdgpu_device *adev); void (*update_rom_clock_gating)(struct amdgpu_device *adev, bool enable); - void (*get_clock_gating_state)(struct amdgpu_device *adev, u32 *flags); + void (*get_clock_gating_state)(struct amdgpu_device *adev, u64 *flags); u32 (*get_die_id)(struct amdgpu_device *adev); u32 (*get_socket_id)(struct amdgpu_device *adev); bool (*is_host_gpu_xgmi_supported)(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c index 88642e7ecdf4..a13c443ea10f 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c @@ -87,7 +87,7 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev, return 0; } -void athub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +void athub_v1_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.h b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.h index b279af59e34f..6be0a6704ea7 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.h @@ -25,6 +25,6 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state); -void athub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags); +void athub_v1_0_get_clockgating(struct amdgpu_device *adev, u64 *flags); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c index a720436857b4..a9521c98e7f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c @@ -93,7 +93,7 @@ int athub_v2_0_set_clockgating(struct amdgpu_device *adev, return 0; } -void athub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +void athub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.h b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.h index 02932c1c8bab..8b763f6dfd81 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.h @@ -25,6 +25,6 @@ int athub_v2_0_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state); -void athub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags); +void athub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c index ad8e87d3d2cb..78508ae6a670 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c @@ -85,7 +85,7 @@ int athub_v2_1_set_clockgating(struct amdgpu_device *adev, return 0; } -void athub_v2_1_get_clockgating(struct amdgpu_device *adev, u32 *flags) +void athub_v2_1_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.h b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.h index 5e6824c0f591..b799f14bce03 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.h +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.h @@ -25,6 +25,6 @@ int athub_v2_1_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state); -void athub_v2_1_get_clockgating(struct amdgpu_device *adev, u32 *flags); +void athub_v2_1_get_clockgating(struct amdgpu_device *adev, u64 *flags); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/df_v1_7.c b/drivers/gpu/drm/amd/amdgpu/df_v1_7.c index 2d01ac0d4c11..b991609f46c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v1_7.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v1_7.c @@ -99,7 +99,7 @@ static void df_v1_7_update_medium_grain_clock_gating(struct amdgpu_device *adev, } static void df_v1_7_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { u32 tmp; diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index f4dfca013ec5..483a441b46aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c @@ -332,7 +332,7 @@ static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev, } static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { u32 tmp; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 9426e252d8aa..5147358f2400 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -8451,7 +8451,7 @@ static int gfx_v10_0_set_clockgating_state(void *handle, return 0; } -static void gfx_v10_0_get_clockgating_state(void *handle, u32 *flags) +static void gfx_v10_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 5f112efda634..46d436be74eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5475,7 +5475,7 @@ static int gfx_v8_0_set_powergating_state(void *handle, return 0; } -static void gfx_v8_0_get_clockgating_state(void *handle, u32 *flags) +static void gfx_v8_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index b8cfcc6b1125..26535ebec498 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -5233,7 +5233,7 @@ static int gfx_v9_0_set_clockgating_state(void *handle, return 0; } -static void gfx_v9_0_get_clockgating_state(void *handle, u32 *flags) +static void gfx_v9_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 5228421b0f72..a455e59f41f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -1161,7 +1161,7 @@ static int gmc_v10_0_set_clockgating_state(void *handle, return athub_v2_0_set_clockgating(adev, state); } -static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags) +static void gmc_v10_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 1932a3e4af7e..382dde1ce74c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1690,7 +1690,7 @@ static int gmc_v8_0_set_powergating_state(void *handle, return 0; } -static void gmc_v8_0_get_clockgating_state(void *handle, u32 *flags) +static void gmc_v8_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6009fbfdcc19..22761a3bb818 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1948,7 +1948,7 @@ static int gmc_v9_0_set_clockgating_state(void *handle, return 0; } -static void gmc_v9_0_get_clockgating_state(void *handle, u32 *flags) +static void gmc_v9_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c index 046216635262..adf89680f53e 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c @@ -124,7 +124,7 @@ static void hdp_v4_0_update_clock_gating(struct amdgpu_device *adev, } static void hdp_v4_0_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c index 5793977953cc..a9ea23fa0def 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c @@ -181,7 +181,7 @@ static void hdp_v5_0_update_clock_gating(struct amdgpu_device *adev, } static void hdp_v5_0_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { uint32_t tmp; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 4c9f0c0f3116..3f44a099c52a 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -546,7 +546,7 @@ static int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, return 0; } -static void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data, data1; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c index 3b901f941627..6fa7090bc6cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c @@ -542,7 +542,7 @@ static int mmhub_v1_7_set_clockgating(struct amdgpu_device *adev, return 0; } -static void mmhub_v1_7_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v1_7_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data, data1; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 3718ff610ab2..636abd855686 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -682,7 +682,7 @@ static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, return 0; } -static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data, data1; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c index 1957fb098c4d..ff44c5364a8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c @@ -577,7 +577,7 @@ static int mmhub_v2_3_set_clockgating(struct amdgpu_device *adev, return 0; } -static void mmhub_v2_3_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v2_3_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data, data1, data2, data3; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c index 619106f7d23d..6e0145b2b408 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c @@ -647,7 +647,7 @@ static int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, return 0; } -static void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u64 *flags) { int data, data1; diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c index 8ce5b8ca1fd7..97201ab0965e 100644 --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c @@ -685,7 +685,7 @@ static int navi10_ih_set_powergating_state(void *handle, return 0; } -static void navi10_ih_get_clockgating_state(void *handle, u32 *flags) +static void navi10_ih_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c index ee7cab37dfd5..6cd1fb2eb913 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c @@ -278,7 +278,7 @@ static void nbio_v2_3_update_medium_grain_light_sleep(struct amdgpu_device *adev } static void nbio_v2_3_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c index 4bbacf1be25a..f7f6ddebd3e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c @@ -210,7 +210,7 @@ static void nbio_v6_1_update_medium_grain_light_sleep(struct amdgpu_device *adev } static void nbio_v6_1_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c index 37a4039fdfc5..aa0326d00c72 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c @@ -205,7 +205,7 @@ static void nbio_v7_0_update_medium_grain_light_sleep(struct amdgpu_device *adev } static void nbio_v7_0_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c index 6f81de6f3cc4..31776b12e4c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c @@ -306,7 +306,7 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev } static void nbio_v7_2_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index c2357e83a8c4..4531761dcf77 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -273,7 +273,7 @@ static void nbio_v7_4_update_medium_grain_light_sleep(struct amdgpu_device *adev } static void nbio_v7_4_get_clockgating_state(struct amdgpu_device *adev, - u32 *flags) + u64 *flags) { int data; diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index e19f14c3ef59..0a7946c59a42 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -1115,7 +1115,7 @@ static int nv_common_set_powergating_state(void *handle, return 0; } -static void nv_common_get_clockgating_state(void *handle, u32 *flags) +static void nv_common_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 4ef4feff5649..3695374896ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1535,7 +1535,7 @@ static int sdma_v3_0_set_powergating_state(void *handle, return 0; } -static void sdma_v3_0_get_clockgating_state(void *handle, u32 *flags) +static void sdma_v3_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index d7e8f7232364..8589ab1c9800 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2372,7 +2372,7 @@ static int sdma_v4_0_set_powergating_state(void *handle, return 0; } -static void sdma_v4_0_get_clockgating_state(void *handle, u32 *flags) +static void sdma_v4_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index a8d49c005f73..775aabde1ae2 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1648,7 +1648,7 @@ static int sdma_v5_0_set_powergating_state(void *handle, return 0; } -static void sdma_v5_0_get_clockgating_state(void *handle, u32 *flags) +static void sdma_v5_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 824eace69884..ca50857b982d 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -1645,7 +1645,7 @@ static int sdma_v5_2_set_powergating_state(void *handle, return 0; } -static void sdma_v5_2_get_clockgating_state(void *handle, u32 *flags) +static void sdma_v5_2_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c b/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c index b6f1322f908c..acdc40f99ab3 100644 --- a/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c @@ -59,7 +59,7 @@ static void smuio_v11_0_update_rom_clock_gating(struct amdgpu_device *adev, bool WREG32_SOC15(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0, data); } -static void smuio_v11_0_get_clock_gating_state(struct amdgpu_device *adev, u32 *flags) +static void smuio_v11_0_get_clock_gating_state(struct amdgpu_device *adev, u64 *flags) { u32 data; diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v11_0_6.c b/drivers/gpu/drm/amd/amdgpu/smuio_v11_0_6.c index 3a18dbb55c32..2afeb8b37f62 100644 --- a/drivers/gpu/drm/amd/amdgpu/smuio_v11_0_6.c +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v11_0_6.c @@ -56,7 +56,7 @@ static void smuio_v11_0_6_update_rom_clock_gating(struct amdgpu_device *adev, bo WREG32_SOC15(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0, data); } -static void smuio_v11_0_6_get_clock_gating_state(struct amdgpu_device *adev, u32 *flags) +static void smuio_v11_0_6_get_clock_gating_state(struct amdgpu_device *adev, u64 *flags) { u32 data; diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c index 39b7c206770f..13e905c22592 100644 --- a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c @@ -58,7 +58,7 @@ static void smuio_v13_0_update_rom_clock_gating(struct amdgpu_device *adev, bool WREG32_SOC15(SMUIO, 0, regCGTT_ROM_CLK_CTRL0, data); } -static void smuio_v13_0_get_clock_gating_state(struct amdgpu_device *adev, u32 *flags) +static void smuio_v13_0_get_clock_gating_state(struct amdgpu_device *adev, u64 *flags) { u32 data; diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v9_0.c b/drivers/gpu/drm/amd/amdgpu/smuio_v9_0.c index 8417890af227..e4e30b9d481b 100644 --- a/drivers/gpu/drm/amd/amdgpu/smuio_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v9_0.c @@ -56,7 +56,7 @@ static void smuio_v9_0_update_rom_clock_gating(struct amdgpu_device *adev, bool WREG32_SOC15(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0, data); } -static void smuio_v9_0_get_clock_gating_state(struct amdgpu_device *adev, u32 *flags) +static void smuio_v9_0_get_clock_gating_state(struct amdgpu_device *adev, u64 *flags) { u32 data; diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3d0251ef8d79..3ee7322081d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1419,7 +1419,7 @@ static int soc15_common_set_clockgating_state(void *handle, return 0; } -static void soc15_common_get_clockgating_state(void *handle, u32 *flags) +static void soc15_common_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 563493d1f830..d7e31e48a2b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -833,7 +833,7 @@ out: return ret; } -static void uvd_v5_0_get_clockgating_state(void *handle, u32 *flags) +static void uvd_v5_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 2d558c2f417d..375c440957dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1494,7 +1494,7 @@ out: return ret; } -static void uvd_v6_0_get_clockgating_state(void *handle, u32 *flags) +static void uvd_v6_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 142e291983b4..8def62c83ffd 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -831,7 +831,7 @@ out: return ret; } -static void vce_v3_0_get_clockgating_state(void *handle, u32 *flags) +static void vce_v3_0_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 039b90cdc3bc..c5b88d15a6df 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -2033,7 +2033,7 @@ static int vi_common_set_powergating_state(void *handle, return 0; } -static void vi_common_get_clockgating_state(void *handle, u32 *flags) +static void vi_common_get_clockgating_state(void *handle, u64 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index fe4e585781bb..741dae17562a 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -116,38 +116,38 @@ enum amd_powergating_state { /* CG flags */ -#define AMD_CG_SUPPORT_GFX_MGCG (1 << 0) -#define AMD_CG_SUPPORT_GFX_MGLS (1 << 1) -#define AMD_CG_SUPPORT_GFX_CGCG (1 << 2) -#define AMD_CG_SUPPORT_GFX_CGLS (1 << 3) -#define AMD_CG_SUPPORT_GFX_CGTS (1 << 4) -#define AMD_CG_SUPPORT_GFX_CGTS_LS (1 << 5) -#define AMD_CG_SUPPORT_GFX_CP_LS (1 << 6) -#define AMD_CG_SUPPORT_GFX_RLC_LS (1 << 7) -#define AMD_CG_SUPPORT_MC_LS (1 << 8) -#define AMD_CG_SUPPORT_MC_MGCG (1 << 9) -#define AMD_CG_SUPPORT_SDMA_LS (1 << 10) -#define AMD_CG_SUPPORT_SDMA_MGCG (1 << 11) -#define AMD_CG_SUPPORT_BIF_LS (1 << 12) -#define AMD_CG_SUPPORT_UVD_MGCG (1 << 13) -#define AMD_CG_SUPPORT_VCE_MGCG (1 << 14) -#define AMD_CG_SUPPORT_HDP_LS (1 << 15) -#define AMD_CG_SUPPORT_HDP_MGCG (1 << 16) -#define AMD_CG_SUPPORT_ROM_MGCG (1 << 17) -#define AMD_CG_SUPPORT_DRM_LS (1 << 18) -#define AMD_CG_SUPPORT_BIF_MGCG (1 << 19) -#define AMD_CG_SUPPORT_GFX_3D_CGCG (1 << 20) -#define AMD_CG_SUPPORT_GFX_3D_CGLS (1 << 21) -#define AMD_CG_SUPPORT_DRM_MGCG (1 << 22) -#define AMD_CG_SUPPORT_DF_MGCG (1 << 23) -#define AMD_CG_SUPPORT_VCN_MGCG (1 << 24) -#define AMD_CG_SUPPORT_HDP_DS (1 << 25) -#define AMD_CG_SUPPORT_HDP_SD (1 << 26) -#define AMD_CG_SUPPORT_IH_CG (1 << 27) -#define AMD_CG_SUPPORT_ATHUB_LS (1 << 28) -#define AMD_CG_SUPPORT_ATHUB_MGCG (1 << 29) -#define AMD_CG_SUPPORT_JPEG_MGCG (1 << 30) -#define AMD_CG_SUPPORT_GFX_FGCG (1 << 31) +#define AMD_CG_SUPPORT_GFX_MGCG (1ULL << 0) +#define AMD_CG_SUPPORT_GFX_MGLS (1ULL << 1) +#define AMD_CG_SUPPORT_GFX_CGCG (1ULL << 2) +#define AMD_CG_SUPPORT_GFX_CGLS (1ULL << 3) +#define AMD_CG_SUPPORT_GFX_CGTS (1ULL << 4) +#define AMD_CG_SUPPORT_GFX_CGTS_LS (1ULL << 5) +#define AMD_CG_SUPPORT_GFX_CP_LS (1ULL << 6) +#define AMD_CG_SUPPORT_GFX_RLC_LS (1ULL << 7) +#define AMD_CG_SUPPORT_MC_LS (1ULL << 8) +#define AMD_CG_SUPPORT_MC_MGCG (1ULL << 9) +#define AMD_CG_SUPPORT_SDMA_LS (1ULL << 10) +#define AMD_CG_SUPPORT_SDMA_MGCG (1ULL << 11) +#define AMD_CG_SUPPORT_BIF_LS (1ULL << 12) +#define AMD_CG_SUPPORT_UVD_MGCG (1ULL << 13) +#define AMD_CG_SUPPORT_VCE_MGCG (1ULL << 14) +#define AMD_CG_SUPPORT_HDP_LS (1ULL << 15) +#define AMD_CG_SUPPORT_HDP_MGCG (1ULL << 16) +#define AMD_CG_SUPPORT_ROM_MGCG (1ULL << 17) +#define AMD_CG_SUPPORT_DRM_LS (1ULL << 18) +#define AMD_CG_SUPPORT_BIF_MGCG (1ULL << 19) +#define AMD_CG_SUPPORT_GFX_3D_CGCG (1ULL << 20) +#define AMD_CG_SUPPORT_GFX_3D_CGLS (1ULL << 21) +#define AMD_CG_SUPPORT_DRM_MGCG (1ULL << 22) +#define AMD_CG_SUPPORT_DF_MGCG (1ULL << 23) +#define AMD_CG_SUPPORT_VCN_MGCG (1ULL << 24) +#define AMD_CG_SUPPORT_HDP_DS (1ULL << 25) +#define AMD_CG_SUPPORT_HDP_SD (1ULL << 26) +#define AMD_CG_SUPPORT_IH_CG (1ULL << 27) +#define AMD_CG_SUPPORT_ATHUB_LS (1ULL << 28) +#define AMD_CG_SUPPORT_ATHUB_MGCG (1ULL << 29) +#define AMD_CG_SUPPORT_JPEG_MGCG (1ULL << 30) +#define AMD_CG_SUPPORT_GFX_FGCG (1ULL << 31) /* PG flags */ #define AMD_PG_SUPPORT_GFX_PG (1 << 0) #define AMD_PG_SUPPORT_GFX_SMG (1 << 1) @@ -298,7 +298,7 @@ struct amd_ip_funcs { enum amd_clockgating_state state); int (*set_powergating_state)(void *handle, enum amd_powergating_state state); - void (*get_clockgating_state)(void *handle, u32 *flags); + void (*get_clockgating_state)(void *handle, u64 *flags); }; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index ec4ea141bfda..78ec9b71197d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3526,7 +3526,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a return 0; } -static void amdgpu_parse_cg_state(struct seq_file *m, u32 flags) +static void amdgpu_parse_cg_state(struct seq_file *m, u64 flags) { int i; @@ -3539,7 +3539,7 @@ static int amdgpu_debugfs_pm_info_show(struct seq_file *m, void *unused) { struct amdgpu_device *adev = (struct amdgpu_device *)m->private; struct drm_device *dev = adev_to_drm(adev); - u32 flags = 0; + u64 flags = 0; int r; if (amdgpu_in_reset(adev)) @@ -3561,7 +3561,7 @@ static int amdgpu_debugfs_pm_info_show(struct seq_file *m, void *unused) amdgpu_device_ip_get_clockgating_state(adev, &flags); - seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags); + seq_printf(m, "Clock Gating Flags Mask: 0x%llx\n", flags); amdgpu_parse_cg_state(m, flags); seq_printf(m, "\n"); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h index a920515e2274..52045ad59bed 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h @@ -26,7 +26,7 @@ struct cg_flag_name { - u32 flag; + u64 flag; const char *name; }; -- cgit From 64440743e89629231fee712879d7a9d5ec7dfb8c Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 18 Mar 2022 14:35:05 +0800 Subject: drm/amd/pm: enable pp_dpm_vclk/dclk sysfs interface support for SMU 13.0.0 Make the pp_dpm_vclk/dclk sysfs interfaces visible for SMU 13.0.0. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 78ec9b71197d..befc7a0f06b7 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2008,12 +2008,14 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { if (!(gc_ver == IP_VERSION(10, 3, 1) || gc_ver == IP_VERSION(10, 3, 0) || - gc_ver == IP_VERSION(10, 1, 2))) + gc_ver == IP_VERSION(10, 1, 2) || + gc_ver == IP_VERSION(11, 0, 0))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { if (!(gc_ver == IP_VERSION(10, 3, 1) || gc_ver == IP_VERSION(10, 3, 0) || - gc_ver == IP_VERSION(10, 1, 2))) + gc_ver == IP_VERSION(10, 1, 2) || + gc_ver == IP_VERSION(11, 0, 0))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) -- cgit From 276c03a0547068026241decd2c1159df0be5941f Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 6 Apr 2022 17:13:54 -0400 Subject: drm/amd/smu: Update SMU13 support for SMU 13.0.0 Modify the common smu13 code and add a new smu 13.0.0 ppt file to handle the smu 13.0.0 specific configuration. v2: squash in typo fix in profile name Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4 + drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 6 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 2 + drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 29 +- drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h | 8 +- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 321 ++++- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 1365 ++++++++++++++++++++ .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h | 28 + drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 11 + 11 files changed, 1727 insertions(+), 50 deletions(-) create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index befc7a0f06b7..05f1ac355ba8 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1994,6 +1994,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ case IP_VERSION(9, 4, 1): case IP_VERSION(9, 4, 2): case IP_VERSION(10, 3, 0): + case IP_VERSION(11, 0, 0): *states = ATTR_STATE_SUPPORTED; break; default: diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 612d07762306..6c71106b12c3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -37,6 +37,7 @@ #include "aldebaran_ppt.h" #include "yellow_carp_ppt.h" #include "cyan_skillfish_ppt.h" +#include "smu_v13_0_0_ppt.h" #include "smu_v13_0_5_ppt.h" #include "amd_pcie.h" @@ -565,6 +566,9 @@ static int smu_set_funcs(struct amdgpu_device *adev) /* Enable pp_od_clk_voltage node */ smu->od_enabled = true; break; + case IP_VERSION(13, 0, 0): + smu_v13_0_0_set_ppt_funcs(smu); + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 49d2c0eb014d..a6a7b6c33683 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -454,6 +454,7 @@ struct smu_umd_pstate_table { struct pstates_clk_freq uclk_pstate; struct pstates_clk_freq vclk_pstate; struct pstates_clk_freq dclk_pstate; + struct pstates_clk_freq fclk_pstate; }; struct cmn2asic_msg_mapping { @@ -1327,6 +1328,8 @@ typedef enum { METRICS_AVERAGE_UCLK, METRICS_AVERAGE_VCLK, METRICS_AVERAGE_DCLK, + METRICS_AVERAGE_VCLK1, + METRICS_AVERAGE_DCLK1, METRICS_AVERAGE_GFXACTIVITY, METRICS_AVERAGE_MEMACTIVITY, METRICS_AVERAGE_VCNACTIVITY, @@ -1345,6 +1348,9 @@ typedef enum { METRICS_SS_DGPU_SHARE, METRICS_UNIQUE_ID_UPPER32, METRICS_UNIQUE_ID_LOWER32, + METRICS_PCIE_RATE, + METRICS_PCIE_WIDTH, + METRICS_CURR_FANPWM, } MetricsMember_t; enum smu_cmn2asic_mapping_type { 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 9f6f306eeca0..3f40cd6e4165 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -366,6 +366,8 @@ enum smu_clk_type { __SMU_DUMMY_MAP(THM_CG), \ __SMU_DUMMY_MAP(CLK_CG), \ __SMU_DUMMY_MAP(DATA_CALCULATION), \ + __SMU_DUMMY_MAP(DPM_VCLK), \ + __SMU_DUMMY_MAP(DPM_DCLK), \ #undef __SMU_DUMMY_MAP #define __SMU_DUMMY_MAP(feature) SMU_FEATURE_##feature##_BIT diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index d0d5b9b2c65b..f55f701e4681 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -28,9 +28,10 @@ #define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x27 #define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 /* MP Apertures */ #define MP0_Public 0x03800000 @@ -49,7 +50,7 @@ #define SMU13_TOOL_SIZE 0x19000 #define MAX_DPM_LEVELS 16 -#define MAX_PCIE_CONF 2 +#define MAX_PCIE_CONF 3 #define CTF_OFFSET_EDGE 5 #define CTF_OFFSET_HOTSPOT 5 @@ -73,12 +74,15 @@ struct smu_13_0_dpm_table { uint32_t min; /* MHz */ uint32_t max; /* MHz */ uint32_t count; + bool is_fine_grained; struct smu_13_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS]; }; struct smu_13_0_pcie_table { uint8_t pcie_gen[MAX_PCIE_CONF]; uint8_t pcie_lane[MAX_PCIE_CONF]; + uint16_t clk_freq[MAX_PCIE_CONF]; + uint32_t num_of_link_levels; }; struct smu_13_0_dpm_tables { @@ -192,8 +196,8 @@ int smu_v13_0_set_fan_control_mode(struct smu_context *smu, uint32_t mode); -int -smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed); +int smu_v13_0_set_fan_speed_pwm(struct smu_context *smu, + uint32_t speed); int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); @@ -238,15 +242,6 @@ int smu_v13_0_set_performance_level(struct smu_context *smu, int smu_v13_0_set_power_source(struct smu_context *smu, enum smu_power_src_type power_src); -int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu, - enum smu_clk_type clk_type, - uint16_t level, - uint32_t *value); - -int smu_v13_0_get_dpm_level_count(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value); - int smu_v13_0_set_single_dpm_table(struct smu_context *smu, enum smu_clk_type clk_type, struct smu_13_0_dpm_table *single_dpm_table); @@ -270,5 +265,13 @@ int smu_v13_0_gfx_ulv_control(struct smu_context *smu, int smu_v13_0_wait_for_event(struct smu_context *smu, enum smu_event_type event, uint64_t event_arg); +int smu_v13_0_set_vcn_enable(struct smu_context *smu, + bool enable); + +int smu_v13_0_set_jpeg_enable(struct smu_context *smu, + bool enable); + +int smu_v13_0_init_pptable_microcode(struct smu_context *smu); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile index 613cdd0d8e83..74e9614a26d3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile @@ -23,7 +23,7 @@ # Makefile for the 'smu manager' sub-component of powerplay. # It provides the smu management services for the driver. -SMU13_MGR = smu_v13_0.o aldebaran_ppt.o yellow_carp_ppt.o smu_v13_0_5_ppt.o +SMU13_MGR = smu_v13_0.o aldebaran_ppt.o yellow_carp_ppt.o smu_v13_0_0_ppt.o smu_v13_0_5_ppt.o AMD_SWSMU_SMU13MGR = $(addprefix $(AMD_SWSMU_PATH)/smu13/,$(SMU13_MGR)) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h index 33a85d57cf15..31e991bde3e5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h @@ -28,7 +28,7 @@ #define ALDEBARAN_UMD_PSTATE_MCLK_LEVEL 0x2 #define MAX_DPM_NUMBER 16 -#define MAX_PCIE_CONF 2 +#define ALDEBARAN_MAX_PCIE_CONF 2 struct aldebaran_dpm_level { bool enabled; @@ -51,9 +51,9 @@ struct aldebaran_single_dpm_table { struct aldebaran_pcie_table { uint16_t count; - uint8_t pcie_gen[MAX_PCIE_CONF]; - uint8_t pcie_lane[MAX_PCIE_CONF]; - uint32_t lclk[MAX_PCIE_CONF]; + uint8_t pcie_gen[ALDEBARAN_MAX_PCIE_CONF]; + uint8_t pcie_lane[ALDEBARAN_MAX_PCIE_CONF]; + uint32_t lclk[ALDEBARAN_MAX_PCIE_CONF]; }; struct aldebaran_dpm_table { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 8d0d07fb25f3..8651f275bc68 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -57,6 +57,7 @@ #undef pr_debug MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin"); +MODULE_FIRMWARE("amdgpu/smu_13_0_0.bin"); #define SMU13_VOLTAGE_SCALE 4 @@ -73,11 +74,15 @@ MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin"); static const int link_width[] = {0, 1, 2, 4, 8, 12, 16}; static const int link_speed[] = {25, 50, 80, 160}; +static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **table, uint32_t *size, + uint32_t pptable_id); + int smu_v13_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; const char *chip_name; char fw_name[30]; + char ucode_prefix[30]; int err = 0; const struct smc_firmware_header_v1_0 *hdr; const struct common_firmware_header *header; @@ -89,15 +94,14 @@ int smu_v13_0_init_microcode(struct smu_context *smu) switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 2): - chip_name = "aldebaran"; + chip_name = "aldebaran_smc"; break; default: - dev_err(adev->dev, "Unsupported IP version 0x%x\n", - adev->ip_versions[MP1_HWIP][0]); - return -EINVAL; + amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix)); + chip_name = ucode_prefix; } - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name); + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", chip_name); err = request_firmware(&adev->pm.fw, fw_name, adev->dev); if (err) @@ -176,6 +180,62 @@ int smu_v13_0_load_microcode(struct smu_context *smu) if (i == adev->usec_timeout) return -ETIME; #endif + + return 0; +} + +int smu_v13_0_init_pptable_microcode(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct amdgpu_firmware_info *ucode = NULL; + uint32_t size = 0, pptable_id = 0; + int ret = 0; + void *table; + + /* doesn't need to load smu firmware in IOV mode */ + if (amdgpu_sriov_vf(adev)) + return 0; + + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + return 0; + + if (!adev->scpm_enabled) + return 0; + + /* override pptable_id from driver parameter */ + if (amdgpu_smu_pptable_id >= 0) { + pptable_id = amdgpu_smu_pptable_id; + dev_info(adev->dev, "override pptable id %d\n", pptable_id); + } else { + pptable_id = smu->smu_table.boot_values.pp_table_id; + + /* + * Temporary solution for SMU V13.0.0: + * - use 99991 signed pptable when SCPM enabled + * TODO: drop this when the pptable carried in vbios + * is ready. + */ + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)) + pptable_id = 99991; + } + + /* "pptable_id == 0" means vbios carries the pptable. */ + if (!pptable_id) + return 0; + + ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id); + if (ret) + return ret; + + smu->pptable_firmware.data = table; + smu->pptable_firmware.size = size; + + ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_PPTABLE]; + ucode->ucode_id = AMDGPU_UCODE_ID_PPTABLE; + ucode->fw = &smu->pptable_firmware; + adev->firmware.fw_size += + ALIGN(smu->pptable_firmware.size, PAGE_SIZE); + return 0; } @@ -216,6 +276,9 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) case IP_VERSION(13, 0, 2): smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE; break; + case IP_VERSION(13, 0, 0): + smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0; + break; case IP_VERSION(13, 0, 1): case IP_VERSION(13, 0, 3): case IP_VERSION(13, 0, 8): @@ -255,6 +318,21 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) return ret; } +static int smu_v13_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t ppt_offset_bytes; + const struct smc_firmware_header_v2_0 *v2; + + v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data; + + ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes); + *size = le32_to_cpu(v2->ppt_size_bytes); + *table = (uint8_t *)v2 + ppt_offset_bytes; + + return 0; +} + static int smu_v13_0_set_pptable_v2_1(struct smu_context *smu, void **table, uint32_t *size, uint32_t pptable_id) { @@ -327,6 +405,9 @@ static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **t } switch (version_minor) { + case 0: + ret = smu_v13_0_set_pptable_v2_0(smu, table, size); + break; case 1: ret = smu_v13_0_set_pptable_v2_1(smu, table, size, pptable_id); break; @@ -351,10 +432,19 @@ int smu_v13_0_setup_pptable(struct smu_context *smu) dev_info(adev->dev, "override pptable id %d\n", pptable_id); } else { pptable_id = smu->smu_table.boot_values.pp_table_id; + + /* + * Temporary solution for SMU V13.0.0: + * - use 9999 unsigned pptable when SCPM disabled + * TODO: drop this when the pptable carried in vbios + * is ready. + */ + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)) + pptable_id = 9999; } /* force using vbios pptable in sriov mode */ - if (amdgpu_sriov_vf(adev) || !pptable_id) + if ((amdgpu_sriov_vf(adev) || !pptable_id) && (amdgpu_emu_mode != 1)) ret = smu_v13_0_get_pptable_from_vbios(smu, &table, &size); else ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id); @@ -407,8 +497,17 @@ int smu_v13_0_init_smc_tables(struct smu_context *smu) } } + smu_table->combo_pptable = + kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL); + if (!smu_table->combo_pptable) { + ret = -ENOMEM; + goto err4_out; + } + return 0; +err4_out: + kfree(smu_table->boot_overdrive_table); err3_out: kfree(smu_table->overdrive_table); err2_out: @@ -425,11 +524,13 @@ int smu_v13_0_fini_smc_tables(struct smu_context *smu) struct smu_dpm_context *smu_dpm = &smu->smu_dpm; kfree(smu_table->gpu_metrics_table); + kfree(smu_table->combo_pptable); kfree(smu_table->boot_overdrive_table); kfree(smu_table->overdrive_table); kfree(smu_table->max_sustainable_clocks); kfree(smu_table->driver_pptable); smu_table->gpu_metrics_table = NULL; + smu_table->combo_pptable = NULL; smu_table->boot_overdrive_table = NULL; smu_table->overdrive_table = NULL; smu_table->max_sustainable_clocks = NULL; @@ -568,6 +669,7 @@ int smu_v13_0_get_vbios_bootup_values(struct smu_context *smu) smu_info); if (!amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev, (uint8_t **)&header)) { + if ((frev == 3) && (crev == 6)) { smu_info_v3_6 = (struct atom_smu_info_v3_6 *)header; @@ -688,7 +790,6 @@ int smu_v13_0_init_display_count(struct smu_context *smu, uint32_t count) return ret; } - int smu_v13_0_set_allowed_mask(struct smu_context *smu) { struct smu_feature *feature = &smu->smu_feature; @@ -718,6 +819,7 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable) struct amdgpu_device *adev = smu->adev; switch (adev->ip_versions[MP1_HWIP][0]) { + case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 1): case IP_VERSION(13, 0, 3): case IP_VERSION(13, 0, 5): @@ -1050,15 +1152,14 @@ smu_v13_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode) return 0; } - int -smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) +int smu_v13_0_set_fan_speed_pwm(struct smu_context *smu, + uint32_t speed) { struct amdgpu_device *adev = smu->adev; uint32_t duty100, duty; uint64_t tmp64; - if (speed > 100) - speed = 100; + speed = MIN(speed, 255); if (smu_v13_0_auto_fan_control(smu, 0)) return -EINVAL; @@ -1069,7 +1170,7 @@ smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) return -EINVAL; tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); + do_div(tmp64, 255); duty = (uint32_t)tmp64; WREG32_SOC15(THM, 0, regCG_FDO_CTRL0, @@ -1087,7 +1188,7 @@ smu_v13_0_set_fan_control_mode(struct smu_context *smu, switch (mode) { case AMD_FAN_CTRL_NONE: - ret = smu_v13_0_set_fan_speed_percent(smu, 100); + ret = smu_v13_0_set_fan_speed_pwm(smu, 255); break; case AMD_FAN_CTRL_MANUAL: ret = smu_v13_0_auto_fan_control(smu, 0); @@ -1111,8 +1212,8 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed) { struct amdgpu_device *adev = smu->adev; - int ret; uint32_t tach_period, crystal_clock_freq; + int ret; if (!speed) return -EINVAL; @@ -1128,9 +1229,7 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, CG_TACH_CTRL, TARGET_PERIOD, tach_period)); - ret = smu_v13_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM); - - return ret; + return smu_v13_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM); } int smu_v13_0_set_xgmi_pstate(struct smu_context *smu, @@ -1462,7 +1561,16 @@ int smu_v13_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c param = (clk_id & 0xffff) << 16; if (max) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max); + if (smu->adev->pm.ac_power) + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetMaxDpmFreq, + param, + max); + else + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetDcModeMaxDpmFreq, + param, + max); if (ret) goto failed; } @@ -1564,24 +1672,39 @@ int smu_v13_0_set_performance_level(struct smu_context *smu, &dpm_context->dpm_tables.uclk_table; struct smu_13_0_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table; + struct smu_13_0_dpm_table *vclk_table = + &dpm_context->dpm_tables.vclk_table; + struct smu_13_0_dpm_table *dclk_table = + &dpm_context->dpm_tables.dclk_table; + struct smu_13_0_dpm_table *fclk_table = + &dpm_context->dpm_tables.fclk_table; struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; struct amdgpu_device *adev = smu->adev; uint32_t sclk_min = 0, sclk_max = 0; uint32_t mclk_min = 0, mclk_max = 0; uint32_t socclk_min = 0, socclk_max = 0; - int ret = 0; + uint32_t vclk_min = 0, vclk_max = 0; + uint32_t dclk_min = 0, dclk_max = 0; + uint32_t fclk_min = 0, fclk_max = 0; + int ret = 0, i; switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: sclk_min = sclk_max = gfx_table->max; mclk_min = mclk_max = mem_table->max; socclk_min = socclk_max = soc_table->max; + vclk_min = vclk_max = vclk_table->max; + dclk_min = dclk_max = dclk_table->max; + fclk_min = fclk_max = fclk_table->max; break; case AMD_DPM_FORCED_LEVEL_LOW: sclk_min = sclk_max = gfx_table->min; mclk_min = mclk_max = mem_table->min; socclk_min = socclk_max = soc_table->min; + vclk_min = vclk_max = vclk_table->min; + dclk_min = dclk_max = dclk_table->min; + fclk_min = fclk_max = fclk_table->min; break; case AMD_DPM_FORCED_LEVEL_AUTO: sclk_min = gfx_table->min; @@ -1590,11 +1713,20 @@ int smu_v13_0_set_performance_level(struct smu_context *smu, mclk_max = mem_table->max; socclk_min = soc_table->min; socclk_max = soc_table->max; + vclk_min = vclk_table->min; + vclk_max = vclk_table->max; + dclk_min = dclk_table->min; + dclk_max = dclk_table->max; + fclk_min = fclk_table->min; + fclk_max = fclk_table->max; break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard; mclk_min = mclk_max = pstate_table->uclk_pstate.standard; socclk_min = socclk_max = pstate_table->socclk_pstate.standard; + vclk_min = vclk_max = pstate_table->vclk_pstate.standard; + dclk_min = dclk_max = pstate_table->dclk_pstate.standard; + fclk_min = fclk_max = pstate_table->fclk_pstate.standard; break; case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: sclk_min = sclk_max = pstate_table->gfxclk_pstate.min; @@ -1606,6 +1738,9 @@ int smu_v13_0_set_performance_level(struct smu_context *smu, sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak; mclk_min = mclk_max = pstate_table->uclk_pstate.peak; socclk_min = socclk_max = pstate_table->socclk_pstate.peak; + vclk_min = vclk_max = pstate_table->vclk_pstate.peak; + dclk_min = dclk_max = pstate_table->dclk_pstate.peak; + fclk_min = fclk_max = pstate_table->fclk_pstate.peak; break; case AMD_DPM_FORCED_LEVEL_MANUAL: case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: @@ -1615,8 +1750,17 @@ int smu_v13_0_set_performance_level(struct smu_context *smu, return -EINVAL; } - mclk_min = mclk_max = 0; - socclk_min = socclk_max = 0; + /* + * Unset those settings for SMU 13.0.2. As soft limits settings + * for those clock domains are not supported. + */ + if (smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) { + mclk_min = mclk_max = 0; + socclk_min = socclk_max = 0; + vclk_min = vclk_max = 0; + dclk_min = dclk_max = 0; + fclk_min = fclk_max = 0; + } if (sclk_min && sclk_max) { ret = smu_v13_0_set_soft_freq_limited_range(smu, @@ -1654,6 +1798,48 @@ int smu_v13_0_set_performance_level(struct smu_context *smu, pstate_table->socclk_pstate.curr.max = socclk_max; } + if (vclk_min && vclk_max) { + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + if (adev->vcn.harvest_config & (1 << i)) + continue; + ret = smu_v13_0_set_soft_freq_limited_range(smu, + i ? SMU_VCLK1 : SMU_VCLK, + vclk_min, + vclk_max); + if (ret) + return ret; + } + pstate_table->vclk_pstate.curr.min = vclk_min; + pstate_table->vclk_pstate.curr.max = vclk_max; + } + + if (dclk_min && dclk_max) { + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + if (adev->vcn.harvest_config & (1 << i)) + continue; + ret = smu_v13_0_set_soft_freq_limited_range(smu, + i ? SMU_DCLK1 : SMU_DCLK, + dclk_min, + dclk_max); + if (ret) + return ret; + } + pstate_table->dclk_pstate.curr.min = dclk_min; + pstate_table->dclk_pstate.curr.max = dclk_max; + } + + if (fclk_min && fclk_max) { + ret = smu_v13_0_set_soft_freq_limited_range(smu, + SMU_FCLK, + fclk_min, + fclk_max); + if (ret) + return ret; + + pstate_table->fclk_pstate.curr.min = fclk_min; + pstate_table->fclk_pstate.curr.max = fclk_max; + } + return ret; } @@ -1674,10 +1860,10 @@ int smu_v13_0_set_power_source(struct smu_context *smu, NULL); } -int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu, - enum smu_clk_type clk_type, - uint16_t level, - uint32_t *value) +static int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint16_t level, + uint32_t *value) { int ret = 0, clk_id = 0; uint32_t param; @@ -1703,18 +1889,14 @@ int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu, if (ret) return ret; - /* - * BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM - * now, we un-support it - */ *value = *value & 0x7fffffff; return ret; } -int smu_v13_0_get_dpm_level_count(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) +static int smu_v13_0_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) { int ret; @@ -1726,6 +1908,44 @@ int smu_v13_0_get_dpm_level_count(struct smu_context *smu, return ret; } +static int smu_v13_0_get_fine_grained_status(struct smu_context *smu, + enum smu_clk_type clk_type, + bool *is_fine_grained_dpm) +{ + int ret = 0, clk_id = 0; + uint32_t param; + uint32_t value; + + if (!is_fine_grained_dpm) + return -EINVAL; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) + return 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + param = (uint32_t)(((clk_id & 0xffff) << 16) | 0xff); + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetDpmFreqByIndex, + param, + &value); + if (ret) + return ret; + + /* + * BIT31: 1 - Fine grained DPM, 0 - Dicrete DPM + * now, we un-support it + */ + *is_fine_grained_dpm = value & 0x80000000; + + return 0; +} + int smu_v13_0_set_single_dpm_table(struct smu_context *smu, enum smu_clk_type clk_type, struct smu_13_0_dpm_table *single_dpm_table) @@ -1742,6 +1962,16 @@ int smu_v13_0_set_single_dpm_table(struct smu_context *smu, return ret; } + if (smu->adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 2)) { + ret = smu_v13_0_get_fine_grained_status(smu, + clk_type, + &single_dpm_table->is_fine_grained); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get fine grained status!\n", __func__); + return ret; + } + } + for (i = 0; i < single_dpm_table->count; i++) { ret = smu_v13_0_get_dpm_freq_by_index(smu, clk_type, @@ -1843,3 +2073,30 @@ int smu_v13_0_get_current_pcie_link_speed(struct smu_context *smu) return link_speed[speed_level]; } +int smu_v13_0_set_vcn_enable(struct smu_context *smu, + bool enable) +{ + struct amdgpu_device *adev = smu->adev; + int i, ret = 0; + + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + if (adev->vcn.harvest_config & (1 << i)) + continue; + + ret = smu_cmn_send_smc_msg_with_param(smu, enable ? + SMU_MSG_PowerUpVcn : SMU_MSG_PowerDownVcn, + i << 16U, NULL); + if (ret) + return ret; + } + + return ret; +} + +int smu_v13_0_set_jpeg_enable(struct smu_context *smu, + bool enable) +{ + return smu_cmn_send_smc_msg_with_param(smu, enable ? + SMU_MSG_PowerUpJpeg : SMU_MSG_PowerDownJpeg, + 0, NULL); +} 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 new file mode 100644 index 000000000000..e4bc8d85b151 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -0,0 +1,1365 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define SWSMU_CODE_LAYER_L2 + +#include +#include +#include +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" +#include "smu_v13_0.h" +#include "smu13_driver_if_v13_0_0.h" +#include "soc15_common.h" +#include "atom.h" +#include "smu_v13_0_0_ppt.h" +#include "smu_v13_0_0_pptable.h" +#include "smu_v13_0_0_ppsmc.h" +#include "nbio/nbio_4_3_0_offset.h" +#include "nbio/nbio_4_3_0_sh_mask.h" +#include "mp/mp_13_0_0_offset.h" +#include "mp/mp_13_0_0_sh_mask.h" + +#include "asic_reg/mp/mp_13_0_0_sh_mask.h" +#include "smu_cmn.h" +#include "amdgpu_ras.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) + +#define FEATURE_MASK(feature) (1ULL << feature) +#define SMC_DPM_FEATURE ( \ + FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)) + +#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000 + +static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = { + MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), + MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), + MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), + MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0), + MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0), + MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0), + MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), + MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1), + MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1), + MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1), + MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), + MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetRunningSmuFeaturesLow, 1), + MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetRunningSmuFeaturesHigh, 1), + MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), + MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), + MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), + MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), + MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), + MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), + MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), + MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1), + MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), + MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), + MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), + MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), + MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), + MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), + MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), + MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), + MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), + MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0), + MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), + MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), + MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), + MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), + MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), +}; + +static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = { + CLK_MAP(GFXCLK, PPCLK_GFXCLK), + CLK_MAP(SCLK, PPCLK_GFXCLK), + CLK_MAP(SOCCLK, PPCLK_SOCCLK), + CLK_MAP(FCLK, PPCLK_FCLK), + CLK_MAP(UCLK, PPCLK_UCLK), + CLK_MAP(MCLK, PPCLK_UCLK), + CLK_MAP(VCLK, PPCLK_VCLK_0), + CLK_MAP(VCLK1, PPCLK_VCLK_1), + CLK_MAP(DCLK, PPCLK_DCLK_0), + CLK_MAP(DCLK1, PPCLK_DCLK_1), +}; + +static struct cmn2asic_mapping smu_v13_0_0_feature_mask_map[SMU_FEATURE_COUNT] = { + [SMU_FEATURE_DPM_GFXCLK_BIT] = {1, FEATURE_DPM_GFXCLK_BIT}, + [SMU_FEATURE_DPM_UCLK_BIT] = {1, FEATURE_DPM_UCLK_BIT}, + [SMU_FEATURE_DPM_FCLK_BIT] = {1, FEATURE_DPM_FCLK_BIT}, + [SMU_FEATURE_DPM_SOCCLK_BIT] = {1, FEATURE_DPM_SOCCLK_BIT}, + [SMU_FEATURE_DPM_LINK_BIT] = {1, FEATURE_DPM_LINK_BIT}, + [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT}, + [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT}, + [SMU_FEATURE_FAN_CONTROL_BIT] = {1, FEATURE_FAN_CONTROL_BIT}, +}; + +static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = { + TAB_MAP(PPTABLE), + TAB_MAP(WATERMARKS), + TAB_MAP(AVFS_PSM_DEBUG), + TAB_MAP(PMSTATUSLOG), + TAB_MAP(SMU_METRICS), + TAB_MAP(DRIVER_SMU_CONFIG), + TAB_MAP(ACTIVITY_MONITOR_COEFF), + [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE}, +}; + +static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { + PWR_MAP(AC), + PWR_MAP(DC), +}; + +static struct cmn2asic_mapping smu_v13_0_0_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), +}; + +static const uint8_t smu_v13_0_0_throttler_map[] = { + [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), + [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), + [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT), + [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT), + [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), + [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), + [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT), + [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT), + [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), + [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), + [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), + [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), + [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT), + [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT), + [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT), + [THROTTLER_GFX_APCC_PLUS_BIT] = (SMU_THROTTLER_APCC_BIT), + [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), +}; + +static int +smu_v13_0_0_get_allowed_feature_mask(struct smu_context *smu, + uint32_t *feature_mask, uint32_t num) +{ + struct amdgpu_device *adev = smu->adev; + + if (num > 2) + return -EINVAL; + + memset(feature_mask, 0, sizeof(uint32_t) * num); + + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT); + + if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) { + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT); + } + + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT); + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT); + + if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) && + (adev->pg_flags & AMD_PG_SUPPORT_MMHUB)) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT); + + if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); + + if (adev->pm.pp_feature & PP_GFXOFF_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT); + + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT); + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT); + + return 0; +} + +static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_13_0_0_powerplay_table *powerplay_table = + table_context->power_play_table; + struct smu_baco_context *smu_baco = &smu->smu_baco; + + if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC) + smu->dc_controlled_by_gpio = true; + + if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_BACO || + powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO) + smu_baco->platform_support = true; + + table_context->thermal_controller_type = + powerplay_table->thermal_controller_type; + + /* + * Instead of having its own buffer space and get overdrive_table copied, + * smu->od_settings just points to the actual overdrive_table + */ + smu->od_settings = &powerplay_table->overdrive_table; + + return 0; +} + +static int smu_v13_0_0_store_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_13_0_0_powerplay_table *powerplay_table = + table_context->power_play_table; + + memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, + sizeof(PPTable_t)); + + return 0; +} + +#ifndef atom_smc_dpm_info_table_13_0_0 +struct atom_smc_dpm_info_table_13_0_0 { + struct atom_common_table_header table_header; + BoardTable_t BoardTable; +}; +#endif + +static int smu_v13_0_0_append_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + struct atom_smc_dpm_info_table_13_0_0 *smc_dpm_table; + BoardTable_t *BoardTable = &smc_pptable->BoardTable; + int index, ret; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + smc_dpm_info); + + ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL, + (uint8_t **)&smc_dpm_table); + if (ret) + return ret; + + memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t)); + + return 0; +} + +static int smu_v13_0_0_setup_pptable(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + void *combo_pptable = smu_table->combo_pptable; + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + /* + * With SCPM enabled, the pptable used will be signed. It cannot + * be used directly by driver. To get the raw pptable, we need to + * rely on the combo pptable(and its revelant SMU message). + */ + if (adev->scpm_enabled) { + ret = smu_cmn_get_combo_pptable(smu); + if (ret) + return ret; + + smu->smu_table.power_play_table = combo_pptable; + smu->smu_table.power_play_table_size = sizeof(struct smu_13_0_0_powerplay_table); + } else { + ret = smu_v13_0_setup_pptable(smu); + if (ret) + return ret; + } + + ret = smu_v13_0_0_store_powerplay_table(smu); + if (ret) + return ret; + + /* + * With SCPM enabled, the operation below will be handled + * by PSP. Driver involvment is unnecessary and useless. + */ + if (!adev->scpm_enabled) { + ret = smu_v13_0_0_append_powerplay_table(smu); + if (ret) + return ret; + } + + ret = smu_v13_0_0_check_powerplay_table(smu); + if (ret) + return ret; + + return ret; +} + +static int smu_v13_0_0_tables_init(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, + sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); + if (!smu_table->metrics_table) + goto err0_out; + smu_table->metrics_time = 0; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); + if (!smu_table->watermarks_table) + goto err2_out; + + return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; +} + +static int smu_v13_0_0_allocate_dpm_context(struct smu_context *smu) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + + smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context), + GFP_KERNEL); + if (!smu_dpm->dpm_context) + return -ENOMEM; + + smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context); + + return 0; +} + +static int smu_v13_0_0_init_smc_tables(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_v13_0_0_tables_init(smu); + if (ret) + return ret; + + ret = smu_v13_0_0_allocate_dpm_context(smu); + if (ret) + return ret; + + return smu_v13_0_init_smc_tables(smu); +} + +static int smu_v13_0_0_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + SkuTable_t *skutable = &pptable->SkuTable; + struct smu_13_0_dpm_table *dpm_table; + struct smu_13_0_pcie_table *pcie_table; + uint32_t link_level; + int ret = 0; + + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v13_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v13_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v13_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* fclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.fclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { + ret = smu_v13_0_set_single_dpm_table(smu, + SMU_FCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* vclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) { + ret = smu_v13_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* dclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) { + ret = smu_v13_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* lclk dpm table setup */ + pcie_table = &dpm_context->dpm_tables.pcie_table; + pcie_table->num_of_link_levels = 0; + for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) { + if (!skutable->PcieGenSpeed[link_level] && + !skutable->PcieLaneCount[link_level] && + !skutable->LclkFreq[link_level]) + continue; + + pcie_table->pcie_gen[pcie_table->num_of_link_levels] = + skutable->PcieGenSpeed[link_level]; + pcie_table->pcie_lane[pcie_table->num_of_link_levels] = + skutable->PcieLaneCount[link_level]; + pcie_table->clk_freq[pcie_table->num_of_link_levels] = + skutable->LclkFreq[link_level]; + pcie_table->num_of_link_levels++; + } + + return 0; +} + +static bool smu_v13_0_0_is_dpm_running(struct smu_context *smu) +{ + int ret = 0; + uint64_t feature_enabled; + + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); + if (ret) + return false; + + return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static void smu_v13_0_0_dump_pptable(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + SkuTable_t *skutable = &pptable->SkuTable; + + dev_info(smu->adev->dev, "Dumped PPTable:\n"); + + dev_info(smu->adev->dev, "Version = 0x%08x\n", skutable->Version); + dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", skutable->FeaturesToRun[0]); + dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", skutable->FeaturesToRun[1]); +} + +static int smu_v13_0_0_system_features_control(struct smu_context *smu, + bool en) +{ + return smu_v13_0_system_features_control(smu, en); +} + +static uint32_t smu_v13_0_get_throttler_status(SmuMetrics_t *metrics) +{ + uint32_t throttler_status = 0; + int i; + + for (i = 0; i < THROTTLER_COUNT; i++) + throttler_status |= + (metrics->ThrottlingPercentage[i] ? 1U << i : 0); + + return throttler_status; +} + +#define SMU_13_0_0_BUSY_THRESHOLD 15 +static int smu_v13_0_0_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table = &smu->smu_table; + SmuMetrics_t *metrics = + &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics); + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) + return ret; + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK_0]; + break; + case METRICS_CURR_VCLK1: + *value = metrics->CurrClock[PPCLK_VCLK_1]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK_0]; + break; + case METRICS_CURR_DCLK1: + *value = metrics->CurrClock[PPCLK_DCLK_1]; + break; + case METRICS_CURR_FCLK: + *value = metrics->CurrClock[PPCLK_FCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD) + *value = metrics->AverageGfxclkFrequencyPostDs; + else + *value = metrics->AverageGfxclkFrequencyPreDs; + break; + case METRICS_AVERAGE_FCLK: + if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD) + *value = metrics->AverageFclkFrequencyPostDs; + else + *value = metrics->AverageFclkFrequencyPreDs; + break; + case METRICS_AVERAGE_UCLK: + if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD) + *value = metrics->AverageMemclkFrequencyPostDs; + else + *value = metrics->AverageMemclkFrequencyPreDs; + break; + case METRICS_AVERAGE_VCLK: + *value = metrics->AverageVclk0Frequency; + break; + case METRICS_AVERAGE_DCLK: + *value = metrics->AverageDclk0Frequency; + break; + case METRICS_AVERAGE_VCLK1: + *value = metrics->AverageVclk1Frequency; + break; + case METRICS_AVERAGE_DCLK1: + *value = metrics->AverageDclk1Frequency; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->AvgTemperature[TEMP_EDGE] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->AvgTemperature[TEMP_HOTSPOT] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->AvgTemperature[TEMP_MEM] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->AvgTemperature[TEMP_VR_GFX] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->AvgTemperature[TEMP_VR_SOC] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = smu_v13_0_get_throttler_status(metrics); + break; + case METRICS_CURR_FANSPEED: + *value = metrics->AvgFanRpm; + break; + case METRICS_CURR_FANPWM: + *value = metrics->AvgFanPwm; + break; + case METRICS_VOLTAGE_VDDGFX: + *value = metrics->AvgVoltage[SVI_PLANE_GFX]; + break; + case METRICS_PCIE_RATE: + *value = metrics->PcieRate; + break; + case METRICS_PCIE_WIDTH: + *value = metrics->PcieWidth; + break; + default: + *value = UINT_MAX; + break; + } + + return ret; +} + +static int smu_v13_0_0_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, + uint32_t *size) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + int ret = 0; + + switch (sensor) { + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: + *(uint16_t *)data = smc_pptable->SkuTable.FanMaximumRpm; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_AVERAGE_UCLK, + (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXCLK, + (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDGFX, + (uint32_t *)data); + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int smu_v13_0_0_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + int clk_id = 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return -EINVAL; + + switch (clk_id) { + case PPCLK_GFXCLK: + member_type = METRICS_AVERAGE_GFXCLK; + break; + case PPCLK_UCLK: + member_type = METRICS_AVERAGE_UCLK; + break; + case PPCLK_FCLK: + member_type = METRICS_AVERAGE_FCLK; + break; + case PPCLK_SOCCLK: + member_type = METRICS_CURR_SOCCLK; + break; + case PPCLK_VCLK_0: + member_type = METRICS_AVERAGE_VCLK; + break; + case PPCLK_DCLK_0: + member_type = METRICS_AVERAGE_DCLK; + break; + case PPCLK_VCLK_1: + member_type = METRICS_AVERAGE_VCLK1; + break; + case PPCLK_DCLK_1: + member_type = METRICS_AVERAGE_DCLK1; + break; + default: + return -EINVAL; + } + + return smu_v13_0_0_get_smu_metrics_data(smu, + member_type, + value); +} + +static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + char *buf) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context; + struct smu_13_0_dpm_table *single_dpm_table; + struct smu_13_0_pcie_table *pcie_table; + uint32_t gen_speed, lane_width; + int i, curr_freq, size = 0; + int ret = 0; + + smu_cmn_get_sysfs_buf(&buf, &size); + + if (amdgpu_ras_intr_triggered()) { + size += sysfs_emit_at(buf, size, "unavailable\n"); + return size; + } + + switch (clk_type) { + case SMU_SCLK: + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); + break; + case SMU_MCLK: + single_dpm_table = &(dpm_context->dpm_tables.uclk_table); + break; + case SMU_SOCCLK: + single_dpm_table = &(dpm_context->dpm_tables.soc_table); + break; + case SMU_FCLK: + single_dpm_table = &(dpm_context->dpm_tables.fclk_table); + break; + case SMU_VCLK: + case SMU_VCLK1: + single_dpm_table = &(dpm_context->dpm_tables.vclk_table); + break; + case SMU_DCLK: + case SMU_DCLK1: + single_dpm_table = &(dpm_context->dpm_tables.dclk_table); + break; + default: + break; + } + + switch (clk_type) { + case SMU_SCLK: + case SMU_MCLK: + case SMU_SOCCLK: + case SMU_FCLK: + case SMU_VCLK: + case SMU_VCLK1: + case SMU_DCLK: + case SMU_DCLK1: + ret = smu_v13_0_0_get_current_clk_freq_by_table(smu, clk_type, &curr_freq); + if (ret) { + dev_err(smu->adev->dev, "Failed to get current clock freq!"); + return ret; + } + + if (single_dpm_table->is_fine_grained) { + /* + * For fine grained dpms, there are only two dpm levels: + * - level 0 -> min clock freq + * - level 1 -> max clock freq + * And the current clock frequency can be any value between them. + * So, if the current clock frequency is not at level 0 or level 1, + * we will fake it as three dpm levels: + * - level 0 -> min clock freq + * - level 1 -> current actual clock freq + * - level 2 -> max clock freq + */ + if ((single_dpm_table->dpm_levels[0].value != curr_freq) && + (single_dpm_table->dpm_levels[1].value != curr_freq)) { + size += sysfs_emit_at(buf, size, "0: %uMhz\n", + single_dpm_table->dpm_levels[0].value); + size += sysfs_emit_at(buf, size, "1: %uMhz *\n", + curr_freq); + size += sysfs_emit_at(buf, size, "2: %uMhz\n", + single_dpm_table->dpm_levels[1].value); + } else { + size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", + single_dpm_table->dpm_levels[0].value, + single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : ""); + size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", + single_dpm_table->dpm_levels[1].value, + single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : ""); + } + } else { + for (i = 0; i < single_dpm_table->count; i++) + size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", + i, single_dpm_table->dpm_levels[i].value, + single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : ""); + } + break; + case SMU_PCIE: + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_PCIE_RATE, + &gen_speed); + if (ret) + return ret; + + ret = smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_PCIE_WIDTH, + &lane_width); + if (ret) + return ret; + + pcie_table = &(dpm_context->dpm_tables.pcie_table); + for (i = 0; i < pcie_table->num_of_link_levels; i++) + size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i, + (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," : + (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," : + (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," : + (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "", + (pcie_table->pcie_lane[i] == 1) ? "x1" : + (pcie_table->pcie_lane[i] == 2) ? "x2" : + (pcie_table->pcie_lane[i] == 3) ? "x4" : + (pcie_table->pcie_lane[i] == 4) ? "x8" : + (pcie_table->pcie_lane[i] == 5) ? "x12" : + (pcie_table->pcie_lane[i] == 6) ? "x16" : "", + pcie_table->clk_freq[i], + (gen_speed == pcie_table->pcie_gen[i]) && + (lane_width == pcie_table->pcie_lane[i]) ? + "*" : ""); + break; + + default: + break; + } + + return size; +} + +static int smu_v13_0_0_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t mask) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context; + struct smu_13_0_dpm_table *single_dpm_table; + uint32_t soft_min_level, soft_max_level; + uint32_t min_freq, max_freq; + int ret = 0; + + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); + break; + case SMU_MCLK: + case SMU_UCLK: + single_dpm_table = &(dpm_context->dpm_tables.uclk_table); + break; + case SMU_SOCCLK: + single_dpm_table = &(dpm_context->dpm_tables.soc_table); + break; + case SMU_FCLK: + single_dpm_table = &(dpm_context->dpm_tables.fclk_table); + break; + case SMU_VCLK: + case SMU_VCLK1: + single_dpm_table = &(dpm_context->dpm_tables.vclk_table); + break; + case SMU_DCLK: + case SMU_DCLK1: + single_dpm_table = &(dpm_context->dpm_tables.dclk_table); + break; + default: + break; + } + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_SOCCLK: + case SMU_FCLK: + case SMU_VCLK: + case SMU_VCLK1: + case SMU_DCLK: + case SMU_DCLK1: + if (single_dpm_table->is_fine_grained) { + /* There is only 2 levels for fine grained DPM */ + soft_max_level = (soft_max_level >= 1 ? 1 : 0); + soft_min_level = (soft_min_level >= 1 ? 1 : 0); + } else { + if ((soft_max_level >= single_dpm_table->count) || + (soft_min_level >= single_dpm_table->count)) + return -EINVAL; + } + + min_freq = single_dpm_table->dpm_levels[soft_min_level].value; + max_freq = single_dpm_table->dpm_levels[soft_max_level].value; + + ret = smu_v13_0_set_soft_freq_limited_range(smu, + clk_type, + min_freq, + max_freq); + break; + case SMU_DCEFCLK: + case SMU_PCIE: + default: + break; + } + + return ret; +} + +static int smu_v13_0_0_update_pcie_parameters(struct smu_context *smu, + uint32_t pcie_gen_cap, + uint32_t pcie_width_cap) +{ + struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_13_0_pcie_table *pcie_table = + &dpm_context->dpm_tables.pcie_table; + uint32_t smu_pcie_arg; + int ret, i; + + for (i = 0; i < pcie_table->num_of_link_levels; i++) { + if (pcie_table->pcie_gen[i] > pcie_gen_cap) + pcie_table->pcie_gen[i] = pcie_gen_cap; + if (pcie_table->pcie_lane[i] > pcie_width_cap) + pcie_table->pcie_lane[i] = pcie_width_cap; + + smu_pcie_arg = i << 16; + smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; + smu_pcie_arg |= pcie_table->pcie_lane[i]; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_OverridePcieParameters, + smu_pcie_arg, + NULL); + if (ret) + return ret; + } + + return 0; +} + +static const struct smu_temperature_range smu13_thermal_policy[] = { + {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, + { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, +}; + +static int smu_v13_0_0_get_thermal_temperature_range(struct smu_context *smu, + struct smu_temperature_range *range) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_13_0_0_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; + + if (!range) + return -EINVAL; + + memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range)); + + range->max = pptable->SkuTable.TemperatureLimit[TEMP_EDGE] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->edge_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_MEM] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; + + return 0; +} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_3 *gpu_metrics = + (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; + SmuMetricsExternal_t metrics_ext; + SmuMetrics_t *metrics = &metrics_ext.SmuMetrics; + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, + &metrics_ext, + true); + if (ret) + return ret; + + smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); + + gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE]; + gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT]; + gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM]; + gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX]; + gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC]; + gpu_metrics->temperature_vrmem = MAX(metrics->AvgTemperature[TEMP_VR_MEM0], + metrics->AvgTemperature[TEMP_VR_MEM1]); + + gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics->AverageUclkActivity; + gpu_metrics->average_mm_activity = MAX(metrics->Vcn0ActivityPercentage, + metrics->Vcn1ActivityPercentage); + + gpu_metrics->average_socket_power = metrics->AverageSocketPower; + gpu_metrics->energy_accumulator = metrics->EnergyAccumulator; + + if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD) + gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs; + else + gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs; + + if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD) + gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs; + else + gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs; + + gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency; + gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency; + gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency; + gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency; + + gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0]; + gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0]; + gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1]; + gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1]; + + gpu_metrics->throttle_status = + smu_v13_0_get_throttler_status(metrics); + gpu_metrics->indep_throttle_status = + smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status, + smu_v13_0_0_throttler_map); + + gpu_metrics->current_fan_speed = metrics->AvgFanRpm; + + gpu_metrics->pcie_link_width = metrics->PcieWidth; + gpu_metrics->pcie_link_speed = metrics->PcieRate; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); + + gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_GFX]; + gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_SOC]; + gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VMEMP]; + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_3); +} + +static int smu_v13_0_0_populate_umd_state_clk(struct smu_context *smu) +{ + struct smu_13_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_13_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_13_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_13_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_13_0_dpm_table *vclk_table = + &dpm_context->dpm_tables.vclk_table; + struct smu_13_0_dpm_table *dclk_table = + &dpm_context->dpm_tables.dclk_table; + struct smu_13_0_dpm_table *fclk_table = + &dpm_context->dpm_tables.fclk_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.peak = gfx_table->max; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; + + pstate_table->vclk_pstate.min = vclk_table->min; + pstate_table->vclk_pstate.peak = vclk_table->max; + + pstate_table->dclk_pstate.min = dclk_table->min; + pstate_table->dclk_pstate.peak = dclk_table->max; + + pstate_table->fclk_pstate.min = fclk_table->min; + pstate_table->fclk_pstate.peak = fclk_table->max; + + /* + * For now, just use the mininum clock frequency. + * TODO: update them when the real pstate settings available + */ + pstate_table->gfxclk_pstate.standard = gfx_table->min; + pstate_table->uclk_pstate.standard = mem_table->min; + pstate_table->socclk_pstate.standard = soc_table->min; + pstate_table->vclk_pstate.standard = vclk_table->min; + pstate_table->dclk_pstate.standard = dclk_table->min; + pstate_table->fclk_pstate.standard = fclk_table->min; + + return 0; +} + +static void smu_v13_0_0_get_unique_id(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + SmuMetrics_t *metrics = + &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics); + struct amdgpu_device *adev = smu->adev; + uint32_t upper32 = 0, lower32 = 0; + int ret; + + ret = smu_cmn_get_metrics_table(smu, NULL, false); + if (ret) + goto out; + + upper32 = metrics->PublicSerialNumberUpper; + lower32 = metrics->PublicSerialNumberLower; + +out: + adev->unique_id = ((uint64_t)upper32 << 32) | lower32; + if (adev->serial[0] == '\0') + sprintf(adev->serial, "%016llx", adev->unique_id); +} + +static int smu_v13_0_0_get_fan_speed_pwm(struct smu_context *smu, + uint32_t *speed) +{ + if (!speed) + return -EINVAL; + + return smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_CURR_FANPWM, + speed); +} + +static int smu_v13_0_0_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed) +{ + if (!speed) + return -EINVAL; + + return smu_v13_0_0_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); +} + +static int smu_v13_0_0_enable_mgpu_fan_boost(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + SkuTable_t *skutable = &pptable->SkuTable; + + /* + * Skip the MGpuFanBoost setting for those ASICs + * which do not support it + */ + if (skutable->MGpuAcousticLimitRpmThreshold == 0) + return 0; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + 0, + NULL); +} + +static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { + .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask, + .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, + .is_dpm_running = smu_v13_0_0_is_dpm_running, + .dump_pptable = smu_v13_0_0_dump_pptable, + .init_microcode = smu_v13_0_init_microcode, + .load_microcode = smu_v13_0_load_microcode, + .init_smc_tables = smu_v13_0_0_init_smc_tables, + .init_power = smu_v13_0_init_power, + .fini_power = smu_v13_0_fini_power, + .check_fw_status = smu_v13_0_check_fw_status, + .setup_pptable = smu_v13_0_0_setup_pptable, + .check_fw_version = smu_v13_0_check_fw_version, + .write_pptable = smu_cmn_write_pptable, + .set_driver_table_location = smu_v13_0_set_driver_table_location, + .system_features_control = smu_v13_0_0_system_features_control, + .set_allowed_mask = smu_v13_0_set_allowed_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .dpm_set_vcn_enable = smu_v13_0_set_vcn_enable, + .dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable, + .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq, + .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values, + .read_sensor = smu_v13_0_0_read_sensor, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .print_clk_levels = smu_v13_0_0_print_clk_levels, + .force_clk_levels = smu_v13_0_0_force_clk_levels, + .update_pcie_parameters = smu_v13_0_0_update_pcie_parameters, + .get_thermal_temperature_range = smu_v13_0_0_get_thermal_temperature_range, + .register_irq_handler = smu_v13_0_register_irq_handler, + .enable_thermal_alert = smu_v13_0_enable_thermal_alert, + .disable_thermal_alert = smu_v13_0_disable_thermal_alert, + .notify_memory_pool_location = smu_v13_0_notify_memory_pool_location, + .get_gpu_metrics = smu_v13_0_0_get_gpu_metrics, + .set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range, + .init_pptable_microcode = smu_v13_0_init_pptable_microcode, + .populate_umd_state_clk = smu_v13_0_0_populate_umd_state_clk, + .set_performance_level = smu_v13_0_set_performance_level, + .gfx_off_control = smu_v13_0_gfx_off_control, + .get_unique_id = smu_v13_0_0_get_unique_id, + .get_fan_speed_pwm = smu_v13_0_0_get_fan_speed_pwm, + .get_fan_speed_rpm = smu_v13_0_0_get_fan_speed_rpm, + .set_fan_speed_pwm = smu_v13_0_set_fan_speed_pwm, + .set_fan_speed_rpm = smu_v13_0_set_fan_speed_rpm, + .get_fan_control_mode = smu_v13_0_get_fan_control_mode, + .set_fan_control_mode = smu_v13_0_set_fan_control_mode, + .enable_mgpu_fan_boost = smu_v13_0_0_enable_mgpu_fan_boost, +}; + +void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu) +{ + smu->ppt_funcs = &smu_v13_0_0_ppt_funcs; + smu->message_map = smu_v13_0_0_message_map; + smu->clock_map = smu_v13_0_0_clk_map; + smu->feature_map = smu_v13_0_0_feature_mask_map; + smu->table_map = smu_v13_0_0_table_map; + smu->pwr_src_map = smu_v13_0_0_pwr_src_map; + smu->workload_map = smu_v13_0_0_workload_map; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h new file mode 100644 index 000000000000..ede494856dbd --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h @@ -0,0 +1,28 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SMU_V13_0_0_PPT_H__ +#define __SMU_V13_0_0_PPT_H__ + +extern void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu); + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 622881ab34c7..1274c794a776 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -581,6 +581,17 @@ bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, case SMU_SOCCLK: feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; break; + case SMU_VCLK: + case SMU_VCLK1: + feature_id = SMU_FEATURE_DPM_VCLK_BIT; + break; + case SMU_DCLK: + case SMU_DCLK1: + feature_id = SMU_FEATURE_DPM_DCLK_BIT; + break; + case SMU_FCLK: + feature_id = SMU_FEATURE_DPM_FCLK_BIT; + break; default: return true; } -- cgit From d6b9a91f5d1bd9f8027dbab1119a3a51f0afed26 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 7 Apr 2022 09:51:41 -0400 Subject: drm/amdgpu: add FGCG support Add the CG flag for Fine Grained Clock Gating. Reviewed-by: Hawking Zhang Signed-off-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/amd_shared.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 9086df53660c..9ae4060a9d0f 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -148,6 +148,7 @@ enum amd_powergating_state { #define AMD_CG_SUPPORT_ATHUB_MGCG (1ULL << 29) #define AMD_CG_SUPPORT_JPEG_MGCG (1ULL << 30) #define AMD_CG_SUPPORT_GFX_FGCG (1ULL << 31) +#define AMD_CG_SUPPORT_REPEATER_FGCG (1ULL << 32) /* PG flags */ #define AMD_PG_SUPPORT_GFX_PG (1 << 0) #define AMD_PG_SUPPORT_GFX_SMG (1 << 1) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 05f1ac355ba8..e92d07f88048 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -66,6 +66,7 @@ static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"}, {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"}, {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"}, {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"}, -- cgit From 915b5ce774b5d59f90f970f97a7295f12cf898bc Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 11 Apr 2022 14:39:59 +0800 Subject: drm/amdgpu: enable more GFX clockgating features for GC 11.0.0 Support more GFX clockgating features(3D_CGCG, 3D_CGLS, MGCG, FGCG and PERF_CLK). Signed-off-by: Evan Quan Reviewed-by: Likun Gao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 100 ++++++++++++++++++++++++++----- drivers/gpu/drm/amd/amdgpu/soc21.c | 5 ++ drivers/gpu/drm/amd/include/amd_shared.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 2 +- 4 files changed, 93 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 60362bd7311f..b598cac52ede 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4883,6 +4883,44 @@ static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev) WREG32_SOC15(GC, 0, regRLC_SAFE_MODE, RLC_SAFE_MODE__CMD_MASK); } +static void gfx_v11_0_update_perf_clk(struct amdgpu_device *adev, + bool enable) +{ + uint32_t def, data; + + if (!(adev->cg_flags & AMD_CG_SUPPORT_GFX_PERF_CLK)) + return; + + def = data = RREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE); + + if (enable) + data &= ~RLC_CGTT_MGCG_OVERRIDE__PERFMON_CLOCK_STATE_MASK; + else + data |= RLC_CGTT_MGCG_OVERRIDE__PERFMON_CLOCK_STATE_MASK; + + if (def != data) + WREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE, data); +} + +static void gfx_v11_0_update_sram_fgcg(struct amdgpu_device *adev, + bool enable) +{ + uint32_t def, data; + + if (!(adev->cg_flags & AMD_CG_SUPPORT_GFX_FGCG)) + return; + + def = data = RREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE); + + if (enable) + data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK; + else + data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK; + + if (def != data) + WREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE, data); +} + static void gfx_v11_0_update_repeater_fgcg(struct amdgpu_device *adev, bool enable) { @@ -4902,19 +4940,40 @@ static void gfx_v11_0_update_repeater_fgcg(struct amdgpu_device *adev, WREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE, data); } -#if 0 static void gfx_v11_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, - bool enable) + bool enable) { - /* TODO: add power related feature later. */ -} + uint32_t data, def; -static void gfx_v11_0_update_3d_clock_gating(struct amdgpu_device *adev, - bool enable) -{ - /* TODO: add power related feature later. */ + if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS))) + return; + + /* It is disabled by HW by default */ + if (enable) { + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG) { + /* 1 - RLC_CGTT_MGCG_OVERRIDE */ + def = data = RREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE); + + data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK); + + if (def != data) + WREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE, data); + } + } else { + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG) { + def = data = RREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE); + + data |= (RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK); + + if (def != data) + WREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE, data); + } + } } -#endif static void gfx_v11_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev, bool enable) @@ -5045,8 +5104,14 @@ static int gfx_v11_0_update_gfx_clock_gating(struct amdgpu_device *adev, gfx_v11_0_update_coarse_grain_clock_gating(adev, enable); + gfx_v11_0_update_medium_grain_clock_gating(adev, enable); + gfx_v11_0_update_repeater_fgcg(adev, enable); + gfx_v11_0_update_sram_fgcg(adev, enable); + + gfx_v11_0_update_perf_clk(adev, enable); + if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGLS | @@ -5139,16 +5204,23 @@ static void gfx_v11_0_get_clockgating_state(void *handle, u64 *flags) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; - /* AMD_CG_SUPPORT_GFX_FGCG */ - data = RREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE); - if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK)) - *flags |= AMD_CG_SUPPORT_GFX_FGCG; - /* AMD_CG_SUPPORT_GFX_MGCG */ data = RREG32_SOC15(GC, 0, regRLC_CGTT_MGCG_OVERRIDE); if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK)) *flags |= AMD_CG_SUPPORT_GFX_MGCG; + /* AMD_CG_SUPPORT_REPEATER_FGCG */ + if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_REPEATER_FGCG_OVERRIDE_MASK)) + *flags |= AMD_CG_SUPPORT_REPEATER_FGCG; + + /* AMD_CG_SUPPORT_GFX_FGCG */ + if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK)) + *flags |= AMD_CG_SUPPORT_GFX_FGCG; + + /* AMD_CG_SUPPORT_GFX_PERF_CLK */ + if (!(data & RLC_CGTT_MGCG_OVERRIDE__PERFMON_CLOCK_STATE_MASK)) + *flags |= AMD_CG_SUPPORT_GFX_PERF_CLK; + /* AMD_CG_SUPPORT_GFX_CGCG */ data = RREG32_SOC15(GC, 0, regRLC_CGCG_CGLS_CTRL); if (data & RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 9e689a1f2ea4..c618f2b8ece8 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -526,7 +526,12 @@ static int soc21_common_early_init(void *handle) case IP_VERSION(11, 0, 0): adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_3D_CGCG | + AMD_CG_SUPPORT_GFX_3D_CGLS | + AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_REPEATER_FGCG | + AMD_CG_SUPPORT_GFX_FGCG | + AMD_CG_SUPPORT_GFX_PERF_CLK | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = AMD_PG_SUPPORT_VCN | diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 9ae4060a9d0f..bcdf7453a403 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -149,6 +149,7 @@ enum amd_powergating_state { #define AMD_CG_SUPPORT_JPEG_MGCG (1ULL << 30) #define AMD_CG_SUPPORT_GFX_FGCG (1ULL << 31) #define AMD_CG_SUPPORT_REPEATER_FGCG (1ULL << 32) +#define AMD_CG_SUPPORT_GFX_PERF_CLK (1ULL << 33) /* PG flags */ #define AMD_PG_SUPPORT_GFX_PG (1 << 0) #define AMD_PG_SUPPORT_GFX_SMG (1 << 1) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index e92d07f88048..6e40e9ba9ff0 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -67,7 +67,7 @@ static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"}, {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"}, - + {AMD_CG_SUPPORT_GFX_PERF_CLK, "Perfmon Clock Gating"}, {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"}, {0, NULL}, -- cgit From 3929f3381e9cc61f73070377825b62667243bfb4 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Tue, 12 Apr 2022 17:07:24 +0800 Subject: drm/amd/pm: enable pp_dpm_vclk/dclk interface for smu_v13_0_7 enable pp_dpm_vclk/dclk interface for smu_v13_0_7 Signed-off-by: Kenneth Feng Reviewed-by: Jack Gui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 6e40e9ba9ff0..d2978396d6b7 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2011,13 +2011,15 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (!(gc_ver == IP_VERSION(10, 3, 1) || gc_ver == IP_VERSION(10, 3, 0) || gc_ver == IP_VERSION(10, 1, 2) || - gc_ver == IP_VERSION(11, 0, 0))) + gc_ver == IP_VERSION(11, 0, 0) || + gc_ver == IP_VERSION(11, 0, 2))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { if (!(gc_ver == IP_VERSION(10, 3, 1) || gc_ver == IP_VERSION(10, 3, 0) || gc_ver == IP_VERSION(10, 1, 2) || - gc_ver == IP_VERSION(11, 0, 0))) + gc_ver == IP_VERSION(11, 0, 0) || + gc_ver == IP_VERSION(11, 0, 2))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) -- cgit From 334682ae81513638aa49da9615c2c0054a711ed4 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Fri, 22 Apr 2022 11:40:51 +0800 Subject: drm/amd/pm: enable workload type change on smu_v13_0_7 enable workload type change on smu_v13_0_7 v2: squash in out of bounds fix (Alex) Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 133 ++++++++++++++++++++- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 +- 4 files changed, 136 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a4c267f15959..7e3231c2191c 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -157,6 +157,7 @@ enum PP_SMC_POWER_PROFILE { PP_SMC_POWER_PROFILE_VR = 0x4, PP_SMC_POWER_PROFILE_COMPUTE = 0x5, PP_SMC_POWER_PROFILE_CUSTOM = 0x6, + PP_SMC_POWER_PROFILE_WINDOW3D = 0x7, PP_SMC_POWER_PROFILE_COUNT, }; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d2978396d6b7..70a0aad05426 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -89,7 +89,8 @@ const char * const amdgpu_pp_profile_name[] = { "VIDEO", "VR", "COMPUTE", - "CUSTOM" + "CUSTOM", + "WINDOW_3D", }; /** 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 d7e42cbe9fb7..d5c5229bc549 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 @@ -161,8 +161,9 @@ static struct cmn2asic_mapping smu_v13_0_7_workload_map[PP_SMC_POWER_PROFILE_COU WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_CUSTOM_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D, WORKLOAD_PPLIB_WINDOW_3D_BIT), }; static const uint8_t smu_v13_0_7_throttler_map[] = { @@ -1322,6 +1323,134 @@ static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu) NULL); } +static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf) +{ + DpmActivityMonitorCoeffIntExternal_t activity_monitor_external[PP_SMC_POWER_PROFILE_COUNT]; + uint32_t i, j, size = 0; + int16_t workload_type = 0; + int result = 0; + + if (!buf) + return -EINVAL; + + size += sysfs_emit_at(buf, size, " "); + for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) + size += sysfs_emit_at(buf, size, "%-14s%s", amdgpu_pp_profile_name[i], + (i == smu->power_profile_mode) ? "* " : " "); + + size += sysfs_emit_at(buf, size, "\n"); + + for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) { + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); + if (workload_type < 0) + return -EINVAL; + + result = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, + (void *)(&activity_monitor_external[i]), false); + if (result) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return result; + } + } + +#define PRINT_DPM_MONITOR(field) \ +do { \ + size += sysfs_emit_at(buf, size, "%-30s", #field); \ + for (j = 0; j <= PP_SMC_POWER_PROFILE_WINDOW3D; j++) \ + size += sysfs_emit_at(buf, size, "%-16d", activity_monitor_external[j].DpmActivityMonitorCoeffInt.field); \ + size += sysfs_emit_at(buf, size, "\n"); \ +} while (0) + + PRINT_DPM_MONITOR(Gfx_ActiveHystLimit); + PRINT_DPM_MONITOR(Gfx_IdleHystLimit); + PRINT_DPM_MONITOR(Gfx_FPS); + PRINT_DPM_MONITOR(Gfx_MinActiveFreqType); + PRINT_DPM_MONITOR(Gfx_BoosterFreqType); + PRINT_DPM_MONITOR(Gfx_MinActiveFreq); + PRINT_DPM_MONITOR(Gfx_BoosterFreq); + PRINT_DPM_MONITOR(Fclk_ActiveHystLimit); + PRINT_DPM_MONITOR(Fclk_IdleHystLimit); + PRINT_DPM_MONITOR(Fclk_FPS); + PRINT_DPM_MONITOR(Fclk_MinActiveFreqType); + PRINT_DPM_MONITOR(Fclk_BoosterFreqType); + PRINT_DPM_MONITOR(Fclk_MinActiveFreq); + PRINT_DPM_MONITOR(Fclk_BoosterFreq); +#undef PRINT_DPM_MONITOR + + return size; +} + +static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) +{ + + DpmActivityMonitorCoeffIntExternal_t activity_monitor_external; + DpmActivityMonitorCoeffInt_t *activity_monitor = + &(activity_monitor_external.DpmActivityMonitorCoeffInt); + int workload_type, ret = 0; + + smu->power_profile_mode = input[size]; + + if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) { + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); + return -EINVAL; + } + + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor_external), false); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return ret; + } + + switch (input[0]) { + case 0: /* Gfxclk */ + activity_monitor->Gfx_ActiveHystLimit = input[1]; + activity_monitor->Gfx_IdleHystLimit = input[2]; + activity_monitor->Gfx_FPS = input[3]; + activity_monitor->Gfx_MinActiveFreqType = input[4]; + activity_monitor->Gfx_BoosterFreqType = input[5]; + activity_monitor->Gfx_MinActiveFreq = input[6]; + activity_monitor->Gfx_BoosterFreq = input[7]; + break; + case 1: /* Fclk */ + activity_monitor->Fclk_ActiveHystLimit = input[1]; + activity_monitor->Fclk_IdleHystLimit = input[2]; + activity_monitor->Fclk_FPS = input[3]; + activity_monitor->Fclk_MinActiveFreqType = input[4]; + activity_monitor->Fclk_BoosterFreqType = input[5]; + activity_monitor->Fclk_MinActiveFreq = input[6]; + activity_monitor->Fclk_BoosterFreq = input[7]; + break; + } + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor_external), true); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); + return ret; + } + } + + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + smu->power_profile_mode); + if (workload_type < 0) + return -EINVAL; + smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, + 1 << workload_type, NULL); + + return ret; +} + static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask, .set_default_dpm_table = smu_v13_0_7_set_default_dpm_table, @@ -1365,6 +1494,8 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .get_fan_control_mode = smu_v13_0_get_fan_control_mode, .set_fan_control_mode = smu_v13_0_set_fan_control_mode, .enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost, + .get_power_profile_mode = smu_v13_0_7_get_power_profile_mode, + .set_power_profile_mode = smu_v13_0_7_set_power_profile_mode, }; void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 1274c794a776..5de7da75d14a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -497,7 +497,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, return mapping.map_to; case CMN2ASIC_MAPPING_WORKLOAD: - if (index > PP_SMC_POWER_PROFILE_CUSTOM || + if (index > PP_SMC_POWER_PROFILE_WINDOW3D || !smu->workload_map) return -EINVAL; -- cgit From 1b85257290f382a78adba1b0a5b59a95cebdfa2f Mon Sep 17 00:00:00 2001 From: Danijel Slivka Date: Thu, 5 May 2022 16:45:32 +0200 Subject: amdgpu/pm: Disallow managing power profiles on SRIOV for Sienna Cichlid Managing power profiles mode is not allowed in SRIOV mode for Sienna Cichlid. This patch is adjusting the "pp_power_profile_mode" and "power_dpm_force_performance_level" accordingly. Signed-off-by: Danijel Slivka Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 70a0aad05426..d3228216b2da 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2025,6 +2025,8 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; + else if (gc_ver == IP_VERSION(10, 3, 0) && amdgpu_sriov_vf(adev)) + *states = ATTR_STATE_UNSUPPORTED; } switch (gc_ver) { @@ -2038,6 +2040,13 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ dev_attr->store = NULL; } break; + case IP_VERSION(10, 3, 0): + if (DEVICE_ATTR_IS(power_dpm_force_performance_level) && + amdgpu_sriov_vf(adev)) { + dev_attr->attr.mode &= ~0222; + dev_attr->store = NULL; + } + break; default: break; } -- cgit From 494c1432542b33f8577bd59e5b084fd50bade6d0 Mon Sep 17 00:00:00 2001 From: Sathishkumar S Date: Wed, 11 May 2022 17:18:31 +0530 Subject: drm/amd/pm: consistent approach for smartshift create smartshift sysfs attributes from dGPU device even on smartshift 1.0 platform to be consistent. Do not populate the attributes on platforms that have APU only but not dGPU or vice versa. V2: avoid checking for the number of VGA/DISPLAY devices (Lijo) move code to read from dGPU or APU into a function and reuse (Lijo) Suggested-by: Alex Deucher Signed-off-by: Sathishkumar S Acked-by: Alex Deucher Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 130 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 68 deletions(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d3228216b2da..5e318b3f6c0f 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1734,22 +1734,11 @@ out: return size; } -/** - * DOC: smartshift_apu_power - * - * The amdgpu driver provides a sysfs API for reporting APU power - * share if it supports smartshift. The value is expressed as - * the proportion of stapm limit where stapm limit is the total APU - * power limit. The result is in percentage. If APU power is 130% of - * STAPM, then APU is using 30% of the dGPU's headroom. - */ - -static ssize_t amdgpu_get_smartshift_apu_power(struct device *dev, struct device_attribute *attr, - char *buf) +static int amdgpu_device_read_powershift(struct amdgpu_device *adev, + uint32_t *ss_power, bool dgpu_share) { - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = drm_to_adev(ddev); - uint32_t ss_power, size; + struct drm_device *ddev = adev_to_drm(adev); + uint32_t size; int r = 0; if (amdgpu_in_reset(adev)) @@ -1763,61 +1752,77 @@ static ssize_t amdgpu_get_smartshift_apu_power(struct device *dev, struct device return r; } - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_APU_SHARE, - (void *)&ss_power, &size); - if (r) - goto out; - - r = sysfs_emit(buf, "%u%%\n", ss_power); + if (dgpu_share) + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_DGPU_SHARE, + (void *)ss_power, &size); + else + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_APU_SHARE, + (void *)ss_power, &size); -out: pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); return r; } -/** - * DOC: smartshift_dgpu_power - * - * The amdgpu driver provides a sysfs API for reporting the dGPU power - * share if the device is in HG and supports smartshift. The value - * is expressed as the proportion of stapm limit where stapm limit - * is the total APU power limit. The value is in percentage. If dGPU - * power is 20% higher than STAPM power(120%), it's using 20% of the - * APU's power headroom. - */ - -static ssize_t amdgpu_get_smartshift_dgpu_power(struct device *dev, struct device_attribute *attr, - char *buf) +static int amdgpu_show_powershift_percent(struct device *dev, + char *buf, bool dgpu_share) { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - uint32_t ss_power, size; - int r = 0; - - if (amdgpu_in_reset(adev)) - return -EPERM; - if (adev->in_suspend && !adev->in_runpm) - return -EPERM; - - r = pm_runtime_get_sync(ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return r; + uint32_t ss_power; + int r = 0, i; + + r = amdgpu_device_read_powershift(adev, &ss_power, dgpu_share); + if (r == -EOPNOTSUPP) { + /* sensor not available on dGPU, try to read from APU */ + adev = NULL; + mutex_lock(&mgpu_info.mutex); + for (i = 0; i < mgpu_info.num_gpu; i++) { + if (mgpu_info.gpu_ins[i].adev->flags & AMD_IS_APU) { + adev = mgpu_info.gpu_ins[i].adev; + break; + } + } + mutex_unlock(&mgpu_info.mutex); + if (adev) + r = amdgpu_device_read_powershift(adev, &ss_power, dgpu_share); } - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_DGPU_SHARE, - (void *)&ss_power, &size); + if (!r) + r = sysfs_emit(buf, "%u%%\n", ss_power); - if (r) - goto out; + return r; +} +/** + * DOC: smartshift_apu_power + * + * The amdgpu driver provides a sysfs API for reporting APU power + * shift in percentage if platform supports smartshift. Value 0 means that + * there is no powershift and values between [1-100] means that the power + * is shifted to APU, the percentage of boost is with respect to APU power + * limit on the platform. + */ - r = sysfs_emit(buf, "%u%%\n", ss_power); +static ssize_t amdgpu_get_smartshift_apu_power(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return amdgpu_show_powershift_percent(dev, buf, false); +} -out: - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return r; +/** + * DOC: smartshift_dgpu_power + * + * The amdgpu driver provides a sysfs API for reporting dGPU power + * shift in percentage if platform supports smartshift. Value 0 means that + * there is no powershift and values between [1-100] means that the power is + * shifted to dGPU, the percentage of boost is with respect to dGPU power + * limit on the platform. + */ + +static ssize_t amdgpu_get_smartshift_dgpu_power(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return amdgpu_show_powershift_percent(dev, buf, true); } /** @@ -1884,18 +1889,7 @@ out: static int ss_power_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, uint32_t mask, enum amdgpu_device_attr_states *states) { - uint32_t ss_power, size; - - if (!amdgpu_acpi_is_power_shift_control_supported()) - *states = ATTR_STATE_UNSUPPORTED; - else if ((adev->flags & AMD_IS_PX) && - !amdgpu_device_supports_smart_shift(adev_to_drm(adev))) - *states = ATTR_STATE_UNSUPPORTED; - else if (amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_APU_SHARE, - (void *)&ss_power, &size)) - *states = ATTR_STATE_UNSUPPORTED; - else if (amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_DGPU_SHARE, - (void *)&ss_power, &size)) + if (!amdgpu_device_supports_smart_shift(adev_to_drm(adev))) *states = ATTR_STATE_UNSUPPORTED; return 0; -- cgit