18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <unistd.h>
88c2ecf20Sopenharmony_ci#include <stdio.h>
98c2ecf20Sopenharmony_ci#include <stdlib.h>
108c2ecf20Sopenharmony_ci#include <errno.h>
118c2ecf20Sopenharmony_ci#include <string.h>
128c2ecf20Sopenharmony_ci#include <getopt.h>
138c2ecf20Sopenharmony_ci#include <sys/utsname.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "helpers/helpers.h"
168c2ecf20Sopenharmony_ci#include "helpers/sysfs.h"
178c2ecf20Sopenharmony_ci#include "helpers/bitmask.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic struct option set_opts[] = {
208c2ecf20Sopenharmony_ci	{"perf-bias", required_argument, NULL, 'b'},
218c2ecf20Sopenharmony_ci	{ },
228c2ecf20Sopenharmony_ci};
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic void print_wrong_arg_exit(void)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	printf(_("invalid or unknown argument\n"));
278c2ecf20Sopenharmony_ci	exit(EXIT_FAILURE);
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ciint cmd_set(int argc, char **argv)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	extern char *optarg;
338c2ecf20Sopenharmony_ci	extern int optind, opterr, optopt;
348c2ecf20Sopenharmony_ci	unsigned int cpu;
358c2ecf20Sopenharmony_ci	struct utsname uts;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	union {
388c2ecf20Sopenharmony_ci		struct {
398c2ecf20Sopenharmony_ci			int perf_bias:1;
408c2ecf20Sopenharmony_ci		};
418c2ecf20Sopenharmony_ci		int params;
428c2ecf20Sopenharmony_ci	} params;
438c2ecf20Sopenharmony_ci	int perf_bias = 0;
448c2ecf20Sopenharmony_ci	int ret = 0;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	ret = uname(&uts);
478c2ecf20Sopenharmony_ci	if (!ret && (!strcmp(uts.machine, "ppc64le") ||
488c2ecf20Sopenharmony_ci		     !strcmp(uts.machine, "ppc64"))) {
498c2ecf20Sopenharmony_ci		fprintf(stderr, _("Subcommand not supported on POWER.\n"));
508c2ecf20Sopenharmony_ci		return ret;
518c2ecf20Sopenharmony_ci	}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	setlocale(LC_ALL, "");
548c2ecf20Sopenharmony_ci	textdomain(PACKAGE);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	params.params = 0;
578c2ecf20Sopenharmony_ci	/* parameter parsing */
588c2ecf20Sopenharmony_ci	while ((ret = getopt_long(argc, argv, "b:",
598c2ecf20Sopenharmony_ci						set_opts, NULL)) != -1) {
608c2ecf20Sopenharmony_ci		switch (ret) {
618c2ecf20Sopenharmony_ci		case 'b':
628c2ecf20Sopenharmony_ci			if (params.perf_bias)
638c2ecf20Sopenharmony_ci				print_wrong_arg_exit();
648c2ecf20Sopenharmony_ci			perf_bias = atoi(optarg);
658c2ecf20Sopenharmony_ci			if (perf_bias < 0 || perf_bias > 15) {
668c2ecf20Sopenharmony_ci				printf(_("--perf-bias param out "
678c2ecf20Sopenharmony_ci					 "of range [0-%d]\n"), 15);
688c2ecf20Sopenharmony_ci				print_wrong_arg_exit();
698c2ecf20Sopenharmony_ci			}
708c2ecf20Sopenharmony_ci			params.perf_bias = 1;
718c2ecf20Sopenharmony_ci			break;
728c2ecf20Sopenharmony_ci		default:
738c2ecf20Sopenharmony_ci			print_wrong_arg_exit();
748c2ecf20Sopenharmony_ci		}
758c2ecf20Sopenharmony_ci	}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (!params.params)
788c2ecf20Sopenharmony_ci		print_wrong_arg_exit();
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/* Default is: set all CPUs */
818c2ecf20Sopenharmony_ci	if (bitmask_isallclear(cpus_chosen))
828c2ecf20Sopenharmony_ci		bitmask_setall(cpus_chosen);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	/* loop over CPUs */
858c2ecf20Sopenharmony_ci	for (cpu = bitmask_first(cpus_chosen);
868c2ecf20Sopenharmony_ci	     cpu <= bitmask_last(cpus_chosen); cpu++) {
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		if (!bitmask_isbitset(cpus_chosen, cpu))
898c2ecf20Sopenharmony_ci			continue;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci		if (sysfs_is_cpu_online(cpu) != 1){
928c2ecf20Sopenharmony_ci			fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
938c2ecf20Sopenharmony_ci			fprintf(stderr, _(" *is offline\n"));
948c2ecf20Sopenharmony_ci			continue;
958c2ecf20Sopenharmony_ci		}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci		if (params.perf_bias) {
988c2ecf20Sopenharmony_ci			ret = msr_intel_set_perf_bias(cpu, perf_bias);
998c2ecf20Sopenharmony_ci			if (ret) {
1008c2ecf20Sopenharmony_ci				fprintf(stderr, _("Error setting perf-bias "
1018c2ecf20Sopenharmony_ci						  "value on CPU %d\n"), cpu);
1028c2ecf20Sopenharmony_ci				break;
1038c2ecf20Sopenharmony_ci			}
1048c2ecf20Sopenharmony_ci		}
1058c2ecf20Sopenharmony_ci	}
1068c2ecf20Sopenharmony_ci	return ret;
1078c2ecf20Sopenharmony_ci}
108