processor_perflib.c revision 613e5f3376e48bd48494cf780b79b97b057d49a7
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#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/cpufreq.h>
33
34#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
35#include <linux/proc_fs.h>
36#include <linux/seq_file.h>
37#include <linux/mutex.h>
38
39#include <asm/uaccess.h>
40#endif
41
42#include <acpi/acpi_bus.h>
43#include <acpi/processor.h>
44
45#define ACPI_PROCESSOR_COMPONENT	0x01000000
46#define ACPI_PROCESSOR_CLASS		"processor"
47#define ACPI_PROCESSOR_FILE_PERFORMANCE	"performance"
48#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
49ACPI_MODULE_NAME("processor_perflib");
50
51static DEFINE_MUTEX(performance_mutex);
52
53/* Use cpufreq debug layer for _PPC changes. */
54#define cpufreq_printk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
55						"cpufreq-core", msg)
56
57/*
58 * _PPC support is implemented as a CPUfreq policy notifier:
59 * This means each time a CPUfreq driver registered also with
60 * the ACPI core is asked to change the speed policy, the maximum
61 * value is adjusted so that it is within the platform limit.
62 *
63 * Also, when a new platform limit value is detected, the CPUfreq
64 * policy is adjusted accordingly.
65 */
66
67/* ignore_ppc:
68 * -1 -> cpufreq low level drivers not initialized -> _PSS, etc. not called yet
69 *       ignore _PPC
70 *  0 -> cpufreq low level drivers initialized -> consider _PPC values
71 *  1 -> ignore _PPC totally -> forced by user through boot param
72 */
73static int ignore_ppc = -1;
74module_param(ignore_ppc, int, 0644);
75MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
76		 "limited by BIOS, this should help");
77
78#define PPC_REGISTERED   1
79#define PPC_IN_USE       2
80
81static int acpi_processor_ppc_status;
82
83static int acpi_processor_ppc_notifier(struct notifier_block *nb,
84				       unsigned long event, void *data)
85{
86	struct cpufreq_policy *policy = data;
87	struct acpi_processor *pr;
88	unsigned int ppc = 0;
89
90	if (event == CPUFREQ_START && ignore_ppc <= 0) {
91		ignore_ppc = 0;
92		return 0;
93	}
94
95	if (ignore_ppc)
96		return 0;
97
98	if (event != CPUFREQ_INCOMPATIBLE)
99		return 0;
100
101	mutex_lock(&performance_mutex);
102
103	pr = per_cpu(processors, policy->cpu);
104	if (!pr || !pr->performance)
105		goto out;
106
107	ppc = (unsigned int)pr->performance_platform_limit;
108
109	if (ppc >= pr->performance->state_count)
110		goto out;
111
112	cpufreq_verify_within_limits(policy, 0,
113				     pr->performance->states[ppc].
114				     core_frequency * 1000);
115
116      out:
117	mutex_unlock(&performance_mutex);
118
119	return 0;
120}
121
122static struct notifier_block acpi_ppc_notifier_block = {
123	.notifier_call = acpi_processor_ppc_notifier,
124};
125
126static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
127{
128	acpi_status status = 0;
129	unsigned long ppc = 0;
130
131
132	if (!pr)
133		return -EINVAL;
134
135	/*
136	 * _PPC indicates the maximum state currently supported by the platform
137	 * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
138	 */
139	status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
140
141	if (status != AE_NOT_FOUND)
142		acpi_processor_ppc_status |= PPC_IN_USE;
143
144	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
145		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
146		return -ENODEV;
147	}
148
149	cpufreq_printk("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
150		       (int)ppc, ppc ? "" : "not");
151
152	pr->performance_platform_limit = (int)ppc;
153
154	return 0;
155}
156
157int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
158{
159	int ret;
160
161	if (ignore_ppc)
162		return 0;
163
164	ret = acpi_processor_get_platform_limit(pr);
165
166	if (ret < 0)
167		return (ret);
168	else
169		return cpufreq_update_policy(pr->id);
170}
171
172void acpi_processor_ppc_init(void)
173{
174	if (!cpufreq_register_notifier
175	    (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
176		acpi_processor_ppc_status |= PPC_REGISTERED;
177	else
178		printk(KERN_DEBUG
179		       "Warning: Processor Platform Limit not supported.\n");
180}
181
182void acpi_processor_ppc_exit(void)
183{
184	if (acpi_processor_ppc_status & PPC_REGISTERED)
185		cpufreq_unregister_notifier(&acpi_ppc_notifier_block,
186					    CPUFREQ_POLICY_NOTIFIER);
187
188	acpi_processor_ppc_status &= ~PPC_REGISTERED;
189}
190
191static int acpi_processor_get_performance_control(struct acpi_processor *pr)
192{
193	int result = 0;
194	acpi_status status = 0;
195	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
196	union acpi_object *pct = NULL;
197	union acpi_object obj = { 0 };
198
199
200	status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
201	if (ACPI_FAILURE(status)) {
202		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PCT"));
203		return -ENODEV;
204	}
205
206	pct = (union acpi_object *)buffer.pointer;
207	if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
208	    || (pct->package.count != 2)) {
209		printk(KERN_ERR PREFIX "Invalid _PCT data\n");
210		result = -EFAULT;
211		goto end;
212	}
213
214	/*
215	 * control_register
216	 */
217
218	obj = pct->package.elements[0];
219
220	if ((obj.type != ACPI_TYPE_BUFFER)
221	    || (obj.buffer.length < sizeof(struct acpi_pct_register))
222	    || (obj.buffer.pointer == NULL)) {
223		printk(KERN_ERR PREFIX "Invalid _PCT data (control_register)\n");
224		result = -EFAULT;
225		goto end;
226	}
227	memcpy(&pr->performance->control_register, obj.buffer.pointer,
228	       sizeof(struct acpi_pct_register));
229
230	/*
231	 * status_register
232	 */
233
234	obj = pct->package.elements[1];
235
236	if ((obj.type != ACPI_TYPE_BUFFER)
237	    || (obj.buffer.length < sizeof(struct acpi_pct_register))
238	    || (obj.buffer.pointer == NULL)) {
239		printk(KERN_ERR PREFIX "Invalid _PCT data (status_register)\n");
240		result = -EFAULT;
241		goto end;
242	}
243
244	memcpy(&pr->performance->status_register, obj.buffer.pointer,
245	       sizeof(struct acpi_pct_register));
246
247      end:
248	kfree(buffer.pointer);
249
250	return result;
251}
252
253static int acpi_processor_get_performance_states(struct acpi_processor *pr)
254{
255	int result = 0;
256	acpi_status status = AE_OK;
257	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
258	struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
259	struct acpi_buffer state = { 0, NULL };
260	union acpi_object *pss = NULL;
261	int i;
262
263
264	status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
265	if (ACPI_FAILURE(status)) {
266		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
267		return -ENODEV;
268	}
269
270	pss = buffer.pointer;
271	if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
272		printk(KERN_ERR PREFIX "Invalid _PSS data\n");
273		result = -EFAULT;
274		goto end;
275	}
276
277	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
278			  pss->package.count));
279
280	pr->performance->state_count = pss->package.count;
281	pr->performance->states =
282	    kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
283		    GFP_KERNEL);
284	if (!pr->performance->states) {
285		result = -ENOMEM;
286		goto end;
287	}
288
289	for (i = 0; i < pr->performance->state_count; i++) {
290
291		struct acpi_processor_px *px = &(pr->performance->states[i]);
292
293		state.length = sizeof(struct acpi_processor_px);
294		state.pointer = px;
295
296		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
297
298		status = acpi_extract_package(&(pss->package.elements[i]),
299					      &format, &state);
300		if (ACPI_FAILURE(status)) {
301			ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
302			result = -EFAULT;
303			kfree(pr->performance->states);
304			goto end;
305		}
306
307		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
308				  "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
309				  i,
310				  (u32) px->core_frequency,
311				  (u32) px->power,
312				  (u32) px->transition_latency,
313				  (u32) px->bus_master_latency,
314				  (u32) px->control, (u32) px->status));
315
316		if (!px->core_frequency) {
317			printk(KERN_ERR PREFIX
318				    "Invalid _PSS data: freq is zero\n");
319			result = -EFAULT;
320			kfree(pr->performance->states);
321			goto end;
322		}
323	}
324
325      end:
326	kfree(buffer.pointer);
327
328	return result;
329}
330
331static int acpi_processor_get_performance_info(struct acpi_processor *pr)
332{
333	int result = 0;
334	acpi_status status = AE_OK;
335	acpi_handle handle = NULL;
336
337
338	if (!pr || !pr->performance || !pr->handle)
339		return -EINVAL;
340
341	status = acpi_get_handle(pr->handle, "_PCT", &handle);
342	if (ACPI_FAILURE(status)) {
343		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
344				  "ACPI-based processor performance control unavailable\n"));
345		return -ENODEV;
346	}
347
348	result = acpi_processor_get_performance_control(pr);
349	if (result)
350		return result;
351
352	result = acpi_processor_get_performance_states(pr);
353	if (result)
354		return result;
355
356	return 0;
357}
358
359int acpi_processor_notify_smm(struct module *calling_module)
360{
361	acpi_status status;
362	static int is_done = 0;
363
364
365	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
366		return -EBUSY;
367
368	if (!try_module_get(calling_module))
369		return -EINVAL;
370
371	/* is_done is set to negative if an error occured,
372	 * and to postitive if _no_ error occured, but SMM
373	 * was already notified. This avoids double notification
374	 * which might lead to unexpected results...
375	 */
376	if (is_done > 0) {
377		module_put(calling_module);
378		return 0;
379	} else if (is_done < 0) {
380		module_put(calling_module);
381		return is_done;
382	}
383
384	is_done = -EIO;
385
386	/* Can't write pstate_control to smi_command if either value is zero */
387	if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) {
388		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
389		module_put(calling_module);
390		return 0;
391	}
392
393	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
394			  "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
395			  acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
396
397	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
398				    (u32) acpi_gbl_FADT.pstate_control, 8);
399	if (ACPI_FAILURE(status)) {
400		ACPI_EXCEPTION((AE_INFO, status,
401				"Failed to write pstate_control [0x%x] to "
402				"smi_command [0x%x]", acpi_gbl_FADT.pstate_control,
403				acpi_gbl_FADT.smi_command));
404		module_put(calling_module);
405		return status;
406	}
407
408	/* Success. If there's no _PPC, we need to fear nothing, so
409	 * we can allow the cpufreq driver to be rmmod'ed. */
410	is_done = 1;
411
412	if (!(acpi_processor_ppc_status & PPC_IN_USE))
413		module_put(calling_module);
414
415	return 0;
416}
417
418EXPORT_SYMBOL(acpi_processor_notify_smm);
419
420#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
421/* /proc/acpi/processor/../performance interface (DEPRECATED) */
422
423static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
424static struct file_operations acpi_processor_perf_fops = {
425	.owner = THIS_MODULE,
426	.open = acpi_processor_perf_open_fs,
427	.read = seq_read,
428	.llseek = seq_lseek,
429	.release = single_release,
430};
431
432static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
433{
434	struct acpi_processor *pr = seq->private;
435	int i;
436
437
438	if (!pr)
439		goto end;
440
441	if (!pr->performance) {
442		seq_puts(seq, "<not supported>\n");
443		goto end;
444	}
445
446	seq_printf(seq, "state count:             %d\n"
447		   "active state:            P%d\n",
448		   pr->performance->state_count, pr->performance->state);
449
450	seq_puts(seq, "states:\n");
451	for (i = 0; i < pr->performance->state_count; i++)
452		seq_printf(seq,
453			   "   %cP%d:                  %d MHz, %d mW, %d uS\n",
454			   (i == pr->performance->state ? '*' : ' '), i,
455			   (u32) pr->performance->states[i].core_frequency,
456			   (u32) pr->performance->states[i].power,
457			   (u32) pr->performance->states[i].transition_latency);
458
459      end:
460	return 0;
461}
462
463static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
464{
465	return single_open(file, acpi_processor_perf_seq_show,
466			   PDE(inode)->data);
467}
468
469static void acpi_cpufreq_add_file(struct acpi_processor *pr)
470{
471	struct acpi_device *device = NULL;
472
473
474	if (acpi_bus_get_device(pr->handle, &device))
475		return;
476
477	/* add file 'performance' [R/W] */
478	proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
479			 acpi_device_dir(device),
480			 &acpi_processor_perf_fops, acpi_driver_data(device));
481	return;
482}
483
484static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
485{
486	struct acpi_device *device = NULL;
487
488
489	if (acpi_bus_get_device(pr->handle, &device))
490		return;
491
492	/* remove file 'performance' */
493	remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
494			  acpi_device_dir(device));
495
496	return;
497}
498
499#else
500static void acpi_cpufreq_add_file(struct acpi_processor *pr)
501{
502	return;
503}
504static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
505{
506	return;
507}
508#endif				/* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
509
510static int acpi_processor_get_psd(struct acpi_processor	*pr)
511{
512	int result = 0;
513	acpi_status status = AE_OK;
514	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
515	struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
516	struct acpi_buffer state = {0, NULL};
517	union acpi_object  *psd = NULL;
518	struct acpi_psd_package *pdomain;
519
520	status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer);
521	if (ACPI_FAILURE(status)) {
522		return -ENODEV;
523	}
524
525	psd = buffer.pointer;
526	if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
527		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
528		result = -EFAULT;
529		goto end;
530	}
531
532	if (psd->package.count != 1) {
533		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
534		result = -EFAULT;
535		goto end;
536	}
537
538	pdomain = &(pr->performance->domain_info);
539
540	state.length = sizeof(struct acpi_psd_package);
541	state.pointer = pdomain;
542
543	status = acpi_extract_package(&(psd->package.elements[0]),
544		&format, &state);
545	if (ACPI_FAILURE(status)) {
546		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
547		result = -EFAULT;
548		goto end;
549	}
550
551	if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
552		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
553		result = -EFAULT;
554		goto end;
555	}
556
557	if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
558		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
559		result = -EFAULT;
560		goto end;
561	}
562
563end:
564	kfree(buffer.pointer);
565	return result;
566}
567
568int acpi_processor_preregister_performance(
569		struct acpi_processor_performance *performance)
570{
571	int count, count_target;
572	int retval = 0;
573	unsigned int i, j;
574	cpumask_t covered_cpus;
575	struct acpi_processor *pr;
576	struct acpi_psd_package *pdomain;
577	struct acpi_processor *match_pr;
578	struct acpi_psd_package *match_pdomain;
579
580	mutex_lock(&performance_mutex);
581
582	retval = 0;
583
584	/* Call _PSD for all CPUs */
585	for_each_possible_cpu(i) {
586		pr = per_cpu(processors, i);
587		if (!pr) {
588			/* Look only at processors in ACPI namespace */
589			continue;
590		}
591
592		if (pr->performance) {
593			retval = -EBUSY;
594			continue;
595		}
596
597		if (!performance || !percpu_ptr(performance, i)) {
598			retval = -EINVAL;
599			continue;
600		}
601
602		pr->performance = percpu_ptr(performance, i);
603		cpu_set(i, pr->performance->shared_cpu_map);
604		if (acpi_processor_get_psd(pr)) {
605			retval = -EINVAL;
606			continue;
607		}
608	}
609	if (retval)
610		goto err_ret;
611
612	/*
613	 * Now that we have _PSD data from all CPUs, lets setup P-state
614	 * domain info.
615	 */
616	for_each_possible_cpu(i) {
617		pr = per_cpu(processors, i);
618		if (!pr)
619			continue;
620
621		/* Basic validity check for domain info */
622		pdomain = &(pr->performance->domain_info);
623		if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
624		    (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) {
625			retval = -EINVAL;
626			goto err_ret;
627		}
628		if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
629		    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
630		    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
631			retval = -EINVAL;
632			goto err_ret;
633		}
634	}
635
636	cpus_clear(covered_cpus);
637	for_each_possible_cpu(i) {
638		pr = per_cpu(processors, i);
639		if (!pr)
640			continue;
641
642		if (cpu_isset(i, covered_cpus))
643			continue;
644
645		pdomain = &(pr->performance->domain_info);
646		cpu_set(i, pr->performance->shared_cpu_map);
647		cpu_set(i, covered_cpus);
648		if (pdomain->num_processors <= 1)
649			continue;
650
651		/* Validate the Domain info */
652		count_target = pdomain->num_processors;
653		count = 1;
654		if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
655			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
656		else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
657			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW;
658		else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
659			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
660
661		for_each_possible_cpu(j) {
662			if (i == j)
663				continue;
664
665			match_pr = per_cpu(processors, j);
666			if (!match_pr)
667				continue;
668
669			match_pdomain = &(match_pr->performance->domain_info);
670			if (match_pdomain->domain != pdomain->domain)
671				continue;
672
673			/* Here i and j are in the same domain */
674
675			if (match_pdomain->num_processors != count_target) {
676				retval = -EINVAL;
677				goto err_ret;
678			}
679
680			if (pdomain->coord_type != match_pdomain->coord_type) {
681				retval = -EINVAL;
682				goto err_ret;
683			}
684
685			cpu_set(j, covered_cpus);
686			cpu_set(j, pr->performance->shared_cpu_map);
687			count++;
688		}
689
690		for_each_possible_cpu(j) {
691			if (i == j)
692				continue;
693
694			match_pr = per_cpu(processors, j);
695			if (!match_pr)
696				continue;
697
698			match_pdomain = &(match_pr->performance->domain_info);
699			if (match_pdomain->domain != pdomain->domain)
700				continue;
701
702			match_pr->performance->shared_type =
703					pr->performance->shared_type;
704			match_pr->performance->shared_cpu_map =
705				pr->performance->shared_cpu_map;
706		}
707	}
708
709err_ret:
710	for_each_possible_cpu(i) {
711		pr = per_cpu(processors, i);
712		if (!pr || !pr->performance)
713			continue;
714
715		/* Assume no coordination on any error parsing domain info */
716		if (retval) {
717			cpus_clear(pr->performance->shared_cpu_map);
718			cpu_set(i, pr->performance->shared_cpu_map);
719			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
720		}
721		pr->performance = NULL; /* Will be set for real in register */
722	}
723
724	mutex_unlock(&performance_mutex);
725	return retval;
726}
727EXPORT_SYMBOL(acpi_processor_preregister_performance);
728
729
730int
731acpi_processor_register_performance(struct acpi_processor_performance
732				    *performance, unsigned int cpu)
733{
734	struct acpi_processor *pr;
735
736
737	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
738		return -EINVAL;
739
740	mutex_lock(&performance_mutex);
741
742	pr = per_cpu(processors, cpu);
743	if (!pr) {
744		mutex_unlock(&performance_mutex);
745		return -ENODEV;
746	}
747
748	if (pr->performance) {
749		mutex_unlock(&performance_mutex);
750		return -EBUSY;
751	}
752
753	WARN_ON(!performance);
754
755	pr->performance = performance;
756
757	if (acpi_processor_get_performance_info(pr)) {
758		pr->performance = NULL;
759		mutex_unlock(&performance_mutex);
760		return -EIO;
761	}
762
763	acpi_cpufreq_add_file(pr);
764
765	mutex_unlock(&performance_mutex);
766	return 0;
767}
768
769EXPORT_SYMBOL(acpi_processor_register_performance);
770
771void
772acpi_processor_unregister_performance(struct acpi_processor_performance
773				      *performance, unsigned int cpu)
774{
775	struct acpi_processor *pr;
776
777
778	mutex_lock(&performance_mutex);
779
780	pr = per_cpu(processors, cpu);
781	if (!pr) {
782		mutex_unlock(&performance_mutex);
783		return;
784	}
785
786	if (pr->performance)
787		kfree(pr->performance->states);
788	pr->performance = NULL;
789
790	acpi_cpufreq_remove_file(pr);
791
792	mutex_unlock(&performance_mutex);
793
794	return;
795}
796
797EXPORT_SYMBOL(acpi_processor_unregister_performance);
798