Blame view

drivers/acpi/processor_perflib.c 19.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /*
   * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
   *
   *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
   *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
   *  			- Added processor hotplug support
   *
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/cpufreq.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
32
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

16be87ea1   Miao Xie   ACPI: cpufreq, pr...
34
  #ifdef CONFIG_X86
910dfae29   Thomas Renninger   ACPI: cpufreq, pr...
35
  #include <asm/cpufeature.h>
16be87ea1   Miao Xie   ACPI: cpufreq, pr...
36
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  
  #include <acpi/acpi_bus.h>
89595b8f2   Bjorn Helgaas   ACPI: consolidate...
39
  #include <acpi/acpi_drivers.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <acpi/processor.h>
a192a9580   Len Brown   ACPI: Move defini...
41
  #define PREFIX "ACPI: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #define ACPI_PROCESSOR_CLASS		"processor"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
  #define ACPI_PROCESSOR_FILE_PERFORMANCE	"performance"
  #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
f52fd66d2   Len Brown   ACPI: clean up AC...
45
  ACPI_MODULE_NAME("processor_perflib");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

65c19bbd2   Arjan van de Ven   sem2mutex: driver...
47
  static DEFINE_MUTEX(performance_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
53
54
55
56
57
  
  /*
   * _PPC support is implemented as a CPUfreq policy notifier:
   * This means each time a CPUfreq driver registered also with
   * the ACPI core is asked to change the speed policy, the maximum
   * value is adjusted so that it is within the platform limit.
   *
   * Also, when a new platform limit value is detected, the CPUfreq
   * policy is adjusted accordingly.
   */
a1531acd4   Thomas Renninger   cpufreq acpi: onl...
58
59
60
61
62
63
  /* ignore_ppc:
   * -1 -> cpufreq low level drivers not initialized -> _PSS, etc. not called yet
   *       ignore _PPC
   *  0 -> cpufreq low level drivers initialized -> consider _PPC values
   *  1 -> ignore _PPC totally -> forced by user through boot param
   */
9f497bcc6   Milan Broz   ACPI: Fix thermal...
64
  static int ignore_ppc = -1;
613e5f337   Milan Broz   ACPI: Fix now sig...
65
  module_param(ignore_ppc, int, 0644);
623b78c39   Thomas Renninger   ACPI: add "proces...
66
67
  MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
  		 "limited by BIOS, this should help");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
  #define PPC_REGISTERED   1
  #define PPC_IN_USE       2
