diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1106-drm-amd-powerplay-support-enabled-ppfeatures-retriev.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1106-drm-amd-powerplay-support-enabled-ppfeatures-retriev.patch | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1106-drm-amd-powerplay-support-enabled-ppfeatures-retriev.patch b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1106-drm-amd-powerplay-support-enabled-ppfeatures-retriev.patch new file mode 100644 index 00000000..a8fec787 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1106-drm-amd-powerplay-support-enabled-ppfeatures-retriev.patch @@ -0,0 +1,355 @@ +From a6654e6b8f6a72f89d6278b628f33f2755a48cc6 Mon Sep 17 00:00:00 2001 +From: Evan Quan <evan.quan@amd.com> +Date: Mon, 14 Jan 2019 14:06:54 +0800 +Subject: [PATCH 1106/2940] drm/amd/powerplay: support enabled ppfeatures + retrieving and setting V3 + +User can use "ppfeatures" sysfs interface to retrieve and set enabled +powerplay features. + +V2: expose this feature for Vega10 and later dGPUs +V3: squash in removal of unused variable (Alex) + +Signed-off-by: Evan Quan <evan.quan@amd.com> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 8 ++ + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 71 ++++++++++++ + .../gpu/drm/amd/include/kgd_pp_interface.h | 2 + + drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 42 +++++++ + .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 104 ++++++++++++++++++ + drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 + + 6 files changed, 229 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +index f972cd156795..2f61e9edb1c1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +@@ -364,6 +364,14 @@ enum amdgpu_pcie_gen { + ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\ + (adev)->powerplay.pp_handle)) + ++#define amdgpu_dpm_get_ppfeature_status(adev, buf) \ ++ ((adev)->powerplay.pp_funcs->get_ppfeature_status(\ ++ (adev)->powerplay.pp_handle, (buf))) ++ ++#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \ ++ ((adev)->powerplay.pp_funcs->set_ppfeature_status(\ ++ (adev)->powerplay.pp_handle, (ppfeatures))) ++ + struct amdgpu_dpm { + struct amdgpu_ps *ps; + /* number of valid power states */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +index 51eb2cf42b81..f21f294e6735 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +@@ -625,6 +625,60 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, + + } + ++/** ++ * DOC: ppfeatures ++ * ++ * The amdgpu driver provides a sysfs API for adjusting what powerplay ++ * features to be enabled. The file ppfeatures is used for this. And ++ * this is only available for Vega10 and later dGPUs. ++ * ++ * Reading back the file will show you the followings: ++ * - Current ppfeature masks ++ * - List of the all supported powerplay features with their naming, ++ * bitmasks and enablement status('Y'/'N' means "enabled"/"disabled"). ++ * ++ * To manually enable or disable a specific feature, just set or clear ++ * the corresponding bit from original ppfeature masks and input the ++ * new ppfeature masks. ++ */ ++static ssize_t amdgpu_set_ppfeature_status(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct drm_device *ddev = dev_get_drvdata(dev); ++ struct amdgpu_device *adev = ddev->dev_private; ++ uint64_t featuremask; ++ int ret; ++ ++ ret = kstrtou64(buf, 0, &featuremask); ++ if (ret) ++ return -EINVAL; ++ ++ pr_debug("featuremask = 0x%llx\n", featuremask); ++ ++ if (adev->powerplay.pp_funcs->set_ppfeature_status) { ++ ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); ++ if (ret) ++ return -EINVAL; ++ } ++ ++ return count; ++} ++ ++static ssize_t amdgpu_get_ppfeature_status(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct drm_device *ddev = dev_get_drvdata(dev); ++ struct amdgpu_device *adev = ddev->dev_private; ++ ++ if (adev->powerplay.pp_funcs->get_ppfeature_status) ++ return amdgpu_dpm_get_ppfeature_status(adev, buf); ++ ++ return snprintf(buf, PAGE_SIZE, "\n"); ++} ++ + /** + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie + * +@@ -1051,6 +1105,9 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR, + static DEVICE_ATTR(gpu_busy_percent, S_IRUGO, + amdgpu_get_busy_percent, NULL); + static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL); ++static DEVICE_ATTR(ppfeatures, S_IRUGO | S_IWUSR, ++ amdgpu_get_ppfeature_status, ++ amdgpu_set_ppfeature_status); + + static ssize_t amdgpu_hwmon_show_temp(struct device *dev, + struct device_attribute *attr, +@@ -2241,6 +2298,17 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) + return ret; + } + ++ if ((adev->asic_type >= CHIP_VEGA10) && ++ !(adev->flags & AMD_IS_APU)) { ++ ret = device_create_file(adev->dev, ++ &dev_attr_ppfeatures); ++ if (ret) { ++ DRM_ERROR("failed to create device file " ++ "ppfeatures\n"); ++ return ret; ++ } ++ } ++ + adev->pm.sysfs_initialized = true; + + return 0; +@@ -2276,6 +2344,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) + device_remove_file(adev->dev, &dev_attr_gpu_busy_percent); + if (adev->flags & !AMD_IS_APU) + device_remove_file(adev->dev, &dev_attr_pcie_bw); ++ if ((adev->asic_type >= CHIP_VEGA10) && ++ !(adev->flags & AMD_IS_APU)) ++ device_remove_file(adev->dev, &dev_attr_ppfeatures); + } + + void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) +diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h +index a2ea4c933360..1130f293c4ee 100644 +--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h ++++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h +@@ -284,6 +284,8 @@ struct amd_pm_funcs { + int (*get_asic_baco_capability)(void *handle, bool *cap); + int (*get_asic_baco_state)(void *handle, int *state); + int (*set_asic_baco_state)(void *handle, int state); ++ int (*get_ppfeature_status)(void *handle, char *buf); ++ int (*set_ppfeature_status)(void *handle, uint64_t ppfeature_masks); + }; + + #endif +diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +index 5d8b5d3c2453..3f73f7cd18b9 100644 +--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c ++++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +@@ -1455,6 +1455,46 @@ static int pp_set_asic_baco_state(void *handle, int state) + return 0; + } + ++static int pp_get_ppfeature_status(void *handle, char *buf) ++{ ++ struct pp_hwmgr *hwmgr = handle; ++ int ret = 0; ++ ++ if (!hwmgr || !hwmgr->pm_en || !buf) ++ return -EINVAL; ++ ++ if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) { ++ pr_info_ratelimited("%s was not implemented.\n", __func__); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&hwmgr->smu_lock); ++ ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf); ++ mutex_unlock(&hwmgr->smu_lock); ++ ++ return ret; ++} ++ ++static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks) ++{ ++ struct pp_hwmgr *hwmgr = handle; ++ int ret = 0; ++ ++ if (!hwmgr || !hwmgr->pm_en) ++ return -EINVAL; ++ ++ if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) { ++ pr_info_ratelimited("%s was not implemented.\n", __func__); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&hwmgr->smu_lock); ++ ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks); ++ mutex_unlock(&hwmgr->smu_lock); ++ ++ return ret; ++} ++ + static const struct amd_pm_funcs pp_dpm_funcs = { + .load_firmware = pp_dpm_load_fw, + .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, +@@ -1508,4 +1548,6 @@ static const struct amd_pm_funcs pp_dpm_funcs = { + .get_asic_baco_capability = pp_get_asic_baco_capability, + .get_asic_baco_state = pp_get_asic_baco_state, + .set_asic_baco_state = pp_set_asic_baco_state, ++ .get_ppfeature_status = pp_get_ppfeature_status, ++ .set_ppfeature_status = pp_set_ppfeature_status, + }; +diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +index 2ba387b0f27c..3e97b9d6f450 100644 +--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c ++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +@@ -2776,6 +2776,108 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, + return 0; + } + ++static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) ++{ ++ static const char *ppfeature_name[] = { ++ "DPM_PREFETCHER", ++ "GFXCLK_DPM", ++ "UCLK_DPM", ++ "SOCCLK_DPM", ++ "UVD_DPM", ++ "VCE_DPM", ++ "ULV", ++ "MP0CLK_DPM", ++ "LINK_DPM", ++ "DCEFCLK_DPM", ++ "GFXCLK_DS", ++ "SOCCLK_DS", ++ "LCLK_DS", ++ "PPT", ++ "TDC", ++ "THERMAL", ++ "GFX_PER_CU_CG", ++ "RM", ++ "DCEFCLK_DS", ++ "ACDC", ++ "VR0HOT", ++ "VR1HOT", ++ "FW_CTF", ++ "LED_DISPLAY", ++ "FAN_CONTROL", ++ "GFX_EDC", ++ "GFXOFF", ++ "CG", ++ "FCLK_DPM", ++ "FCLK_DS", ++ "MP1CLK_DS", ++ "MP0CLK_DS", ++ "XGMI"}; ++ static const char *output_title[] = { ++ "FEATURES", ++ "BITMASK", ++ "ENABLEMENT"}; ++ uint64_t features_enabled; ++ int i; ++ int ret = 0; ++ int size = 0; ++ ++ ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); ++ PP_ASSERT_WITH_CODE(!ret, ++ "[EnableAllSmuFeatures] Failed to get enabled smc features!", ++ return ret); ++ ++ size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); ++ size += sprintf(buf + size, "%-19s %-22s %s\n", ++ output_title[0], ++ output_title[1], ++ output_title[2]); ++ for (i = 0; i < GNLD_FEATURES_MAX; i++) { ++ size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", ++ ppfeature_name[i], ++ 1ULL << i, ++ (features_enabled & (1ULL << i)) ? "Y" : "N"); ++ } ++ ++ return size; ++} ++ ++static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) ++{ ++ uint64_t features_enabled; ++ uint64_t features_to_enable; ++ uint64_t features_to_disable; ++ int ret = 0; ++ ++ if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) ++ return -EINVAL; ++ ++ ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); ++ if (ret) ++ return ret; ++ ++ features_to_disable = ++ (features_enabled ^ new_ppfeature_masks) & features_enabled; ++ features_to_enable = ++ (features_enabled ^ new_ppfeature_masks) ^ features_to_disable; ++ ++ pr_debug("features_to_disable 0x%llx\n", features_to_disable); ++ pr_debug("features_to_enable 0x%llx\n", features_to_enable); ++ ++ if (features_to_disable) { ++ ret = vega20_enable_smc_features(hwmgr, false, features_to_disable); ++ if (ret) ++ return ret; ++ } ++ ++ if (features_to_enable) { ++ ret = vega20_enable_smc_features(hwmgr, true, features_to_enable); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) + { +@@ -3572,6 +3674,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = { + .force_clock_level = vega20_force_clock_level, + .print_clock_levels = vega20_print_clock_levels, + .read_sensor = vega20_read_sensor, ++ .get_ppfeature_status = vega20_get_ppfeature_status, ++ .set_ppfeature_status = vega20_set_ppfeature_status, + /* powergate related */ + .powergate_uvd = vega20_power_gate_uvd, + .powergate_vce = vega20_power_gate_vce, +diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +index 577cec90aef1..b1cd70dcd6e7 100644 +--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h ++++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +@@ -341,6 +341,8 @@ struct pp_hwmgr_func { + int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); + int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); + int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); ++ int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf); ++ int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks); + }; + + struct pp_table_func { +-- +2.17.1 + |