xref: /openbmc/linux/drivers/acpi/processor_perflib.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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  * when registering a cpufreq driver with this ACPI processor driver, the
170  * _PCT and _PSS structures are read out and written into struct
171  * acpi_processor_performance.
172  */
173 static int acpi_processor_set_pdc (struct acpi_processor *pr)
174 {
175 	acpi_status             status = AE_OK;
176 	u32			arg0_buf[3];
177 	union acpi_object	arg0 = {ACPI_TYPE_BUFFER};
178 	struct acpi_object_list no_object = {1, &arg0};
179 	struct acpi_object_list *pdc;
180 
181 	ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
182 
183 	arg0.buffer.length = 12;
184 	arg0.buffer.pointer = (u8 *) arg0_buf;
185 	arg0_buf[0] = ACPI_PDC_REVISION_ID;
186 	arg0_buf[1] = 0;
187 	arg0_buf[2] = 0;
188 
189 	pdc = (pr->performance->pdc) ? pr->performance->pdc : &no_object;
190 
191 	status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
192 
193 	if ((ACPI_FAILURE(status)) && (pr->performance->pdc))
194 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n"));
195 
196 	return_VALUE(status);
197 }
198 
199 
200 static int
201 acpi_processor_get_performance_control (
202 	struct acpi_processor *pr)
203 {
204 	int			result = 0;
205 	acpi_status		status = 0;
206 	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};
207 	union acpi_object	*pct = NULL;
208 	union acpi_object	obj = {0};
209 
210 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
211 
212 	status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
213 	if(ACPI_FAILURE(status)) {
214 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
215 		return_VALUE(-ENODEV);
216 	}
217 
218 	pct = (union acpi_object *) buffer.pointer;
219 	if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
220 		|| (pct->package.count != 2)) {
221 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
222 		result = -EFAULT;
223 		goto end;
224 	}
225 
226 	/*
227 	 * control_register
228 	 */
229 
230 	obj = pct->package.elements[0];
231 
232 	if ((obj.type != ACPI_TYPE_BUFFER)
233 		|| (obj.buffer.length < sizeof(struct acpi_pct_register))
234 		|| (obj.buffer.pointer == NULL)) {
235 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
236 			"Invalid _PCT data (control_register)\n"));
237 		result = -EFAULT;
238 		goto end;
239 	}
240 	memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
241 
242 
243 	/*
244 	 * status_register
245 	 */
246 
247 	obj = pct->package.elements[1];
248 
249 	if ((obj.type != ACPI_TYPE_BUFFER)
250 		|| (obj.buffer.length < sizeof(struct acpi_pct_register))
251 		|| (obj.buffer.pointer == NULL)) {
252 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
253 			"Invalid _PCT data (status_register)\n"));
254 		result = -EFAULT;
255 		goto end;
256 	}
257 
258 	memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
259 
260 end:
261 	acpi_os_free(buffer.pointer);
262 
263 	return_VALUE(result);
264 }
265 
266 
267 static int
268 acpi_processor_get_performance_states (
269 	struct acpi_processor	*pr)
270 {
271 	int			result = 0;
272 	acpi_status		status = AE_OK;
273 	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};
274 	struct acpi_buffer	format = {sizeof("NNNNNN"), "NNNNNN"};
275 	struct acpi_buffer	state = {0, NULL};
276 	union acpi_object 	*pss = NULL;
277 	int			i;
278 
279 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
280 
281 	status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
282 	if(ACPI_FAILURE(status)) {
283 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
284 		return_VALUE(-ENODEV);
285 	}
286 
287 	pss = (union acpi_object *) buffer.pointer;
288 	if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
289 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
290 		result = -EFAULT;
291 		goto end;
292 	}
293 
294 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
295 		pss->package.count));
296 
297 	pr->performance->state_count = pss->package.count;
298 	pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
299 	if (!pr->performance->states) {
300 		result = -ENOMEM;
301 		goto end;
302 	}
303 
304 	for (i = 0; i < pr->performance->state_count; i++) {
305 
306 		struct acpi_processor_px *px = &(pr->performance->states[i]);
307 
308 		state.length = sizeof(struct acpi_processor_px);
309 		state.pointer = px;
310 
311 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
312 
313 		status = acpi_extract_package(&(pss->package.elements[i]),
314 			&format, &state);
315 		if (ACPI_FAILURE(status)) {
316 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
317 			result = -EFAULT;
318 			kfree(pr->performance->states);
319 			goto end;
320 		}
321 
322 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
323 			"State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
324 			i,
325 			(u32) px->core_frequency,
326 			(u32) px->power,
327 			(u32) px->transition_latency,
328 			(u32) px->bus_master_latency,
329 			(u32) px->control,
330 			(u32) px->status));
331 
332 		if (!px->core_frequency) {
333 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
334 			result = -EFAULT;
335 			kfree(pr->performance->states);
336 			goto end;
337 		}
338 	}
339 
340 end:
341 	acpi_os_free(buffer.pointer);
342 
343 	return_VALUE(result);
344 }
345 
346 
347 static int
348 acpi_processor_get_performance_info (
349 	struct acpi_processor	*pr)
350 {
351 	int			result = 0;
352 	acpi_status		status = AE_OK;
353 	acpi_handle		handle = NULL;
354 
355 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
356 
357 	if (!pr || !pr->performance || !pr->handle)
358 		return_VALUE(-EINVAL);
359 
360 	acpi_processor_set_pdc(pr);
361 
362 	status = acpi_get_handle(pr->handle, "_PCT", &handle);
363 	if (ACPI_FAILURE(status)) {
364 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
365 			"ACPI-based processor performance control unavailable\n"));
366 		return_VALUE(-ENODEV);
367 	}
368 
369 	result = acpi_processor_get_performance_control(pr);
370 	if (result)
371 		return_VALUE(result);
372 
373 	result = acpi_processor_get_performance_states(pr);
374 	if (result)
375 		return_VALUE(result);
376 
377 	result = acpi_processor_get_platform_limit(pr);
378 	if (result)
379 		return_VALUE(result);
380 
381 	return_VALUE(0);
382 }
383 
384 
385 int acpi_processor_notify_smm(struct module *calling_module) {
386 	acpi_status		status;
387 	static int		is_done = 0;
388 
389 	ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
390 
391 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
392 		return_VALUE(-EBUSY);
393 
394 	if (!try_module_get(calling_module))
395 		return_VALUE(-EINVAL);
396 
397 	/* is_done is set to negative if an error occured,
398 	 * and to postitive if _no_ error occured, but SMM
399 	 * was already notified. This avoids double notification
400 	 * which might lead to unexpected results...
401 	 */
402 	if (is_done > 0) {
403 		module_put(calling_module);
404 		return_VALUE(0);
405 	}
406 	else if (is_done < 0) {
407 		module_put(calling_module);
408 		return_VALUE(is_done);
409 	}
410 
411 	is_done = -EIO;
412 
413 	/* Can't write pstate_cnt to smi_cmd if either value is zero */
414 	if ((!acpi_fadt.smi_cmd) ||
415 	    (!acpi_fadt.pstate_cnt)) {
416 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
417 			"No SMI port or pstate_cnt\n"));
418 		module_put(calling_module);
419 		return_VALUE(0);
420 	}
421 
422 	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));
423 
424 	/* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
425 	 * it anyway, so we need to support it... */
426 	if (acpi_fadt_is_v1) {
427 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
428 	}
429 
430 	status = acpi_os_write_port (acpi_fadt.smi_cmd,
431 				     (u32) acpi_fadt.pstate_cnt, 8);
432 	if (ACPI_FAILURE (status)) {
433 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
434 				  "Failed to write pstate_cnt [0x%x] to "
435 				  "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
436 		module_put(calling_module);
437 		return_VALUE(status);
438 	}
439 
440 	/* Success. If there's no _PPC, we need to fear nothing, so
441 	 * we can allow the cpufreq driver to be rmmod'ed. */
442 	is_done = 1;
443 
444 	if (!(acpi_processor_ppc_status & PPC_IN_USE))
445 		module_put(calling_module);
446 
447 	return_VALUE(0);
448 }
449 EXPORT_SYMBOL(acpi_processor_notify_smm);
450 
451 
452 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
453 /* /proc/acpi/processor/../performance interface (DEPRECATED) */
454 
455 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
456 static struct file_operations acpi_processor_perf_fops = {
457 	.open 		= acpi_processor_perf_open_fs,
458 	.read		= seq_read,
459 	.llseek		= seq_lseek,
460 	.release	= single_release,
461 };
462 
463 static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
464 {
465 	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
466 	int			i;
467 
468 	ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
469 
470 	if (!pr)
471 		goto end;
472 
473 	if (!pr->performance) {
474 		seq_puts(seq, "<not supported>\n");
475 		goto end;
476 	}
477 
478 	seq_printf(seq, "state count:             %d\n"
479 			"active state:            P%d\n",
480 			pr->performance->state_count,
481 			pr->performance->state);
482 
483 	seq_puts(seq, "states:\n");
484 	for (i = 0; i < pr->performance->state_count; i++)
485 		seq_printf(seq, "   %cP%d:                  %d MHz, %d mW, %d uS\n",
486 			(i == pr->performance->state?'*':' '), i,
487 			(u32) pr->performance->states[i].core_frequency,
488 			(u32) pr->performance->states[i].power,
489 			(u32) pr->performance->states[i].transition_latency);
490 
491 end:
492 	return_VALUE(0);
493 }
494 
495 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
496 {
497 	return single_open(file, acpi_processor_perf_seq_show,
498 						PDE(inode)->data);
499 }
500 
501 static ssize_t
502 acpi_processor_write_performance (
503         struct file		*file,
504         const char		__user *buffer,
505         size_t			count,
506         loff_t			*data)
507 {
508 	int			result = 0;
509 	struct seq_file		*m = (struct seq_file *) file->private_data;
510 	struct acpi_processor	*pr = (struct acpi_processor *) m->private;
511 	struct acpi_processor_performance *perf;
512 	char			state_string[12] = {'\0'};
513 	unsigned int            new_state = 0;
514 	struct cpufreq_policy   policy;
515 
516 	ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
517 
518 	if (!pr || (count > sizeof(state_string) - 1))
519 		return_VALUE(-EINVAL);
520 
521 	perf = pr->performance;
522 	if (!perf)
523 		return_VALUE(-EINVAL);
524 
525 	if (copy_from_user(state_string, buffer, count))
526 		return_VALUE(-EFAULT);
527 
528 	state_string[count] = '\0';
529 	new_state = simple_strtoul(state_string, NULL, 0);
530 
531 	if (new_state >= perf->state_count)
532 		return_VALUE(-EINVAL);
533 
534 	cpufreq_get_policy(&policy, pr->id);
535 
536 	policy.cpu = pr->id;
537 	policy.min = perf->states[new_state].core_frequency * 1000;
538 	policy.max = perf->states[new_state].core_frequency * 1000;
539 
540 	result = cpufreq_set_policy(&policy);
541 	if (result)
542 		return_VALUE(result);
543 
544 	return_VALUE(count);
545 }
546 
547 static void
548 acpi_cpufreq_add_file (
549 	struct acpi_processor *pr)
550 {
551 	struct proc_dir_entry	*entry = NULL;
552 	struct acpi_device	*device = NULL;
553 
554 	ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
555 
556 	if (acpi_bus_get_device(pr->handle, &device))
557 		return_VOID;
558 
559 	/* add file 'performance' [R/W] */
560 	entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
561 		  S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
562 	if (!entry)
563 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
564 			"Unable to create '%s' fs entry\n",
565 			ACPI_PROCESSOR_FILE_PERFORMANCE));
566 	else {
567 		entry->proc_fops = &acpi_processor_perf_fops;
568 		entry->proc_fops->write = acpi_processor_write_performance;
569 		entry->data = acpi_driver_data(device);
570 		entry->owner = THIS_MODULE;
571 	}
572 	return_VOID;
573 }
574 
575 static void
576 acpi_cpufreq_remove_file (
577 	struct acpi_processor *pr)
578 {
579 	struct acpi_device	*device = NULL;
580 
581 	ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
582 
583 	if (acpi_bus_get_device(pr->handle, &device))
584 		return_VOID;
585 
586 	/* remove file 'performance' */
587 	remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
588 		  acpi_device_dir(device));
589 
590 	return_VOID;
591 }
592 
593 #else
594 static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
595 static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
596 #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
597 
598 
599 int
600 acpi_processor_register_performance (
601 	struct acpi_processor_performance * performance,
602 	unsigned int cpu)
603 {
604 	struct acpi_processor *pr;
605 
606 	ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
607 
608 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
609 		return_VALUE(-EINVAL);
610 
611 	down(&performance_sem);
612 
613 	pr = processors[cpu];
614 	if (!pr) {
615 		up(&performance_sem);
616 		return_VALUE(-ENODEV);
617 	}
618 
619 	if (pr->performance) {
620 		up(&performance_sem);
621 		return_VALUE(-EBUSY);
622 	}
623 
624 	pr->performance = performance;
625 
626 	if (acpi_processor_get_performance_info(pr)) {
627 		pr->performance = NULL;
628 		up(&performance_sem);
629 		return_VALUE(-EIO);
630 	}
631 
632 	acpi_cpufreq_add_file(pr);
633 
634 	up(&performance_sem);
635 	return_VALUE(0);
636 }
637 EXPORT_SYMBOL(acpi_processor_register_performance);
638 
639 
640 void
641 acpi_processor_unregister_performance (
642 	struct acpi_processor_performance * performance,
643 	unsigned int cpu)
644 {
645 	struct acpi_processor *pr;
646 
647 	ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
648 
649 	down(&performance_sem);
650 
651 	pr = processors[cpu];
652 	if (!pr) {
653 		up(&performance_sem);
654 		return_VOID;
655 	}
656 
657 	kfree(pr->performance->states);
658 	pr->performance = NULL;
659 
660 	acpi_cpufreq_remove_file(pr);
661 
662 	up(&performance_sem);
663 
664 	return_VOID;
665 }
666 EXPORT_SYMBOL(acpi_processor_unregister_performance);
667