Commit 64f3bf2f authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Thomas Gleixner

ACPI/processor: Convert to hotplug state machine

Install the callbacks via the state machine.
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: default avatar"Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: linux-acpi@vger.kernel.org
Cc: rt@linutronix.de
Cc: Len Brown <lenb@kernel.org>
Link: http://lkml.kernel.org/r/20160906170457.32393-12-bigeasy@linutronix.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 8904f5a5
...@@ -110,55 +110,46 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) ...@@ -110,55 +110,46 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
static int __acpi_processor_start(struct acpi_device *device); static int __acpi_processor_start(struct acpi_device *device);
static int acpi_cpu_soft_notify(struct notifier_block *nfb, static int acpi_soft_cpu_online(unsigned int cpu)
unsigned long action, void *hcpu)
{ {
unsigned int cpu = (unsigned long)hcpu;
struct acpi_processor *pr = per_cpu(processors, cpu); struct acpi_processor *pr = per_cpu(processors, cpu);
struct acpi_device *device; struct acpi_device *device;
action &= ~CPU_TASKS_FROZEN;
switch (action) {
case CPU_ONLINE:
case CPU_DEAD:
break;
default:
return NOTIFY_DONE;
}
if (!pr || acpi_bus_get_device(pr->handle, &device)) if (!pr || acpi_bus_get_device(pr->handle, &device))
return NOTIFY_DONE; return 0;
/*
if (action == CPU_ONLINE) { * CPU got physically hotplugged and onlined for the first time:
/* * Initialize missing things.
* CPU got physically hotplugged and onlined for the first time: */
* Initialize missing things. if (pr->flags.need_hotplug_init) {
*/ int ret;
if (pr->flags.need_hotplug_init) {
int ret; pr_info("Will online and init hotplugged CPU: %d\n",
pr->id);
pr_info("Will online and init hotplugged CPU: %d\n", pr->flags.need_hotplug_init = 0;
pr->id); ret = __acpi_processor_start(device);
pr->flags.need_hotplug_init = 0; WARN(ret, "Failed to start CPU: %d\n", pr->id);
ret = __acpi_processor_start(device); } else {
WARN(ret, "Failed to start CPU: %d\n", pr->id); /* Normal CPU soft online event. */
} else { acpi_processor_ppc_has_changed(pr, 0);
/* Normal CPU soft online event. */ acpi_processor_hotplug(pr);
acpi_processor_ppc_has_changed(pr, 0); acpi_processor_reevaluate_tstate(pr, false);
acpi_processor_hotplug(pr); acpi_processor_tstate_has_changed(pr);
acpi_processor_reevaluate_tstate(pr, action);
acpi_processor_tstate_has_changed(pr);
}
} else if (action == CPU_DEAD) {
/* Invalidate flag.throttling after the CPU is offline. */
acpi_processor_reevaluate_tstate(pr, action);
} }
return NOTIFY_OK; return 0;
} }
static struct notifier_block acpi_cpu_notifier = { static int acpi_soft_cpu_dead(unsigned int cpu)
.notifier_call = acpi_cpu_soft_notify, {
}; struct acpi_processor *pr = per_cpu(processors, cpu);
struct acpi_device *device;
if (!pr || acpi_bus_get_device(pr->handle, &device))
return 0;
acpi_processor_reevaluate_tstate(pr, true);
return 0;
}
#ifdef CONFIG_ACPI_CPU_FREQ_PSS #ifdef CONFIG_ACPI_CPU_FREQ_PSS
static int acpi_pss_perf_init(struct acpi_processor *pr, static int acpi_pss_perf_init(struct acpi_processor *pr,
...@@ -303,7 +294,7 @@ static int acpi_processor_stop(struct device *dev) ...@@ -303,7 +294,7 @@ static int acpi_processor_stop(struct device *dev)
* This is needed for the powernow-k8 driver, that works even without * This is needed for the powernow-k8 driver, that works even without
* ACPI, but needs symbols from this driver * ACPI, but needs symbols from this driver
*/ */
static enum cpuhp_state hp_online;
static int __init acpi_processor_driver_init(void) static int __init acpi_processor_driver_init(void)
{ {
int result = 0; int result = 0;
...@@ -315,11 +306,22 @@ static int __init acpi_processor_driver_init(void) ...@@ -315,11 +306,22 @@ static int __init acpi_processor_driver_init(void)
if (result < 0) if (result < 0)
return result; return result;
register_hotcpu_notifier(&acpi_cpu_notifier); result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"acpi/cpu-drv:online",
acpi_soft_cpu_online, NULL);
if (result < 0)
goto err;
hp_online = result;
cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead",
NULL, acpi_soft_cpu_dead);
acpi_thermal_cpufreq_init(); acpi_thermal_cpufreq_init();
acpi_processor_ppc_init(); acpi_processor_ppc_init();
acpi_processor_throttling_init(); acpi_processor_throttling_init();
return 0; return 0;
err:
driver_unregister(&acpi_processor_driver);
return result;
} }
static void __exit acpi_processor_driver_exit(void) static void __exit acpi_processor_driver_exit(void)
...@@ -329,7 +331,8 @@ static void __exit acpi_processor_driver_exit(void) ...@@ -329,7 +331,8 @@ static void __exit acpi_processor_driver_exit(void)
acpi_processor_ppc_exit(); acpi_processor_ppc_exit();
acpi_thermal_cpufreq_exit(); acpi_thermal_cpufreq_exit();
unregister_hotcpu_notifier(&acpi_cpu_notifier); cpuhp_remove_state_nocalls(hp_online);
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
driver_unregister(&acpi_processor_driver); driver_unregister(&acpi_processor_driver);
} }
......
...@@ -375,11 +375,11 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr) ...@@ -375,11 +375,11 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
* 3. TSD domain * 3. TSD domain
*/ */
void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
unsigned long action) bool is_dead)
{ {
int result = 0; int result = 0;
if (action == CPU_DEAD) { if (is_dead) {
/* When one CPU is offline, the T-state throttling /* When one CPU is offline, the T-state throttling
* will be invalidated. * will be invalidated.
*/ */
......
...@@ -359,7 +359,7 @@ extern int acpi_processor_set_throttling(struct acpi_processor *pr, ...@@ -359,7 +359,7 @@ extern int acpi_processor_set_throttling(struct acpi_processor *pr,
* onlined/offlined. In such case the flags.throttling will be updated. * onlined/offlined. In such case the flags.throttling will be updated.
*/ */
extern void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, extern void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
unsigned long action); bool is_dead);
extern const struct file_operations acpi_processor_throttling_fops; extern const struct file_operations acpi_processor_throttling_fops;
extern void acpi_processor_throttling_init(void); extern void acpi_processor_throttling_init(void);
#else #else
...@@ -380,7 +380,7 @@ static inline int acpi_processor_set_throttling(struct acpi_processor *pr, ...@@ -380,7 +380,7 @@ static inline int acpi_processor_set_throttling(struct acpi_processor *pr,
} }
static inline void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, static inline void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
unsigned long action) {} bool is_dead) {}
static inline void acpi_processor_throttling_init(void) {} static inline void acpi_processor_throttling_init(void) {}
#endif /* CONFIG_ACPI_CPU_FREQ_PSS */ #endif /* CONFIG_ACPI_CPU_FREQ_PSS */
......
...@@ -25,6 +25,7 @@ enum cpuhp_state { ...@@ -25,6 +25,7 @@ enum cpuhp_state {
CPUHP_IRQ_POLL_DEAD, CPUHP_IRQ_POLL_DEAD,
CPUHP_BLOCK_SOFTIRQ_DEAD, CPUHP_BLOCK_SOFTIRQ_DEAD,
CPUHP_VIRT_SCSI_DEAD, CPUHP_VIRT_SCSI_DEAD,
CPUHP_ACPI_CPUDRV_DEAD,
CPUHP_WORKQUEUE_PREP, CPUHP_WORKQUEUE_PREP,
CPUHP_POWER_NUMA_PREPARE, CPUHP_POWER_NUMA_PREPARE,
CPUHP_HRTIMERS_PREPARE, CPUHP_HRTIMERS_PREPARE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment