ACPI P-State: Force P-State to use the first usable entry in P-State table
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 14 Sep 2010 14:26:47 +0000 (22:26 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 14 Sep 2010 14:26:47 +0000 (22:26 +0800)
It looks like on certain boxes P-State will be set to the last usable
P-State (i.e. lowest frequency)

sys/dev/acpica5/acpi_cpu_pstate.c

index f2c7142..dd155a9 100644 (file)
@@ -121,6 +121,7 @@ static struct acpi_pst_domain *
 static struct acpi_pst_domain *
                acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
 static int     acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int);
+static int     acpi_pst_global_set_pstate(int);
 
 static int     acpi_pst_check_csr(struct acpi_pst_softc *);
 static int     acpi_pst_check_pstates(struct acpi_pst_softc *);
@@ -663,13 +664,29 @@ acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i)
        return 0;
 }
 
+static int
+acpi_pst_global_set_pstate(int i)
+{
+       struct acpi_pst_domain *dom;
+
+       LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
+               /* Skip dead domain */
+               if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
+                       continue;
+               acpi_pst_domain_set_pstate(dom, i);
+       }
+       acpi_pst_global_state = i;
+
+       return 0;
+}
+
 static void
 acpi_pst_postattach(void *arg __unused)
 {
        struct acpi_pst_domain *dom;
        struct acpi_cpux_softc *cpux;
        device_t *devices;
-       int i, ndevices, error, has_domain;
+       int i, ndevices, error, has_domain, sstate;
 
        devices = NULL;
        ndevices = 0;
@@ -692,6 +709,7 @@ acpi_pst_postattach(void *arg __unused)
        if (acpi_pst_md == NULL)
                kprintf("ACPI: no P-State CPU driver\n");
 
+       sstate = 0x7fffffff;
        has_domain = 0;
        LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
                struct acpi_pst_softc *sc;
@@ -798,6 +816,9 @@ acpi_pst_postattach(void *arg __unused)
                                        dom, 0, acpi_pst_sysctl_select,
                                        "IU", "select freq");
                }
+
+               if (dom->pd_state < sstate)
+                       sstate = dom->pd_state;
        }
 
        if (has_domain && acpi_pst_md != NULL &&
@@ -808,6 +829,8 @@ acpi_pst_postattach(void *arg __unused)
                                CTLTYPE_UINT | CTLFLAG_RW,
                                NULL, 0, acpi_pst_sysctl_global,
                                "IU", "select freq for all domains");
+
+               acpi_pst_global_set_pstate(sstate);
        }
 }
 
@@ -900,7 +923,6 @@ acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
 static int
 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
 {
-       struct acpi_pst_domain *dom;
        int error, i, freq;
 
        KKASSERT(acpi_pst_global_state >= 0 &&
@@ -916,13 +938,7 @@ acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
        if (i < 0)
                return EINVAL;
 
-       LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
-               /* Skip dead domain */
-               if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
-                       continue;
-               acpi_pst_domain_set_pstate(dom, i);
-       }
-       acpi_pst_global_state = i;
+       acpi_pst_global_set_pstate(i);
 
        return 0;
 }