Blame view

drivers/acpi/processor_core.c 24.8 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  /*
   * acpi_processor.c - ACPI Processor Driver ($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.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *  TBD:
   *	1. Make # power states dynamic.
   *	2. Support duty_cycle values that span bit 4.
   *	3. Optimize by having scheduler determine business instead of
   *	   having us try to calculate it here.
   *	4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/types.h>
  #include <linux/pci.h>
  #include <linux/pm.h>
  #include <linux/cpufreq.h>
  #include <linux/cpu.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/dmi.h>
  #include <linux/moduleparam.h>
  
  #include <asm/io.h>
  #include <asm/system.h>
  #include <asm/cpu.h>
  #include <asm/delay.h>
  #include <asm/uaccess.h>
  #include <asm/processor.h>
  #include <asm/smp.h>
  #include <asm/acpi.h>
  
  #include <acpi/acpi_bus.h>
  #include <acpi/acpi_drivers.h>
  #include <acpi/processor.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  #define ACPI_PROCESSOR_COMPONENT	0x01000000
  #define ACPI_PROCESSOR_CLASS		"processor"
  #define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
  #define ACPI_PROCESSOR_DEVICE_NAME	"Processor"
  #define ACPI_PROCESSOR_FILE_INFO	"info"
  #define ACPI_PROCESSOR_FILE_THROTTLING	"throttling"
  #define ACPI_PROCESSOR_FILE_LIMIT	"limit"
  #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
  #define ACPI_PROCESSOR_NOTIFY_POWER	0x81
  
  #define ACPI_PROCESSOR_LIMIT_USER	0
  #define ACPI_PROCESSOR_LIMIT_THERMAL	1
  
  #define ACPI_STA_PRESENT 0x00000001
  
  #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
4be44fcd3   Len Brown   [ACPI] Lindent al...
76
  ACPI_MODULE_NAME("acpi_processor")
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77

4be44fcd3   Len Brown   [ACPI] Lindent al...
78
      MODULE_AUTHOR("Paul Diefenbaugh");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
  MODULE_LICENSE("GPL");
4be44fcd3   Len Brown   [ACPI] Lindent al...
81
82
83
  static int acpi_processor_add(struct acpi_device *device);
  static int acpi_processor_start(struct acpi_device *device);
  static int acpi_processor_remove(struct acpi_device *device, int type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
4be44fcd3   Len Brown   [ACPI] Lindent al...
85
  static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
  static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
  static int acpi_processor_handle_eject(struct acpi_processor *pr);
  
  static struct acpi_driver acpi_processor_driver = {
4be44fcd3   Len Brown   [ACPI] Lindent al...
90
91
92
93
94
95
96
97
  	.name = ACPI_PROCESSOR_DRIVER_NAME,
  	.class = ACPI_PROCESSOR_CLASS,
  	.ids = ACPI_PROCESSOR_HID,
  	.ops = {
  		.add = acpi_processor_add,
  		.remove = acpi_processor_remove,
  		.start = acpi_processor_start,
  		},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
  };
  
  #define INSTALL_NOTIFY_HANDLER		1
  #define UNINSTALL_NOTIFY_HANDLER	2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  static struct file_operations acpi_processor_info_fops = {
4be44fcd3   Len Brown   [ACPI] Lindent al...
103
104
105
106
  	.open = acpi_processor_info_open_fs,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = single_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  };
4be44fcd3   Len Brown   [ACPI] Lindent al...
108
  struct acpi_processor *processors[NR_CPUS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  struct acpi_processor_errata errata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
  /* --------------------------------------------------------------------------
                                  Errata Handling
     -------------------------------------------------------------------------- */
