v4.19.13 snapshot.
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
new file mode 100644
index 0000000..ccd08dd
--- /dev/null
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -0,0 +1,648 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <getopt.h>
+
+#include "cpufreq.h"
+#include "helpers/sysfs.h"
+#include "helpers/helpers.h"
+#include "helpers/bitmask.h"
+
+#define LINE_LEN 10
+
+static unsigned int count_cpus(void)
+{
+	FILE *fp;
+	char value[LINE_LEN];
+	unsigned int ret = 0;
+	unsigned int cpunr = 0;
+
+	fp = fopen("/proc/stat", "r");
+	if (!fp) {
+		printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
+		return 1;
+	}
+
+	while (!feof(fp)) {
+		if (!fgets(value, LINE_LEN, fp))
+			continue;
+		value[LINE_LEN - 1] = '\0';
+		if (strlen(value) < (LINE_LEN - 2))
+			continue;
+		if (strstr(value, "cpu "))
+			continue;
+		if (sscanf(value, "cpu%d ", &cpunr) != 1)
+			continue;
+		if (cpunr > ret)
+			ret = cpunr;
+	}
+	fclose(fp);
+
+	/* cpu count starts from 0, on error return 1 (UP) */
+	return ret + 1;
+}
+
+
+static void proc_cpufreq_output(void)
+{
+	unsigned int cpu, nr_cpus;
+	struct cpufreq_policy *policy;
+	unsigned int min_pctg = 0;
+	unsigned int max_pctg = 0;
+	unsigned long min, max;
+
+	printf(_("          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"));
+
+	nr_cpus = count_cpus();
+	for (cpu = 0; cpu < nr_cpus; cpu++) {
+		policy = cpufreq_get_policy(cpu);
+		if (!policy)
+			continue;
+
+		if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
+			max = 0;
+		} else {
+			min_pctg = (policy->min * 100) / max;
+			max_pctg = (policy->max * 100) / max;
+		}
+		printf("CPU%3d    %9lu kHz (%3d %%)  -  %9lu kHz (%3d %%)  -  %s\n",
+			cpu , policy->min, max ? min_pctg : 0, policy->max,
+			max ? max_pctg : 0, policy->governor);
+
+		cpufreq_put_policy(policy);
+	}
+}
+
+static int no_rounding;
+static void print_speed(unsigned long speed)
+{
+	unsigned long tmp;
+
+	if (no_rounding) {
+		if (speed > 1000000)
+			printf("%u.%06u GHz", ((unsigned int) speed/1000000),
+				((unsigned int) speed%1000000));
+		else if (speed > 1000)
+			printf("%u.%03u MHz", ((unsigned int) speed/1000),
+				(unsigned int) (speed%1000));
+		else
+			printf("%lu kHz", speed);
+	} else {
+		if (speed > 1000000) {
+			tmp = speed%10000;
+			if (tmp >= 5000)
+				speed += 10000;
+			printf("%u.%02u GHz", ((unsigned int) speed/1000000),
+				((unsigned int) (speed%1000000)/10000));
+		} else if (speed > 100000) {
+			tmp = speed%1000;
+			if (tmp >= 500)
+				speed += 1000;
+			printf("%u MHz", ((unsigned int) speed/1000));
+		} else if (speed > 1000) {
+			tmp = speed%100;
+			if (tmp >= 50)
+				speed += 100;
+			printf("%u.%01u MHz", ((unsigned int) speed/1000),
+				((unsigned int) (speed%1000)/100));
+		}
+	}
+
+	return;
+}
+
+static void print_duration(unsigned long duration)
+{
+	unsigned long tmp;
+
+	if (no_rounding) {
+		if (duration > 1000000)
+			printf("%u.%06u ms", ((unsigned int) duration/1000000),
+				((unsigned int) duration%1000000));
+		else if (duration > 100000)
+			printf("%u us", ((unsigned int) duration/1000));
+		else if (duration > 1000)
+			printf("%u.%03u us", ((unsigned int) duration/1000),
+				((unsigned int) duration%1000));
+		else
+			printf("%lu ns", duration);
+	} else {
+		if (duration > 1000000) {
+			tmp = duration%10000;
+			if (tmp >= 5000)
+				duration += 10000;
+			printf("%u.%02u ms", ((unsigned int) duration/1000000),
+				((unsigned int) (duration%1000000)/10000));
+		} else if (duration > 100000) {
+			tmp = duration%1000;
+			if (tmp >= 500)
+				duration += 1000;
+			printf("%u us", ((unsigned int) duration / 1000));
+		} else if (duration > 1000) {
+			tmp = duration%100;
+			if (tmp >= 50)
+				duration += 100;
+			printf("%u.%01u us", ((unsigned int) duration/1000),
+				((unsigned int) (duration%1000)/100));
+		} else
+			printf("%lu ns", duration);
+	}
+	return;
+}
+
+/* --boost / -b */
+
+static int get_boost_mode(unsigned int cpu)
+{
+	int support, active, b_states = 0, ret, pstate_no, i;
+	/* ToDo: Make this more global */
+	unsigned long pstates[MAX_HW_PSTATES] = {0,};
+
+	if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
+	    cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
+		return 0;
+
+	ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
+	if (ret) {
+		printf(_("Error while evaluating Boost Capabilities"
+				" on CPU %d -- are you root?\n"), cpu);
+		return ret;
+	}
+	/* P state changes via MSR are identified via cpuid 80000007
+	   on Intel and AMD, but we assume boost capable machines can do that
+	   if (cpuid_eax(0x80000000) >= 0x80000007
+	   && (cpuid_edx(0x80000007) & (1 << 7)))
+	*/
+
+	printf(_("  boost state support:\n"));
+
+	printf(_("    Supported: %s\n"), support ? _("yes") : _("no"));
+	printf(_("    Active: %s\n"), active ? _("yes") : _("no"));
+
+	if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+	    cpupower_cpu_info.family >= 0x10) {
+		ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
+				     pstates, &pstate_no);
+		if (ret)
+			return ret;
+
+		printf(_("    Boost States: %d\n"), b_states);
+		printf(_("    Total States: %d\n"), pstate_no);
+		for (i = 0; i < pstate_no; i++) {
+			if (!pstates[i])
+				continue;
+			if (i < b_states)
+				printf(_("    Pstate-Pb%d: %luMHz (boost state)"
+					 "\n"), i, pstates[i]);
+			else
+				printf(_("    Pstate-P%d:  %luMHz\n"),
+				       i - b_states, pstates[i]);
+		}
+	} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) {
+		double bclk;
+		unsigned long long intel_turbo_ratio = 0;
+		unsigned int ratio;
+
+		/* Any way to autodetect this ? */
+		if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB)
+			bclk = 100.00;
+		else
+			bclk = 133.33;
+		intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu);
+		dprint ("    Ratio: 0x%llx - bclk: %f\n",
+			intel_turbo_ratio, bclk);
+
+		ratio = (intel_turbo_ratio >> 24) & 0xFF;
+		if (ratio)
+			printf(_("    %.0f MHz max turbo 4 active cores\n"),
+			       ratio * bclk);
+
+		ratio = (intel_turbo_ratio >> 16) & 0xFF;
+		if (ratio)
+			printf(_("    %.0f MHz max turbo 3 active cores\n"),
+			       ratio * bclk);
+
+		ratio = (intel_turbo_ratio >> 8) & 0xFF;
+		if (ratio)
+			printf(_("    %.0f MHz max turbo 2 active cores\n"),
+			       ratio * bclk);
+
+		ratio = (intel_turbo_ratio >> 0) & 0xFF;
+		if (ratio)
+			printf(_("    %.0f MHz max turbo 1 active cores\n"),
+			       ratio * bclk);
+	}
+	return 0;
+}
+
+/* --freq / -f */
+
+static int get_freq_kernel(unsigned int cpu, unsigned int human)
+{
+	unsigned long freq = cpufreq_get_freq_kernel(cpu);
+	printf(_("  current CPU frequency: "));
+	if (!freq) {
+		printf(_(" Unable to call to kernel\n"));
+		return -EINVAL;
+	}
+	if (human) {
+		print_speed(freq);
+	} else
+		printf("%lu", freq);
+	printf(_(" (asserted by call to kernel)\n"));
+	return 0;
+}
+
+
+/* --hwfreq / -w */
+
+static int get_freq_hardware(unsigned int cpu, unsigned int human)
+{
+	unsigned long freq = cpufreq_get_freq_hardware(cpu);
+	printf(_("  current CPU frequency: "));
+	if (!freq) {
+		printf("Unable to call hardware\n");
+		return -EINVAL;
+	}
+	if (human) {
+		print_speed(freq);
+	} else
+		printf("%lu", freq);
+	printf(_(" (asserted by call to hardware)\n"));
+	return 0;
+}
+
+/* --hwlimits / -l */
+
+static int get_hardware_limits(unsigned int cpu, unsigned int human)
+{
+	unsigned long min, max;
+
+	if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
+		printf(_("Not Available\n"));
+		return -EINVAL;
+	}
+
+	if (human) {
+		printf(_("  hardware limits: "));
+		print_speed(min);
+		printf(" - ");
+		print_speed(max);
+		printf("\n");
+	} else {
+		printf("%lu %lu\n", min, max);
+	}
+	return 0;
+}
+
+/* --driver / -d */
+
+static int get_driver(unsigned int cpu)
+{
+	char *driver = cpufreq_get_driver(cpu);
+	if (!driver) {
+		printf(_("  no or unknown cpufreq driver is active on this CPU\n"));
+		return -EINVAL;
+	}
+	printf("  driver: %s\n", driver);
+	cpufreq_put_driver(driver);
+	return 0;
+}
+
+/* --policy / -p */
+
+static int get_policy(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
+	if (!policy) {
+		printf(_("  Unable to determine current policy\n"));
+		return -EINVAL;
+	}
+	printf(_("  current policy: frequency should be within "));
+	print_speed(policy->min);
+	printf(_(" and "));
+	print_speed(policy->max);
+
+	printf(".\n                  ");
+	printf(_("The governor \"%s\" may decide which speed to use\n"
+	       "                  within this range.\n"),
+	       policy->governor);
+	cpufreq_put_policy(policy);
+	return 0;
+}
+
+/* --governors / -g */
+
+static int get_available_governors(unsigned int cpu)
+{
+	struct cpufreq_available_governors *governors =
+		cpufreq_get_available_governors(cpu);
+
+	printf(_("  available cpufreq governors: "));
+	if (!governors) {
+		printf(_("Not Available\n"));
+		return -EINVAL;
+	}
+
+	while (governors->next) {
+		printf("%s ", governors->governor);
+		governors = governors->next;
+	}
+	printf("%s\n", governors->governor);
+	cpufreq_put_available_governors(governors);
+	return 0;
+}
+
+
+/* --affected-cpus  / -a */
+
+static int get_affected_cpus(unsigned int cpu)
+{
+	struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
+
+	printf(_("  CPUs which need to have their frequency coordinated by software: "));
+	if (!cpus) {
+		printf(_("Not Available\n"));
+		return -EINVAL;
+	}
+
+	while (cpus->next) {
+		printf("%d ", cpus->cpu);
+		cpus = cpus->next;
+	}
+	printf("%d\n", cpus->cpu);
+	cpufreq_put_affected_cpus(cpus);
+	return 0;
+}
+
+/* --related-cpus  / -r */
+
+static int get_related_cpus(unsigned int cpu)
+{
+	struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
+
+	printf(_("  CPUs which run at the same hardware frequency: "));
+	if (!cpus) {
+		printf(_("Not Available\n"));
+		return -EINVAL;
+	}
+
+	while (cpus->next) {
+		printf("%d ", cpus->cpu);
+		cpus = cpus->next;
+	}
+	printf("%d\n", cpus->cpu);
+	cpufreq_put_related_cpus(cpus);
+	return 0;
+}
+
+/* --stats / -s */
+
+static int get_freq_stats(unsigned int cpu, unsigned int human)
+{
+	unsigned long total_trans = cpufreq_get_transitions(cpu);
+	unsigned long long total_time;
+	struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
+	while (stats) {
+		if (human) {
+			print_speed(stats->frequency);
+			printf(":%.2f%%",
+				(100.0 * stats->time_in_state) / total_time);
+		} else
+			printf("%lu:%llu",
+				stats->frequency, stats->time_in_state);
+		stats = stats->next;
+		if (stats)
+			printf(", ");
+	}
+	cpufreq_put_stats(stats);
+	if (total_trans)
+		printf("  (%lu)\n", total_trans);
+	return 0;
+}
+
+/* --latency / -y */
+
+static int get_latency(unsigned int cpu, unsigned int human)
+{
+	unsigned long latency = cpufreq_get_transition_latency(cpu);
+
+	printf(_("  maximum transition latency: "));
+	if (!latency || latency == UINT_MAX) {
+		printf(_(" Cannot determine or is not supported.\n"));
+		return -EINVAL;
+	}
+
+	if (human) {
+		print_duration(latency);
+		printf("\n");
+	} else
+		printf("%lu\n", latency);
+	return 0;
+}
+
+static void debug_output_one(unsigned int cpu)
+{
+	struct cpufreq_available_frequencies *freqs;
+
+	get_driver(cpu);
+	get_related_cpus(cpu);
+	get_affected_cpus(cpu);
+	get_latency(cpu, 1);
+	get_hardware_limits(cpu, 1);
+
+	freqs = cpufreq_get_available_frequencies(cpu);
+	if (freqs) {
+		printf(_("  available frequency steps:  "));
+		while (freqs->next) {
+			print_speed(freqs->frequency);
+			printf(", ");
+			freqs = freqs->next;
+		}
+		print_speed(freqs->frequency);
+		printf("\n");
+		cpufreq_put_available_frequencies(freqs);
+	}
+
+	get_available_governors(cpu);
+	get_policy(cpu);
+	if (get_freq_hardware(cpu, 1) < 0)
+		get_freq_kernel(cpu, 1);
+	get_boost_mode(cpu);
+}
+
+static struct option info_opts[] = {
+	{"debug",	 no_argument,		 NULL,	 'e'},
+	{"boost",	 no_argument,		 NULL,	 'b'},
+	{"freq",	 no_argument,		 NULL,	 'f'},
+	{"hwfreq",	 no_argument,		 NULL,	 'w'},
+	{"hwlimits",	 no_argument,		 NULL,	 'l'},
+	{"driver",	 no_argument,		 NULL,	 'd'},
+	{"policy",	 no_argument,		 NULL,	 'p'},
+	{"governors",	 no_argument,		 NULL,	 'g'},
+	{"related-cpus",  no_argument,	 NULL,	 'r'},
+	{"affected-cpus", no_argument,	 NULL,	 'a'},
+	{"stats",	 no_argument,		 NULL,	 's'},
+	{"latency",	 no_argument,		 NULL,	 'y'},
+	{"proc",	 no_argument,		 NULL,	 'o'},
+	{"human",	 no_argument,		 NULL,	 'm'},
+	{"no-rounding", no_argument,	 NULL,	 'n'},
+	{ },
+};
+
+int cmd_freq_info(int argc, char **argv)
+{
+	extern char *optarg;
+	extern int optind, opterr, optopt;
+	int ret = 0, cont = 1;
+	unsigned int cpu = 0;
+	unsigned int human = 0;
+	int output_param = 0;
+
+	do {
+		ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts,
+				  NULL);
+		switch (ret) {
+		case '?':
+			output_param = '?';
+			cont = 0;
+			break;
+		case -1:
+			cont = 0;
+			break;
+		case 'b':
+		case 'o':
+		case 'a':
+		case 'r':
+		case 'g':
+		case 'p':
+		case 'd':
+		case 'l':
+		case 'w':
+		case 'f':
+		case 'e':
+		case 's':
+		case 'y':
+			if (output_param) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			output_param = ret;
+			break;
+		case 'm':
+			if (human) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			human = 1;
+			break;
+		case 'n':
+			no_rounding = 1;
+			break;
+		default:
+			fprintf(stderr, "invalid or unknown argument\n");
+			return EXIT_FAILURE;
+		}
+	} while (cont);
+
+	switch (output_param) {
+	case 'o':
+		if (!bitmask_isallclear(cpus_chosen)) {
+			printf(_("The argument passed to this tool can't be "
+				 "combined with passing a --cpu argument\n"));
+			return -EINVAL;
+		}
+		break;
+	case 0:
+		output_param = 'e';
+	}
+
+	ret = 0;
+
+	/* Default is: show output of CPU 0 only */
+	if (bitmask_isallclear(cpus_chosen))
+		bitmask_setbit(cpus_chosen, 0);
+
+	switch (output_param) {
+	case -1:
+		printf(_("You can't specify more than one --cpu parameter and/or\n"
+		       "more than one output-specific argument\n"));
+		return -EINVAL;
+	case '?':
+		printf(_("invalid or unknown argument\n"));
+		return -EINVAL;
+	case 'o':
+		proc_cpufreq_output();
+		return EXIT_SUCCESS;
+	}
+
+	for (cpu = bitmask_first(cpus_chosen);
+	     cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+		if (!bitmask_isbitset(cpus_chosen, cpu))
+			continue;
+
+		printf(_("analyzing CPU %d:\n"), cpu);
+
+		if (sysfs_is_cpu_online(cpu) != 1) {
+			printf(_(" *is offline\n"));
+			printf("\n");
+			continue;
+		}
+
+		switch (output_param) {
+		case 'b':
+			get_boost_mode(cpu);
+			break;
+		case 'e':
+			debug_output_one(cpu);
+			break;
+		case 'a':
+			ret = get_affected_cpus(cpu);
+			break;
+		case 'r':
+			ret = get_related_cpus(cpu);
+			break;
+		case 'g':
+			ret = get_available_governors(cpu);
+			break;
+		case 'p':
+			ret = get_policy(cpu);
+			break;
+		case 'd':
+			ret = get_driver(cpu);
+			break;
+		case 'l':
+			ret = get_hardware_limits(cpu, human);
+			break;
+		case 'w':
+			ret = get_freq_hardware(cpu, human);
+			break;
+		case 'f':
+			ret = get_freq_kernel(cpu, human);
+			break;
+		case 's':
+			ret = get_freq_stats(cpu, human);
+			break;
+		case 'y':
+			ret = get_latency(cpu, human);
+			break;
+		}
+		if (ret)
+			return ret;
+	}
+	return ret;
+}