Author: jkim
Date: Wed Dec  6 21:40:24 2017
New Revision: 326638
URL: https://svnweb.freebsd.org/changeset/base/326638

Log:
  MFC:  r267961, r309361, r322710, r323286, r326378, r326383, r326407
  
  Sync. hwpstate with head.
  
  r267961 (hselasky, partial):
  
  Remove a redundant TUNABLE statement.
  
  r309361 (danfe):
  
  - Mention mismatching numbers in MSR vs. ACPI _PSS count warning.
  - Rephrase unsupported AMD CPUs message and wrap as an overly long line.
  - Improve readability when reporting resulted P-state transition (debug).
  
  r322710, r323286 (cem):
  
  - Add support for family 17h pstate info from MSRs.
  - Yield CPU awaiting frequency change.
  
  r326378, r326383, r326407:
  
  - Fix some style(9) nits.
  - Add a tunable "debug.hwpstate_verify" to check P-state after changing it
  and turn it off by default.

Modified:
  stable/10/sys/x86/cpufreq/hwpstate.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/x86/cpufreq/hwpstate.c
==============================================================================
--- stable/10/sys/x86/cpufreq/hwpstate.c        Wed Dec  6 21:39:01 2017        
(r326637)
+++ stable/10/sys/x86/cpufreq/hwpstate.c        Wed Dec  6 21:40:24 2017        
(r326638)
@@ -83,11 +83,15 @@ __FBSDID("$FreeBSD$");
 #define        AMD_10H_11H_CUR_DID(msr)                (((msr) >> 6) & 0x07)
 #define        AMD_10H_11H_CUR_FID(msr)                ((msr) & 0x3F)
 
+#define        AMD_17H_CUR_VID(msr)                    (((msr) >> 14) & 0xFF)
+#define        AMD_17H_CUR_DID(msr)                    (((msr) >> 8) & 0x3F)
+#define        AMD_17H_CUR_FID(msr)                    ((msr) & 0xFF)
+
 #define        HWPSTATE_DEBUG(dev, msg...)                     \
