]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/acpi/processor_core.c
cpuidle: fix C3 for no bus-master control case
[karo-tx-linux.git] / drivers / acpi / processor_core.c
index 81aceb5da7c7948f905787fd040c5b9f7f810c1b..a7351084f2f8d48a28c5e024aff9a0b83ac8dce2 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/seq_file.h>
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
+#include <linux/cpuidle.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -88,14 +89,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr);
 extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 
 
+static const struct acpi_device_id processor_device_ids[] = {
+       {ACPI_PROCESSOR_HID, 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, processor_device_ids);
+
 static struct acpi_driver acpi_processor_driver = {
        .name = "processor",
        .class = ACPI_PROCESSOR_CLASS,
-       .ids = ACPI_PROCESSOR_HID,
+       .ids = processor_device_ids,
        .ops = {
                .add = acpi_processor_add,
                .remove = acpi_processor_remove,
                .start = acpi_processor_start,
+               .suspend = acpi_processor_suspend,
+               .resume = acpi_processor_resume,
                },
 };
 
@@ -692,16 +701,23 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
        switch (event) {
        case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
                acpi_processor_ppc_has_changed(pr);
-               acpi_bus_generate_event(device, event,
+               acpi_bus_generate_proc_event(device, event,
                                        pr->performance_platform_limit);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 device->dev.bus_id, event,
+                                                 pr->performance_platform_limit);
                break;
        case ACPI_PROCESSOR_NOTIFY_POWER:
                acpi_processor_cst_has_changed(pr);
-               acpi_bus_generate_event(device, event, 0);
+               acpi_bus_generate_proc_event(device, event, 0);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 device->dev.bus_id, event, 0);
                break;
        case ACPI_PROCESSOR_NOTIFY_THROTTLING:
                acpi_processor_tstate_has_changed(pr);
-               acpi_bus_generate_event(device, event, 0);
+               acpi_bus_generate_proc_event(device, event, 0);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 device->dev.bus_id, event, 0);
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
@@ -711,6 +727,25 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
        return;
 }
 
+static int acpi_cpu_soft_notify(struct notifier_block *nfb,
+               unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct acpi_processor *pr = processors[cpu];
+
+       if (action == CPU_ONLINE && pr) {
+               acpi_processor_ppc_has_changed(pr);
+               acpi_processor_cst_has_changed(pr);
+               acpi_processor_tstate_has_changed(pr);
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block acpi_cpu_notifier =
+{
+           .notifier_call = acpi_cpu_soft_notify,
+};
+
 static int acpi_processor_add(struct acpi_device *device)
 {
        struct acpi_processor *pr = NULL;
@@ -974,6 +1009,7 @@ void acpi_processor_install_hotplug_notify(void)
                            ACPI_UINT32_MAX,
                            processor_walk_namespace_cb, &action, NULL);
 #endif
+       register_hotcpu_notifier(&acpi_cpu_notifier);
 }
 
 static
@@ -986,6 +1022,7 @@ void acpi_processor_uninstall_hotplug_notify(void)
                            ACPI_UINT32_MAX,
                            processor_walk_namespace_cb, &action, NULL);
 #endif
+       unregister_hotcpu_notifier(&acpi_cpu_notifier);
 }
 
 /*
@@ -1013,11 +1050,13 @@ static int __init acpi_processor_init(void)
                return -ENOMEM;
        acpi_processor_dir->owner = THIS_MODULE;
 
+       result = cpuidle_register_driver(&acpi_idle_driver);
+       if (result < 0)
+               goto out_proc;
+
        result = acpi_bus_register_driver(&acpi_processor_driver);
-       if (result < 0) {
-               remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-               return result;
-       }
+       if (result < 0)
+               goto out_cpuidle;
 
        acpi_processor_install_hotplug_notify();
 
@@ -1026,11 +1065,18 @@ static int __init acpi_processor_init(void)
        acpi_processor_ppc_init();
 
        return 0;
+
+out_cpuidle:
+       cpuidle_unregister_driver(&acpi_idle_driver);
+
+out_proc:
+       remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+
+       return result;
 }
 
 static void __exit acpi_processor_exit(void)
 {
-
        acpi_processor_ppc_exit();
 
        acpi_thermal_cpufreq_exit();
@@ -1039,6 +1085,8 @@ static void __exit acpi_processor_exit(void)
 
        acpi_bus_unregister_driver(&acpi_processor_driver);
 
+       cpuidle_unregister_driver(&acpi_idle_driver);
+
        remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
 
        return;