powerd: Add options to limit CPU power domains' frequency
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 17 Jul 2015 14:50:06 +0000 (22:50 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 20 Jul 2015 02:03:31 +0000 (10:03 +0800)
usr.sbin/powerd/powerd.8
usr.sbin/powerd/powerd.c

index 010989a..6bb340d 100644 (file)
@@ -1,7 +1,7 @@
 .\" (c) Copyright 2010 by Matthew Dillon and Dima Ruban.  Permission to
 .\"    use and distribute based on the DragonFly copyright.
 .\"
-.Dd July 16, 2015
+.Dd July 17, 2015
 .Dt POWERD 8
 .Os
 .Sh NAME
@@ -10,6 +10,8 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl cdeftQ
+.Op Fl h Ar highest_freq
+.Op Fl l Ar lowest_freq
 .Op Fl p Ar hysteresis
 .Op Fl r Ar poll_time
 .Op Fl u Ar trigger_up
@@ -54,6 +56,16 @@ much
 (if any)
 on some of the modern Intel CPUs,
 when the CPU is idle.
+.It Fl h Ar highest_freq
+If CPU power domain frequency adjustment is enabled,
+then frequency of CPU power domains will not be set to a value higher
+than the specified limit.
+(unit: MHz)
+.It Fl l Ar lowest_freq
+If CPU power domain frequency adjustment is enabled,
+then frequency of CPU power domains will not be set to a value lower
+than the specified limit.
+(unit: MHz)
 .It Fl p Ar hysteresis
 Percent of the upper limit to subtract as an hysteresis value to scale
 down to the min performance.
index 655eead..436bd76 100644 (file)
@@ -145,6 +145,8 @@ static double TriggerDown;  /* load per cpu to force the min freq */
 static int HasPerfbias = 0;
 static int AdjustCpuFreq = 1;
 static int AdjustCstate = 0;
+static int HighestCpuFreq;
+static int LowestCpuFreq;
 
 static volatile int stopped;
 
@@ -172,7 +174,7 @@ main(int ac, char **av)
        srt = 8.0;      /* time for samples - 8 seconds */
        pollrate = 1.0; /* polling rate in seconds */
 
-       while ((ch = getopt(ac, av, "cdefp:r:tu:B:L:P:QT:")) != -1) {
+       while ((ch = getopt(ac, av, "cdefh:l:p:r:tu:B:L:P:QT:")) != -1) {
                switch(ch) {
                case 'c':
                        AdjustCstate = 1;
@@ -186,6 +188,12 @@ main(int ac, char **av)
                case 'f':
                        AdjustCpuFreq = 0;
                        break;
+               case 'h':
+                       HighestCpuFreq = strtol(optarg, NULL, 10);
+                       break;
+               case 'l':
+                       LowestCpuFreq = strtol(optarg, NULL, 10);
+                       break;
                case 'p':
                        Hysteresis = (int)strtol(optarg, NULL, 10);
                        break;
@@ -505,9 +513,11 @@ acpi_getcpufreq_str(int dom_id, int *highest0, int *lowest0)
        ptr = buf;
        highest = lowest = 0;
        while (ptr && (v = strtol(ptr, &ptr, 10)) > 0) {
-               if (lowest == 0 || lowest > v)
+               if ((lowest == 0 || lowest > v) &&
+                   (LowestCpuFreq <= 0 || v >= LowestCpuFreq))
                        lowest = v;
-               if (highest == 0 || highest < v)
+               if ((highest == 0 || highest < v) &&
+                   (HighestCpuFreq <= 0 || v <= HighestCpuFreq))
                        highest = v;
                /* 
                 * Detect turbo mode
@@ -526,7 +536,7 @@ acpi_getcpufreq_bin(int dom_id, int *highest0, int *lowest0)
        char sysid[64];
        int freq[MAXFREQ];
        size_t freqlen;
-       int freqcnt;
+       int freqcnt, i;
 
        /*
         * Retrieve availability list
@@ -540,11 +550,23 @@ acpi_getcpufreq_bin(int dom_id, int *highest0, int *lowest0)
        if (freqcnt == 0)
                return 0;
 
-       *lowest0 = freq[freqcnt - 1];
+       for (i = freqcnt - 1; i >= 0; --i) {
+               *lowest0 = freq[i];
+               if (LowestCpuFreq <= 0 || *lowest0 >= LowestCpuFreq)
+                       break;
+       }
 
+       i = 0;
        *highest0 = freq[0];
-       if (!TurboOpt && freqcnt > 1 && freq[0] - freq[1] == 1)
+       if (!TurboOpt && freqcnt > 1 && freq[0] - freq[1] == 1) {
+               i = 1;
                *highest0 = freq[1];
+       }
+       for (; i < freqcnt; ++i) {
+               if (HighestCpuFreq <= 0 || *highest0 <= HighestCpuFreq)
+                       break;
+               *highest0 = freq[i];
+       }
        return 1;
 }
 
@@ -564,6 +586,7 @@ void
 usage(void)
 {
        fprintf(stderr, "usage: powerd [-cdeftQ] [-p hysteresis] "
+           "[-h highest_freq] [-l lowest_freq] "
            "[-r poll_interval] [-u trigger_up] "
            "[-B min_battery_life] [-L low_battery_linger] "
            "[-P battery_poll_interval] [-T sample_interval]\n");
@@ -1081,6 +1104,9 @@ restore_perf(void)
 {
        cpumask_t ocpu_used, ocpu_pwrdom_used;
 
+       /* Remove highest cpu frequency limitation */
+       HighestCpuFreq = 0;
+
        ocpu_used = cpu_used;
        ocpu_pwrdom_used = cpu_pwrdom_used;