18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * processor_driver.c - ACPI Processor Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 68c2ecf20Sopenharmony_ci * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 78c2ecf20Sopenharmony_ci * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> 88c2ecf20Sopenharmony_ci * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 98c2ecf20Sopenharmony_ci * - Added processor hotplug support 108c2ecf20Sopenharmony_ci * Copyright (C) 2013, Intel Corporation 118c2ecf20Sopenharmony_ci * Rafael J. Wysocki <rafael.j.wysocki@intel.com> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/init.h> 178c2ecf20Sopenharmony_ci#include <linux/cpufreq.h> 188c2ecf20Sopenharmony_ci#include <linux/cpu.h> 198c2ecf20Sopenharmony_ci#include <linux/cpuidle.h> 208c2ecf20Sopenharmony_ci#include <linux/slab.h> 218c2ecf20Sopenharmony_ci#include <linux/acpi.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <acpi/processor.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "internal.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 288c2ecf20Sopenharmony_ci#define ACPI_PROCESSOR_NOTIFY_POWER 0x81 298c2ecf20Sopenharmony_ci#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define _COMPONENT ACPI_PROCESSOR_COMPONENT 328c2ecf20Sopenharmony_ciACPI_MODULE_NAME("processor_driver"); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciMODULE_AUTHOR("Paul Diefenbaugh"); 358c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ACPI Processor Driver"); 368c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int acpi_processor_start(struct device *dev); 398c2ecf20Sopenharmony_cistatic int acpi_processor_stop(struct device *dev); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic const struct acpi_device_id processor_device_ids[] = { 428c2ecf20Sopenharmony_ci {ACPI_PROCESSOR_OBJECT_HID, 0}, 438c2ecf20Sopenharmony_ci {ACPI_PROCESSOR_DEVICE_HID, 0}, 448c2ecf20Sopenharmony_ci {"", 0}, 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, processor_device_ids); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic struct device_driver acpi_processor_driver = { 498c2ecf20Sopenharmony_ci .name = "processor", 508c2ecf20Sopenharmony_ci .bus = &cpu_subsys, 518c2ecf20Sopenharmony_ci .acpi_match_table = processor_device_ids, 528c2ecf20Sopenharmony_ci .probe = acpi_processor_start, 538c2ecf20Sopenharmony_ci .remove = acpi_processor_stop, 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic void acpi_processor_notify(acpi_handle handle, u32 event, void *data) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci struct acpi_device *device = data; 598c2ecf20Sopenharmony_ci struct acpi_processor *pr; 608c2ecf20Sopenharmony_ci int saved; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (device->handle != handle) 638c2ecf20Sopenharmony_ci return; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci pr = acpi_driver_data(device); 668c2ecf20Sopenharmony_ci if (!pr) 678c2ecf20Sopenharmony_ci return; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci switch (event) { 708c2ecf20Sopenharmony_ci case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: 718c2ecf20Sopenharmony_ci saved = pr->performance_platform_limit; 728c2ecf20Sopenharmony_ci acpi_processor_ppc_has_changed(pr, 1); 738c2ecf20Sopenharmony_ci if (saved == pr->performance_platform_limit) 748c2ecf20Sopenharmony_ci break; 758c2ecf20Sopenharmony_ci acpi_bus_generate_netlink_event(device->pnp.device_class, 768c2ecf20Sopenharmony_ci dev_name(&device->dev), event, 778c2ecf20Sopenharmony_ci pr->performance_platform_limit); 788c2ecf20Sopenharmony_ci break; 798c2ecf20Sopenharmony_ci case ACPI_PROCESSOR_NOTIFY_POWER: 808c2ecf20Sopenharmony_ci acpi_processor_power_state_has_changed(pr); 818c2ecf20Sopenharmony_ci acpi_bus_generate_netlink_event(device->pnp.device_class, 828c2ecf20Sopenharmony_ci dev_name(&device->dev), event, 0); 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case ACPI_PROCESSOR_NOTIFY_THROTTLING: 858c2ecf20Sopenharmony_ci acpi_processor_tstate_has_changed(pr); 868c2ecf20Sopenharmony_ci acpi_bus_generate_netlink_event(device->pnp.device_class, 878c2ecf20Sopenharmony_ci dev_name(&device->dev), event, 0); 888c2ecf20Sopenharmony_ci break; 898c2ecf20Sopenharmony_ci default: 908c2ecf20Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_INFO, 918c2ecf20Sopenharmony_ci "Unsupported event [0x%x]\n", event)); 928c2ecf20Sopenharmony_ci break; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic int __acpi_processor_start(struct acpi_device *device); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic int acpi_soft_cpu_online(unsigned int cpu) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci struct acpi_processor *pr = per_cpu(processors, cpu); 1038c2ecf20Sopenharmony_ci struct acpi_device *device; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (!pr || acpi_bus_get_device(pr->handle, &device)) 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci /* 1088c2ecf20Sopenharmony_ci * CPU got physically hotplugged and onlined for the first time: 1098c2ecf20Sopenharmony_ci * Initialize missing things. 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_ci if (pr->flags.need_hotplug_init) { 1128c2ecf20Sopenharmony_ci int ret; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci pr_info("Will online and init hotplugged CPU: %d\n", 1158c2ecf20Sopenharmony_ci pr->id); 1168c2ecf20Sopenharmony_ci pr->flags.need_hotplug_init = 0; 1178c2ecf20Sopenharmony_ci ret = __acpi_processor_start(device); 1188c2ecf20Sopenharmony_ci WARN(ret, "Failed to start CPU: %d\n", pr->id); 1198c2ecf20Sopenharmony_ci } else { 1208c2ecf20Sopenharmony_ci /* Normal CPU soft online event. */ 1218c2ecf20Sopenharmony_ci acpi_processor_ppc_has_changed(pr, 0); 1228c2ecf20Sopenharmony_ci acpi_processor_hotplug(pr); 1238c2ecf20Sopenharmony_ci acpi_processor_reevaluate_tstate(pr, false); 1248c2ecf20Sopenharmony_ci acpi_processor_tstate_has_changed(pr); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic int acpi_soft_cpu_dead(unsigned int cpu) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct acpi_processor *pr = per_cpu(processors, cpu); 1328c2ecf20Sopenharmony_ci struct acpi_device *device; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (!pr || acpi_bus_get_device(pr->handle, &device)) 1358c2ecf20Sopenharmony_ci return 0; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci acpi_processor_reevaluate_tstate(pr, true); 1388c2ecf20Sopenharmony_ci return 0; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_CPU_FREQ_PSS 1428c2ecf20Sopenharmony_cistatic int acpi_pss_perf_init(struct acpi_processor *pr, 1438c2ecf20Sopenharmony_ci struct acpi_device *device) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci int result = 0; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci acpi_processor_ppc_has_changed(pr, 0); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci acpi_processor_get_throttling_info(pr); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (pr->flags.throttling) 1528c2ecf20Sopenharmony_ci pr->flags.limit = 1; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci pr->cdev = thermal_cooling_device_register("Processor", device, 1558c2ecf20Sopenharmony_ci &processor_cooling_ops); 1568c2ecf20Sopenharmony_ci if (IS_ERR(pr->cdev)) { 1578c2ecf20Sopenharmony_ci result = PTR_ERR(pr->cdev); 1588c2ecf20Sopenharmony_ci return result; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci dev_dbg(&device->dev, "registered as cooling_device%d\n", 1628c2ecf20Sopenharmony_ci pr->cdev->id); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci result = sysfs_create_link(&device->dev.kobj, 1658c2ecf20Sopenharmony_ci &pr->cdev->device.kobj, 1668c2ecf20Sopenharmony_ci "thermal_cooling"); 1678c2ecf20Sopenharmony_ci if (result) { 1688c2ecf20Sopenharmony_ci dev_err(&device->dev, 1698c2ecf20Sopenharmony_ci "Failed to create sysfs link 'thermal_cooling'\n"); 1708c2ecf20Sopenharmony_ci goto err_thermal_unregister; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci result = sysfs_create_link(&pr->cdev->device.kobj, 1748c2ecf20Sopenharmony_ci &device->dev.kobj, 1758c2ecf20Sopenharmony_ci "device"); 1768c2ecf20Sopenharmony_ci if (result) { 1778c2ecf20Sopenharmony_ci dev_err(&pr->cdev->device, 1788c2ecf20Sopenharmony_ci "Failed to create sysfs link 'device'\n"); 1798c2ecf20Sopenharmony_ci goto err_remove_sysfs_thermal; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci err_remove_sysfs_thermal: 1858c2ecf20Sopenharmony_ci sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); 1868c2ecf20Sopenharmony_ci err_thermal_unregister: 1878c2ecf20Sopenharmony_ci thermal_cooling_device_unregister(pr->cdev); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci return result; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic void acpi_pss_perf_exit(struct acpi_processor *pr, 1938c2ecf20Sopenharmony_ci struct acpi_device *device) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci if (pr->cdev) { 1968c2ecf20Sopenharmony_ci sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); 1978c2ecf20Sopenharmony_ci sysfs_remove_link(&pr->cdev->device.kobj, "device"); 1988c2ecf20Sopenharmony_ci thermal_cooling_device_unregister(pr->cdev); 1998c2ecf20Sopenharmony_ci pr->cdev = NULL; 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci#else 2038c2ecf20Sopenharmony_cistatic inline int acpi_pss_perf_init(struct acpi_processor *pr, 2048c2ecf20Sopenharmony_ci struct acpi_device *device) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci return 0; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic inline void acpi_pss_perf_exit(struct acpi_processor *pr, 2108c2ecf20Sopenharmony_ci struct acpi_device *device) {} 2118c2ecf20Sopenharmony_ci#endif /* CONFIG_ACPI_CPU_FREQ_PSS */ 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic int __acpi_processor_start(struct acpi_device *device) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci struct acpi_processor *pr = acpi_driver_data(device); 2168c2ecf20Sopenharmony_ci acpi_status status; 2178c2ecf20Sopenharmony_ci int result = 0; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (!pr) 2208c2ecf20Sopenharmony_ci return -ENODEV; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (pr->flags.need_hotplug_init) 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci result = acpi_cppc_processor_probe(pr); 2268c2ecf20Sopenharmony_ci if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS)) 2278c2ecf20Sopenharmony_ci dev_dbg(&device->dev, "CPPC data invalid or not present\n"); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) 2308c2ecf20Sopenharmony_ci acpi_processor_power_init(pr); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci result = acpi_pss_perf_init(pr, device); 2338c2ecf20Sopenharmony_ci if (result) 2348c2ecf20Sopenharmony_ci goto err_power_exit; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, 2378c2ecf20Sopenharmony_ci acpi_processor_notify, device); 2388c2ecf20Sopenharmony_ci if (ACPI_SUCCESS(status)) 2398c2ecf20Sopenharmony_ci return 0; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci result = -ENODEV; 2428c2ecf20Sopenharmony_ci acpi_pss_perf_exit(pr, device); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cierr_power_exit: 2458c2ecf20Sopenharmony_ci acpi_processor_power_exit(pr); 2468c2ecf20Sopenharmony_ci return result; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int acpi_processor_start(struct device *dev) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct acpi_device *device = ACPI_COMPANION(dev); 2528c2ecf20Sopenharmony_ci int ret; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (!device) 2558c2ecf20Sopenharmony_ci return -ENODEV; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* Protect against concurrent CPU hotplug operations */ 2588c2ecf20Sopenharmony_ci cpu_hotplug_disable(); 2598c2ecf20Sopenharmony_ci ret = __acpi_processor_start(device); 2608c2ecf20Sopenharmony_ci cpu_hotplug_enable(); 2618c2ecf20Sopenharmony_ci return ret; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic int acpi_processor_stop(struct device *dev) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct acpi_device *device = ACPI_COMPANION(dev); 2678c2ecf20Sopenharmony_ci struct acpi_processor *pr; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (!device) 2708c2ecf20Sopenharmony_ci return 0; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, 2738c2ecf20Sopenharmony_ci acpi_processor_notify); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci pr = acpi_driver_data(device); 2768c2ecf20Sopenharmony_ci if (!pr) 2778c2ecf20Sopenharmony_ci return 0; 2788c2ecf20Sopenharmony_ci acpi_processor_power_exit(pr); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci acpi_pss_perf_exit(pr, device); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci acpi_cppc_processor_exit(pr); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci return 0; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cibool acpi_processor_cpufreq_init; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic int acpi_processor_notifier(struct notifier_block *nb, 2908c2ecf20Sopenharmony_ci unsigned long event, void *data) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct cpufreq_policy *policy = data; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (event == CPUFREQ_CREATE_POLICY) { 2958c2ecf20Sopenharmony_ci acpi_thermal_cpufreq_init(policy); 2968c2ecf20Sopenharmony_ci acpi_processor_ppc_init(policy); 2978c2ecf20Sopenharmony_ci } else if (event == CPUFREQ_REMOVE_POLICY) { 2988c2ecf20Sopenharmony_ci acpi_processor_ppc_exit(policy); 2998c2ecf20Sopenharmony_ci acpi_thermal_cpufreq_exit(policy); 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci return 0; 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic struct notifier_block acpi_processor_notifier_block = { 3068c2ecf20Sopenharmony_ci .notifier_call = acpi_processor_notifier, 3078c2ecf20Sopenharmony_ci}; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci/* 3108c2ecf20Sopenharmony_ci * We keep the driver loaded even when ACPI is not running. 3118c2ecf20Sopenharmony_ci * This is needed for the powernow-k8 driver, that works even without 3128c2ecf20Sopenharmony_ci * ACPI, but needs symbols from this driver 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_cistatic enum cpuhp_state hp_online; 3158c2ecf20Sopenharmony_cistatic int __init acpi_processor_driver_init(void) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci int result = 0; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (acpi_disabled) 3208c2ecf20Sopenharmony_ci return 0; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci result = driver_register(&acpi_processor_driver); 3238c2ecf20Sopenharmony_ci if (result < 0) 3248c2ecf20Sopenharmony_ci return result; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, 3278c2ecf20Sopenharmony_ci "acpi/cpu-drv:online", 3288c2ecf20Sopenharmony_ci acpi_soft_cpu_online, NULL); 3298c2ecf20Sopenharmony_ci if (result < 0) 3308c2ecf20Sopenharmony_ci goto err; 3318c2ecf20Sopenharmony_ci hp_online = result; 3328c2ecf20Sopenharmony_ci cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead", 3338c2ecf20Sopenharmony_ci NULL, acpi_soft_cpu_dead); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (!cpufreq_register_notifier(&acpi_processor_notifier_block, 3368c2ecf20Sopenharmony_ci CPUFREQ_POLICY_NOTIFIER)) { 3378c2ecf20Sopenharmony_ci acpi_processor_cpufreq_init = true; 3388c2ecf20Sopenharmony_ci acpi_processor_ignore_ppc_init(); 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci acpi_processor_throttling_init(); 3428c2ecf20Sopenharmony_ci return 0; 3438c2ecf20Sopenharmony_cierr: 3448c2ecf20Sopenharmony_ci driver_unregister(&acpi_processor_driver); 3458c2ecf20Sopenharmony_ci return result; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic void __exit acpi_processor_driver_exit(void) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci if (acpi_disabled) 3518c2ecf20Sopenharmony_ci return; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci if (acpi_processor_cpufreq_init) { 3548c2ecf20Sopenharmony_ci cpufreq_unregister_notifier(&acpi_processor_notifier_block, 3558c2ecf20Sopenharmony_ci CPUFREQ_POLICY_NOTIFIER); 3568c2ecf20Sopenharmony_ci acpi_processor_cpufreq_init = false; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci cpuhp_remove_state_nocalls(hp_online); 3608c2ecf20Sopenharmony_ci cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD); 3618c2ecf20Sopenharmony_ci driver_unregister(&acpi_processor_driver); 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cimodule_init(acpi_processor_driver_init); 3658c2ecf20Sopenharmony_cimodule_exit(acpi_processor_driver_exit); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ciMODULE_ALIAS("processor"); 368