a1531acd4   Thomas Renninger   cpufreq acpi: onl...
70
  static int acpi_processor_ppc_status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  
  static int acpi_processor_ppc_notifier(struct notifier_block *nb,
4be44fcd3   Len Brown   [ACPI] Lindent al...
73
  				       unsigned long event, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
  {
  	struct cpufreq_policy *policy = data;
  	struct acpi_processor *pr;
  	unsigned int ppc = 0;
a1531acd4   Thomas Renninger   cpufreq acpi: onl...
78
79
80
81
  	if (event == CPUFREQ_START && ignore_ppc <= 0) {
  		ignore_ppc = 0;
  		return 0;
  	}
623b78c39   Thomas Renninger   ACPI: add "proces...
82
83
  	if (ignore_ppc)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	if (event != CPUFREQ_INCOMPATIBLE)
9b67c5d48   Thomas Renninger   acpi cpufreq clea...
85
86
87
  		return 0;
  
  	mutex_lock(&performance_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88

706546d02   Mike Travis   ACPI: change proc...
89
  	pr = per_cpu(processors, policy->cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  	if (!pr || !pr->performance)
  		goto out;
4be44fcd3   Len Brown   [ACPI] Lindent al...
92
  	ppc = (unsigned int)pr->performance_platform_limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

0916bd3eb   Dave Jones   [PATCH] Correct b...
94
  	if (ppc >= pr->performance->state_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
  		goto out;
  
  	cpufreq_verify_within_limits(policy, 0,
4be44fcd3   Len Brown   [ACPI] Lindent al...
98
99
  				     pr->performance->states[ppc].
  				     core_frequency * 1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

4be44fcd3   Len Brown   [ACPI] Lindent al...
101
        out:
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
102
  	mutex_unlock(&performance_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
  static struct notifier_block acpi_ppc_notifier_block = {
  	.notifier_call = acpi_processor_ppc_notifier,
  };
4be44fcd3   Len Brown   [ACPI] Lindent al...
109
  static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
111
  	acpi_status status = 0;
27663c585   Matthew Wilcox   ACPI: Change acpi...
112
  	unsigned long long ppc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
  
  	if (!pr)
d550d98d3   Patrick Mochel   ACPI: delete trac...
116
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
120
121
122
123
124
125
  
  	/*
  	 * _PPC indicates the maximum state currently supported by the platform
  	 * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
  	 */
  	status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
  
  	if (status != AE_NOT_FOUND)
  		acpi_processor_ppc_status |= PPC_IN_USE;
4be44fcd3   Len Brown   [ACPI] Lindent al...
126
  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
127
  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
d550d98d3   Patrick Mochel   ACPI: delete trac...
128
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  	}
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
130
131
  	pr_debug("CPU %d: _PPC is %d - frequency %s limited
  ", pr->id,
919158d17   Thomas Renninger   ACPI: cpufreq: Pr...
132
  		       (int)ppc, ppc ? "" : "not");
4be44fcd3   Len Brown   [ACPI] Lindent al...
133
  	pr->performance_platform_limit = (int)ppc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134

d550d98d3   Patrick Mochel   ACPI: delete trac...
135
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  }
d81c45e1c   Zhao Yakui   ACPI: Notify the ...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE	0x80
  /*
   * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
   * @handle: ACPI processor handle
   * @status: the status code of _PPC evaluation
   *	0: success. OSPM is now using the performance state specificed.
   *	1: failure. OSPM has not changed the number of P-states in use
   */
  static void acpi_processor_ppc_ost(acpi_handle handle, int status)
  {
  	union acpi_object params[2] = {
  		{.type = ACPI_TYPE_INTEGER,},
  		{.type = ACPI_TYPE_INTEGER,},
  	};
  	struct acpi_object_list arg_list = {2, params};
  	acpi_handle temp;
  
  	params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
  	params[1].integer.value =  status;
  
  	/* when there is no _OST , skip it */
  	if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
  		return;
  
  	acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
  	return;
  }
  
  int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  {
623b78c39   Thomas Renninger   ACPI: add "proces...
167
  	int ret;
d81c45e1c   Zhao Yakui   ACPI: Notify the ...
168
169
170
171
172
173
174
  	if (ignore_ppc) {
  		/*
  		 * Only when it is notification event, the _OST object
  		 * will be evaluated. Otherwise it is skipped.
  		 */
  		if (event_flag)
  			acpi_processor_ppc_ost(pr->handle, 1);
623b78c39   Thomas Renninger   ACPI: add "proces...
175
  		return 0;
d81c45e1c   Zhao Yakui   ACPI: Notify the ...
176
  	}
623b78c39   Thomas Renninger   ACPI: add "proces...
177
178
  
  	ret = acpi_processor_get_platform_limit(pr);
d81c45e1c   Zhao Yakui   ACPI: Notify the ...
179
180
181
182
183
184
185
186
187
188
  	/*
  	 * Only when it is notification event, the _OST object
  	 * will be evaluated. Otherwise it is skipped.
  	 */
  	if (event_flag) {
  		if (ret < 0)
  			acpi_processor_ppc_ost(pr->handle, 1);
  		else
  			acpi_processor_ppc_ost(pr->handle, 0);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
  	if (ret < 0)
  		return (ret);
  	else
  		return cpufreq_update_policy(pr->id);
  }
e2f74f355   Thomas Renninger   [ACPI/CPUFREQ] In...
194
195
196
197
198
199
200
201
202
203
204
205
  int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
  {
  	struct acpi_processor *pr;
  
  	pr = per_cpu(processors, cpu);
  	if (!pr || !pr->performance || !pr->performance->state_count)
  		return -ENODEV;
  	*limit = pr->performance->states[pr->performance_platform_limit].
  		core_frequency * 1000;
  	return 0;
  }
  EXPORT_SYMBOL(acpi_processor_get_bios_limit);
4be44fcd3   Len Brown   [ACPI] Lindent al...
206
207
208
209
  void acpi_processor_ppc_init(void)
  {
  	if (!cpufreq_register_notifier
  	    (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
  		acpi_processor_ppc_status |= PPC_REGISTERED;
  	else
4be44fcd3   Len Brown   [ACPI] Lindent al...
212
213
214
  		printk(KERN_DEBUG
  		       "Warning: Processor Platform Limit not supported.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
216
217
  void acpi_processor_ppc_exit(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  	if (acpi_processor_ppc_status & PPC_REGISTERED)
4be44fcd3   Len Brown   [ACPI] Lindent al...
219
220
  		cpufreq_unregister_notifier(&acpi_ppc_notifier_block,
  					    CPUFREQ_POLICY_NOTIFIER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
  
  	acpi_processor_ppc_status &= ~PPC_REGISTERED;
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
224
  static int acpi_processor_get_performance_control(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
226
227
228
229
230
  	int result = 0;
  	acpi_status status = 0;
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  	union acpi_object *pct = NULL;
  	union acpi_object obj = { 0 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  
  	status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
4be44fcd3   Len Brown   [ACPI] Lindent al...
234
  	if (ACPI_FAILURE(status)) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
235
  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PCT"));
d550d98d3   Patrick Mochel   ACPI: delete trac...
236
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
238
  	pct = (union acpi_object *)buffer.pointer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  	if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
4be44fcd3   Len Brown   [ACPI] Lindent al...
240
  	    || (pct->package.count != 2)) {
6468463ab   Len Brown   ACPI: un-export A...
241
242
  		printk(KERN_ERR PREFIX "Invalid _PCT data
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
248
249
250
251
252
253
  		result = -EFAULT;
  		goto end;
  	}
  
  	/*
  	 * control_register
  	 */
  
  	obj = pct->package.elements[0];
  
  	if ((obj.type != ACPI_TYPE_BUFFER)
4be44fcd3   Len Brown   [ACPI] Lindent al...
254
255
  	    || (obj.buffer.length < sizeof(struct acpi_pct_register))
  	    || (obj.buffer.pointer == NULL)) {
6468463ab   Len Brown   ACPI: un-export A...
256
257
  		printk(KERN_ERR PREFIX "Invalid _PCT data (control_register)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  		result = -EFAULT;
  		goto end;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
261
262
  	memcpy(&pr->performance->control_register, obj.buffer.pointer,
  	       sizeof(struct acpi_pct_register));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
266
267
268
269
270
  
  	/*
  	 * status_register
  	 */
  
  	obj = pct->package.elements[1];
  
  	if ((obj.type != ACPI_TYPE_BUFFER)
4be44fcd3   Len Brown   [ACPI] Lindent al...
271
272
  	    || (obj.buffer.length < sizeof(struct acpi_pct_register))
  	    || (obj.buffer.pointer == NULL)) {
6468463ab   Len Brown   ACPI: un-export A...
273
274
  		printk(KERN_ERR PREFIX "Invalid _PCT data (status_register)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
  		result = -EFAULT;
  		goto end;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
278
279
  	memcpy(&pr->performance->status_register, obj.buffer.pointer,
  	       sizeof(struct acpi_pct_register));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280

4be44fcd3   Len Brown   [ACPI] Lindent al...
281
        end:
02438d877   Len Brown   ACPI: delete acpi...
282
  	kfree(buffer.pointer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

d550d98d3   Patrick Mochel   ACPI: delete trac...
284
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
286
  static int acpi_processor_get_performance_states(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
288
289
290
291
292
293
294
  	int result = 0;
  	acpi_status status = AE_OK;
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  	struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
  	struct acpi_buffer state = { 0, NULL };
  	union acpi_object *pss = NULL;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
  
  	status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
4be44fcd3   Len Brown   [ACPI] Lindent al...
298
  	if (ACPI_FAILURE(status)) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
299
  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
d550d98d3   Patrick Mochel   ACPI: delete trac...
300
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  	}
50dd09697   Jan Engelhardt   ACPI: Remove unne...
302
  	pss = buffer.pointer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  	if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
6468463ab   Len Brown   ACPI: un-export A...
304
305
  		printk(KERN_ERR PREFIX "Invalid _PSS data
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
308
309
310
311
  		result = -EFAULT;
  		goto end;
  	}
  
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states
  ",
4be44fcd3   Len Brown   [ACPI] Lindent al...
312
  			  pss->package.count));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  
  	pr->performance->state_count = pss->package.count;
4be44fcd3   Len Brown   [ACPI] Lindent al...
315
316
317
  	pr->performance->states =
  	    kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
  		    GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  	if (!pr->performance->states) {
  		result = -ENOMEM;
  		goto end;
  	}
  
  	for (i = 0; i < pr->performance->state_count; i++) {
  
  		struct acpi_processor_px *px = &(pr->performance->states[i]);
  
  		state.length = sizeof(struct acpi_processor_px);
  		state.pointer = px;
  
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d
  ", i));
  
  		status = acpi_extract_package(&(pss->package.elements[i]),
4be44fcd3   Len Brown   [ACPI] Lindent al...
334
  					      &format, &state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  		if (ACPI_FAILURE(status)) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
336
  			ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
340
341
342
  			result = -EFAULT;
  			kfree(pr->performance->states);
  			goto end;
  		}
  
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
343
344
345
346
347
348
349
350
  				  "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]
  ",
  				  i,
  				  (u32) px->core_frequency,
  				  (u32) px->power,
  				  (u32) px->transition_latency,
  				  (u32) px->bus_master_latency,
  				  (u32) px->control, (u32) px->status));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

34d531e64   Len Brown   ACPI: sanity chec...
352
353
354
355
356
357
358
359
360
361
  		/*
   		 * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
  		 */
  		if (!px->core_frequency ||
  		    ((u32)(px->core_frequency * 1000) !=
  		     (px->core_frequency * 1000))) {
  			printk(KERN_ERR FW_BUG PREFIX
  			       "Invalid BIOS _PSS frequency: 0x%llx MHz
  ",
  			       px->core_frequency);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
366
  			result = -EFAULT;
  			kfree(pr->performance->states);
  			goto end;
  		}
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
367
        end:
02438d877   Len Brown   ACPI: delete acpi...
368
  	kfree(buffer.pointer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369

d550d98d3   Patrick Mochel   ACPI: delete trac...
370
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
372
  static int acpi_processor_get_performance_info(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
374
375
376
  	int result = 0;
  	acpi_status status = AE_OK;
  	acpi_handle handle = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  	if (!pr || !pr->performance || !pr->handle)
d550d98d3   Patrick Mochel   ACPI: delete trac...
379
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
  	status = acpi_get_handle(pr->handle, "_PCT", &handle);
  	if (ACPI_FAILURE(status)) {
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
384
385
  				  "ACPI-based processor performance control unavailable
  "));
d550d98d3   Patrick Mochel   ACPI: delete trac...
386
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
  	}
  
  	result = acpi_processor_get_performance_control(pr);
  	if (result)
910dfae29   Thomas Renninger   ACPI: cpufreq, pr...
391
  		goto update_bios;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
  
  	result = acpi_processor_get_performance_states(pr);
  	if (result)
910dfae29   Thomas Renninger   ACPI: cpufreq, pr...
395
  		goto update_bios;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

455c0d71d   Darrick J. Wong   ACPI: Fix regress...
397
398
399
400
401
  	/* We need to call _PPC once when cpufreq starts */
  	if (ignore_ppc != 1)
  		result = acpi_processor_get_platform_limit(pr);
  
  	return result;
910dfae29   Thomas Renninger   ACPI: cpufreq, pr...
402
403
404
405
406
407
  
  	/*
  	 * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
  	 * the BIOS is older than the CPU and does not know its frequencies
  	 */
   update_bios:
16be87ea1   Miao Xie   ACPI: cpufreq, pr...
408
  #ifdef CONFIG_X86
910dfae29   Thomas Renninger   ACPI: cpufreq, pr...
409
410
411
412
413
414
  	if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
  		if(boot_cpu_has(X86_FEATURE_EST))
  			printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
  			       "frequency support
  ");
  	}
16be87ea1   Miao Xie   ACPI: cpufreq, pr...
415
  #endif
910dfae29   Thomas Renninger   ACPI: cpufreq, pr...
416
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
418
419
420
421
  int acpi_processor_notify_smm(struct module *calling_module)
  {
  	acpi_status status;
  	static int is_done = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
  
  	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
d550d98d3   Patrick Mochel   ACPI: delete trac...
425
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  
  	if (!try_module_get(calling_module))
d550d98d3   Patrick Mochel   ACPI: delete trac...
428
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429

58f87ed0d   Lucas De Marchi   ACPI: Fix typos
430
431
  	/* is_done is set to negative if an error occurred,
  	 * and to postitive if _no_ error occurred, but SMM
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
436
  	 * was already notified. This avoids double notification
  	 * which might lead to unexpected results...
  	 */
  	if (is_done > 0) {
  		module_put(calling_module);
d550d98d3   Patrick Mochel   ACPI: delete trac...
437
  		return 0;
4be44fcd3   Len Brown   [ACPI] Lindent al...
438
  	} else if (is_done < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
  		module_put(calling_module);
d550d98d3   Patrick Mochel   ACPI: delete trac...
440
  		return is_done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
  	}
  
  	is_done = -EIO;
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
444
  	/* Can't write pstate_control to smi_command if either value is zero */
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
445
  	if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) {
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
446
447
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  		module_put(calling_module);
d550d98d3   Patrick Mochel   ACPI: delete trac...
449
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
451
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
452
453
  			  "Writing pstate_control [0x%x] to smi_command [0x%x]
  ",
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
454
  			  acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

cee324b14   Alexey Starikovskiy   ACPICA: use new A...
456
457
  	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
  				    (u32) acpi_gbl_FADT.pstate_control, 8);
4be44fcd3   Len Brown   [ACPI] Lindent al...
458
  	if (ACPI_FAILURE(status)) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
459
  		ACPI_EXCEPTION((AE_INFO, status,
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
460
  				"Failed to write pstate_control [0x%x] to "
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
461
462
  				"smi_command [0x%x]", acpi_gbl_FADT.pstate_control,
  				acpi_gbl_FADT.smi_command));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  		module_put(calling_module);
d550d98d3   Patrick Mochel   ACPI: delete trac...
464
  		return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
470
471
472
  	}
  
  	/* Success. If there's no _PPC, we need to fear nothing, so
  	 * we can allow the cpufreq driver to be rmmod'ed. */
  	is_done = 1;
  
  	if (!(acpi_processor_ppc_status & PPC_IN_USE))
  		module_put(calling_module);
d550d98d3   Patrick Mochel   ACPI: delete trac...
473
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475

4be44fcd3   Len Brown   [ACPI] Lindent al...
476
  EXPORT_SYMBOL(acpi_processor_notify_smm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477

3b2d99429   Venkatesh Pallipadi   P-state software ...
478
479
480
481
482
483
484
485
486
  static int acpi_processor_get_psd(struct acpi_processor	*pr)
  {
  	int result = 0;
  	acpi_status status = AE_OK;
  	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  	struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
  	struct acpi_buffer state = {0, NULL};
  	union acpi_object  *psd = NULL;
  	struct acpi_psd_package *pdomain;
3b2d99429   Venkatesh Pallipadi   P-state software ...
487
488
  	status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer);
  	if (ACPI_FAILURE(status)) {
9011bff4b   Len Brown   ACPI: delete newl...
489
  		return -ENODEV;
3b2d99429   Venkatesh Pallipadi   P-state software ...
490
  	}
50dd09697   Jan Engelhardt   ACPI: Remove unne...
491
  	psd = buffer.pointer;
3b2d99429   Venkatesh Pallipadi   P-state software ...
492
  	if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
55ac9a018   Lin Ming   ACPI: replace ACP...
493
494
  		printk(KERN_ERR PREFIX "Invalid _PSD data
  ");
3b2d99429   Venkatesh Pallipadi   P-state software ...
495
496
497
498
499
  		result = -EFAULT;
  		goto end;
  	}
  
  	if (psd->package.count != 1) {
55ac9a018   Lin Ming   ACPI: replace ACP...
500
501
  		printk(KERN_ERR PREFIX "Invalid _PSD data
  ");
3b2d99429   Venkatesh Pallipadi   P-state software ...
502
503
504
505
506
507
508
509
510
511
512
513
  		result = -EFAULT;
  		goto end;
  	}
  
  	pdomain = &(pr->performance->domain_info);
  
  	state.length = sizeof(struct acpi_psd_package);
  	state.pointer = pdomain;
  
  	status = acpi_extract_package(&(psd->package.elements[0]),
  		&format, &state);
  	if (ACPI_FAILURE(status)) {
55ac9a018   Lin Ming   ACPI: replace ACP...
514
515
  		printk(KERN_ERR PREFIX "Invalid _PSD data
  ");
3b2d99429   Venkatesh Pallipadi   P-state software ...
516
517
518
519
520
  		result = -EFAULT;
  		goto end;
  	}
  
  	if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
55ac9a018   Lin Ming   ACPI: replace ACP...
521
522
  		printk(KERN_ERR PREFIX "Unknown _PSD:num_entries
  ");
3b2d99429   Venkatesh Pallipadi   P-state software ...
523
524
525
526
527
  		result = -EFAULT;
  		goto end;
  	}
  
  	if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
55ac9a018   Lin Ming   ACPI: replace ACP...
528
529
  		printk(KERN_ERR PREFIX "Unknown _PSD:revision
  ");
3b2d99429   Venkatesh Pallipadi   P-state software ...
530
531
532
  		result = -EFAULT;
  		goto end;
  	}
e1eb47797   Stanislaw Gruszka   ACPI: Avoid wipin...
533
534
535
536
537
538
539
540
  	if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
  	    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
  	    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
  		printk(KERN_ERR PREFIX "Invalid _PSD:coord_type
  ");
  		result = -EFAULT;
  		goto end;
  	}
3b2d99429   Venkatesh Pallipadi   P-state software ...
541
  end:
02438d877   Len Brown   ACPI: delete acpi...
542
  	kfree(buffer.pointer);
9011bff4b   Len Brown   ACPI: delete newl...
543
  	return result;
3b2d99429   Venkatesh Pallipadi   P-state software ...
544
545
546
  }
  
  int acpi_processor_preregister_performance(
a29d8b8e2   Tejun Heo   percpu: add __per...
547
  		struct acpi_processor_performance __percpu *performance)
3b2d99429   Venkatesh Pallipadi   P-state software ...
548
549
550
551
  {
  	int count, count_target;
  	int retval = 0;
  	unsigned int i, j;
2fdf66b49   Rusty Russell   cpumask: convert ...
552
  	cpumask_var_t covered_cpus;
3b2d99429   Venkatesh Pallipadi   P-state software ...
553
554
555
556
  	struct acpi_processor *pr;
  	struct acpi_psd_package *pdomain;
  	struct acpi_processor *match_pr;
  	struct acpi_psd_package *match_pdomain;
79f559977   Li Zefan   cpumask: use zall...
557
  	if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
2fdf66b49   Rusty Russell   cpumask: convert ...
558
  		return -ENOMEM;
785fcccd6   Len Brown   ACPI: resolve mer...
559
  	mutex_lock(&performance_mutex);
3b2d99429   Venkatesh Pallipadi   P-state software ...
560

e1eb47797   Stanislaw Gruszka   ACPI: Avoid wipin...
561
562
563
564
  	/*
  	 * Check if another driver has already registered, and abort before
  	 * changing pr->performance if it has. Check input data as well.
  	 */
193de0c79   KAMEZAWA Hiroyuki   ACPI: use for_eac...
565
  	for_each_possible_cpu(i) {
706546d02   Mike Travis   ACPI: change proc...
566
  		pr = per_cpu(processors, i);
3b2d99429   Venkatesh Pallipadi   P-state software ...
567
568
569
570
571
572
573
  		if (!pr) {
  			/* Look only at processors in ACPI namespace */
  			continue;
  		}
  
  		if (pr->performance) {
  			retval = -EBUSY;
e1eb47797   Stanislaw Gruszka   ACPI: Avoid wipin...
574
  			goto err_out;
3b2d99429   Venkatesh Pallipadi   P-state software ...
575
  		}
b36128c83   Rusty Russell   alloc_percpu: cha...
576
  		if (!performance || !per_cpu_ptr(performance, i)) {
3b2d99429   Venkatesh Pallipadi   P-state software ...
577
  			retval = -EINVAL;
e1eb47797   Stanislaw Gruszka   ACPI: Avoid wipin...
578
  			goto err_out;
3b2d99429   Venkatesh Pallipadi   P-state software ...
579
  		}
e1eb47797   Stanislaw Gruszka   ACPI: Avoid wipin...
580
581
582
583
584
585
586
  	}
  
  	/* Call _PSD for all CPUs */
  	for_each_possible_cpu(i) {
  		pr = per_cpu(processors, i);
  		if (!pr)
  			continue;
3b2d99429   Venkatesh Pallipadi   P-state software ...
587

b36128c83   Rusty Russell   alloc_percpu: cha...
588
  		pr->performance = per_cpu_ptr(performance, i);
2fdf66b49   Rusty Russell   cpumask: convert ...
589
  		cpumask_set_cpu(i, pr->performance->shared_cpu_map);
3b2d99429   Venkatesh Pallipadi   P-state software ...
590
591
592
593
594
595
596
597
598
599
600
601
  		if (acpi_processor_get_psd(pr)) {
  			retval = -EINVAL;
  			continue;
  		}
  	}
  	if (retval)
  		goto err_ret;
  
  	/*
  	 * Now that we have _PSD data from all CPUs, lets setup P-state 
  	 * domain info.
  	 */
193de0c79   KAMEZAWA Hiroyuki   ACPI: use for_eac...
602
  	for_each_possible_cpu(i) {
706546d02   Mike Travis   ACPI: change proc...
603
  		pr = per_cpu(processors, i);
3b2d99429   Venkatesh Pallipadi   P-state software ...
604
605
  		if (!pr)
  			continue;
2fdf66b49   Rusty Russell   cpumask: convert ...
606
  		if (cpumask_test_cpu(i, covered_cpus))
3b2d99429   Venkatesh Pallipadi   P-state software ...
607
608
609
  			continue;
  
  		pdomain = &(pr->performance->domain_info);
2fdf66b49   Rusty Russell   cpumask: convert ...
610
611
  		cpumask_set_cpu(i, pr->performance->shared_cpu_map);
  		cpumask_set_cpu(i, covered_cpus);
3b2d99429   Venkatesh Pallipadi   P-state software ...
612
613
614
615
616
617
  		if (pdomain->num_processors <= 1)
  			continue;
  
  		/* Validate the Domain info */
  		count_target = pdomain->num_processors;
  		count = 1;
46f18e3a2   Venkatesh Pallipadi   ACPI: HW P-state ...
618
  		if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
3b2d99429   Venkatesh Pallipadi   P-state software ...
619
  			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
46f18e3a2   Venkatesh Pallipadi   ACPI: HW P-state ...
620
621
622
  		else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
  			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW;
  		else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
3b2d99429   Venkatesh Pallipadi   P-state software ...
623
  			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
3b2d99429   Venkatesh Pallipadi   P-state software ...
624

193de0c79   KAMEZAWA Hiroyuki   ACPI: use for_eac...
625
  		for_each_possible_cpu(j) {
3b2d99429   Venkatesh Pallipadi   P-state software ...
626
627
  			if (i == j)
  				continue;
706546d02   Mike Travis   ACPI: change proc...
628
  			match_pr = per_cpu(processors, j);
3b2d99429   Venkatesh Pallipadi   P-state software ...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  			if (!match_pr)
  				continue;
  
  			match_pdomain = &(match_pr->performance->domain_info);
  			if (match_pdomain->domain != pdomain->domain)
  				continue;
  
  			/* Here i and j are in the same domain */
  
  			if (match_pdomain->num_processors != count_target) {
  				retval = -EINVAL;
  				goto err_ret;
  			}
  
  			if (pdomain->coord_type != match_pdomain->coord_type) {
  				retval = -EINVAL;
  				goto err_ret;
  			}
2fdf66b49   Rusty Russell   cpumask: convert ...
647
648
  			cpumask_set_cpu(j, covered_cpus);
  			cpumask_set_cpu(j, pr->performance->shared_cpu_map);
3b2d99429   Venkatesh Pallipadi   P-state software ...
649
650
  			count++;
  		}
193de0c79   KAMEZAWA Hiroyuki   ACPI: use for_eac...
651
  		for_each_possible_cpu(j) {
3b2d99429   Venkatesh Pallipadi   P-state software ...
652
653
  			if (i == j)
  				continue;
706546d02   Mike Travis   ACPI: change proc...
654
  			match_pr = per_cpu(processors, j);
3b2d99429   Venkatesh Pallipadi   P-state software ...
655
656
657
658
659
660
661
662
663
  			if (!match_pr)
  				continue;
  
  			match_pdomain = &(match_pr->performance->domain_info);
  			if (match_pdomain->domain != pdomain->domain)
  				continue;
  
  			match_pr->performance->shared_type = 
  					pr->performance->shared_type;
2fdf66b49   Rusty Russell   cpumask: convert ...
664
665
  			cpumask_copy(match_pr->performance->shared_cpu_map,
  				     pr->performance->shared_cpu_map);
3b2d99429   Venkatesh Pallipadi   P-state software ...
666
667
668
669
  		}
  	}
  
  err_ret:
193de0c79   KAMEZAWA Hiroyuki   ACPI: use for_eac...
670
  	for_each_possible_cpu(i) {
706546d02   Mike Travis   ACPI: change proc...
671
  		pr = per_cpu(processors, i);
3b2d99429   Venkatesh Pallipadi   P-state software ...
672
673
674
675
676
  		if (!pr || !pr->performance)
  			continue;
  
  		/* Assume no coordination on any error parsing domain info */
  		if (retval) {
2fdf66b49   Rusty Russell   cpumask: convert ...
677
678
  			cpumask_clear(pr->performance->shared_cpu_map);
  			cpumask_set_cpu(i, pr->performance->shared_cpu_map);
3b2d99429   Venkatesh Pallipadi   P-state software ...
679
680
681
682
  			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
  		}
  		pr->performance = NULL; /* Will be set for real in register */
  	}
e1eb47797   Stanislaw Gruszka   ACPI: Avoid wipin...
683
  err_out:
785fcccd6   Len Brown   ACPI: resolve mer...
684
  	mutex_unlock(&performance_mutex);
2fdf66b49   Rusty Russell   cpumask: convert ...
685
  	free_cpumask_var(covered_cpus);
9011bff4b   Len Brown   ACPI: delete newl...
686
  	return retval;
3b2d99429   Venkatesh Pallipadi   P-state software ...
687
688
  }
  EXPORT_SYMBOL(acpi_processor_preregister_performance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  int
4be44fcd3   Len Brown   [ACPI] Lindent al...
690
691
  acpi_processor_register_performance(struct acpi_processor_performance
  				    *performance, unsigned int cpu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
  {
  	struct acpi_processor *pr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
d550d98d3   Patrick Mochel   ACPI: delete trac...
695
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696

65c19bbd2   Arjan van de Ven   sem2mutex: driver...
697
  	mutex_lock(&performance_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698

706546d02   Mike Travis   ACPI: change proc...
699
  	pr = per_cpu(processors, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  	if (!pr) {
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
701
  		mutex_unlock(&performance_mutex);
d550d98d3   Patrick Mochel   ACPI: delete trac...
702
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
  	}
  
  	if (pr->performance) {
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
706
  		mutex_unlock(&performance_mutex);
d550d98d3   Patrick Mochel   ACPI: delete trac...
707
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
  	}
a913f5070   Andrew Morton   [PATCH] powernow-...
709
  	WARN_ON(!performance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
  	pr->performance = performance;
  
  	if (acpi_processor_get_performance_info(pr)) {
  		pr->performance = NULL;
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
714
  		mutex_unlock(&performance_mutex);
d550d98d3   Patrick Mochel   ACPI: delete trac...
715
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  	}
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
717
  	mutex_unlock(&performance_mutex);
d550d98d3   Patrick Mochel   ACPI: delete trac...
718
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720

4be44fcd3   Len Brown   [ACPI] Lindent al...
721
  EXPORT_SYMBOL(acpi_processor_register_performance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  
  void
4be44fcd3   Len Brown   [ACPI] Lindent al...
724
725
  acpi_processor_unregister_performance(struct acpi_processor_performance
  				      *performance, unsigned int cpu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
  {
  	struct acpi_processor *pr;
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
728
  	mutex_lock(&performance_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729

706546d02   Mike Travis   ACPI: change proc...
730
  	pr = per_cpu(processors, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  	if (!pr) {
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
732
  		mutex_unlock(&performance_mutex);
d550d98d3   Patrick Mochel   ACPI: delete trac...
733
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  	}
a913f5070   Andrew Morton   [PATCH] powernow-...
735
736
  	if (pr->performance)
  		kfree(pr->performance->states);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
  	pr->performance = NULL;
65c19bbd2   Arjan van de Ven   sem2mutex: driver...
738
  	mutex_unlock(&performance_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739

d550d98d3   Patrick Mochel   ACPI: delete trac...
740
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
742

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
  EXPORT_SYMBOL(acpi_processor_unregister_performance);