4be44fcd3   Len Brown   [ACPI] Lindent al...
113
  static int acpi_processor_errata_piix4(struct pci_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
115
116
117
  	u8 rev = 0;
  	u8 value1 = 0;
  	u8 value2 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  
  	ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
  
  	if (!dev)
  		return_VALUE(-EINVAL);
  
  	/*
  	 * Note that 'dev' references the PIIX4 ACPI Controller.
  	 */
  
  	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
  
  	switch (rev) {
  	case 0:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step
  "));
  		break;
  	case 1:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step
  "));
  		break;
  	case 2:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E
  "));
  		break;
  	case 3:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M
  "));
  		break;
  	default:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4
  "));
  		break;
  	}
  
  	switch (rev) {
  
  	case 0:		/* PIIX4 A-step */
  	case 1:		/* PIIX4 B-step */
  		/*
  		 * See specification changes #13 ("Manual Throttle Duty Cycle")
  		 * and #14 ("Enabling and Disabling Manual Throttle"), plus
  		 * erratum #5 ("STPCLK# Deassertion Time") from the January
  		 * 2002 PIIX4 specification update.  Applies to only older
  		 * PIIX4 models.
  		 */
  		errata.piix4.throttle = 1;
  
  	case 2:		/* PIIX4E */
  	case 3:		/* PIIX4M */
  		/*
  		 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
  		 * Livelock") from the January 2002 PIIX4 specification update.
  		 * Applies to all PIIX4 models.
  		 */
  
  		/*
  		 * BM-IDE
  		 * ------
  		 * Find the PIIX4 IDE Controller and get the Bus Master IDE
  		 * Status register address.  We'll use this later to read
  		 * each IDE controller's DMA status to make sure we catch all
  		 * DMA activity.
  		 */
  		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
4be44fcd3   Len Brown   [ACPI] Lindent al...
183
184
  				     PCI_DEVICE_ID_INTEL_82371AB,
  				     PCI_ANY_ID, PCI_ANY_ID, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  		if (dev) {
  			errata.piix4.bmisx = pci_resource_start(dev, 4);
  			pci_dev_put(dev);
  		}
  
  		/*
  		 * Type-F DMA
  		 * ----------
  		 * Find the PIIX4 ISA Controller and read the Motherboard
  		 * DMA controller's status to see if Type-F (Fast) DMA mode
  		 * is enabled (bit 7) on either channel.  Note that we'll
  		 * disable C3 support if this is enabled, as some legacy
  		 * devices won't operate well if fast DMA is disabled.
  		 */
  		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
4be44fcd3   Len Brown   [ACPI] Lindent al...
200
201
  				     PCI_DEVICE_ID_INTEL_82371AB_0,
  				     PCI_ANY_ID, PCI_ANY_ID, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
210
211
212
213
214
  		if (dev) {
  			pci_read_config_byte(dev, 0x76, &value1);
  			pci_read_config_byte(dev, 0x77, &value2);
  			if ((value1 & 0x80) || (value2 & 0x80))
  				errata.piix4.fdma = 1;
  			pci_dev_put(dev);
  		}
  
  		break;
  	}
  
  	if (errata.piix4.bmisx)
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
215
216
  				  "Bus master activity detection (BM-IDE) erratum enabled
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
  	if (errata.piix4.fdma)
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
219
220
  				  "Type-F DMA livelock erratum (C3 disabled)
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
  
  	return_VALUE(0);
  }
