Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/acpi Add MD support for the vendor-independent ...



details:   https://anonhg.NetBSD.org/src/rev/8ae37458da73
branches:  trunk
changeset: 757184:8ae37458da73
user:      jruoho <jruoho%NetBSD.org@localhost>
date:      Wed Aug 18 04:12:29 2010 +0000

description:
Add MD support for the vendor-independent extended PSS. Some conforming AMD
systems are known to work. Alas, not all of them. We still need to deal with
the variety of different PowerNow! revisions.

diffstat:

 sys/arch/x86/acpi/acpi_cpu_md.c |  144 +++++++++++++++++++++++++--------------
 1 files changed, 92 insertions(+), 52 deletions(-)

diffs (253 lines):

diff -r 0ada09abbf7a -r 8ae37458da73 sys/arch/x86/acpi/acpi_cpu_md.c
--- a/sys/arch/x86/acpi/acpi_cpu_md.c   Wed Aug 18 02:53:54 2010 +0000
+++ b/sys/arch/x86/acpi/acpi_cpu_md.c   Wed Aug 18 04:12:29 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_md.c,v 1.12 2010/08/14 05:13:20 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_md.c,v 1.13 2010/08/18 04:12:29 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.12 2010/08/14 05:13:20 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.13 2010/08/18 04:12:29 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -56,7 +56,6 @@
 static int      acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO);
 static int      acpicpu_md_pstate_sysctl_set(SYSCTLFN_PROTO);
 static int      acpicpu_md_pstate_sysctl_all(SYSCTLFN_PROTO);
-static int      acpicpu_md_tstate_get_status(uint64_t *);
 
 extern uint32_t cpus_running;
 extern struct acpicpu_softc **acpicpu_sc;
@@ -135,7 +134,7 @@
        case CPUVENDOR_AMD:
 
                /*
-                * XXX: Deal with PowerNow! and C1E here.
+                * XXX: Deal with (non-XPSS) PowerNow! and C1E.
                 */
                break;
        }
@@ -253,6 +252,10 @@
                str = "est";
                break;
 
+       case CPUVENDOR_AMD:
+               str = "powernow";
+               break;
+
        default:
                return ENODEV;
        }
@@ -449,37 +452,61 @@
 int
 acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq)
 {
-       struct acpicpu_pstate *ps;
+       struct acpicpu_pstate *ps = NULL;
        uint64_t val;
        uint32_t i;
 
+       for (i = 0; i < sc->sc_pstate_count; i++) {
+
+               ps = &sc->sc_pstate[i];
+
+               if (ps->ps_freq != 0)
+                       break;
+       }
+
+       if (__predict_false(ps == NULL))
+               return EINVAL;
+
        switch (cpu_vendor) {
 
        case CPUVENDOR_INTEL:
-
-               val = rdmsr(MSR_PERF_STATUS);
-               val = val & 0xffff;
-
-               for (i = 0; i < sc->sc_pstate_count; i++) {
-
-                       ps = &sc->sc_pstate[i];
+               ps->ps_status_addr = MSR_PERF_STATUS;
+               ps->ps_status_mask = __BITS(0, 15);
+               break;
 
-                       if (ps->ps_freq == 0)
-                               continue;
+       case CPUVENDOR_AMD:
 
-                       if (val == ps->ps_status) {
-                               *freq = ps->ps_freq;
-                               return 0;
-                       }
-               }
+               if ((ps->ps_flags & ACPICPU_FLAG_P_XPSS) == 0)
+                       return EOPNOTSUPP;
 
-               return EIO;
+               break;
 
        default:
                return ENODEV;
        }
 
-       return 0;
+       if (ps->ps_status_addr == 0)
+               return EINVAL;
+
+       val = rdmsr(ps->ps_status_addr);
+
+       if (ps->ps_status_mask != 0)
+               val = val & ps->ps_status_mask;
+
+       for (i = 0; i < sc->sc_pstate_count; i++) {
+
+               ps = &sc->sc_pstate[i];
+
+               if (ps->ps_freq == 0)
+                       continue;
+
+               if (val == ps->ps_status) {
+                       *freq = ps->ps_freq;
+                       return 0;
+               }
+       }
+
+       return EIO;
 }
 
 int
