]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ACPI/processor: Convert to hotplug state machine
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Tue, 6 Sep 2016 17:04:47 +0000 (19:04 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 19 Sep 2016 19:44:29 +0000 (21:44 +0200)
Install the callbacks via the state machine.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: "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.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
drivers/acpi/processor_driver.c
drivers/acpi/processor_throttling.c
include/acpi/processor.h
include/linux/cpuhotplug.h

index 0553aeebb2288098e07f1e5c4203110cede48f99..13e5ac415abf43853317f29a78db425d584b9d60 100644 (file)
@@ -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_cpu_soft_notify(struct notifier_block *nfb,
-                                         unsigned long action, void *hcpu)
+static int acpi_soft_cpu_online(unsigned int cpu)
 {
-       unsigned int cpu = (unsigned long)hcpu;
        struct acpi_processor *pr = per_cpu(processors, cpu);
        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))
-               return NOTIFY_DONE;
-
-       if (action == CPU_ONLINE) {
-               /*
-                * CPU got physically hotplugged and onlined for the first time:
-                * Initialize missing things.
-                */
-               if (pr->flags.need_hotplug_init) {
-                       int ret;
-
-                       pr_info("Will online and init hotplugged CPU: %d\n",
-                               pr->id);
-                       pr->flags.need_hotplug_init = 0;
-                       ret = __acpi_processor_start(device);
-                       WARN(ret, "Failed to start CPU: %d\n", pr->id);
-               } else {
-                       /* Normal CPU soft online event. */
-                       acpi_processor_ppc_has_changed(pr, 0);
-                       acpi_processor_hotplug(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 0;
+       /*
+        * CPU got physically hotplugged and onlined for the first time:
+        * Initialize missing things.
+        */
+       if (pr->flags.need_hotplug_init) {
+               int ret;
+
+               pr_info("Will online and init hotplugged CPU: %d\n",
+                       pr->id);
+               pr->flags.need_hotplug_init = 0;
+               ret = __acpi_processor_start(device);
+               WARN(ret, "Failed to start CPU: %d\n", pr->id);
+       } else {
+               /* Normal CPU soft online event. */
+               acpi_processor_ppc_has_changed(pr, 0);
+               acpi_processor_hotplug(pr);
+               acpi_processor_reevaluate_tstate(pr, false);
+               acpi_processor_tstate_has_changed(pr);
        }
-       return NOTIFY_OK;
+       return 0;
 }
 
-static struct notifier_block acpi_cpu_notifier = {
-           .notifier_call = acpi_cpu_soft_notify,
-};
+static int acpi_soft_cpu_dead(unsigned int cpu)
+{
+       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
 static int acpi_pss_perf_init(struct acpi_processor *pr,
@@ -303,7 +294,7 @@ static int acpi_processor_stop(struct device *dev)
  * This is needed for the powernow-k8 driver, that works even without
  * ACPI, but needs symbols from this driver
  */
-
+static enum cpuhp_state hp_online;
 static int __init acpi_processor_driver_init(void)
 {
        int result = 0;
@@ -315,11 +306,22 @@ static int __init acpi_processor_driver_init(void)
        if (result < 0)
                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_processor_ppc_init();
        acpi_processor_throttling_init();
        return 0;
+err:
+       driver_unregister(&acpi_processor_driver);
+       return result;
 }
 
 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_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);
 }
 
index c72e64893d039f9e4d32d19da926ccd8f71a200a..d51ca1c05619567798281c2733fdf3dd28909d5d 100644 (file)
@@ -375,11 +375,11 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
  *     3. TSD domain
  */
 void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
-                                       unsigned long action)
+                                       bool is_dead)
 {
        int result = 0;
 
-       if (action == CPU_DEAD) {
+       if (is_dead) {
                /* When one CPU is offline, the T-state throttling
                 * will be invalidated.
                 */
index bfe6b2e10f3a0b9258a25c9f9d3ff4f5ca2c5377..f3db11c2465446cfa2cc1a160be13fb98a7af650 100644 (file)
@@ -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.
  */
 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 void acpi_processor_throttling_init(void);
 #else
@@ -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,
-                       unsigned long action) {}
+                       bool is_dead) {}
 
 static inline void acpi_processor_throttling_init(void) {}
 #endif /* CONFIG_ACPI_CPU_FREQ_PSS */
index e7146ee88ea4f573baf759b3fb8f26a5bab95ed4..7706987c78270677ea38a8899765ee47c5ba1791 100644 (file)
@@ -25,6 +25,7 @@ enum cpuhp_state {
        CPUHP_IRQ_POLL_DEAD,
        CPUHP_BLOCK_SOFTIRQ_DEAD,
        CPUHP_VIRT_SCSI_DEAD,
+       CPUHP_ACPI_CPUDRV_DEAD,
        CPUHP_WORKQUEUE_PREP,
        CPUHP_POWER_NUMA_PREPARE,
        CPUHP_HRTIMERS_PREPARE,