8713cbefa   Adrian Bunk   [ACPI] add static...
224
  static int acpi_processor_errata(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
226
227
  	int result = 0;
  	struct pci_dev *dev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
232
233
234
235
236
237
  
  	ACPI_FUNCTION_TRACE("acpi_processor_errata");
  
  	if (!pr)
  		return_VALUE(-EINVAL);
  
  	/*
  	 * PIIX4
  	 */
  	dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
4be44fcd3   Len Brown   [ACPI] Lindent al...
238
239
  			     PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
  			     PCI_ANY_ID, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
244
245
246
  	if (dev) {
  		result = acpi_processor_errata_piix4(dev);
  		pci_dev_put(dev);
  	}
  
  	return_VALUE(result);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  /* --------------------------------------------------------------------------
02df8b938   Venkatesh Pallipadi   [ACPI] enable C2 ...
248
249
250
251
252
253
254
255
256
                                Common ACPI processor fucntions
     -------------------------------------------------------------------------- */
  
  /*
   * _PDC is required for a BIOS-OS handshake for most of the newer
   * ACPI processor features.
   */
  
  int acpi_processor_set_pdc(struct acpi_processor *pr,
4be44fcd3   Len Brown   [ACPI] Lindent al...
257
  			   struct acpi_object_list *pdc_in)
02df8b938   Venkatesh Pallipadi   [ACPI] enable C2 ...
258
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
259
260
261
262
263
  	acpi_status status = AE_OK;
  	u32 arg0_buf[3];
  	union acpi_object arg0 = { ACPI_TYPE_BUFFER };
  	struct acpi_object_list no_object = { 1, &arg0 };
  	struct acpi_object_list *pdc;
02df8b938   Venkatesh Pallipadi   [ACPI] enable C2 ...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  
  	ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
  
  	arg0.buffer.length = 12;
  	arg0.buffer.pointer = (u8 *) arg0_buf;
  	arg0_buf[0] = ACPI_PDC_REVISION_ID;
  	arg0_buf[1] = 0;
  	arg0_buf[2] = 0;
  
  	pdc = (pdc_in) ? pdc_in : &no_object;
  
  	status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
  
  	if ((ACPI_FAILURE(status)) && (pdc_in))
4be44fcd3   Len Brown   [ACPI] Lindent al...
278
279
280
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  				  "Error evaluating _PDC, using legacy perf. control...
  "));
02df8b938   Venkatesh Pallipadi   [ACPI] enable C2 ...
281
282
283
  
  	return_VALUE(status);
  }
02df8b938   Venkatesh Pallipadi   [ACPI] enable C2 ...
284
  /* --------------------------------------------------------------------------
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
                                FS Interface (/proc)
     -------------------------------------------------------------------------- */
4be44fcd3   Len Brown   [ACPI] Lindent al...
287
  static struct proc_dir_entry *acpi_processor_dir = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
  
  static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
291
  	struct acpi_processor *pr = (struct acpi_processor *)seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
296
297
298
299
  
  	ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
  
  	if (!pr)
  		goto end;
  
  	seq_printf(seq, "processor id:            %d
  "
4be44fcd3   Len Brown   [ACPI] Lindent al...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  		   "acpi id:                 %d
  "
  		   "bus mastering control:   %s
  "
  		   "power management:        %s
  "
  		   "throttling control:      %s
  "
  		   "limit interface:         %s
  ",
  		   pr->id,
  		   pr->acpi_id,
  		   pr->flags.bm_control ? "yes" : "no",
  		   pr->flags.power ? "yes" : "no",
  		   pr->flags.throttling ? "yes" : "no",
  		   pr->flags.limit ? "yes" : "no");
  
        end:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
