ACPI and power management updates for 3.8-rc1

* Introduction of device PM QoS flags.
 
 * ACPI device power management update allowing subsystems other than
   PCI to use it more easily.
 
 * ACPI device enumeration rework allowing additional kinds of devices
   to be enumerated via ACPI.  From Mika Westerberg, Adrian Hunter,
   Mathias Nyman, Andy Shevchenko, and Rafael J. Wysocki.
 
 * ACPICA update to version 20121018 from Bob Moore and Lv Zheng.
 
 * ACPI memory hotplug update from Wen Congyang and Yasuaki Ishimatsu.
 
 * Introduction of acpi_handle_<level>() messaging macros and ACPI-based CPU
   hot-remove support from Toshi Kani.
 
 * ACPI EC updates from Feng Tang.
 
 * cpufreq updates from Viresh Kumar, Fabio Baltieri and others.
 
 * cpuidle changes to quickly notice governor prediction failure from
   Youquan Song.
 
 * Support for using multiple cpuidle drivers at the same time and cpuidle
   cleanups from Daniel Lezcano.
 
 * devfreq updates from Nishanth Menon and others.
 
 * cpupower update from Thomas Renninger.
 
 * Fixes and small cleanups all over the place.
 
 --
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJQxxevAAoJEKhOf7ml8uNsHacQAK2xoQozDddPBAaTCf1OWW/G
 J4E2qMn+gy4AtFmQ0/xeZVvvylOCn9eu/kv3QJ/bFlVoUsqTgfPwQBjT6HjF1Acn
 7yVFdr9H/tn2wi9nW2Gv6Tl2Hr/kFLpo0f5Kd40Z+P8SV5sKX5ktJcVpJ/I/P4Vh
 Qw2nWtj7hQktZDERzgG4ZpMbQToNhbLhbKWB9ad3/XQSSA9JkfgvBFgrTEGHcZD5
 bwsggjNdOAWNGeDdzRsQSDn0Alld5ILVdSJ5xKimO1O70WvKc7fqA1IdYRIeKL90
 yz4bcoYKzl9iktlw8+x5o1U9mrc8TFV5p4+zV+t5Z6pzS/J3kWvnsW4zu9sCrxFv
 Wic3SKyiem7s2dxrYyj4ZXAci3GK4ouRTrCLqk7/00tEGdwAQD1ZNfsUJp6jKayz
 FvtZUgItcOyrlQ6B4nh951OY6dI3AUYJ2NuWWNr5NZkgVAvQGV8zTGOImbeVeL2+
 pMiw14zScO3ylYilVcjTKDDMj2sDZ68mw5PIcbmksvWsCLo26jDBVDtLVmtYWyd4
 ek3WnOrQZr0R3agvOLLssMKXompvpP+N4Klf4rV+GtqGsWtHryYKys2Laju9FwFj
 yYLchxYlxhGTzqq8LjF90HDL0TWpPe6cPi+B5ow9g/SXLexbMKNQGhv3Jovm2yR3
 j54tKBWy7e9AAYEDPirX
 =6OEP
 -----END PGP SIGNATURE-----

Merge tag 'pm+acpi-for-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI and power management updates from Rafael Wysocki:

 - Introduction of device PM QoS flags.

 - ACPI device power management update allowing subsystems other than
   PCI to use it more easily.

 - ACPI device enumeration rework allowing additional kinds of devices
   to be enumerated via ACPI.  From Mika Westerberg, Adrian Hunter,
   Mathias Nyman, Andy Shevchenko, and Rafael J. Wysocki.

 - ACPICA update to version 20121018 from Bob Moore and Lv Zheng.

 - ACPI memory hotplug update from Wen Congyang and Yasuaki Ishimatsu.

 - Introduction of acpi_handle_<level>() messaging macros and ACPI-based
   CPU hot-remove support from Toshi Kani.

 - ACPI EC updates from Feng Tang.

 - cpufreq updates from Viresh Kumar, Fabio Baltieri and others.

 - cpuidle changes to quickly notice governor prediction failure from
   Youquan Song.

 - Support for using multiple cpuidle drivers at the same time and
   cpuidle cleanups from Daniel Lezcano.

 - devfreq updates from Nishanth Menon and others.

 - cpupower update from Thomas Renninger.

 - Fixes and small cleanups all over the place.

