Merge branches 'pm-cpufreq', 'pm-hibernate' and 'acpi-processor'

* pm-cpufreq:
  intel_pstate: Change busy calculation to use fixed point math.

* pm-hibernate:
  PM / hibernate: Fix restore hang in freeze_processes()

* acpi-processor:
  ACPI / processor: Rework processor throttling with work_on_cpu()
This commit is contained in:
Rafael J. Wysocki 2014-02-28 00:14:11 +01:00
commit 6c09ea49ce
2 changed files with 33 additions and 37 deletions

View File

@ -56,6 +56,12 @@ struct throttling_tstate {
int target_state; /* target T-state */ int target_state; /* target T-state */
}; };
struct acpi_processor_throttling_arg {
struct acpi_processor *pr;
int target_state;
bool force;
};
#define THROTTLING_PRECHANGE (1) #define THROTTLING_PRECHANGE (1)
#define THROTTLING_POSTCHANGE (2) #define THROTTLING_POSTCHANGE (2)
@ -1060,16 +1066,24 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
return 0; return 0;
} }
static long acpi_processor_throttling_fn(void *data)
{
struct acpi_processor_throttling_arg *arg = data;
struct acpi_processor *pr = arg->pr;
return pr->throttling.acpi_processor_set_throttling(pr,
arg->target_state, arg->force);
}
int acpi_processor_set_throttling(struct acpi_processor *pr, int acpi_processor_set_throttling(struct acpi_processor *pr,
int state, bool force) int state, bool force)
{ {
cpumask_var_t saved_mask;
int ret = 0; int ret = 0;
unsigned int i; unsigned int i;
struct acpi_processor *match_pr; struct acpi_processor *match_pr;
struct acpi_processor_throttling *p_throttling; struct acpi_processor_throttling *p_throttling;
struct acpi_processor_throttling_arg arg;
struct throttling_tstate t_state; struct throttling_tstate t_state;
cpumask_var_t online_throttling_cpus;
if (!pr) if (!pr)
return -EINVAL; return -EINVAL;
@ -1080,14 +1094,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
if ((state < 0) || (state > (pr->throttling.state_count - 1))) if ((state < 0) || (state > (pr->throttling.state_count - 1)))
return -EINVAL; return -EINVAL;
if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
return -ENOMEM;
if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
free_cpumask_var(saved_mask);
return -ENOMEM;
}
if (cpu_is_offline(pr->id)) { if (cpu_is_offline(pr->id)) {
/* /*
* the cpu pointed by pr->id is offline. Unnecessary to change * the cpu pointed by pr->id is offline. Unnecessary to change
@ -1096,17 +1102,15 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
return -ENODEV; return -ENODEV;
} }
cpumask_copy(saved_mask, &current->cpus_allowed);
t_state.target_state = state; t_state.target_state = state;
p_throttling = &(pr->throttling); p_throttling = &(pr->throttling);
cpumask_and(online_throttling_cpus, cpu_online_mask,
p_throttling->shared_cpu_map);
/* /*
* The throttling notifier will be called for every * The throttling notifier will be called for every
* affected cpu in order to get one proper T-state. * affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE. * The notifier event is THROTTLING_PRECHANGE.
*/ */
for_each_cpu(i, online_throttling_cpus) { for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
t_state.cpu = i; t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE, acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state); &t_state);
@ -1118,21 +1122,18 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
* it can be called only for the cpu pointed by pr. * it can be called only for the cpu pointed by pr.
*/ */
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
/* FIXME: use work_on_cpu() */ arg.pr = pr;
if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { arg.target_state = state;
/* Can't migrate to the pr->id CPU. Exit */ arg.force = force;
ret = -ENODEV; ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg);
goto exit;
}
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state, force);
} else { } else {
/* /*
* When the T-state coordination is SW_ALL or HW_ALL, * When the T-state coordination is SW_ALL or HW_ALL,
* it is necessary to set T-state for every affected * it is necessary to set T-state for every affected
* cpus. * cpus.
*/ */
for_each_cpu(i, online_throttling_cpus) { for_each_cpu_and(i, cpu_online_mask,
p_throttling->shared_cpu_map) {
match_pr = per_cpu(processors, i); match_pr = per_cpu(processors, i);
/* /*
* If the pointer is invalid, we will report the * If the pointer is invalid, we will report the
@ -1153,13 +1154,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
"on CPU %d\n", i)); "on CPU %d\n", i));
continue; continue;
} }
t_state.cpu = i;
/* FIXME: use work_on_cpu() */ arg.pr = match_pr;
if (set_cpus_allowed_ptr(current, cpumask_of(i))) arg.target_state = state;
continue; arg.force = force;
ret = match_pr->throttling. ret = work_on_cpu(pr->id, acpi_processor_throttling_fn,
acpi_processor_set_throttling( &arg);
match_pr, t_state.target_state, force);
} }
} }
/* /*
@ -1168,17 +1168,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
* affected cpu to update the T-states. * affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE * The notifier event is THROTTLING_POSTCHANGE
*/ */
for_each_cpu(i, online_throttling_cpus) { for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
t_state.cpu = i; t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE, acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state); &t_state);
} }
/* restore the previous state */
/* FIXME: use work_on_cpu() */
set_cpus_allowed_ptr(current, saved_mask);
exit:
free_cpumask_var(online_throttling_cpus);
free_cpumask_var(saved_mask);
return ret; return ret;
} }

View File

@ -1580,6 +1580,7 @@ static int fw_pm_notify(struct notifier_block *notify_block,
switch (mode) { switch (mode) {
case PM_HIBERNATION_PREPARE: case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE: case PM_SUSPEND_PREPARE:
case PM_RESTORE_PREPARE:
kill_requests_without_uevent(); kill_requests_without_uevent();
device_cache_fw_images(); device_cache_fw_images();
break; break;