322
323
  	return_VALUE(0);
  }
  
  static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
  {
  	return single_open(file, acpi_processor_info_seq_show,
4be44fcd3   Len Brown   [ACPI] Lindent al...
324
  			   PDE(inode)->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
326
  static int acpi_processor_add_fs(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
328
  	struct proc_dir_entry *entry = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
333
  
  	ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
  
  	if (!acpi_device_dir(device)) {
  		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
4be44fcd3   Len Brown   [ACPI] Lindent al...
334
  						     acpi_processor_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
339
340
341
  		if (!acpi_device_dir(device))
  			return_VALUE(-ENODEV);
  	}
  	acpi_device_dir(device)->owner = THIS_MODULE;
  
  	/* 'info' [R] */
  	entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
342
  				  S_IRUGO, acpi_device_dir(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
  	if (!entry)
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
345
346
347
  				  "Unable to create '%s' fs entry
  ",
  				  ACPI_PROCESSOR_FILE_INFO));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
354
355
  	else {
  		entry->proc_fops = &acpi_processor_info_fops;
  		entry->data = acpi_driver_data(device);
  		entry->owner = THIS_MODULE;
  	}
  
  	/* 'throttling' [R/W] */
  	entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
4be44fcd3   Len Brown   [ACPI] Lindent al...
356
357
  				  S_IFREG | S_IRUGO | S_IWUSR,
  				  acpi_device_dir(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  	if (!entry)
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
360
361
362
  				  "Unable to create '%s' fs entry
  ",
  				  ACPI_PROCESSOR_FILE_THROTTLING));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
368
369
370
371
  	else {
  		entry->proc_fops = &acpi_processor_throttling_fops;
  		entry->proc_fops->write = acpi_processor_write_throttling;
  		entry->data = acpi_driver_data(device);
  		entry->owner = THIS_MODULE;
  	}
  
  	/* 'limit' [R/W] */
  	entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
4be44fcd3   Len Brown   [ACPI] Lindent al...
372
373
  				  S_IFREG | S_IRUGO | S_IWUSR,
  				  acpi_device_dir(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
  	if (!entry)
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
376
377
378
  				  "Unable to create '%s' fs entry
  ",
  				  ACPI_PROCESSOR_FILE_LIMIT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
385
386
387
  	else {
  		entry->proc_fops = &acpi_processor_limit_fops;
  		entry->proc_fops->write = acpi_processor_write_limit;
  		entry->data = acpi_driver_data(device);
  		entry->owner = THIS_MODULE;
  	}
  
  	return_VALUE(0);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
388
  static int acpi_processor_remove_fs(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
391
392
  {
  	ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
  
  	if (acpi_device_dir(device)) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
393
394
  		remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
  				  acpi_device_dir(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  		remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
4be44fcd3   Len Brown   [ACPI] Lindent al...
396
397
398
  				  acpi_device_dir(device));
  		remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
  				  acpi_device_dir(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
402
403
404
405
406
407
  		remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
  		acpi_device_dir(device) = NULL;
  	}
  
  	return_VALUE(0);
  }
  
  /* Use the acpiid in MADT to map cpus in case of SMP */
  #ifndef CONFIG_SMP
4a35a46bf   Len Brown   [ACPI] revert bad...
408
  #define convert_acpiid_to_cpu(acpi_id) (0xff)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
412
413
414
415
416
417
418
419
  #else
  
  #ifdef CONFIG_IA64
  #define arch_acpiid_to_apicid 	ia64_acpiid_to_sapicid
  #define arch_cpu_to_apicid 	ia64_cpu_to_sapicid
  #define ARCH_BAD_APICID		(0xffff)
  #else
  #define arch_acpiid_to_apicid 	x86_acpiid_to_apicid
  #define arch_cpu_to_apicid 	x86_cpu_to_apicid
  #define ARCH_BAD_APICID		(0xff)
  #endif
4a35a46bf   Len Brown   [ACPI] revert bad...
420
  static u8 convert_acpiid_to_cpu(u8 acpi_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
  {
  	u16 apic_id;
4a35a46bf   Len Brown   [ACPI] revert bad...
423
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
  
  	apic_id = arch_acpiid_to_apicid[acpi_id];
  	if (apic_id == ARCH_BAD_APICID)
  		return -1;
  
  	for (i = 0; i < NR_CPUS; i++) {
4a35a46bf   Len Brown   [ACPI] revert bad...
430
431
  		if (arch_cpu_to_apicid[i] == apic_id)
  			return i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
436
437
438
439
  	}
  	return -1;
  }
  #endif
  
  /* --------------------------------------------------------------------------
                                   Driver Interface
     -------------------------------------------------------------------------- */
4be44fcd3   Len Brown   [ACPI] Lindent al...
440
  static int acpi_processor_get_info(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
442
443
444
  	acpi_status status = 0;
  	union acpi_object object = { 0 };
  	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
4a35a46bf   Len Brown   [ACPI] revert bad...
445
  	u8 cpu_index;
4be44fcd3   Len Brown   [ACPI] Lindent al...
446
  	static int cpu0_initialized;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  
  	ACPI_FUNCTION_TRACE("acpi_processor_get_info");
  
  	if (!pr)
  		return_VALUE(-EINVAL);
  
  	if (num_online_cpus() > 1)
  		errata.smp = TRUE;
  
  	acpi_processor_errata(pr);
  
  	/*
  	 * Check to see if we have bus mastering arbitration control.  This
  	 * is required for proper C3 usage (to maintain cache coherency).
  	 */
  	if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) {
  		pr->flags.bm_control = 1;
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
465
466
467
  				  "Bus mastering arbitration control present
  "));
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
469
470
  				  "No bus mastering arbitration control
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
473
474
475
476
477
478
479
  
  	/*
  	 * Evalute the processor object.  Note that it is common on SMP to
  	 * have the first (boot) processor with a valid PBLK address while
  	 * all others have a NULL address.
  	 */
  	status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
  	if (ACPI_FAILURE(status)) {
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
480
481
  				  "Error evaluating processor object
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
485
486
  		return_VALUE(-ENODEV);
  	}
  
  	/*
  	 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
4be44fcd3   Len Brown   [ACPI] Lindent al...
487
  	 *      >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
489
  	 */
  	pr->acpi_id = object.processor.proc_id;
4a35a46bf   Len Brown   [ACPI] revert bad...
490
  	cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491

4be44fcd3   Len Brown   [ACPI] Lindent al...
492
  	/* Handle UP system running SMP kernel, with no LAPIC in MADT */
4a35a46bf   Len Brown   [ACPI] revert bad...
493
  	if (!cpu0_initialized && (cpu_index == 0xff) &&
4be44fcd3   Len Brown   [ACPI] Lindent al...
494
495
496
497
498
499
500
501
502
503
504
505
506
  	    (num_online_cpus() == 1)) {
  		cpu_index = 0;
  	}
  
  	cpu0_initialized = 1;
  
  	pr->id = cpu_index;
  
  	/*
  	 *  Extra Processor objects may be enumerated on MP systems with
  	 *  less than the max # of CPUs. They should be ignored _iff
  	 *  they are physically not present.
  	 */
4a35a46bf   Len Brown   [ACPI] revert bad...
507
  	if (cpu_index >= NR_CPUS) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
508
509
  		if (ACPI_FAILURE
  		    (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
4a35a46bf   Len Brown   [ACPI] revert bad...
510
  			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
511
512
513
514
515
516
  					  "Error getting cpuindex for acpiid 0x%x
  ",
  					  pr->acpi_id));
  			return_VALUE(-ENODEV);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
  
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]
  ", pr->id,
4be44fcd3   Len Brown   [ACPI] Lindent al...
520
  			  pr->acpi_id));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
526
527
  
  	if (!object.processor.pblk_address)
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)
  "));
  	else if (object.processor.pblk_length != 6)
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]
  ",