@@ -492,23 +519,45 @@
        switch (cpu_vendor) {
 
        case CPUVENDOR_INTEL:
-               msr.msr_read  = true;
-               msr.msr_type  = MSR_PERF_CTL;
-               msr.msr_value = ps->ps_control;
-               msr.msr_mask  = 0xffffULL;
+               ps->ps_control_addr = MSR_PERF_CTL;
+               ps->ps_control_mask = __BITS(0, 15);
+
+               ps->ps_status_addr  = MSR_PERF_STATUS;
+               ps->ps_status_mask  = __BITS(0, 15);
+               break;
+
+       case CPUVENDOR_AMD:
+
+               if ((ps->ps_flags & ACPICPU_FLAG_P_XPSS) == 0)
+                       return EOPNOTSUPP;
+
                break;
 
        default:
                return ENODEV;
        }
 
+       msr.msr_read  = false;
+       msr.msr_type  = ps->ps_control_addr;
+       msr.msr_value = ps->ps_control;
+
+       if (ps->ps_control_mask != 0) {
+               msr.msr_mask = ps->ps_control_mask;
+               msr.msr_read = true;
+       }
+
        xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL);
        xc_wait(xc);
 
+       if (ps->ps_status_addr == 0)
+               return 0;
+
        for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) {
 
-               val = rdmsr(MSR_PERF_STATUS);
-               val = val & 0xffff;
+               val = rdmsr(ps->ps_status_addr);
+
+               if (ps->ps_status_mask != 0)
+                       val = val & ps->ps_status_mask;
 
                if (val == ps->ps_status)
                        return 0;
@@ -523,14 +572,20 @@
 acpicpu_md_tstate_get(struct acpicpu_softc *sc, uint32_t *percent)
 {
        struct acpicpu_tstate *ts;
-       uint64_t val;
+       uint64_t val, sta;
        uint32_t i;
-       int rv;
+
+       switch (cpu_vendor) {
 
-       rv = acpicpu_md_tstate_get_status(&val);
+       case CPUVENDOR_INTEL:
+               sta = MSR_THERM_CONTROL;
+               break;
 
-       if (rv != 0)
-               return rv;
+       default:
+               return ENODEV;
+       }
+
+       val = rdmsr(sta);
 
        for (i = 0; i < sc->sc_tstate_count; i++) {
 
@@ -548,29 +603,12 @@
        return EIO;
 }
 
-static int
-acpicpu_md_tstate_get_status(uint64_t *val)
-{
-
-       switch (cpu_vendor) {
-
-       case CPUVENDOR_INTEL:
-               *val = rdmsr(MSR_THERM_CONTROL);
-               break;
-
-       default:
-               return ENODEV;
-       }
-
-       return 0;
-}
-
 int
 acpicpu_md_tstate_set(struct acpicpu_tstate *ts)
 {
        struct msr_rw_info msr;
-       uint64_t xc, val;
-       int i;
+       uint64_t xc, val, sta;
+       uint32_t i;
 
        switch (cpu_vendor) {
 
@@ -579,6 +617,8 @@
                msr.msr_type  = MSR_THERM_CONTROL;
                msr.msr_value = ts->ts_control;
                msr.msr_mask = __BITS(1, 4);
+
+               sta = MSR_THERM_CONTROL;
                break;
 
        default:
@@ -593,7 +633,7 @@
 
        for (i = val = 0; i < ACPICPU_T_STATE_RETRY; i++) {
 
-               (void)acpicpu_md_tstate_get_status(&val);
+               val = rdmsr(sta);
 
                if (val == ts->ts_status)
                        return 0;



Home | Main Index | Thread Index | Old Index