xref: /linux/drivers/acpi/processor_driver.c (revision 906fd46a65383cd639e5eec72a047efc33045d86)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * processor_driver.c - ACPI Processor Driver
4  *
5  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7  *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
8  *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
9  *  			- Added processor hotplug support
10  *  Copyright (C) 2013, Intel Corporation
11  *                      Rafael J. Wysocki <rafael.j.wysocki@intel.com>
12  */
13 
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/cpufreq.h>
18 #include <linux/cpu.h>
19 #include <linux/cpuidle.h>
20 #include <linux/slab.h>
21 #include <linux/acpi.h>
22 
23 #include <acpi/processor.h>
24 
25 #include "internal.h"
26 
27 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
28 #define ACPI_PROCESSOR_NOTIFY_POWER	0x81
29 #define ACPI_PROCESSOR_NOTIFY_THROTTLING	0x82
30 #define ACPI_PROCESSOR_NOTIFY_HIGEST_PERF_CHANGED	0x85
31 
32 MODULE_AUTHOR("Paul Diefenbaugh");
33 MODULE_DESCRIPTION("ACPI Processor Driver");
34 MODULE_LICENSE("GPL");
35 
36 static int acpi_processor_start(struct device *dev);
37 static int acpi_processor_stop(struct device *dev);
38 
39 static const struct acpi_device_id processor_device_ids[] = {
40 	{ACPI_PROCESSOR_OBJECT_HID, 0},
41 	{ACPI_PROCESSOR_DEVICE_HID, 0},
42 	{"", 0},
43 };
44 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
45 
46 static struct device_driver acpi_processor_driver = {
47 	.name = "processor",
48 	.bus = &cpu_subsys,
49 	.acpi_match_table = processor_device_ids,
50 	.probe = acpi_processor_start,
51 	.remove = acpi_processor_stop,
52 };
53 
54 static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
55 {
56 	struct acpi_device *device = data;
57 	struct acpi_processor *pr;
58 	int saved;
59 
60 	if (device->handle != handle)
61 		return;
62 
63 	pr = acpi_driver_data(device);
64 	if (!pr)
65 		return;
66 
67 	switch (event) {
68 	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
69 		saved = pr->performance_platform_limit;
70 		acpi_processor_ppc_has_changed(pr, 1);
71 		if (saved == pr->performance_platform_limit)
72 			break;
73 		acpi_bus_generate_netlink_event(device->pnp.device_class,
74 						  dev_name(&device->dev), event,
75 						  pr->performance_platform_limit);
76 		break;
77 	case ACPI_PROCESSOR_NOTIFY_POWER:
78 		acpi_processor_power_state_has_changed(pr);
79 		acpi_bus_generate_netlink_event(device->pnp.device_class,
80 						  dev_name(&device->dev), event, 0);
81 		break;
82 	case ACPI_PROCESSOR_NOTIFY_THROTTLING:
83 		acpi_processor_tstate_has_changed(pr);
84 		acpi_bus_generate_netlink_event(device->pnp.device_class,
85 						  dev_name(&device->dev), event, 0);
86 		break;
87 	case ACPI_PROCESSOR_NOTIFY_HIGEST_PERF_CHANGED:
88 		cpufreq_update_limits(pr->id);
89 		acpi_bus_generate_netlink_event(device->pnp.device_class,
90 						  dev_name(&device->dev), event, 0);
91 		break;
92 	default:
93 		acpi_handle_debug(handle, "Unsupported event [0x%x]\n", event);
94 		break;
95 	}
96 
97 	return;
98 }
99 
100 static int __acpi_processor_start(struct acpi_device *device);
101 
102 static int acpi_soft_cpu_online(unsigned int cpu)
103 {
104 	struct acpi_processor *pr = per_cpu(processors, cpu);
105 	struct acpi_device *device;
106 
107 	if (!pr)
108 		return 0;
109 
110 	device = acpi_fetch_acpi_dev(pr->handle);
111 	if (!device)
112 		return 0;
113 
114 	/*
115 	 * CPU got physically hotplugged and onlined for the first time:
116 	 * Initialize missing things.
117 	 */
118 	if (pr->flags.need_hotplug_init) {
119 		int ret;
120 
121 		pr_info("Will online and init hotplugged CPU: %d\n",
122 			pr->id);
123 		pr->flags.need_hotplug_init = 0;
124 		ret = __acpi_processor_start(device);
125 		WARN(ret, "Failed to start CPU: %d\n", pr->id);
126 	} else {
127 		/* Normal CPU soft online event. */
128 		acpi_processor_ppc_has_changed(pr, 0);
129 		acpi_processor_hotplug(pr);
130 		acpi_processor_reevaluate_tstate(pr, false);
131 		acpi_processor_tstate_has_changed(pr);
132 	}
133 	return 0;
134 }
135 
136 static int acpi_soft_cpu_dead(unsigned int cpu)
137 {
138 	struct acpi_processor *pr = per_cpu(processors, cpu);
139 
140 	if (!pr || !acpi_fetch_acpi_dev(pr->handle))
141 		return 0;
142 
143 	acpi_processor_reevaluate_tstate(pr, true);
144 	return 0;
145 }
146 
147 #ifdef CONFIG_ACPI_CPU_FREQ_PSS
148 static void acpi_pss_perf_init(struct acpi_processor *pr)
149 {
150 	acpi_processor_ppc_has_changed(pr, 0);
151 
152 	acpi_processor_get_throttling_info(pr);
153 
154 	if (pr->flags.throttling)
155 		pr->flags.limit = 1;
156 }
157 #else
158 static inline void acpi_pss_perf_init(struct acpi_processor *pr) {}
159 #endif /* CONFIG_ACPI_CPU_FREQ_PSS */
160 
161 static int __acpi_processor_start(struct acpi_device *device)
162 {
163 	struct acpi_processor *pr = acpi_driver_data(device);
164 	acpi_status status;
165 	int result = 0;
166 
167 	if (!pr)
168 		return -ENODEV;
169 
170 	if (pr->flags.need_hotplug_init)
171 		return 0;
172 
173 	result = acpi_cppc_processor_probe(pr);
174 	if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
175 		dev_dbg(&device->dev, "CPPC data invalid or not present\n");
176 
177 	if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
178 		acpi_processor_power_init(pr);
179 
180 	acpi_pss_perf_init(pr);
181 
182 	result = acpi_processor_thermal_init(pr, device);
183 	if (result)
184 		goto err_power_exit;
185 
186 	status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
187 					     acpi_processor_notify, device);
188 	if (ACPI_SUCCESS(status))
189 		return 0;
190 
191 	result = -ENODEV;
192 	acpi_processor_thermal_exit(pr, device);
193 
194 err_power_exit:
195 	acpi_processor_power_exit(pr);
196 	return result;
197 }
198 
199 static int acpi_processor_start(struct device *dev)
200 {
201 	struct acpi_device *device = ACPI_COMPANION(dev);
202 	int ret;
203 
204 	if (!device)
205 		return -ENODEV;
206 
207 	/* Protect against concurrent CPU hotplug operations */
208 	cpu_hotplug_disable();
209 	ret = __acpi_processor_start(device);
210 	cpu_hotplug_enable();
211 	return ret;
212 }
213 
214 static int acpi_processor_stop(struct device *dev)
215 {
216 	struct acpi_device *device = ACPI_COMPANION(dev);
217 	struct acpi_processor *pr;
218 
219 	if (!device)
220 		return 0;
221 
222 	acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
223 				   acpi_processor_notify);
224 
225 	pr = acpi_driver_data(device);
226 	if (!pr)
227 		return 0;
228 	acpi_processor_power_exit(pr);
229 
230 	acpi_cppc_processor_exit(pr);
231 
232 	acpi_processor_thermal_exit(pr, device);
233 
234 	return 0;
235 }
236 
237 bool acpi_processor_cpufreq_init;
238 
239 static int acpi_processor_notifier(struct notifier_block *nb,
240 				   unsigned long event, void *data)
241 {
242 	struct cpufreq_policy *policy = data;
243 
244 	if (event == CPUFREQ_CREATE_POLICY) {
245 		acpi_thermal_cpufreq_init(policy);
246 		acpi_processor_ppc_init(policy);
247 	} else if (event == CPUFREQ_REMOVE_POLICY) {
248 		acpi_processor_ppc_exit(policy);
249 		acpi_thermal_cpufreq_exit(policy);
250 	}
251 
252 	return 0;
253 }
254 
255 static struct notifier_block acpi_processor_notifier_block = {
256 	.notifier_call = acpi_processor_notifier,
257 };
258 
259 /*
260  * We keep the driver loaded even when ACPI is not running.
261  * This is needed for the powernow-k8 driver, that works even without
262  * ACPI, but needs symbols from this driver
263  */
264 static enum cpuhp_state hp_online;
265 static int __init acpi_processor_driver_init(void)
266 {
267 	int result = 0;
268 
269 	if (acpi_disabled)
270 		return 0;
271 
272 	if (!cpufreq_register_notifier(&acpi_processor_notifier_block,
273 				       CPUFREQ_POLICY_NOTIFIER)) {
274 		acpi_processor_cpufreq_init = true;
275 		acpi_processor_ignore_ppc_init();
276 	}
277 
278 	result = driver_register(&acpi_processor_driver);
279 	if (result < 0)
280 		return result;
281 
282 	result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
283 					   "acpi/cpu-drv:online",
284 					   acpi_soft_cpu_online, NULL);
285 	if (result < 0)
286 		goto err;
287 	hp_online = result;
288 	cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead",
289 				  NULL, acpi_soft_cpu_dead);
290 
291 	acpi_processor_throttling_init();
292 	return 0;
293 err:
294 	driver_unregister(&acpi_processor_driver);
295 	return result;
296 }
297 
298 static void __exit acpi_processor_driver_exit(void)
299 {
300 	if (acpi_disabled)
301 		return;
302 
303 	if (acpi_processor_cpufreq_init) {
304 		cpufreq_unregister_notifier(&acpi_processor_notifier_block,
305 					    CPUFREQ_POLICY_NOTIFIER);
306 		acpi_processor_cpufreq_init = false;
307 	}
308 
309 	cpuhp_remove_state_nocalls(hp_online);
310 	cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
311 	driver_unregister(&acpi_processor_driver);
312 }
313 
314 module_init(acpi_processor_driver_init);
315 module_exit(acpi_processor_driver_exit);
316 
317 MODULE_ALIAS("processor");
318