* tag 'pm+acpi-for-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (196 commits)
  mmc: sdhci-acpi: enable runtime-pm for device HID INT33C6
  ACPI: add Haswell LPSS devices to acpi_platform_device_ids list
  ACPI: add documentation about ACPI 5 enumeration
  pnpacpi: fix incorrect TEST_ALPHA() test
  ACPI / PM: Fix header of acpi_dev_pm_detach() in acpi.h
  ACPI / video: ignore BIOS initial backlight value for HP Folio 13-2000
  ACPI : do not use Lid and Sleep button for S5 wakeup
  ACPI / PNP: Do not crash due to stale pointer use during system resume
  ACPI / video: Add "Asus UL30VT" to ACPI video detect blacklist
  ACPI: do acpisleep dmi check when CONFIG_ACPI_SLEEP is set
  spi / ACPI: add ACPI enumeration support
  gpio / ACPI: add ACPI support
  PM / devfreq: remove compiler error with module governors (2)
  cpupower: IvyBridge (0x3a and 0x3e models) support
  cpupower: Provide -c param for cpupower monitor to schedule process on all cores
  cpupower tools: Fix warning and a bug with the cpu package count
  cpupower tools: Fix malloc of cpu_info structure
  cpupower tools: Fix issues with sysfs_topology_read_file
  cpupower tools: Fix minor warnings
  cpupower tools: Update .gitignore for files created in the debug directories
  ...
This commit is contained in:
Linus Torvalds 2012-12-11 12:45:35 -08:00
commit bad73c5aa0
233 changed files with 9505 additions and 3361 deletions

View file

@ -20,3 +20,10 @@ utils/cpufreq-set.o
utils/cpufreq-aperf.o
cpupower
bench/cpufreq-bench
debug/kernel/Module.symvers
debug/i386/centrino-decode
debug/i386/dump_psb
debug/i386/intel_gsic
debug/i386/powernow-k8-decode
debug/x86_64/centrino-decode
debug/x86_64/powernow-k8-decode

View file

@ -253,7 +253,8 @@ clean:
| xargs rm -f
-rm -f $(OUTPUT)cpupower
-rm -f $(OUTPUT)libcpupower.so*
-rm -rf $(OUTPUT)po/*.{gmo,pot}
-rm -rf $(OUTPUT)po/*.gmo
-rm -rf $(OUTPUT)po/*.pot
$(MAKE) -C bench O=$(OUTPUT) clean

View file

@ -26,7 +26,10 @@ $(OUTPUT)powernow-k8-decode: powernow-k8-decode.c
all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode
clean:
rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode}
rm -rf $(OUTPUT)centrino-decode
rm -rf $(OUTPUT)dump_psb
rm -rf $(OUTPUT)intel_gsic
rm -rf $(OUTPUT)powernow-k8-decode
install:
$(INSTALL) -d $(DESTDIR)${bindir}

View file

@ -7,11 +7,11 @@ cpupower\-monitor \- Report processor frequency and idle statistics
.RB "\-l"
.B cpupower monitor
.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
.RB [ -c ] [ "\-m <mon1>," [ "<mon2>,..." ] ]
.RB [ "\-i seconds" ]
.br
.B cpupower monitor
.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
.RB [ -c ][ "\-m <mon1>," [ "<mon2>,..." ] ]
.RB command
.br
.SH DESCRIPTION
@ -64,6 +64,17 @@ Only display specific monitors. Use the monitor string(s) provided by \-l option
Measure intervall.
.RE
.PP
\-c
.RS 4
Schedule the process on every core before starting and ending measuring.
This could be needed for the Idle_Stats monitor when no other MSR based
monitor (has to be run on the core that is measured) is run in parallel.
This is to wake up the processors from deeper sleep states and let the
kernel re
-account its cpuidle (C-state) information before reading the
cpuidle timings from sysfs.
.RE
.PP
command
.RS 4
Measure idle and frequency characteristics of an arbitrary command/workload.

View file

@ -158,6 +158,8 @@ out:
cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
case 0x2A: /* SNB */
case 0x2D: /* SNB Xeon */
case 0x3A: /* IVB */
case 0x3E: /* IVB Xeon */
cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
break;

