hwpstate_amd(4): Sane defaults for min/max perf on insane capabilities
If the CPPC_CAPABILITY_1 register stays at its reset value (0) even after enabling CPPC, as observed in the field (see the referenced PR below), use sane min/max performance limits as hinted by the ACPI spec, i.e., all 0s for the minimum value and all 1s for the maximum one. While here, let's cope upfront with some more insane situations, where the minimum value would be greater than the maximum one, but also if they would be equal which does not seem to make sense at all in the CPPC frame (and, anyway, in this case, the actual minimum and maximum values we program should have no effect at all). That last case actually also covers the one exposed in the previous paragraph. PR: 292615 Reviewed by: aokblast Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D55007
This commit is contained in:
@@ -661,6 +661,7 @@ amd_set_autonomous_hwp_cb(void *args)
|
||||
{
|
||||
struct set_autonomous_hwp_data *const data = args;
|
||||
struct hwpstate_softc *const sc = data->sc;
|
||||
uint64_t lowest_perf, highest_perf;
|
||||
int error;
|
||||
|
||||
/* We proceed sequentially, so we'll clear out errors on progress. */
|
||||
@@ -690,13 +691,31 @@ amd_set_autonomous_hwp_cb(void *args)
|
||||
* CPPC driver.
|
||||
*/
|
||||
SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_EPP_BITS, 0x80);
|
||||
SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MIN_PERF_BITS,
|
||||
BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, data->caps));
|
||||
SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MAX_PERF_BITS,
|
||||
BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, data->caps));
|
||||
/* enable autonomous mode by setting desired performance to 0 */
|
||||
|
||||
/* Enable autonomous mode by setting desired performance to 0. */
|
||||
SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_DES_PERF_BITS, 0);
|
||||
|
||||
/*
|
||||
* When MSR_AMD_CPPC_CAPS_1 stays at its reset value (0) before CPPC
|
||||
* activation (not supposed to happen, but happens in the field), we use
|
||||
* reasonable default values that are explicitly described by the ACPI
|
||||
* spec (all 0s for the minimum value, all 1s for the maximum one).
|
||||
* Going further, we actually do the same as long as the minimum and
|
||||
* maximum performance levels are not sorted or are equal (in which case
|
||||
* CPPC is not supposed to make sense at all), which covers the reset
|
||||
* value case.
|
||||
*/
|
||||
lowest_perf = BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, data->caps);
|
||||
highest_perf = BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, data->caps);
|
||||
if (lowest_perf >= highest_perf) {
|
||||
lowest_perf = 0;
|
||||
highest_perf = -1;
|
||||
}
|
||||
SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MIN_PERF_BITS,
|
||||
lowest_perf);
|
||||
SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MAX_PERF_BITS,
|
||||
highest_perf);
|
||||
|
||||
error = wrmsr_safe(MSR_AMD_CPPC_REQUEST, sc->cppc.request);
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user