-       do{                                             \
-               if(hwpstate_verbose)                    \
+       do {                                            \
+               if (hwpstate_verbose)                   \
                        device_printf(dev, msg);        \
-       }while(0)
+       } while (0)
 
 struct hwpstate_setting {
        int     freq;           /* CPU clock in Mhz or 100ths of a percent. */
@@ -117,11 +121,14 @@ static int        
hwpstate_get_info_from_acpi_perf(device_t d
 static int     hwpstate_get_info_from_msr(device_t dev);
 static int     hwpstate_goto_pstate(device_t dev, int pstate_id);
 
-static int     hwpstate_verbose = 0;
-SYSCTL_INT(_debug, OID_AUTO, hwpstate_verbose, CTLFLAG_RW | CTLFLAG_TUN,
-       &hwpstate_verbose, 0, "Debug hwpstate");
-TUNABLE_INT("debug.hwpstate_verbose", &hwpstate_verbose);
+static int     hwpstate_verbose;
+SYSCTL_INT(_debug, OID_AUTO, hwpstate_verbose, CTLFLAG_RWTUN,
+    &hwpstate_verbose, 0, "Debug hwpstate");
 
+static int     hwpstate_verify;
+SYSCTL_INT(_debug, OID_AUTO, hwpstate_verify, CTLFLAG_RWTUN,
+    &hwpstate_verify, 0, "Verify P-state after setting");
+
 static device_method_t hwpstate_methods[] = {
        /* Device interface */
        DEVMETHOD(device_identify,      hwpstate_identify),
@@ -155,61 +162,69 @@ DRIVER_MODULE(hwpstate, cpu, hwpstate_driver, hwpstate
  * Go to Px-state on all cpus considering the limit.
  */
 static int
-hwpstate_goto_pstate(device_t dev, int pstate)
+hwpstate_goto_pstate(device_t dev, int id)
 {
-       int i;
+       sbintime_t sbt;
        uint64_t msr;
-       int j;
-       int limit;
-       int id = pstate;
-       int error;
-       
+       int cpu, i, j, limit;
+
        /* get the current pstate limit */
        msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
        limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr);
-       if(limit > id)
+       if (limit > id)
                id = limit;
 
+       cpu = curcpu;
+       HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, cpu);
+       /* Go To Px-state */
+       wrmsr(MSR_AMD_10H_11H_CONTROL, id);
+
        /*
         * We are going to the same Px-state on all cpus.
         * Probably should take _PSD into account.
         */
-       error = 0;
        CPU_FOREACH(i) {
+               if (i == cpu)
+                       continue;
+
                /* Bind to each cpu. */
                thread_lock(curthread);
                sched_bind(curthread, i);
                thread_unlock(curthread);
-               HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n",
-                       id, PCPU_GET(cpuid));
+               HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, i);
                /* Go To Px-state */
                wrmsr(MSR_AMD_10H_11H_CONTROL, id);
        }
-       CPU_FOREACH(i) {
-               /* Bind to each cpu. */
-               thread_lock(curthread);
-               sched_bind(curthread, i);
-               thread_unlock(curthread);
-               /* wait loop (100*100 usec is enough ?) */
-               for(j = 0; j < 100; j++){
-                       /* get the result. not assure msr=id */
-                       msr = rdmsr(MSR_AMD_10H_11H_STATUS);
-                       if(msr == id){
-                               break;
+
+       /*
+        * Verify whether each core is in the requested P-state.
+        */
+       if (hwpstate_verify) {
+               CPU_FOREACH(i) {
+                       thread_lock(curthread);
+                       sched_bind(curthread, i);
+                       thread_unlock(curthread);
+                       /* wait loop (100*100 usec is enough ?) */
+                       for (j = 0; j < 100; j++) {
+                               /* get the result. not assure msr=id */
+                               msr = rdmsr(MSR_AMD_10H_11H_STATUS);
+                               if (msr == id)
+                                       break;
+                               sbt = SBT_1MS / 10;
+                               tsleep_sbt(dev, PZERO, "pstate_goto", sbt,
+                                   sbt >> tc_precexp, 0);
                        }
-                       DELAY(100);
+                       HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n",
+                           (int)msr, i);
+                       if (msr != id) {
+                               HWPSTATE_DEBUG(dev,
+                                   "error: loop is not enough.\n");
+                               return (ENXIO);
+                       }
                }
-               HWPSTATE_DEBUG(dev, "result  P%d-state on cpu%d\n",
-                   (int)msr, PCPU_GET(cpuid));
-               if (msr != id) {
-                       HWPSTATE_DEBUG(dev, "error: loop is not enough.\n");
-                       error = ENXIO;
-               }
        }
-       thread_lock(curthread);
-       sched_unbind(curthread);
-       thread_unlock(curthread);
-       return (error);
+
+       return (0);
 }
 
 static int
@@ -243,7 +258,7 @@ hwpstate_get(device_t dev, struct cf_setting *cf)
        if (cf == NULL)
                return (EINVAL);
        msr = rdmsr(MSR_AMD_10H_11H_STATUS);
-       if(msr >= sc->cfnum)
+       if (msr >= sc->cfnum)
                return (EINVAL);
        set = sc->hwpstate_settings[msr];
 
@@ -368,7 +383,8 @@ hwpstate_probe(device_t dev)
                 */
                msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
                if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) {
-                       HWPSTATE_DEBUG(dev, "msr and acpi _PSS count 
mismatch.\n");
+                       HWPSTATE_DEBUG(dev, "MSR (%jd) and ACPI _PSS (%d)"
+                           " count mismatch\n", (intmax_t)msr, sc->cfnum);
                        error = TRUE;
                }
        }
@@ -417,7 +433,7 @@ hwpstate_get_info_from_msr(device_t dev)
                fid = AMD_10H_11H_CUR_FID(msr);
 
                /* Convert fid/did to frequency. */
-               switch(family) {
+               switch (family) {
                case 0x11:
                        hwpstate_set[i].freq = (100 * (fid + 0x08)) >> did;
                        break;
@@ -427,8 +443,18 @@ hwpstate_get_info_from_msr(device_t dev)
                case 0x16:
                        hwpstate_set[i].freq = (100 * (fid + 0x10)) >> did;
                        break;
+               case 0x17:
+                       did = AMD_17H_CUR_DID(msr);
+                       if (did == 0) {
+                               HWPSTATE_DEBUG(dev, "unexpected did: 0\n");
+                               did = 1;
+                       }
+                       fid = AMD_17H_CUR_FID(msr);
+                       hwpstate_set[i].freq = (200 * fid) / did;
+                       break;
                default:
-                       HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family 
0x%02x CPU's are not implemented yet. sorry.\n", family);
+                       HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family"
+                           " 0x%02x CPUs are not supported yet\n", family);
                        return (ENXIO);
                }
                hwpstate_set[i].pstate_id = i;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to