Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8851b4b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-tools'

* pm-tools:
  cpupower: Add Haswell family 0x45 specific idle monitor to show PC8,9,10 states
  cpupower: Haswell also supports the C-states introduced with SandyBridge
  cpupower: Introduce idle-set subcommand and C-state enabling/disabling
  cpupower: Implement disabling of cstate interface
  cpupower: Make idlestate usage unsigned
parents 37998bb0 7ee767b6
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -128,10 +128,12 @@ UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
	utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
	utils/helpers/pci.o utils/helpers/bitmask.o \
	utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
	utils/idle_monitor/hsw_ext_idle.o \
	utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
	utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
	utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
	utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
	utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o \
	utils/cpuidle-set.o

UTIL_SRC := $(UTIL_OBJS:.o=.c)

+9 −1
Original line number Diff line number Diff line
@@ -110,13 +110,21 @@ May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP
kernel frequency driver periodically cleared aperf/mperf registers in those
kernels.

.SS "Nehalem" "SandyBridge"
.SS "Nehalem" "SandyBridge" "HaswellExtended"
Intel Core and Package sleep state counters.
Threads (hyperthreaded cores) may not be able to enter deeper core states if
its sibling is utilized.
Deepest package sleep states may in reality show up as machine/platform wide
sleep states and can only be entered if all cores are idle. Look up Intel
manuals (some are provided in the References section) for further details.
The monitors are named after the CPU family where the sleep state capabilities
got introduced and may not match exactly the CPU name of the platform.
For example an IvyBridge processor has sleep state capabilities which got
introduced in Nehalem and SandyBridge processor families.
Thus on an IvyBridge processor one will get Nehalem and SandyBridge sleep
state monitors.
HaswellExtended extra package sleep state capabilities are available only in a
specific Haswell (family 0x45) and probably also other future processors.

.SS "Fam_12h" "Fam_14h"
AMD laptop and desktop processor (family 12h and 14h) sleep state counters.
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ extern int cmd_set(int argc, const char **argv);
extern int cmd_info(int argc, const char **argv);
extern int cmd_freq_set(int argc, const char **argv);
extern int cmd_freq_info(int argc, const char **argv);
extern int cmd_idle_set(int argc, const char **argv);
extern int cmd_idle_info(int argc, const char **argv);
extern int cmd_monitor(int argc, const char **argv);

+9 −15
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@

