Skip to content

Commit

Permalink
Merge tag 'pm+acpi-3.11-rc1-more' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/rafael/linux-pm

Pull more power management and ACPI updates from Rafael Wysocki:

 - Fix for a recent cpufreq regression that caused WARN() to trigger
   overzealously in a couple of places and spam the kernel log with
   useless garbage as a result.  From Viresh Kumar.

 - ACPI dock fix removing a discrepancy between the definition of
   acpi_dock_init(), which says that the function returns int, and its
   header in the header file, which says that it is a void function.
   The function is now defined as void too.

 - ACPI PM fix for failures to update device power states as needed, for
   example, during resume from system suspend, because the old state was
   deeper than the new one, but the new one is not D0.

 - Fix for two debug messages in the ACPI power resources code that
   don't have a newline at the end and make the kernel log difficult to
   read.  From Mika Westerberg.

 - Two ACPI cleanups from Naresh Bhat and Haicheng Li.

 - cpupower updates from Thomas Renninger, including Intel Haswell
   support improvements and a new idle-set subcommand among other
   things.

* tag 'pm+acpi-3.11-rc1-more' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / power: add missing newline to debug messages
  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
  ACPI / fan: Initialize acpi_state variable
  ACPI / scan: remove unused LIST_HEAD(acpi_device_list)
  ACPI / dock: Actually define acpi_dock_init() as void
  ACPI / PM: Fix corner case in acpi_bus_update_power()
  cpufreq: Fix serialization of frequency transitions
  • Loading branch information
Linus Torvalds committed Jul 11, 2013
2 parents 8cbd0ee + d8851b4 commit 7728f03
Show file tree
Hide file tree
Showing 18 changed files with 502 additions and 43 deletions.
23 changes: 18 additions & 5 deletions drivers/acpi/device_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,14 +324,27 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
if (result)
return result;

if (state == ACPI_STATE_UNKNOWN)
if (state == ACPI_STATE_UNKNOWN) {
state = ACPI_STATE_D0;

result = acpi_device_set_power(device, state);
if (!result && state_p)
result = acpi_device_set_power(device, state);
if (result)
return result;
} else {
if (device->power.flags.power_resources) {
/*
* We don't need to really switch the state, bu we need
* to update the power resources' reference counters.
*/
result = acpi_power_transition(device, state);
if (result)
return result;
}
device->power.state = state;
}
if (state_p)
*state_p = state;

return result;
return 0;
}
EXPORT_SYMBOL_GPL(acpi_bus_update_power);

Expand Down
7 changes: 3 additions & 4 deletions drivers/acpi/dock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1064,22 +1064,21 @@ find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
}

int __init acpi_dock_init(void)
void __init acpi_dock_init(void)
{
if (acpi_disabled)
return 0;
return;

/* look for dock stations and bays */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);

if (!dock_station_count) {
pr_info(PREFIX "No dock devices found.\n");
return 0;
return;
}

register_acpi_bus_notifier(&dock_acpi_notifier);
pr_info(PREFIX "%s: %d docks/bays found\n",
ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
return 0;
}
2 changes: 1 addition & 1 deletion drivers/acpi/fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
{
struct acpi_device *device = cdev->devdata;
int result;
int acpi_state;
int acpi_state = ACPI_STATE_D0;

if (!device)
return -EINVAL;
Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource)

if (resource->ref_count++) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Power resource [%s] already on",
"Power resource [%s] already on\n",
resource->name));
} else {
result = __acpi_power_on(resource);
Expand Down Expand Up @@ -325,7 +325,7 @@ static int acpi_power_off_unlocked(struct acpi_power_resource *resource)

if (!resource->ref_count) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Power resource [%s] already off",
"Power resource [%s] already off\n",
resource->name));
return 0;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ bool acpi_force_hot_remove;

static const char *dummy_hid = "device";

static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
static DEFINE_MUTEX(acpi_scan_lock);
static LIST_HEAD(acpi_scan_handlers_list);
Expand Down
7 changes: 4 additions & 3 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,12 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
switch (state) {

case CPUFREQ_PRECHANGE:
if (WARN(policy->transition_ongoing,
if (WARN(policy->transition_ongoing ==
cpumask_weight(policy->cpus),
"In middle of another frequency transition\n"))
return;

policy->transition_ongoing = true;
policy->transition_ongoing++;

/* detect if the driver reported a value as "old frequency"
* which is not equal to what the cpufreq core thinks is
Expand All @@ -341,7 +342,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
"No frequency transition in progress\n"))
return;

policy->transition_ongoing = false;
policy->transition_ongoing--;

adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
Expand Down
2 changes: 1 addition & 1 deletion include/linux/cpufreq.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ struct cpufreq_policy {

struct kobject kobj;
struct completion kobj_unregister;
bool transition_ongoing; /* Tracks transition status */
int transition_ongoing; /* Tracks transition status */
};

#define CPUFREQ_ADJUST (0)
Expand Down
4 changes: 3 additions & 1 deletion tools/power/cpupower/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
10 changes: 9 additions & 1 deletion tools/power/cpupower/man/cpupower-monitor.1
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions tools/power/cpupower/utils/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
24 changes: 9 additions & 15 deletions tools/power/cpupower/utils/cpuidle-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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++) {
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
118 changes: 118 additions & 0 deletions tools/power/cpupower/utils/cpuidle-set.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#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;
}
13 changes: 7 additions & 6 deletions tools/power/cpupower/utils/cpupower.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@
#include "helpers/helpers.h"
#include "helpers/bitmask.h"

struct cmd_struct {
const char *cmd;
int (*main)(int, const char **);
int needs_root;
};

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

static int cmd_help(int argc, const char **argv);
Expand All @@ -43,10 +37,17 @@ int be_verbose;

static void print_help(void);

struct cmd_struct {
const char *cmd;
int (*main)(int, const char **);
int needs_root;
};

static struct cmd_struct commands[] = {
{ "frequency-info", cmd_freq_info, 0 },
{ "frequency-set", cmd_freq_set, 1 },
{ "idle-info", cmd_idle_info, 0 },
{ "idle-set", cmd_idle_set, 1 },
{ "set", cmd_set, 1 },
{ "info", cmd_info, 0 },
{ "monitor", cmd_monitor, 0 },
Expand Down
Loading

0 comments on commit 7728f03

Please sign in to comment.