162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <unistd.h> 862306a36Sopenharmony_ci#include <stdio.h> 962306a36Sopenharmony_ci#include <stdlib.h> 1062306a36Sopenharmony_ci#include <errno.h> 1162306a36Sopenharmony_ci#include <string.h> 1262306a36Sopenharmony_ci#include <getopt.h> 1362306a36Sopenharmony_ci#include <sys/utsname.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "helpers/helpers.h" 1662306a36Sopenharmony_ci#include "helpers/sysfs.h" 1762306a36Sopenharmony_ci#include "helpers/bitmask.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic struct option set_opts[] = { 2062306a36Sopenharmony_ci {"perf-bias", required_argument, NULL, 'b'}, 2162306a36Sopenharmony_ci {"epp", required_argument, NULL, 'e'}, 2262306a36Sopenharmony_ci {"amd-pstate-mode", required_argument, NULL, 'm'}, 2362306a36Sopenharmony_ci {"turbo-boost", required_argument, NULL, 't'}, 2462306a36Sopenharmony_ci { }, 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void print_wrong_arg_exit(void) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci printf(_("invalid or unknown argument\n")); 3062306a36Sopenharmony_ci exit(EXIT_FAILURE); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciint cmd_set(int argc, char **argv) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci extern char *optarg; 3662306a36Sopenharmony_ci extern int optind, opterr, optopt; 3762306a36Sopenharmony_ci unsigned int cpu; 3862306a36Sopenharmony_ci struct utsname uts; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci union { 4162306a36Sopenharmony_ci struct { 4262306a36Sopenharmony_ci int perf_bias:1; 4362306a36Sopenharmony_ci int epp:1; 4462306a36Sopenharmony_ci int mode:1; 4562306a36Sopenharmony_ci int turbo_boost:1; 4662306a36Sopenharmony_ci }; 4762306a36Sopenharmony_ci int params; 4862306a36Sopenharmony_ci } params; 4962306a36Sopenharmony_ci int perf_bias = 0, turbo_boost = 1; 5062306a36Sopenharmony_ci int ret = 0; 5162306a36Sopenharmony_ci char epp[30], mode[20]; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci ret = uname(&uts); 5462306a36Sopenharmony_ci if (!ret && (!strcmp(uts.machine, "ppc64le") || 5562306a36Sopenharmony_ci !strcmp(uts.machine, "ppc64"))) { 5662306a36Sopenharmony_ci fprintf(stderr, _("Subcommand not supported on POWER.\n")); 5762306a36Sopenharmony_ci return ret; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci setlocale(LC_ALL, ""); 6162306a36Sopenharmony_ci textdomain(PACKAGE); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci params.params = 0; 6462306a36Sopenharmony_ci /* parameter parsing */ 6562306a36Sopenharmony_ci while ((ret = getopt_long(argc, argv, "b:e:m:", 6662306a36Sopenharmony_ci set_opts, NULL)) != -1) { 6762306a36Sopenharmony_ci switch (ret) { 6862306a36Sopenharmony_ci case 'b': 6962306a36Sopenharmony_ci if (params.perf_bias) 7062306a36Sopenharmony_ci print_wrong_arg_exit(); 7162306a36Sopenharmony_ci perf_bias = atoi(optarg); 7262306a36Sopenharmony_ci if (perf_bias < 0 || perf_bias > 15) { 7362306a36Sopenharmony_ci printf(_("--perf-bias param out " 7462306a36Sopenharmony_ci "of range [0-%d]\n"), 15); 7562306a36Sopenharmony_ci print_wrong_arg_exit(); 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci params.perf_bias = 1; 7862306a36Sopenharmony_ci break; 7962306a36Sopenharmony_ci case 'e': 8062306a36Sopenharmony_ci if (params.epp) 8162306a36Sopenharmony_ci print_wrong_arg_exit(); 8262306a36Sopenharmony_ci if (sscanf(optarg, "%29s", epp) != 1) { 8362306a36Sopenharmony_ci print_wrong_arg_exit(); 8462306a36Sopenharmony_ci return -EINVAL; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci params.epp = 1; 8762306a36Sopenharmony_ci break; 8862306a36Sopenharmony_ci case 'm': 8962306a36Sopenharmony_ci if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) 9062306a36Sopenharmony_ci print_wrong_arg_exit(); 9162306a36Sopenharmony_ci if (params.mode) 9262306a36Sopenharmony_ci print_wrong_arg_exit(); 9362306a36Sopenharmony_ci if (sscanf(optarg, "%19s", mode) != 1) { 9462306a36Sopenharmony_ci print_wrong_arg_exit(); 9562306a36Sopenharmony_ci return -EINVAL; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci params.mode = 1; 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci case 't': 10062306a36Sopenharmony_ci if (params.turbo_boost) 10162306a36Sopenharmony_ci print_wrong_arg_exit(); 10262306a36Sopenharmony_ci turbo_boost = atoi(optarg); 10362306a36Sopenharmony_ci if (turbo_boost < 0 || turbo_boost > 1) { 10462306a36Sopenharmony_ci printf("--turbo-boost param out of range [0-1]\n"); 10562306a36Sopenharmony_ci print_wrong_arg_exit(); 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci params.turbo_boost = 1; 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci default: 11262306a36Sopenharmony_ci print_wrong_arg_exit(); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!params.params) 11762306a36Sopenharmony_ci print_wrong_arg_exit(); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (params.mode) { 12062306a36Sopenharmony_ci ret = cpupower_set_amd_pstate_mode(mode); 12162306a36Sopenharmony_ci if (ret) 12262306a36Sopenharmony_ci fprintf(stderr, "Error setting mode\n"); 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (params.turbo_boost) { 12662306a36Sopenharmony_ci ret = cpupower_set_turbo_boost(turbo_boost); 12762306a36Sopenharmony_ci if (ret) 12862306a36Sopenharmony_ci fprintf(stderr, "Error setting turbo-boost\n"); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Default is: set all CPUs */ 13262306a36Sopenharmony_ci if (bitmask_isallclear(cpus_chosen)) 13362306a36Sopenharmony_ci bitmask_setall(cpus_chosen); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* loop over CPUs */ 13662306a36Sopenharmony_ci for (cpu = bitmask_first(cpus_chosen); 13762306a36Sopenharmony_ci cpu <= bitmask_last(cpus_chosen); cpu++) { 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (!bitmask_isbitset(cpus_chosen, cpu)) 14062306a36Sopenharmony_ci continue; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (sysfs_is_cpu_online(cpu) != 1){ 14362306a36Sopenharmony_ci fprintf(stderr, _("Cannot set values on CPU %d:"), cpu); 14462306a36Sopenharmony_ci fprintf(stderr, _(" *is offline\n")); 14562306a36Sopenharmony_ci continue; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (params.perf_bias) { 14962306a36Sopenharmony_ci ret = cpupower_intel_set_perf_bias(cpu, perf_bias); 15062306a36Sopenharmony_ci if (ret) { 15162306a36Sopenharmony_ci fprintf(stderr, _("Error setting perf-bias " 15262306a36Sopenharmony_ci "value on CPU %d\n"), cpu); 15362306a36Sopenharmony_ci break; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (params.epp) { 15862306a36Sopenharmony_ci ret = cpupower_set_epp(cpu, epp); 15962306a36Sopenharmony_ci if (ret) { 16062306a36Sopenharmony_ci fprintf(stderr, 16162306a36Sopenharmony_ci "Error setting epp value on CPU %d\n", cpu); 16262306a36Sopenharmony_ci break; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci return ret; 16862306a36Sopenharmony_ci} 169