View file

@ -92,6 +92,14 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
extern struct cpupower_cpu_info cpupower_cpu_info;
/* cpuid and cpuinfo helpers **************************/
struct cpuid_core_info {
int pkg;
int core;
int cpu;
/* flags */
unsigned int is_online:1;
};
/* CPU topology/hierarchy parsing ******************/
struct cpupower_topology {
@ -101,18 +109,12 @@ struct cpupower_topology {
unsigned int threads; /* per core */
/* Array gets mallocated with cores entries, holding per core info */
struct {
int pkg;
int core;
int cpu;
/* flags */
unsigned int is_online:1;
} *core_info;
struct cpuid_core_info *core_info;
};
extern int get_cpu_topology(struct cpupower_topology *cpu_top);
extern void cpu_topology_release(struct cpupower_topology cpu_top);
/* CPU topology/hierarchy parsing ******************/
/* X86 ONLY ****************************************/

View file

@ -37,25 +37,6 @@ unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
return (unsigned int) numread;
}
static unsigned int sysfs_write_file(const char *path,
const char *value, size_t len)
{
int fd;
ssize_t numwrite;
fd = open(path, O_WRONLY);
if (fd == -1)
return 0;
numwrite = write(fd, value, len);
if (numwrite < 1) {
close(fd);
return 0;
}
close(fd);
return (unsigned int) numwrite;
}
/*
* Detect whether a CPU is online
*

View file

@ -20,9 +20,8 @@
#include <helpers/sysfs.h>
/* returns -1 on failure, 0 on success */
int sysfs_topology_read_file(unsigned int cpu, const char *fname)
static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
{
unsigned long value;
char linebuf[MAX_LINE_LEN];
char *endp;
char path[SYSFS_PATH_MAX];
@ -31,20 +30,12 @@ int sysfs_topology_read_file(unsigned int cpu, const char *fname)
cpu, fname);
if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
return -1;
value = strtoul(linebuf, &endp, 0);
*result = strtol(linebuf, &endp, 0);
if (endp == linebuf || errno == ERANGE)
return -1;
return value;
return 0;
}
struct cpuid_core_info {
unsigned int pkg;
unsigned int thread;
unsigned int cpu;
/* flags */
unsigned int is_online:1;
};
static int __compare(const void *t1, const void *t2)
{
struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
@ -53,9 +44,9 @@ static int __compare(const void *t1, const void *t2)
return -1;
else if (top1->pkg > top2->pkg)
return 1;
else if (top1->thread < top2->thread)
else if (top1->core < top2->core)
return -1;
else if (top1->thread > top2->thread)
else if (top1->core > top2->core)
return 1;
else if (top1->cpu < top2->cpu)
return -1;
@ -73,28 +64,42 @@ static int __compare(const void *t1, const void *t2)
*/
int get_cpu_topology(struct cpupower_topology *cpu_top)
{
int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF);
int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus);
cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
if (cpu_top->core_info == NULL)
return -ENOMEM;
cpu_top->pkgs = cpu_top->cores = 0;
for (cpu = 0; cpu < cpus; cpu++) {
cpu_top->core_info[cpu].cpu = cpu;
cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
cpu_top->core_info[cpu].pkg =
sysfs_topology_read_file(cpu, "physical_package_id");
if ((int)cpu_top->core_info[cpu].pkg != -1 &&
cpu_top->core_info[cpu].pkg > cpu_top->pkgs)
cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
cpu_top->core_info[cpu].core =
sysfs_topology_read_file(cpu, "core_id");
if(sysfs_topology_read_file(
cpu,
"physical_package_id",
&(cpu_top->core_info[cpu].pkg)) < 0)
return -1;
if(sysfs_topology_read_file(
cpu,
"core_id",
&(cpu_top->core_info[cpu].core)) < 0)
return -1;
}
cpu_top->pkgs++;
qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
__compare);
/* Count the number of distinct pkgs values. This works
because the primary sort of the core_info struct was just
done by pkg value. */
last_pkg = cpu_top->core_info[0].pkg;
for(cpu = 1; cpu < cpus; cpu++) {
if(cpu_top->core_info[cpu].pkg != last_pkg) {
last_pkg = cpu_top->core_info[cpu].pkg;
cpu_top->pkgs++;
}
}
cpu_top->pkgs++;
/* Intel's cores count is not consecutively numbered, there may
* be a core_id of 3, but none of 2. Assume there always is 0
* Get amount of cores by counting duplicates in a package

View file

@ -39,6 +39,7 @@ static int mode;
static int interval = 1;
static char *show_monitors_param;
static struct cpupower_topology cpu_top;
static unsigned int wake_cpus;
/* ToDo: Document this in the manpage */
static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
@ -84,7 +85,7 @@ int fill_string_with_spaces(char *s, int n)
void print_header(int topology_depth)
{
int unsigned mon;
int state, need_len, pr_mon_len;
int state, need_len;
cstate_t s;
char buf[128] = "";
int percent_width = 4;
@ -93,7 +94,6 @@ void print_header(int topology_depth)
printf("%s|", buf);
for (mon = 0; mon < avail_monitors; mon++) {
pr_mon_len = 0;
need_len = monitors[mon]->hw_states_num * (percent_width + 3)
- 1;
if (mon != 0) {
@ -315,16 +315,28 @@ int fork_it(char **argv)
int do_interval_measure(int i)
{
unsigned int num;
int cpu;
if (wake_cpus)
for (cpu = 0; cpu < cpu_count; cpu++)
bind_cpu(cpu);
for (num = 0; num < avail_monitors; num++) {
dprint("HW C-state residency monitor: %s - States: %d\n",
monitors[num]->name, monitors[num]->hw_states_num);
monitors[num]->start();
}
sleep(i);
if (wake_cpus)
for (cpu = 0; cpu < cpu_count; cpu++)
bind_cpu(cpu);
for (num = 0; num < avail_monitors; num++)
monitors[num]->stop();
return 0;
}
@ -333,7 +345,7 @@ static void cmdline(int argc, char *argv[])
int opt;
progname = basename(argv[0]);
while ((opt = getopt(argc, argv, "+li:m:")) != -1) {
while ((opt = getopt(argc, argv, "+lci:m:")) != -1) {
switch (opt) {
case 'l':
if (mode)
@ -352,6 +364,9 @@ static void cmdline(int argc, char *argv[])
mode = show;
show_monitors_param = optarg;
break;
case 'c':
wake_cpus = 1;
break;
default:
print_wrong_arg_exit();
}

View file

@ -65,4 +65,21 @@ extern long long timespec_diff_us(struct timespec start, struct timespec end);
"could be inaccurate\n"), mes, ov); \
}
/* Taken over from x86info project sources -> return 0 on success */
#include <sched.h>
#include <sys/types.h>
#include <unistd.h>
static inline int bind_cpu(int cpu)
{
cpu_set_t set;
if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) {
CPU_ZERO(&set);
CPU_SET(cpu, &set);
return sched_setaffinity(getpid(), sizeof(set), &set);
}
return 1;
}
#endif /* __CPUIDLE_INFO_HW__ */

View file

@ -150,9 +150,15 @@ static struct cpuidle_monitor *snb_register(void)
|| cpupower_cpu_info.family != 6)
return NULL;
if (cpupower_cpu_info.model != 0x2A
&& cpupower_cpu_info.model != 0x2D)
switch (cpupower_cpu_info.model) {
case 0x2A: /* SNB */
case 0x2D: /* SNB Xeon */
case 0x3A: /* IVB */
case 0x3E: /* IVB Xeon */
break;
default:
return NULL;
}
is_valid = calloc(cpu_count, sizeof(int));
for (num = 0; num < SNB_CSTATE_COUNT; num++) {