From dbe50d5473a314313989fa7ef8073c9d2acc4fbd Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 26 Feb 2015 20:23:56 +0800 Subject: [PATCH] acpi/pstate: Allow user to force package level P-state domain Some CPUs only have package P-states, but some BIOSes put each hyperthread to its own P-state domain; allow user to override. It is not enabled by default. --- sys/dev/acpica/acpi_cpu_pstate.c | 54 +++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/sys/dev/acpica/acpi_cpu_pstate.c b/sys/dev/acpica/acpi_cpu_pstate.c index 2becab875d..9f9f082334 100644 --- a/sys/dev/acpica/acpi_cpu_pstate.c +++ b/sys/dev/acpica/acpi_cpu_pstate.c @@ -162,6 +162,9 @@ static const struct acpi_pst_md *acpi_pst_md; static int acpi_pst_ht_reuse_domain = 1; TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain); +static int acpi_pst_force_pkg_domain = 0; +TUNABLE_INT("hw.acpi.cpu.pst.force_pkg_domain", &acpi_pst_force_pkg_domain); + static device_method_t acpi_pst_methods[] = { /* Device interface */ DEVMETHOD(device_probe, acpi_pst_probe), @@ -297,7 +300,7 @@ done: static int acpi_pst_attach(device_t dev) { - struct acpi_pst_softc *sc = device_get_softc(dev), *pst; + struct acpi_pst_softc *sc = device_get_softc(dev); struct acpi_pst_domain *dom = NULL; ACPI_BUFFER buf; ACPI_STATUS status; @@ -383,6 +386,8 @@ acpi_pst_attach(device_t dev) buf.Length = ACPI_ALLOCATE_BUFFER; status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf); if (ACPI_FAILURE(status)) { + struct acpi_pst_softc *pst; + /* * No _PCT. See the comment in acpi_pst_probe() near * _PSD check. @@ -643,6 +648,53 @@ fetch_ppc: sc->pst_state = sc->pst_sstart; + /* + * Some CPUs only have package P-states, but some BIOSes put each + * hyperthread to its own P-state domain; allow user to override. + */ + if (LIST_EMPTY(&dom->pd_pstlist) && acpi_pst_force_pkg_domain) { + cpumask_t mask; + + mask = get_cpumask_from_level(sc->pst_cpuid, CHIP_LEVEL); + if (CPUMASK_TESTNZERO(mask)) { + struct acpi_pst_softc *pst = NULL; + struct acpi_pst_domain *dom1; + + LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) { + LIST_FOREACH(pst, &dom1->pd_pstlist, + pst_link) { + if (CPUMASK_TESTBIT(mask, + pst->pst_cpuid)) + break; + } + if (pst != NULL) + break; + } + if (pst != NULL && + memcmp(&pst->pst_creg, &sc->pst_creg, + sizeof(sc->pst_creg)) == 0 && + memcmp(&pst->pst_sreg, &sc->pst_sreg, + sizeof(sc->pst_sreg)) == 0) { + /* + * Use the same domain for CPUs in the + * same package. + */ + device_printf(dev, "Destroy domain%u, " + "force pkg domain%u\n", + dom->pd_dom, dom1->pd_dom); + LIST_REMOVE(dom, pd_link); + kfree(dom, M_DEVBUF); + dom = dom1; + /* + * Make sure that adding us will not + * overflow the domain containing + * siblings in the same package. + */ + acpi_pst_domain_check_nproc(dev, dom); + } + } + } + /* Link us with the domain */ sc->pst_domain = dom; LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link); -- 2.41.0