Module Name: src Committed By: jruoho Date: Thu Oct 28 04:27:40 UTC 2010
Modified Files: src/sys/dev/acpi: acpi_cpu_pstate.c Log Message: Only override data from XPSS if the conventional _PSS did not contain the required information. Problem found and diagnosed by jakllsch@; on some AMD systems vendors fill _PSS correctly, but do not duplicate the data in XPSS. To generate a diff of this commit: cvs rdiff -u -r1.33 -r1.34 src/sys/dev/acpi/acpi_cpu_pstate.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/acpi_cpu_pstate.c diff -u src/sys/dev/acpi/acpi_cpu_pstate.c:1.33 src/sys/dev/acpi/acpi_cpu_pstate.c:1.34 --- src/sys/dev/acpi/acpi_cpu_pstate.c:1.33 Sat Aug 21 13:12:15 2010 +++ src/sys/dev/acpi/acpi_cpu_pstate.c Thu Oct 28 04:27:40 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_cpu_pstate.c,v 1.33 2010/08/21 13:12:15 jmcneill Exp $ */ +/* $NetBSD: acpi_cpu_pstate.c,v 1.34 2010/10/28 04:27:40 jruoho Exp $ */ /*- * Copyright (c) 2010 Jukka Ruohonen <jruoho...@iki.fi> @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.33 2010/08/21 13:12:15 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.34 2010/10/28 04:27:40 jruoho Exp $"); #include <sys/param.h> #include <sys/evcnt.h> @@ -75,12 +75,13 @@ } /* - * Check the availability of extended _PSS. - * If present, this will override the data. - * Note that XPSS can not be used on Intel - * systems where _PDC or _OSC may be used. + * Append additional information from the + * extended _PSS, if available. Note that + * XPSS can not be used on Intel systems + * that use either _PDC or _OSC. */ if (sc->sc_cap == 0) { + rv = acpicpu_pstate_xpss(sc); if (ACPI_SUCCESS(rv)) @@ -486,13 +487,11 @@ static ACPI_STATUS acpicpu_pstate_xpss(struct acpicpu_softc *sc) { - static const size_t size = sizeof(struct acpicpu_pstate); - struct acpicpu_pstate *ps, *pstate = NULL; + struct acpicpu_pstate *ps; ACPI_OBJECT *obj; ACPI_BUFFER buf; ACPI_STATUS rv; - uint32_t count, pstate_count; - uint32_t i, j; + uint32_t i = 0; rv = acpi_eval_struct(sc->sc_node->ad_handle, "XPSS", &buf); @@ -506,56 +505,17 @@ goto out; } - pstate_count = count = obj->Package.Count; - - if (count == 0) { - rv = AE_NOT_EXIST; - goto out; - } - - if (count > ACPICPU_P_STATE_MAX) { + if (obj->Package.Count != sc->sc_pstate_count) { rv = AE_LIMIT; goto out; } - pstate = kmem_zalloc(count * size, KM_SLEEP); - - if (pstate == NULL) { - rv = AE_NO_MEMORY; - goto out; - } - - for (count = i = 0; i < pstate_count; i++) { - - ps = &pstate[i]; - rv = acpicpu_pstate_xpss_add(ps, &obj->Package.Elements[i]); - - if (ACPI_FAILURE(rv)) { - ps->ps_freq = 0; - continue; - } - - for (j = 0; j < i; j++) { + while (i < sc->sc_pstate_count) { - if (ps->ps_freq >= pstate[j].ps_freq) { - ps->ps_freq = 0; - break; - } - } - - if (ps->ps_freq != 0) - count++; - } + ps = &sc->sc_pstate[i]; + acpicpu_pstate_xpss_add(ps, &obj->Package.Elements[i]); - if (count > 0) { - if (sc->sc_pstate != NULL) - kmem_free(sc->sc_pstate, sc->sc_pstate_count * size); - sc->sc_pstate = pstate; - sc->sc_pstate_count = pstate_count; - rv = AE_OK; - } else { - kmem_free(pstate, pstate_count * size); - rv = AE_NOT_EXIST; + i++; } out: @@ -597,18 +557,33 @@ return AE_LIMIT; } - ps->ps_freq = elm[0].Integer.Value; - ps->ps_power = elm[1].Integer.Value; - ps->ps_latency = elm[2].Integer.Value; - ps->ps_latency_bm = elm[3].Integer.Value; + /* + * Only overwrite the elements that were + * not available from the conventional _PSS. + */ + if (ps->ps_freq == 0) + ps->ps_freq = elm[0].Integer.Value; - if (ps->ps_freq == 0 || ps->ps_freq > 9999) - return AE_BAD_DECIMAL_CONSTANT; + if (ps->ps_power == 0) + ps->ps_power = elm[1].Integer.Value; + + if (ps->ps_latency == 0) + ps->ps_latency = elm[2].Integer.Value; + + if (ps->ps_latency_bm == 0) + ps->ps_latency_bm = elm[3].Integer.Value; - ps->ps_control = ACPI_GET64(elm[4].Buffer.Pointer); - ps->ps_status = ACPI_GET64(elm[5].Buffer.Pointer); - ps->ps_control_mask = ACPI_GET64(elm[6].Buffer.Pointer); - ps->ps_status_mask = ACPI_GET64(elm[7].Buffer.Pointer); + if (ps->ps_control == 0) + ps->ps_control = ACPI_GET64(elm[4].Buffer.Pointer); + + if (ps->ps_status == 0) + ps->ps_status = ACPI_GET64(elm[5].Buffer.Pointer); + + if (ps->ps_control_mask == 0) + ps->ps_control_mask = ACPI_GET64(elm[6].Buffer.Pointer); + + if (ps->ps_status_mask == 0) + ps->ps_status_mask = ACPI_GET64(elm[7].Buffer.Pointer); /* * The latency is often defined to be @@ -619,6 +594,9 @@ ps->ps_flags |= ACPICPU_FLAG_P_XPSS; + if (ps->ps_freq > 9999) + return AE_BAD_DECIMAL_CONSTANT; + return AE_OK; }