static void cpuidle_cpu_output(unsigned int cpu, int verbose)
{
	int idlestates, idlestate;
	unsigned int idlestates, idlestate;
	char *tmp;

	printf(_ ("Analyzing CPU %d:\n"), cpu);
@@ -31,10 +31,8 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
	if (idlestates == 0) {
		printf(_("CPU %u: No idle states\n"), cpu);
		return;
	} else if (idlestates <= 0) {
		printf(_("CPU %u: Can't read idle state info\n"), cpu);
		return;
	}

	printf(_("Number of idle states: %d\n"), idlestates);
	printf(_("Available idle states:"));
	for (idlestate = 0; idlestate < idlestates; idlestate++) {
@@ -50,10 +48,14 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
		return;

	for (idlestate = 0; idlestate < idlestates; idlestate++) {
		int disabled = sysfs_is_idlestate_disabled(cpu, idlestate);
		/* Disabled interface not supported on older kernels */
		if (disabled < 0)
			disabled = 0;
		tmp = sysfs_get_idlestate_name(cpu, idlestate);
		if (!tmp)
			continue;
		printf("%s:\n", tmp);
		printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : "");
		free(tmp);

		tmp = sysfs_get_idlestate_desc(cpu, idlestate);
@@ -98,21 +100,13 @@ static void cpuidle_general_output(void)
static void proc_cpuidle_cpu_output(unsigned int cpu)
{
	long max_allowed_cstate = 2000000000;
	int cstates, cstate;
	unsigned int cstate, cstates;

	cstates = sysfs_get_idlestate_count(cpu);
	if (cstates == 0) {
		/*
		 * Go on and print same useless info as you'd see with
		 * cat /proc/acpi/processor/../power
		 *	printf(_("CPU %u: No C-states available\n"), cpu);
		 *	return;
		 */
	} else if (cstates <= 0) {
		printf(_("CPU %u: Can't read C-state info\n"), cpu);
		printf(_("CPU %u: No C-states info\n"), cpu);
		return;
	}
	/* printf("Cstates: %d\n", cstates); */

	printf(_("active state:            C0\n"));
	printf(_("max_cstate:              C%u\n"), cstates-1);
+118 −0
Original line number Diff line number Diff line
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>

#include <getopt.h>

#include "cpufreq.h"
#include "helpers/helpers.h"
#include "helpers/sysfs.h"

static struct option info_opts[] = {
	{ .name = "disable",	.has_arg = required_argument,	.flag = NULL,	.val = 'd'},
	{ .name = "enable",	.has_arg = required_argument,	.flag = NULL,	.val = 'e'},
	{ },
};


int cmd_idle_set(int argc, char **argv)
{
	extern char *optarg;
	extern int optind, opterr, optopt;
	int ret = 0, cont = 1, param = 0, idlestate = 0;
	unsigned int cpu = 0;

	do {
		ret = getopt_long(argc, argv, "d:e:", info_opts, NULL);
		if (ret == -1)
			break;
		switch (ret) {
		case '?':
			param = '?';
			cont = 0;
			break;
		case 'd':
			if (param) {
				param = -1;
				cont = 0;
				break;
			}
			param = ret;
			idlestate = atoi(optarg);
			break;
		case 'e':
			if (param) {
				param = -1;
				cont = 0;
				break;
			}
			param = ret;
			idlestate = atoi(optarg);
			break;
		case -1:
			cont = 0;
			break;
		}
	} while (cont);

	switch (param) {
	case -1:
		printf(_("You can't specify more than one "
			 "output-specific argument\n"));
		exit(EXIT_FAILURE);
	case '?':
		printf(_("invalid or unknown argument\n"));
		exit(EXIT_FAILURE);
	}

	/* Default is: set all CPUs */
	if (bitmask_isallclear(cpus_chosen))
		bitmask_setall(cpus_chosen);

	for (cpu = bitmask_first(cpus_chosen);
	     cpu <= bitmask_last(cpus_chosen); cpu++) {

		if (!bitmask_isbitset(cpus_chosen, cpu))
			continue;

		switch (param) {

		case 'd':
			ret = sysfs_idlestate_disable(cpu, idlestate, 1);
			if (ret == 0)
		printf(_("Idlestate %u disabled on CPU %u\n"),  idlestate, cpu);
			else if (ret == -1)
		printf(_("Idlestate %u not available on CPU %u\n"),
		       idlestate, cpu);
			else if (ret == -2)
		printf(_("Idlestate disabling not supported by kernel\n"));
			else
		printf(_("Idlestate %u not disabled on CPU %u\n"),
		       idlestate, cpu);
			break;
		case 'e':
			ret = sysfs_idlestate_disable(cpu, idlestate, 0);
			if (ret == 0)
		printf(_("Idlestate %u enabled on CPU %u\n"),  idlestate, cpu);
			else if (ret == -1)
		printf(_("Idlestate %u not available on CPU %u\n"),
		       idlestate, cpu);
			else if (ret == -2)
		printf(_("Idlestate enabling not supported by kernel\n"));
			else
		printf(_("Idlestate %u not enabled on CPU %u\n"),
		       idlestate, cpu);
			break;
		default:
			/* Not reachable with proper args checking */
			printf(_("Invalid or unknown argument\n"));
			exit(EXIT_FAILURE);
			break;
		}
	}
	return EXIT_SUCCESS;
}
Loading