4be44fcd3   Len Brown   [ACPI] Lindent al...
528
  				  object.processor.pblk_length));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  	else {
  		pr->throttling.address = object.processor.pblk_address;
  		pr->throttling.duty_offset = acpi_fadt.duty_offset;
  		pr->throttling.duty_width = acpi_fadt.duty_width;
  
  		pr->pblk = object.processor.pblk_address;
  
  		/*
  		 * We don't care about error returns - we just try to mark
  		 * these reserved so that nobody else is confused into thinking
  		 * that this region might be unused..
  		 *
  		 * (In particular, allocating the IO range for Cardbus)
  		 */
  		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
  	}
  
  #ifdef CONFIG_CPU_FREQ
  	acpi_processor_ppc_has_changed(pr);
  #endif
  	acpi_processor_get_throttling_info(pr);
  	acpi_processor_get_limit_info(pr);
  
  	return_VALUE(0);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
554
  static int acpi_processor_start(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
556
557
558
  	int result = 0;
  	acpi_status status = AE_OK;
  	struct acpi_processor *pr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
  
  	ACPI_FUNCTION_TRACE("acpi_processor_start");
  
  	pr = acpi_driver_data(device);
  
  	result = acpi_processor_get_info(pr);
  	if (result) {
  		/* Processor is physically not present */
  		return_VALUE(0);
  	}
  
  	BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
  
  	processors[pr->id] = pr;
  
  	result = acpi_processor_add_fs(device);
  	if (result)
  		goto end;
  
  	status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
4be44fcd3   Len Brown   [ACPI] Lindent al...
579
  					     acpi_processor_notify, pr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  	if (ACPI_FAILURE(status)) {
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
582
583
  				  "Error installing device notify handler
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
586
587
588
589
  	}
  
  	acpi_processor_power_init(pr, device);
  
  	if (pr->flags.throttling) {
  		printk(KERN_INFO PREFIX "%s [%s] (supports",
4be44fcd3   Len Brown   [ACPI] Lindent al...
590
  		       acpi_device_name(device), acpi_device_bid(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
594
  		printk(" %d throttling states", pr->throttling.state_count);
  		printk(")
  ");
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
595
        end:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
  
  	return_VALUE(result);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
599
  static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
601
602
  	struct acpi_processor *pr = (struct acpi_processor *)data;
  	struct acpi_device *device = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
609
610
611
612
613
614
615
  
  	ACPI_FUNCTION_TRACE("acpi_processor_notify");
  
  	if (!pr)
  		return_VOID;
  
  	if (acpi_bus_get_device(pr->handle, &device))
  		return_VOID;
  
  	switch (event) {
  	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
  		acpi_processor_ppc_has_changed(pr);
  		acpi_bus_generate_event(device, event,
4be44fcd3   Len Brown   [ACPI] Lindent al...
616
  					pr->performance_platform_limit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
621
622
623
  		break;
  	case ACPI_PROCESSOR_NOTIFY_POWER:
  		acpi_processor_cst_has_changed(pr);
  		acpi_bus_generate_event(device, event, 0);
  		break;
  	default:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
624
625
  				  "Unsupported event [0x%x]
  ", event));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
629
630
  		break;
  	}
  
  	return_VOID;
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
631
  static int acpi_processor_add(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
633
  	struct acpi_processor *pr = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  
  	ACPI_FUNCTION_TRACE("acpi_processor_add");
  
  	if (!device)
  		return_VALUE(-EINVAL);
  
  	pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL);
  	if (!pr)
  		return_VALUE(-ENOMEM);
  	memset(pr, 0, sizeof(struct acpi_processor));
  
  	pr->handle = device->handle;
  	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
  	acpi_driver_data(device) = pr;
  
  	return_VALUE(0);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
652
  static int acpi_processor_remove(struct acpi_device *device, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
654
655
  	acpi_status status = AE_OK;
  	struct acpi_processor *pr = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
  
  	ACPI_FUNCTION_TRACE("acpi_processor_remove");
  
  	if (!device || !acpi_driver_data(device))
  		return_VALUE(-EINVAL);
4be44fcd3   Len Brown   [ACPI] Lindent al...
661
  	pr = (struct acpi_processor *)acpi_driver_data(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  
  	if (pr->id >= NR_CPUS) {
  		kfree(pr);
  		return_VALUE(0);
  	}
  
  	if (type == ACPI_BUS_REMOVAL_EJECT) {
  		if (acpi_processor_handle_eject(pr))
  			return_VALUE(-EINVAL);
  	}
  
  	acpi_processor_power_exit(pr, device);
  
  	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
4be44fcd3   Len Brown   [ACPI] Lindent al...
676
  					    acpi_processor_notify);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
  	if (ACPI_FAILURE(status)) {
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
679
680
  				  "Error removing notify handler
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  	}
  
  	acpi_processor_remove_fs(device);
  
  	processors[pr->id] = NULL;
  
  	kfree(pr);
  
  	return_VALUE(0);
  }
  
  #ifdef CONFIG_ACPI_HOTPLUG_CPU
  /****************************************************************************
   * 	Acpi processor hotplug support 				       	    *
   ****************************************************************************/
  
  static int is_processor_present(acpi_handle handle);
4be44fcd3   Len Brown   [ACPI] Lindent al...
698
  static int is_processor_present(acpi_handle handle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
700
701
  	acpi_status status;
  	unsigned long sta = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
704
705
706
707
  
  	ACPI_FUNCTION_TRACE("is_processor_present");
  
  	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
  	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
  		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
708
709
  				  "Processor Device is not present
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
  		return_VALUE(0);
  	}
  	return_VALUE(1);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
  static
4be44fcd3   Len Brown   [ACPI] Lindent al...
715
  int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
717
718
719
  	acpi_handle phandle;
  	struct acpi_device *pdev;
  	struct acpi_processor *pr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  
  	ACPI_FUNCTION_TRACE("acpi_processor_device_add");
  
  	if (acpi_get_parent(handle, &phandle)) {
  		return_VALUE(-ENODEV);
  	}
  
  	if (acpi_bus_get_device(phandle, &pdev)) {
  		return_VALUE(-ENODEV);
  	}
  
  	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
  		return_VALUE(-ENODEV);
  	}
3fb02738b   Rajesh Shah   [PATCH] acpi brid...
734
  	acpi_bus_start(*device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
737
738
  
  	pr = acpi_driver_data(*device);
  	if (!pr)
  		return_VALUE(-ENODEV);
4be44fcd3   Len Brown   [ACPI] Lindent al...
739
  	if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
742
743
  		kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
  	}
  	return_VALUE(0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  static void
4be44fcd3   Len Brown   [ACPI] Lindent al...
745
  acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
747
748
  	struct acpi_processor *pr;
  	struct acpi_device *device = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
751
752
753
754
755
756
757
  	int result;
  
  	ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify");
  
  	switch (event) {
  	case ACPI_NOTIFY_BUS_CHECK:
  	case ACPI_NOTIFY_DEVICE_CHECK:
  		printk("Processor driver received %s event
  ",
4be44fcd3   Len Brown   [ACPI] Lindent al...
758
759
  		       (event == ACPI_NOTIFY_BUS_CHECK) ?
  		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
762
763
764
765
766
767
  
  		if (!is_processor_present(handle))
  			break;
  
  		if (acpi_bus_get_device(handle, &device)) {
  			result = acpi_processor_device_add(handle, &device);
  			if (result)
  				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
768
769
  						  "Unable to add the device
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
773
774
775
  			break;
  		}
  
  		pr = acpi_driver_data(device);
  		if (!pr) {
  			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
776
777
  					  "Driver data is NULL
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
781
782
783
784
785
786
  			break;
  		}
  
  		if (pr->id >= 0 && (pr->id < NR_CPUS)) {
  			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
  			break;
  		}
  
  		result = acpi_processor_start(device);
4be44fcd3   Len Brown   [ACPI] Lindent al...
787
  		if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
  			kobject_hotplug(&device->kobj, KOBJ_ONLINE);
  		} else {
  			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
791
792
793
  					  "Device [%s] failed to start
  ",
  					  acpi_device_bid(device)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
  		}
4be44fcd3   Len Brown   [ACPI] Lindent al...
795
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  	case ACPI_NOTIFY_EJECT_REQUEST:
4be44fcd3   Len Brown   [ACPI] Lindent al...
797
798
799
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  				  "received ACPI_NOTIFY_EJECT_REQUEST
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
  
  		if (acpi_bus_get_device(handle, &device)) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
802
803
804
  			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  					  "Device don't exist, dropping EJECT
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
806
807
808
  			break;
  		}
  		pr = acpi_driver_data(device);
  		if (!pr) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
809
810
811
  			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  					  "Driver data is NULL, dropping EJECT
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
814
815
816
817
818
819
  			return_VOID;
  		}
  
  		if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
  			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
  		break;
  	default:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
820
821
  				  "Unsupported event [0x%x]
  ", event));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
824
825
826
827
828
829
  		break;
  	}
  
  	return_VOID;
  }
  
  static acpi_status
  processor_walk_namespace_cb(acpi_handle handle,
4be44fcd3   Len Brown   [ACPI] Lindent al...
830
  			    u32 lvl, void *context, void **rv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
832
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  	int *action = context;
4be44fcd3   Len Brown   [ACPI] Lindent al...
834
  	acpi_object_type type = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
837
  
  	status = acpi_get_type(handle, &type);
  	if (ACPI_FAILURE(status))
4be44fcd3   Len Brown   [ACPI] Lindent al...
838
  		return (AE_OK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
  
  	if (type != ACPI_TYPE_PROCESSOR)
4be44fcd3   Len Brown   [ACPI] Lindent al...
841
  		return (AE_OK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842

4be44fcd3   Len Brown   [ACPI] Lindent al...
843
  	switch (*action) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
845
  	case INSTALL_NOTIFY_HANDLER:
  		acpi_install_notify_handler(handle,
4be44fcd3   Len Brown   [ACPI] Lindent al...
846
847
848
  					    ACPI_SYSTEM_NOTIFY,
  					    acpi_processor_hotplug_notify,
  					    NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
851
  		break;
  	case UNINSTALL_NOTIFY_HANDLER:
  		acpi_remove_notify_handler(handle,
4be44fcd3   Len Brown   [ACPI] Lindent al...
852
853
  					   ACPI_SYSTEM_NOTIFY,
  					   acpi_processor_hotplug_notify);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
855
856
857
  		break;
  	default:
  		break;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
858
  	return (AE_OK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
860
  static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
  {
  	ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init");
  
  	if (!is_processor_present(handle)) {
  		return_VALUE(AE_ERROR);
  	}
  
  	if (acpi_map_lsapic(handle, p_cpu))
  		return_VALUE(AE_ERROR);
  
  	if (arch_register_cpu(*p_cpu)) {
  		acpi_unmap_lsapic(*p_cpu);
  		return_VALUE(AE_ERROR);
  	}
  
  	return_VALUE(AE_OK);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
878
  static int acpi_processor_handle_eject(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
  {
  	if (cpu_online(pr->id)) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
881
  		return (-EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
  	}
  	arch_unregister_cpu(pr->id);
  	acpi_unmap_lsapic(pr->id);
4be44fcd3   Len Brown   [ACPI] Lindent al...
885
  	return (0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
  }
  #else
4be44fcd3   Len Brown   [ACPI] Lindent al...
888
  static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
  {
  	return AE_ERROR;
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
892
  static int acpi_processor_handle_eject(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
894
  	return (-EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
896
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
  static
  void acpi_processor_install_hotplug_notify(void)
  {
  #ifdef CONFIG_ACPI_HOTPLUG_CPU
  	int action = INSTALL_NOTIFY_HANDLER;
  	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
903
904
905
  			    ACPI_ROOT_OBJECT,
  			    ACPI_UINT32_MAX,
  			    processor_walk_namespace_cb, &action, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
  #endif
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
911
912
913
  static
  void acpi_processor_uninstall_hotplug_notify(void)
  {
  #ifdef CONFIG_ACPI_HOTPLUG_CPU
  	int action = UNINSTALL_NOTIFY_HANDLER;
  	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
4be44fcd3   Len Brown   [ACPI] Lindent al...
914
915
916
  			    ACPI_ROOT_OBJECT,
  			    ACPI_UINT32_MAX,
  			    processor_walk_namespace_cb, &action, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
921
922
923
924
  #endif
  }
  
  /*
   * We keep the driver loaded even when ACPI is not running.
   * This is needed for the powernow-k8 driver, that works even without
   * ACPI, but needs symbols from this driver
   */
4be44fcd3   Len Brown   [ACPI] Lindent al...
925
  static int __init acpi_processor_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
927
  	int result = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
  
  	ACPI_FUNCTION_TRACE("acpi_processor_init");
  
  	memset(&processors, 0, sizeof(processors));
  	memset(&errata, 0, sizeof(errata));
  
  	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
  	if (!acpi_processor_dir)
  		return_VALUE(0);
  	acpi_processor_dir->owner = THIS_MODULE;
  
  	result = acpi_bus_register_driver(&acpi_processor_driver);
  	if (result < 0) {
  		remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
  		return_VALUE(0);
  	}
  
  	acpi_processor_install_hotplug_notify();
  
  	acpi_thermal_cpufreq_init();
  
  	acpi_processor_ppc_init();
  
  	return_VALUE(0);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
953
  static void __exit acpi_processor_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
  {
  	ACPI_FUNCTION_TRACE("acpi_processor_exit");
  
  	acpi_processor_ppc_exit();
  
  	acpi_thermal_cpufreq_exit();
  
  	acpi_processor_uninstall_hotplug_notify();
  
  	acpi_bus_unregister_driver(&acpi_processor_driver);
  
  	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
  
  	return_VOID;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
972
973
974
  module_init(acpi_processor_init);
  module_exit(acpi_processor_exit);
  
  EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
  
  MODULE_ALIAS("processor");