^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <getopt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "cpufreq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "cpuidle.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "helpers/helpers.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define NORM_FREQ_LEN 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static struct option set_opts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {"min", required_argument, NULL, 'd'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {"max", required_argument, NULL, 'u'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {"governor", required_argument, NULL, 'g'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {"freq", required_argument, NULL, 'f'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {"related", no_argument, NULL, 'r'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void print_error(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) printf(_("Error setting new values. Common errors:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "- Do you have proper administration rights? (super-user?)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) "- Is the governor you requested available and modprobed?\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) "- Trying to set an invalid policy?\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) "- Trying to set a specific frequency, but userspace governor is not available,\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) " for example because of hardware which cannot be set to a specific frequency\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) " or because the userspace governor isn't loaded?\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct freq_units {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) char *str_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int power_of_ten;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) const struct freq_units def_units[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {"hz", -3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {"khz", 0}, /* default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {"mhz", 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {"ghz", 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {"thz", 9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {NULL, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static void print_unknown_arg(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) printf(_("invalid or unknown argument\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static unsigned long string_to_frequency(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) char normalized[NORM_FREQ_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) const struct freq_units *unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const char *scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned long freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int power = 0, match_count = 0, i, cp, pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) while (*str == '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (*scan == '.' && match_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) match_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) else if (*scan == '.' && match_count == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (*scan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) match_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) for (unit = def_units; unit->str_unit; unit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) for (i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) scan[i] && tolower(scan[i]) == unit->str_unit[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (scan[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) match_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) power = unit->power_of_ten;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (match_count != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* count the number of digits to be copied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) for (cp = 0; isdigit(str[cp]); cp++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (str[cp] == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) while (power > -1 && isdigit(str[cp+1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) cp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) power--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (power >= -1) { /* not enough => pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pad = power + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) } else { /* too much => strip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) pad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) cp += power + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* check bounds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* copy digits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for (i = 0; i < cp; i++, str++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (*str == '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) normalized[i] = *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* and pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) for (; i < cp + pad; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) normalized[i] = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* round up, down ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) match_count = (normalized[i-1] >= '5');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* and drop the decimal part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* final conversion (and applying rounding) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) freq = strtoul(normalized, &end, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (match_count && freq != ULONG_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) freq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (!cur_pol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) printf(_("wrong, unknown or unhandled CPU?\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!new_pol->min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) new_pol->min = cur_pol->min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!new_pol->max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) new_pol->max = cur_pol->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!new_pol->governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) new_pol->governor = cur_pol->governor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ret = cpufreq_set_policy(cpu, new_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) cpufreq_put_policy(cur_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long freq, unsigned int pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) switch (pc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return cpufreq_set_frequency(cpu, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* if only one value of a policy is to be changed, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * use a "fast path".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (new_pol->min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return cpufreq_modify_policy_min(cpu, new_pol->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) else if (new_pol->max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return cpufreq_modify_policy_max(cpu, new_pol->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) else if (new_pol->governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return cpufreq_modify_policy_governor(cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) new_pol->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* slow path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return do_new_policy(cpu, new_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int cmd_freq_set(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) extern char *optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) extern int optind, opterr, optopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int ret = 0, cont = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int double_parm = 0, related = 0, policychange = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned long freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) char gov[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct cpufreq_policy new_pol = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .max = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .governor = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* parameter parsing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = getopt_long(argc, argv, "d:u:g:f:r", set_opts, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case '?':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) print_unknown_arg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) cont = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (related)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) double_parm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) related++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (new_pol.min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) double_parm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) policychange++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) new_pol.min = string_to_frequency(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (new_pol.min == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) print_unknown_arg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (new_pol.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) double_parm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) policychange++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) new_pol.max = string_to_frequency(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (new_pol.max == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) print_unknown_arg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) double_parm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) freq = string_to_frequency(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (freq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) print_unknown_arg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (new_pol.governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) double_parm++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) policychange++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) print_unknown_arg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if ((sscanf(optarg, "%19s", gov)) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) print_unknown_arg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) new_pol.governor = gov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) } while (cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* parameter checking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (double_parm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) printf("the same parameter was passed more than once\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (freq && policychange) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) printf(_("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) "-g/--governor parameters\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!freq && !policychange) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) printf(_("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) "-g/--governor must be passed\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Default is: set all CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (bitmask_isallclear(cpus_chosen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) bitmask_setall(cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* Also set frequency settings for related CPUs if -r is passed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (related) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) for (cpu = bitmask_first(cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) cpu <= bitmask_last(cpus_chosen); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct cpufreq_affected_cpus *cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!bitmask_isbitset(cpus_chosen, cpu) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) cpupower_is_cpu_online(cpu) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) cpus = cpufreq_get_related_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) while (cpus->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) bitmask_setbit(cpus_chosen, cpus->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) cpus = cpus->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Set the last cpu in related cpus list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) bitmask_setbit(cpus_chosen, cpus->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) cpufreq_put_related_cpus(cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /* loop over CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) for (cpu = bitmask_first(cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) cpu <= bitmask_last(cpus_chosen); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!bitmask_isbitset(cpus_chosen, cpu) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) cpupower_is_cpu_online(cpu) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) printf(_("Setting cpu: %d\n"), cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ret = do_one_cpu(cpu, &new_pol, freq, policychange);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) print_error();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }