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