Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * processor_driver.c - ACPI Processor Driver
0004  *
0005  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
0006  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
0007  *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
0008  *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
0009  *              - Added processor hotplug support
0010  *  Copyright (C) 2013, Intel Corporation
0011  *                      Rafael J. Wysocki <rafael.j.wysocki@intel.com>
0012  */
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/init.h>
0017 #include <linux/cpufreq.h>
0018 #include <linux/cpu.h>
0019 #include <linux/cpuidle.h>
0020 #include <linux/slab.h>
0021 #include <linux/acpi.h>
0022 
0023 #include <acpi/processor.h>
0024 
0025 #include "internal.h"
0026 
0027 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
0028 #define ACPI_PROCESSOR_NOTIFY_POWER 0x81
0029 #define ACPI_PROCESSOR_NOTIFY_THROTTLING    0x82
0030 
0031 MODULE_AUTHOR("Paul Diefenbaugh");
0032 MODULE_DESCRIPTION("ACPI Processor Driver");
0033 MODULE_LICENSE("GPL");
0034 
0035 static int acpi_processor_start(struct device *dev);
0036 static int acpi_processor_stop(struct device *dev);
0037 
0038 static const struct acpi_device_id processor_device_ids[] = {
0039     {ACPI_PROCESSOR_OBJECT_HID, 0},
0040     {ACPI_PROCESSOR_DEVICE_HID, 0},
0041     {"", 0},
0042 };
0043 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
0044 
0045 static struct device_driver acpi_processor_driver = {
0046     .name = "processor",
0047     .bus = &cpu_subsys,
0048     .acpi_match_table = processor_device_ids,
0049     .probe = acpi_processor_start,
0050     .remove = acpi_processor_stop,
0051 };
0052 
0053 static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
0054 {
0055     struct acpi_device *device = data;
0056     struct acpi_processor *pr;
0057     int saved;
0058 
0059     if (device->handle != handle)
0060         return;
0061 
0062     pr = acpi_driver_data(device);
0063     if (!pr)
0064         return;
0065 
0066     switch (event) {
0067     case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
0068         saved = pr->performance_platform_limit;
0069         acpi_processor_ppc_has_changed(pr, 1);
0070         if (saved == pr->performance_platform_limit)
0071             break;
0072         acpi_bus_generate_netlink_event(device->pnp.device_class,
0073                           dev_name(&device->dev), event,
0074                           pr->performance_platform_limit);
0075         break;
0076     case ACPI_PROCESSOR_NOTIFY_POWER:
0077         acpi_processor_power_state_has_changed(pr);
0078         acpi_bus_generate_netlink_event(device->pnp.device_class,
0079                           dev_name(&device->dev), event, 0);
0080         break;
0081     case ACPI_PROCESSOR_NOTIFY_THROTTLING:
0082         acpi_processor_tstate_has_changed(pr);
0083         acpi_bus_generate_netlink_event(device->pnp.device_class,
0084                           dev_name(&device->dev), event, 0);
0085         break;
0086     default:
0087         acpi_handle_debug(handle, "Unsupported event [0x%x]\n", event);
0088         break;
0089     }
0090 
0091     return;
0092 }
0093 
0094 static int __acpi_processor_start(struct acpi_device *device);
0095 
0096 static int acpi_soft_cpu_online(unsigned int cpu)
0097 {
0098     struct acpi_processor *pr = per_cpu(processors, cpu);
0099     struct acpi_device *device;
0100 
0101     if (!pr)
0102         return 0;
0103 
0104     device = acpi_fetch_acpi_dev(pr->handle);
0105     if (!device)
0106         return 0;
0107 
0108     /*
0109      * CPU got physically hotplugged and onlined for the first time:
0110      * Initialize missing things.
0111      */
0112     if (pr->flags.need_hotplug_init) {
0113         int ret;
0114 
0115         pr_info("Will online and init hotplugged CPU: %d\n",
0116             pr->id);
0117         pr->flags.need_hotplug_init = 0;
0118         ret = __acpi_processor_start(device);
0119         WARN(ret, "Failed to start CPU: %d\n", pr->id);
0120     } else {
0121         /* Normal CPU soft online event. */
0122         acpi_processor_ppc_has_changed(pr, 0);
0123         acpi_processor_hotplug(pr);
0124         acpi_processor_reevaluate_tstate(pr, false);
0125         acpi_processor_tstate_has_changed(pr);
0126     }
0127     return 0;
0128 }
0129 
0130 static int acpi_soft_cpu_dead(unsigned int cpu)
0131 {
0132     struct acpi_processor *pr = per_cpu(processors, cpu);
0133 
0134     if (!pr || !acpi_fetch_acpi_dev(pr->handle))
0135         return 0;
0136 
0137     acpi_processor_reevaluate_tstate(pr, true);
0138     return 0;
0139 }
0140 
0141 #ifdef CONFIG_ACPI_CPU_FREQ_PSS
0142 static void acpi_pss_perf_init(struct acpi_processor *pr)
0143 {
0144     acpi_processor_ppc_has_changed(pr, 0);
0145 
0146     acpi_processor_get_throttling_info(pr);
0147 
0148     if (pr->flags.throttling)
0149         pr->flags.limit = 1;
0150 }
0151 #else
0152 static inline void acpi_pss_perf_init(struct acpi_processor *pr) {}
0153 #endif /* CONFIG_ACPI_CPU_FREQ_PSS */
0154 
0155 static int __acpi_processor_start(struct acpi_device *device)
0156 {
0157     struct acpi_processor *pr = acpi_driver_data(device);
0158     acpi_status status;
0159     int result = 0;
0160 
0161     if (!pr)
0162         return -ENODEV;
0163 
0164     if (pr->flags.need_hotplug_init)
0165         return 0;
0166 
0167     result = acpi_cppc_processor_probe(pr);
0168     if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
0169         dev_dbg(&device->dev, "CPPC data invalid or not present\n");
0170 
0171     if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
0172         acpi_processor_power_init(pr);
0173 
0174     acpi_pss_perf_init(pr);
0175 
0176     result = acpi_processor_thermal_init(pr, device);
0177     if (result)
0178         goto err_power_exit;
0179 
0180     status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
0181                          acpi_processor_notify, device);
0182     if (ACPI_SUCCESS(status))
0183         return 0;
0184 
0185     result = -ENODEV;
0186     acpi_processor_thermal_exit(pr, device);
0187 
0188 err_power_exit:
0189     acpi_processor_power_exit(pr);
0190     return result;
0191 }
0192 
0193 static int acpi_processor_start(struct device *dev)
0194 {
0195     struct acpi_device *device = ACPI_COMPANION(dev);
0196     int ret;
0197 
0198     if (!device)
0199         return -ENODEV;
0200 
0201     /* Protect against concurrent CPU hotplug operations */
0202     cpu_hotplug_disable();
0203     ret = __acpi_processor_start(device);
0204     cpu_hotplug_enable();
0205     return ret;
0206 }
0207 
0208 static int acpi_processor_stop(struct device *dev)
0209 {
0210     struct acpi_device *device = ACPI_COMPANION(dev);
0211     struct acpi_processor *pr;
0212 
0213     if (!device)
0214         return 0;
0215 
0216     acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
0217                    acpi_processor_notify);
0218 
0219     pr = acpi_driver_data(device);
0220     if (!pr)
0221         return 0;
0222     acpi_processor_power_exit(pr);
0223 
0224     acpi_cppc_processor_exit(pr);
0225 
0226     acpi_processor_thermal_exit(pr, device);
0227 
0228     return 0;
0229 }
0230 
0231 bool acpi_processor_cpufreq_init;
0232 
0233 static int acpi_processor_notifier(struct notifier_block *nb,
0234                    unsigned long event, void *data)
0235 {
0236     struct cpufreq_policy *policy = data;
0237 
0238     if (event == CPUFREQ_CREATE_POLICY) {
0239         acpi_thermal_cpufreq_init(policy);
0240         acpi_processor_ppc_init(policy);
0241     } else if (event == CPUFREQ_REMOVE_POLICY) {
0242         acpi_processor_ppc_exit(policy);
0243         acpi_thermal_cpufreq_exit(policy);
0244     }
0245 
0246     return 0;
0247 }
0248 
0249 static struct notifier_block acpi_processor_notifier_block = {
0250     .notifier_call = acpi_processor_notifier,
0251 };
0252 
0253 /*
0254  * We keep the driver loaded even when ACPI is not running.
0255  * This is needed for the powernow-k8 driver, that works even without
0256  * ACPI, but needs symbols from this driver
0257  */
0258 static enum cpuhp_state hp_online;
0259 static int __init acpi_processor_driver_init(void)
0260 {
0261     int result = 0;
0262 
0263     if (acpi_disabled)
0264         return 0;
0265 
0266     result = driver_register(&acpi_processor_driver);
0267     if (result < 0)
0268         return result;
0269 
0270     result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
0271                        "acpi/cpu-drv:online",
0272                        acpi_soft_cpu_online, NULL);
0273     if (result < 0)
0274         goto err;
0275     hp_online = result;
0276     cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead",
0277                   NULL, acpi_soft_cpu_dead);
0278 
0279     if (!cpufreq_register_notifier(&acpi_processor_notifier_block,
0280                        CPUFREQ_POLICY_NOTIFIER)) {
0281         acpi_processor_cpufreq_init = true;
0282         acpi_processor_ignore_ppc_init();
0283     }
0284 
0285     acpi_processor_throttling_init();
0286     return 0;
0287 err:
0288     driver_unregister(&acpi_processor_driver);
0289     return result;
0290 }
0291 
0292 static void __exit acpi_processor_driver_exit(void)
0293 {
0294     if (acpi_disabled)
0295         return;
0296 
0297     if (acpi_processor_cpufreq_init) {
0298         cpufreq_unregister_notifier(&acpi_processor_notifier_block,
0299                         CPUFREQ_POLICY_NOTIFIER);
0300         acpi_processor_cpufreq_init = false;
0301     }
0302 
0303     cpuhp_remove_state_nocalls(hp_online);
0304     cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
0305     driver_unregister(&acpi_processor_driver);
0306 }
0307 
0308 module_init(acpi_processor_driver_init);
0309 module_exit(acpi_processor_driver_exit);
0310 
0311 MODULE_ALIAS("processor");