xref: /linux/drivers/acpi/processor_perflib.c (revision 20d0021394c1b070bf04b22c5bc8fdb437edd4c5)
1 /*
2  * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
7  *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8  *  			- Added processor hotplug support
9  *
10  *
11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or (at
16  *  your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful, but
19  *  WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  *  General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with this program; if not, write to the Free Software Foundation, Inc.,
25  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26  *
27  */
28 
29 
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/cpufreq.h>
34 
35 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
36 #include <linux/proc_fs.h>
37 #include <linux/seq_file.h>
38 
39 #include <asm/uaccess.h>
40 #endif
41 
42 #include <acpi/acpi_bus.h>
43 #include <acpi/processor.h>
44 
45 
46 #define ACPI_PROCESSOR_COMPONENT	0x01000000
47 #define ACPI_PROCESSOR_CLASS		"processor"
48 #define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
49 #define ACPI_PROCESSOR_FILE_PERFORMANCE	"performance"
50 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
51 ACPI_MODULE_NAME		("acpi_processor")
52 
53 
54 static DECLARE_MUTEX(performance_sem);
55 
56 /*
57  * _PPC support is implemented as a CPUfreq policy notifier:
58  * This means each time a CPUfreq driver registered also with
59  * the ACPI core is asked to change the speed policy, the maximum
60  * value is adjusted so that it is within the platform limit.
61  *
62  * Also, when a new platform limit value is detected, the CPUfreq
63  * policy is adjusted accordingly.
64  */
65 
66 #define PPC_REGISTERED   1
67 #define PPC_IN_USE       2
68 
69 static int acpi_processor_ppc_status = 0;
70 
71 static int acpi_processor_ppc_notifier(struct notifier_block *nb,
72 	unsigned long event,
73 	void *data)
74 {
75 	struct cpufreq_policy *policy = data;
76 	struct acpi_processor *pr;
77 	unsigned int ppc = 0;
78 
79 	down(&performance_sem);
80 
81 	if (event != CPUFREQ_INCOMPATIBLE)
82 		goto out;
83 
84 	pr = processors[policy->cpu];
85 	if (!pr || !pr->performance)
86 		goto out;
87 
88 	ppc = (unsigned int) pr->performance_platform_limit;
89 	if (!ppc)
90 		goto out;
91 
92 	if (ppc > pr->performance->state_count)
93 		goto out;
94 
95 	cpufreq_verify_within_limits(policy, 0,
96 		pr->performance->states[ppc].core_frequency * 1000);
97 
98  out:
99 	up(&performance_sem);
100 
101 	return 0;
102 }
103 
104 
105 static struct notifier_block acpi_ppc_notifier_block = {
106 	.notifier_call = acpi_processor_ppc_notifier,
107 };
108 
109 
110 static int
111 acpi_processor_get_platform_limit (
112 	struct acpi_processor*	pr)
113 {
114 	acpi_status		status = 0;
115 	unsigned long		ppc = 0;
116 
117 	ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
118 
119 	if (!pr)
120 		return_VALUE(-EINVAL);
121 
122 	/*
123 	 * _PPC indicates the maximum state currently supported by the platform
124 	 * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
125 	 */
126 	status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
127 
128 	if (status != AE_NOT_FOUND)
129 		acpi_processor_ppc_status |= PPC_IN_USE;
130 
131 	if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
132 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
133 		return_VALUE(-ENODEV);
134 	}
135 
136 	pr->performance_platform_limit = (int) ppc;
137 
138 	return_VALUE(0);
139 }
140 
141 
142 int acpi_processor_ppc_has_changed(
143 	struct acpi_processor *pr)
144 {
145 	int ret = acpi_processor_get_platform_limit(pr);
146 	if (ret < 0)
147 		return (ret);
148 	else
149 		return cpufreq_update_policy(pr->id);
150 }
151 
152 
153 void acpi_processor_ppc_init(void) {
154 	if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
155 		acpi_processor_ppc_status |= PPC_REGISTERED;
156 	else
157 		printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
158 }
159 
160 
161 void acpi_processor_ppc_exit(void) {
162 	if (acpi_processor_ppc_status & PPC_REGISTERED)
163 		cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
164 
165 	acpi_processor_ppc_status &= ~PPC_REGISTERED;
166 }
167 
168 
169 static int
170 acpi_processor_get_performance_control (
171 	struct acpi_processor *pr)
172 {
173 	int			result = 0;
174 	acpi_status		status = 0;
175 	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};
176 	union acpi_object	*pct = NULL;
177 	union acpi_object	obj = {0};
178 
179 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
180 
181 	status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
182 	if(ACPI_FAILURE(status)) {
183 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
184 		return_VALUE(-ENODEV);
185 	}
186 
187 	pct = (union acpi_object *) buffer.pointer;
188 	if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
189 		|| (pct->package.count != 2)) {
190 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
191 		result = -EFAULT;
192 		goto end;
193 	}
194 
195 	/*
196 	 * control_register
197 	 */
198 
199 	obj = pct->package.elements[0];
200 
201 	if ((obj.type != ACPI_TYPE_BUFFER)
202 		|| (obj.buffer.length < sizeof(struct acpi_pct_register))
203 		|| (obj.buffer.pointer == NULL)) {
204 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
205 			"Invalid _PCT data (control_register)\n"));
206 		result = -EFAULT;
207 		goto end;
208 	}
209 	memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
210 
211 
212 	/*
213 	 * status_register
214 	 */
215 
216 	obj = pct->package.elements[1];
217 
218 	if ((obj.type != ACPI_TYPE_BUFFER)
219 		|| (obj.buffer.length < sizeof(struct acpi_pct_register))
220 		|| (obj.buffer.pointer == NULL)) {
221 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
222 			"Invalid _PCT data (status_register)\n"));
223 		result = -EFAULT;
224 		goto end;
225 	}
226 
227 	memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
228 
229 end:
230 	acpi_os_free(buffer.pointer);
231 
232 	return_VALUE(result);
233 }
234 
235 
236 static int
237 acpi_processor_get_performance_states (
238 	struct acpi_processor	*pr)
239 {
240 	int			result = 0;
241 	acpi_status		status = AE_OK;
242 	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};
243 	struct acpi_buffer	format = {sizeof("NNNNNN"), "NNNNNN"};
244 	struct acpi_buffer	state = {0, NULL};
245 	union acpi_object 	*pss = NULL;
246 	int			i;
247 
248 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
249 
250 	status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
251 	if(ACPI_FAILURE(status)) {
252 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
253 		return_VALUE(-ENODEV);
254 	}
255 
256 	pss = (union acpi_object *) buffer.pointer;
257 	if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
258 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
259 		result = -EFAULT;
260 		goto end;
261 	}
262 
263 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
264 		pss->package.count));
265 
266 	pr->performance->state_count = pss->package.count;
267 	pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
268 	if (!pr->performance->states) {
269 		result = -ENOMEM;
270 		goto end;
271 	}
272 
273 	for (i = 0; i < pr->performance->state_count; i++) {
274 
275 		struct acpi_processor_px *px = &(pr->performance->states[i]);
276 
277 		state.length = sizeof(struct acpi_processor_px);
278 		state.pointer = px;
279 
280 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
281 
282 		status = acpi_extract_package(&(pss->package.elements[i]),
283 			&format, &state);
284 		if (ACPI_FAILURE(status)) {
285 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
286 			result = -EFAULT;
287 			kfree(pr->performance->states);
288 			goto end;
289 		}
290 
291 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
292 			"State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
293 			i,
294 			(u32) px->core_frequency,
295 			(u32) px->power,
296 			(u32) px->transition_latency,
297 			(u32) px->bus_master_latency,
298 			(u32) px->control,
299 			(u32) px->status));
300 
301 		if (!px->core_frequency) {
302 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
303 			result = -EFAULT;
304 			kfree(pr->performance->states);
305 			goto end;
306 		}
307 	}
308 
309 end:
310 	acpi_os_free(buffer.pointer);
311 
312 	return_VALUE(result);
313 }
314 
315 
316 static int
317 acpi_processor_get_performance_info (
318 	struct acpi_processor	*pr)
319 {
320 	int			result = 0;
321 	acpi_status		status = AE_OK;
322 	acpi_handle		handle = NULL;
323 
324 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
325 
326 	if (!pr || !pr->performance || !pr->handle)
327 		return_VALUE(-EINVAL);
328 
329 	acpi_processor_set_pdc(pr, pr->performance->pdc);
330 
331 	status = acpi_get_handle(pr->handle, "_PCT", &handle);
332 	if (ACPI_FAILURE(status)) {
333 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
334 			"ACPI-based processor performance control unavailable\n"));
335 		return_VALUE(-ENODEV);
336 	}
337 
338 	result = acpi_processor_get_performance_control(pr);
339 	if (result)
340 		return_VALUE(result);
341 
342 	result = acpi_processor_get_performance_states(pr);
343 	if (result)
344 		return_VALUE(result);
345 
346 	result = acpi_processor_get_platform_limit(pr);
347 	if (result)
348 		return_VALUE(result);
349 
350 	return_VALUE(0);
351 }
352 
353 
354 int acpi_processor_notify_smm(struct module *calling_module) {
355 	acpi_status		status;
356 	static int		is_done = 0;
357 
358 	ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
359 
360 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
361 		return_VALUE(-EBUSY);
362 
363 	if (!try_module_get(calling_module))
364 		return_VALUE(-EINVAL);
365 
366 	/* is_done is set to negative if an error occured,
367 	 * and to postitive if _no_ error occured, but SMM
368 	 * was already notified. This avoids double notification
369 	 * which might lead to unexpected results...
370 	 */
371 	if (is_done > 0) {
372 		module_put(calling_module);
373 		return_VALUE(0);
374 	}
375 	else if (is_done < 0) {
376 		module_put(calling_module);
377 		return_VALUE(is_done);
378 	}
379 
380 	is_done = -EIO;
381 
382 	/* Can't write pstate_cnt to smi_cmd if either value is zero */
383 	if ((!acpi_fadt.smi_cmd) ||
384 	    (!acpi_fadt.pstate_cnt)) {
385 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
386 			"No SMI port or pstate_cnt\n"));
387 		module_put(calling_module);
388 		return_VALUE(0);
389 	}
390 
391 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
392 
393 	/* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
394 	 * it anyway, so we need to support it... */
395 	if (acpi_fadt_is_v1) {
396 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
397 	}
398 
399 	status = acpi_os_write_port (acpi_fadt.smi_cmd,
400 				     (u32) acpi_fadt.pstate_cnt, 8);
401 	if (ACPI_FAILURE (status)) {
402 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
403 				  "Failed to write pstate_cnt [0x%x] to "
404 				  "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
405 		module_put(calling_module);
406 		return_VALUE(status);
407 	}
408 
409 	/* Success. If there's no _PPC, we need to fear nothing, so
410 	 * we can allow the cpufreq driver to be rmmod'ed. */
411 	is_done = 1;
412 
413 	if (!(acpi_processor_ppc_status & PPC_IN_USE))
414 		module_put(calling_module);
415 
416 	return_VALUE(0);
417 }
418 EXPORT_SYMBOL(acpi_processor_notify_smm);
419 
420 
421 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
422 /* /proc/acpi/processor/../performance interface (DEPRECATED) */
423 
424 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
425 static struct file_operations acpi_processor_perf_fops = {
426 	.open 		= acpi_processor_perf_open_fs,
427 	.read		= seq_read,
428 	.llseek		= seq_lseek,
429 	.release	= single_release,
430 };
431 
432 static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
433 {
434 	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
435 	int			i;
436 
437 	ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
438 
439 	if (!pr)
440 		goto end;
441 
442 	if (!pr->performance) {
443 		seq_puts(seq, "<not supported>\n");
444 		goto end;
445 	}
446 
447 	seq_printf(seq, "state count:             %d\n"
448 			"active state:            P%d\n",
449 			pr->performance->state_count,
450 			pr->performance->state);
451 
452 	seq_puts(seq, "states:\n");
453 	for (i = 0; i < pr->performance->state_count; i++)
454 		seq_printf(seq, "   %cP%d:                  %d MHz, %d mW, %d uS\n",
455 			(i == pr->performance->state?'*':' '), i,
456 			(u32) pr->performance->states[i].core_frequency,
457 			(u32) pr->performance->states[i].power,
458 			(u32) pr->performance->states[i].transition_latency);
459 
460 end:
461 	return_VALUE(0);
462 }
463 
464 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
465 {
466 	return single_open(file, acpi_processor_perf_seq_show,
467 						PDE(inode)->data);
468 }
469 
470 static ssize_t
471 acpi_processor_write_performance (
472         struct file		*file,
473         const char		__user *buffer,
474         size_t			count,
475         loff_t			*data)
476 {
477 	int			result = 0;
478 	struct seq_file		*m = (struct seq_file *) file->private_data;
479 	struct acpi_processor	*pr = (struct acpi_processor *) m->private;
480 	struct acpi_processor_performance *perf;
481 	char			state_string[12] = {'\0'};
482 	unsigned int            new_state = 0;
483 	struct cpufreq_policy   policy;
484 
485 	ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
486 
487 	if (!pr || (count > sizeof(state_string) - 1))
488 		return_VALUE(-EINVAL);
489 
490 	perf = pr->performance;
491 	if (!perf)
492 		return_VALUE(-EINVAL);
493 
494 	if (copy_from_user(state_string, buffer, count))
495 		return_VALUE(-EFAULT);
496 
497 	state_string[count] = '\0';
498 	new_state = simple_strtoul(state_string, NULL, 0);
499 
500 	if (new_state >= perf->state_count)
501 		return_VALUE(-EINVAL);
502 
503 	cpufreq_get_policy(&policy, pr->id);
504 
505 	policy.cpu = pr->id;
506 	policy.min = perf->states[new_state].core_frequency * 1000;
507 	policy.max = perf->states[new_state].core_frequency * 1000;
508 
509 	result = cpufreq_set_policy(&policy);
510 	if (result)
511 		return_VALUE(result);
512 
513 	return_VALUE(count);
514 }
515 
516 static void
517 acpi_cpufreq_add_file (
518 	struct acpi_processor *pr)
519 {
520 	struct proc_dir_entry	*entry = NULL;
521 	struct acpi_device	*device = NULL;
522 
523 	ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
524 
525 	if (acpi_bus_get_device(pr->handle, &device))
526 		return_VOID;
527 
528 	/* add file 'performance' [R/W] */
529 	entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
530 		  S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
531 	if (!entry)
532 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
533 			"Unable to create '%s' fs entry\n",
534 			ACPI_PROCESSOR_FILE_PERFORMANCE));
535 	else {
536 		entry->proc_fops = &acpi_processor_perf_fops;
537 		entry->proc_fops->write = acpi_processor_write_performance;
538 		entry->data = acpi_driver_data(device);
539 		entry->owner = THIS_MODULE;
540 	}
541 	return_VOID;
542 }
543 
544 static void
545 acpi_cpufreq_remove_file (
546 	struct acpi_processor *pr)
547 {
548 	struct acpi_device	*device = NULL;
549 
550 	ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
551 
552 	if (acpi_bus_get_device(pr->handle, &device))
553 		return_VOID;
554 
555 	/* remove file 'performance' */
556 	remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
557 		  acpi_device_dir(device));
558 
559 	return_VOID;
560 }
561 
562 #else
563 static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
564 static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
565 #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
566 
567 
568 int
569 acpi_processor_register_performance (
570 	struct acpi_processor_performance * performance,
571 	unsigned int cpu)
572 {
573 	struct acpi_processor *pr;
574 
575 	ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
576 
577 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
578 		return_VALUE(-EINVAL);
579 
580 	down(&performance_sem);
581 
582 	pr = processors[cpu];
583 	if (!pr) {
584 		up(&performance_sem);
585 		return_VALUE(-ENODEV);
586 	}
587 
588 	if (pr->performance) {
589 		up(&performance_sem);
590 		return_VALUE(-EBUSY);
591 	}
592 
593 	pr->performance = performance;
594 
595 	if (acpi_processor_get_performance_info(pr)) {
596 		pr->performance = NULL;
597 		up(&performance_sem);
598 		return_VALUE(-EIO);
599 	}
600 
601 	acpi_cpufreq_add_file(pr);
602 
603 	up(&performance_sem);
604 	return_VALUE(0);
605 }
606 EXPORT_SYMBOL(acpi_processor_register_performance);
607 
608 
609 void
610 acpi_processor_unregister_performance (
611 	struct acpi_processor_performance * performance,
612 	unsigned int cpu)
613 {
614 	struct acpi_processor *pr;
615 
616 	ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
617 
618 	down(&performance_sem);
619 
620 	pr = processors[cpu];
621 	if (!pr) {
622 		up(&performance_sem);
623 		return_VOID;
624 	}
625 
626 	kfree(pr->performance->states);
627 	pr->performance = NULL;
628 
629 	acpi_cpufreq_remove_file(pr);
630 
631 	up(&performance_sem);
632 
633 	return_VOID;
634 }
635 EXPORT_SYMBOL(acpi_processor_unregister_performance);
636