Index: usr.sbin/powerd/powerd.c =================================================================== --- usr.sbin/powerd/powerd.c (revision 265255) +++ usr.sbin/powerd/powerd.c (working copy) @@ -175,7 +175,62 @@ return (0); } +/* + * Fetch minimum and maximum available frequencies. + * + * The fetch can start at any given minimum/maximum values with which + * to cap the search for. For example, if minfreq is set at 500, then + * no frequencies below 500 will be considered. + * + * A value of -1 for each parameter as "no default" - ie, find the + * largest and/or smallest available. + */ static int +fetch_min_max_freqs(int *minfreq, int *maxfreq) +{ + char *freqstr = NULL, *p, *q; + int i, j; + size_t len = 0; + int freq, pwr; + int ret; + int numfreqs = 0; + + if (sysctl(levels_mib, 4, NULL, &len, NULL, 0)) + return (-1); + if ((freqstr = malloc(len)) == NULL) + return (-1); + if (sysctl(levels_mib, 4, freqstr, &len, NULL, 0)) + return (-1); + + /* XXX why not strsep? */ + for (p = freqstr; *p != '\0'; p++) + if (*p == ' ') + numfreqs++; + + for (i = 0, j = 0, p = freqstr; i < numfreqs; i++) { + q = strchr(p, ' '); + if (q != NULL) + *q = '\0'; + if (sscanf(p, "%d/%d", &freq, &pwr) != 2) { + ret = -1; + goto finish; + } + + if (*minfreq == -1 || freq < *minfreq) + *minfreq = freq; + if (*maxfreq == -1 || freq > *maxfreq) + *maxfreq = freq; + + p = q + 1; + } + +finish: + free(freqstr); + return (0); + +} + +static int read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, int maxfreq) { char *freqstr, *p, *q; @@ -450,6 +505,7 @@ const char *pidfile = NULL; int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load; int minfreq = -1, maxfreq = -1; + int minfreq_avail, maxfreq_avail; int ch, mode, mode_ac, mode_battery, mode_none, idle, to; uint64_t mjoules_used; size_t len; @@ -543,6 +599,20 @@ if (sysctlnametomib("dev.cpu.0.freq_levels", levels_mib, &len)) err(1, "lookup freq_levels"); + /* Fetch the minimum/maximum frequency range supported */ + minfreq_avail = -1; + maxfreq_avail = -1; + if (fetch_min_max_freqs(&minfreq_avail, &maxfreq_avail) != 0) + err(1, "error reading supported CPU frequencies"); + + /* + * If no minimum frequency is given, cap it at 50% of the + * frequency. Some boards go all the way down to 100MHz + * which is extremely slow to .. well, do anything from. + */ + if (minfreq == -1) + minfreq = maxfreq_avail / 2; + /* Check if we can read the load and supported freqs. */ if (read_usage_times(NULL)) err(1, "read_usage_times");