Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

amd-pstate: Add sysfs support for floor_freq and floor_count

When Floor Performance feature is supported by the platform, expose
two sysfs files:

* amd_pstate_floor_freq to allow userspace to request the floor
frequency for each CPU.

* amd_pstate_floor_count which advertises the number of distinct
levels of floor frequencies supported on this platform.

Reset the floor_perf to bios_floor_perf in the suspend, offline, and
exit paths, and restore the value to the cached user-request
floor_freq on the resume and online paths mirroring how bios_min_perf
is handled for MSR_AMD_CPPC_REQ.

Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>

authored by

Gautham R. Shenoy and committed by
Mario Limonciello (AMD)
b9f103d0 97838281

+89 -6
+87 -6
drivers/cpufreq/amd-pstate.c
··· 383 383 return ret; 384 384 } 385 385 386 - cpudata->bios_floor_perf = floor_perf; 387 386 387 + cpudata->bios_floor_perf = floor_perf; 388 + cpudata->floor_freq = perf_to_freq(cpudata->perf, cpudata->nominal_freq, 389 + floor_perf); 388 390 return 0; 389 391 } 390 392 ··· 1290 1288 return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]); 1291 1289 } 1292 1290 1291 + static ssize_t store_amd_pstate_floor_freq(struct cpufreq_policy *policy, 1292 + const char *buf, size_t count) 1293 + { 1294 + struct amd_cpudata *cpudata = policy->driver_data; 1295 + union perf_cached perf = READ_ONCE(cpudata->perf); 1296 + unsigned int freq; 1297 + u8 floor_perf; 1298 + int ret; 1299 + 1300 + ret = kstrtouint(buf, 0, &freq); 1301 + if (ret) 1302 + return ret; 1303 + 1304 + if (freq < policy->cpuinfo.min_freq || freq > policy->max) 1305 + return -EINVAL; 1306 + 1307 + floor_perf = freq_to_perf(perf, cpudata->nominal_freq, freq); 1308 + ret = amd_pstate_set_floor_perf(policy, floor_perf); 1309 + 1310 + if (!ret) 1311 + cpudata->floor_freq = freq; 1312 + 1313 + return ret ?: count; 1314 + } 1315 + 1316 + static ssize_t show_amd_pstate_floor_freq(struct cpufreq_policy *policy, char *buf) 1317 + { 1318 + struct amd_cpudata *cpudata = policy->driver_data; 1319 + 1320 + return sysfs_emit(buf, "%u\n", cpudata->floor_freq); 1321 + } 1322 + 1323 + static ssize_t show_amd_pstate_floor_count(struct cpufreq_policy *policy, char *buf) 1324 + { 1325 + struct amd_cpudata *cpudata = policy->driver_data; 1326 + u8 count = cpudata->floor_perf_cnt; 1327 + 1328 + return sysfs_emit(buf, "%u\n", count); 1329 + } 1330 + 1293 1331 cpufreq_freq_attr_ro(amd_pstate_max_freq); 1294 1332 cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); 1295 1333 ··· 1338 1296 cpufreq_freq_attr_ro(amd_pstate_hw_prefcore); 1339 1297 cpufreq_freq_attr_rw(energy_performance_preference); 1340 1298 cpufreq_freq_attr_ro(energy_performance_available_preferences); 1299 + cpufreq_freq_attr_rw(amd_pstate_floor_freq); 1300 + cpufreq_freq_attr_ro(amd_pstate_floor_count); 1341 1301 1342 1302 struct freq_attr_visibility { 1343 1303 struct freq_attr *attr; ··· 1364 1320 return cppc_state == AMD_PSTATE_ACTIVE; 1365 1321 } 1366 1322 1323 + /* Determines whether amd_pstate_floor_freq related attributes should be visible */ 1324 + static bool floor_freq_visibility(void) 1325 + { 1326 + return cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO); 1327 + } 1328 + 1367 1329 static struct freq_attr_visibility amd_pstate_attr_visibility[] = { 1368 1330 {&amd_pstate_max_freq, always_visible}, 1369 1331 {&amd_pstate_lowest_nonlinear_freq, always_visible}, ··· 1378 1328 {&amd_pstate_hw_prefcore, prefcore_visibility}, 1379 1329 {&energy_performance_preference, epp_visibility}, 1380 1330 {&energy_performance_available_preferences, epp_visibility}, 1331 + {&amd_pstate_floor_freq, floor_freq_visibility}, 1332 + {&amd_pstate_floor_count, floor_freq_visibility}, 1381 1333 }; 1382 1334 1383 1335 static struct freq_attr **get_freq_attrs(void) ··· 1800 1748 1801 1749 static int amd_pstate_cpu_online(struct cpufreq_policy *policy) 1802 1750 { 1803 - return amd_pstate_cppc_enable(policy); 1751 + struct amd_cpudata *cpudata = policy->driver_data; 1752 + union perf_cached perf = READ_ONCE(cpudata->perf); 1753 + u8 cached_floor_perf; 1754 + int ret; 1755 + 1756 + ret = amd_pstate_cppc_enable(policy); 1757 + if (ret) 1758 + return ret; 1759 + 1760 + cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq); 1761 + return amd_pstate_set_floor_perf(policy, cached_floor_perf); 1804 1762 } 1805 1763 1806 1764 static int amd_pstate_cpu_offline(struct cpufreq_policy *policy) 1807 1765 { 1808 1766 struct amd_cpudata *cpudata = policy->driver_data; 1809 1767 union perf_cached perf = READ_ONCE(cpudata->perf); 1768 + int ret; 1810 1769 1811 1770 /* 1812 1771 * Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified 1813 1772 * min_perf value across kexec reboots. If this CPU is just onlined normally after this, the 1814 1773 * limits, epp and desired perf will get reset to the cached values in cpudata struct 1815 1774 */ 1816 - return amd_pstate_update_perf(policy, perf.bios_min_perf, 1775 + ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 1817 1776 FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached), 1818 1777 FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), 1819 1778 FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached), 1820 1779 false); 1780 + if (ret) 1781 + return ret; 1782 + 1783 + return amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1821 1784 } 1822 1785 1823 1786 static int amd_pstate_suspend(struct cpufreq_policy *policy) ··· 1854 1787 if (ret) 1855 1788 return ret; 1856 1789 1790 + ret = amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1791 + if (ret) 1792 + return ret; 1793 + 1857 1794 /* set this flag to avoid setting core offline*/ 1858 1795 cpudata->suspended = true; 1859 1796 ··· 1869 1798 struct amd_cpudata *cpudata = policy->driver_data; 1870 1799 union perf_cached perf = READ_ONCE(cpudata->perf); 1871 1800 int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur); 1801 + u8 cached_floor_perf; 1802 + int ret; 1872 1803 1873 1804 /* Set CPPC_REQ to last sane value until the governor updates it */ 1874 - return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf, 1875 - 0U, false); 1805 + ret = amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf, 1806 + 0U, false); 1807 + if (ret) 1808 + return ret; 1809 + 1810 + cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq); 1811 + return amd_pstate_set_floor_perf(policy, cached_floor_perf); 1876 1812 } 1877 1813 1878 1814 static int amd_pstate_epp_resume(struct cpufreq_policy *policy) 1879 1815 { 1880 1816 struct amd_cpudata *cpudata = policy->driver_data; 1817 + union perf_cached perf = READ_ONCE(cpudata->perf); 1818 + u8 cached_floor_perf; 1881 1819 1882 1820 if (cpudata->suspended) { 1883 1821 int ret; ··· 1899 1819 cpudata->suspended = false; 1900 1820 } 1901 1821 1902 - return 0; 1822 + cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq); 1823 + return amd_pstate_set_floor_perf(policy, cached_floor_perf); 1903 1824 } 1904 1825 1905 1826 static struct cpufreq_driver amd_pstate_driver = {
+2
drivers/cpufreq/amd-pstate.h
··· 74 74 * @max_limit_freq: Cached value of policy->max (in khz) 75 75 * @nominal_freq: the frequency (in khz) that mapped to nominal_perf 76 76 * @lowest_nonlinear_freq: the frequency (in khz) that mapped to lowest_nonlinear_perf 77 + * @floor_freq: Cached value of the user requested floor_freq 77 78 * @cur: Difference of Aperf/Mperf/tsc count between last and current sample 78 79 * @prev: Last Aperf/Mperf/tsc count value read from register 79 80 * @freq: current cpu frequency value (in khz) ··· 104 103 u32 max_limit_freq; 105 104 u32 nominal_freq; 106 105 u32 lowest_nonlinear_freq; 106 + u32 floor_freq; 107 107 108 108 struct amd_aperf_mperf cur; 109 109 struct amd_aperf_mperf prev;