processor_core.c revision fa118564ed66f785f957d8230745b62e9244700d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  			- Added processor hotplug support
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This program is free software; you can redistribute it and/or modify
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  it under the terms of the GNU General Public License as published by
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  the Free Software Foundation; either version 2 of the License, or (at
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  your option) any later version.
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This program is distributed in the hope that it will be useful, but
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  WITHOUT ANY WARRANTY; without even the implied warranty of
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  General Public License for more details.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  You should have received a copy of the GNU General Public License along
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  with this program; if not, write to the Free Software Foundation, Inc.,
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  TBD:
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	1. Make # power states dynamic.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	2. Support duty_cycle values that span bit 4.
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	3. Optimize by having scheduler determine business instead of
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	   having us try to calculate it here.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pm.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpufreq.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpu.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dmi.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h>
474f86d3a8e297205780cca027e974fd5f81064780Len Brown#include <linux/cpuidle.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu.h>
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/delay.h>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/processor.h>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/smp.h>
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/acpi.h>
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h>
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h>
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/processor.h>
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62a192a9580bcc41692be1f36b77c3b681827f566aLen Brown#define PREFIX "ACPI: "
63a192a9580bcc41692be1f36b77c3b681827f566aLen Brown
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_CLASS		"processor"
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_DEVICE_NAME	"Processor"
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_FILE_INFO	"info"
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_FILE_THROTTLING	"throttling"
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_FILE_LIMIT	"limit"
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_NOTIFY_POWER	0x81
7101854e697a77a434104b2f7e6d7fd463a978af32Luming Yu#define ACPI_PROCESSOR_NOTIFY_THROTTLING	0x82
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_LIMIT_USER	0
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_PROCESSOR_LIMIT_THERMAL	1
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
77f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("processor_core");
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
79f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownMODULE_AUTHOR("Paul Diefenbaugh");
807cda93e008e1a477970adbf82dba81a5d4f0ae40Len BrownMODULE_DESCRIPTION("ACPI Processor Driver");
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
834be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_add(struct acpi_device *device);
844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_remove(struct acpi_device *device, int type);
8574cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#ifdef CONFIG_ACPI_PROCFS
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
8774cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#endif
887ec0a7290797f57b780f792d12f4bcc19c83aa4fBjorn Helgaasstatic void acpi_processor_notify(struct acpi_device *device, u32 event);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_processor_handle_eject(struct acpi_processor *pr);
9101854e697a77a434104b2f7e6d7fd463a978af32Luming Yu
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renningerstatic const struct acpi_device_id processor_device_ids[] = {
94ad93a765c1834db031b5bf1c2baf2a50d0462ca4Myron Stowe	{ACPI_PROCESSOR_OBJECT_HID, 0},
959eccbc2f67efd0d19c47f40182abf2965c287addBjorn Helgaas	{"ACPI0007", 0},
961ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger	{"", 0},
971ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger};
981ba90e3a87c46500623afdc3898573e4a5ebb21bThomas RenningerMODULE_DEVICE_TABLE(acpi, processor_device_ids);
991ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_driver acpi_processor_driver = {
101c2b6705b75d9c7aff98a4602a32230639e10891cLen Brown	.name = "processor",
1024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.class = ACPI_PROCESSOR_CLASS,
1031ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger	.ids = processor_device_ids,
1044be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.ops = {
1054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		.add = acpi_processor_add,
1064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		.remove = acpi_processor_remove,
107b04e7bdb984e3b7f62fb7f44146a529f88cc7639Thomas Gleixner		.suspend = acpi_processor_suspend,
108b04e7bdb984e3b7f62fb7f44146a529f88cc7639Thomas Gleixner		.resume = acpi_processor_resume,
1097ec0a7290797f57b780f792d12f4bcc19c83aa4fBjorn Helgaas		.notify = acpi_processor_notify,
1104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		},
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSTALL_NOTIFY_HANDLER		1
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UNINSTALL_NOTIFY_HANDLER	2
11574cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#ifdef CONFIG_ACPI_PROCFS
116d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_processor_info_fops = {
117cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev	.owner = THIS_MODULE,
1184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.open = acpi_processor_info_open_fs,
1194be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.read = seq_read,
1204be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.llseek = seq_lseek,
1214be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.release = single_release,
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
12374cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#endif
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125706546d02384b64e083bd9130c56eaa599c66038Mike TravisDEFINE_PER_CPU(struct acpi_processor *, processors);
1269f22271898707aed2f84cc75ab3bd109173cdbbfAndreas Mohrstruct acpi_processor_errata errata __read_mostly;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* --------------------------------------------------------------------------
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                Errata Handling
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   -------------------------------------------------------------------------- */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1324be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_errata_piix4(struct pci_dev *dev)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1344be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u8 value1 = 0;
1354be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u8 value2 = 0;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev)
139d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EINVAL;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note that 'dev' references the PIIX4 ACPI Controller.
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	switch (dev->revision) {
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 3:
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16344c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	switch (dev->revision) {
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:		/* PIIX4 A-step */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:		/* PIIX4 B-step */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * See specification changes #13 ("Manual Throttle Duty Cycle")
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * and #14 ("Enabling and Disabling Manual Throttle"), plus
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * erratum #5 ("STPCLK# Deassertion Time") from the January
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * 2002 PIIX4 specification update.  Applies to only older
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * PIIX4 models.
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		errata.piix4.throttle = 1;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:		/* PIIX4E */
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 3:		/* PIIX4M */
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Livelock") from the January 2002 PIIX4 specification update.
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Applies to all PIIX4 models.
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * BM-IDE
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ------
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Find the PIIX4 IDE Controller and get the Bus Master IDE
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Status register address.  We'll use this later to read
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * each IDE controller's DMA status to make sure we catch all
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * DMA activity.
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
1934be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				     PCI_DEVICE_ID_INTEL_82371AB,
1944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				     PCI_ANY_ID, PCI_ANY_ID, NULL);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev) {
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			errata.piix4.bmisx = pci_resource_start(dev, 4);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_dev_put(dev);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Type-F DMA
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ----------
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Find the PIIX4 ISA Controller and read the Motherboard
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * DMA controller's status to see if Type-F (Fast) DMA mode
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * is enabled (bit 7) on either channel.  Note that we'll
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * disable C3 support if this is enabled, as some legacy
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * devices won't operate well if fast DMA is disabled.
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
2104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				     PCI_DEVICE_ID_INTEL_82371AB_0,
2114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				     PCI_ANY_ID, PCI_ANY_ID, NULL);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev) {
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_byte(dev, 0x76, &value1);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_byte(dev, 0x77, &value2);
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((value1 & 0x80) || (value2 & 0x80))
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				errata.piix4.fdma = 1;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_dev_put(dev);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (errata.piix4.bmisx)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
2254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Bus master activity detection (BM-IDE) erratum enabled\n"));
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (errata.piix4.fdma)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
2284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Type-F DMA livelock erratum (C3 disabled)\n"));
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
230d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2338713cbefafbb5a101ade541a4b0ffa108bf697ccAdrian Bunkstatic int acpi_processor_errata(struct acpi_processor *pr)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2354be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	int result = 0;
2364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct pci_dev *dev = NULL;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pr)
240d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EINVAL;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * PIIX4
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
2464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			     PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
2474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			     PCI_ANY_ID, NULL);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev) {
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = acpi_processor_errata_piix4(dev);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev_put(dev);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
253d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return result;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* --------------------------------------------------------------------------
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                              FS Interface (/proc)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   -------------------------------------------------------------------------- */
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26074cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#ifdef CONFIG_ACPI_PROCFS
2614be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic struct proc_dir_entry *acpi_processor_dir = NULL;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26550dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt	struct acpi_processor *pr = seq->private;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pr)
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto end;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	seq_printf(seq, "processor id:            %d\n"
2724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   "acpi id:                 %d\n"
2734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   "bus mastering control:   %s\n"
2744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   "power management:        %s\n"
2754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   "throttling control:      %s\n"
2764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   "limit interface:         %s\n",
2774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   pr->id,
2784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   pr->acpi_id,
2794be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   pr->flags.bm_control ? "yes" : "no",
2804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   pr->flags.power ? "yes" : "no",
2814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   pr->flags.throttling ? "yes" : "no",
2824be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		   pr->flags.limit ? "yes" : "no");
2834be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
2844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown      end:
285d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return single_open(file, acpi_processor_info_seq_show,
2914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			   PDE(inode)->data);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
294bf8b4542f92c4d8222941b1cab055fa350ab2fb4Thomas Renningerstatic int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct proc_dir_entry *entry = NULL;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!acpi_device_dir(device)) {
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
3014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						     acpi_processor_dir);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!acpi_device_dir(device))
303d550d98d3317378d93a4869db204725d270ec812Patrick Mochel			return -ENODEV;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 'info' [R] */
307cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev	entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
308cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 S_IRUGO, acpi_device_dir(device),
309cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 &acpi_processor_info_fops,
310cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 acpi_driver_data(device));
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!entry)
312d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EIO;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 'throttling' [R/W] */
315cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev	entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
316cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 S_IFREG | S_IRUGO | S_IWUSR,
317cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 acpi_device_dir(device),
318cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 &acpi_processor_throttling_fops,
319cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 acpi_driver_data(device));
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!entry)
321d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EIO;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 'limit' [R/W] */
324cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev	entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
325cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 S_IFREG | S_IRUGO | S_IWUSR,
326cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 acpi_device_dir(device),
327cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 &acpi_processor_limit_fops,
328cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev				 acpi_driver_data(device));
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!entry)
330d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EIO;
331d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3334be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_remove_fs(struct acpi_device *device)
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_device_dir(device)) {
3374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
3384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  acpi_device_dir(device));
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
3404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  acpi_device_dir(device));
3414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
3424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  acpi_device_dir(device));
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpi_device_dir(device) = NULL;
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
347d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34974cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#else
35074cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakuistatic inline int acpi_processor_add_fs(struct acpi_device *device)
35174cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui{
35274cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui	return 0;
35374cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui}
35474cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakuistatic inline int acpi_processor_remove_fs(struct acpi_device *device)
35574cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui{
35674cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui	return 0;
35774cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui}
35874cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#endif
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use the acpiid in MADT to map cpus in case of SMP */
361f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_SMP
363b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowestatic int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; }
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
366f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiystatic struct acpi_table_madt *madt;
367f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
368f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiystatic int map_lapic_id(struct acpi_subtable_header *entry,
369f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		 u32 acpi_id, int *apic_id)
370f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy{
371f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	struct acpi_madt_local_apic *lapic =
372f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		(struct acpi_madt_local_apic *)entry;
373f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if ((lapic->lapic_flags & ACPI_MADT_ENABLED) &&
374f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	    lapic->processor_id == acpi_id) {
375f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		*apic_id = lapic->id;
376f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		return 1;
377f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	}
378f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	return 0;
379f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy}
380f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
3817237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddhastatic int map_x2apic_id(struct acpi_subtable_header *entry,
3827237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha			 int device_declaration, u32 acpi_id, int *apic_id)
3837237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha{
3847237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	struct acpi_madt_local_x2apic *apic =
3857237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha		(struct acpi_madt_local_x2apic *)entry;
3867237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	u32 tmp = apic->local_apic_id;
3877237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha
3887237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	/* Only check enabled APICs*/
3897237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
3907237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha		return 0;
3917237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha
3927237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	/* Device statement declaration type */
3937237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	if (device_declaration) {
3947237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha		if (apic->uid == acpi_id)
3957237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha			goto found;
3967237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	}
3977237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha
3987237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	return 0;
3997237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddhafound:
4007237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	*apic_id = tmp;
4017237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha	return 1;
4027237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha}
4037237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha
404f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiystatic int map_lsapic_id(struct acpi_subtable_header *entry,
405b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		int device_declaration, u32 acpi_id, int *apic_id)
406f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy{
407f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	struct acpi_madt_local_sapic *lsapic =
408f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		(struct acpi_madt_local_sapic *)entry;
409b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	u32 tmp = (lsapic->id << 8) | lsapic->eid;
410b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe
411f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	/* Only check enabled APICs*/
412b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
413b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		return 0;
414b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe
415b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	/* Device statement declaration type */
416b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	if (device_declaration) {
417b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		if (entry->length < 16)
418b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			printk(KERN_ERR PREFIX
419b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			    "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n",
420b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			    tmp);
421b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		else if (lsapic->uid == acpi_id)
422b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			goto found;
423b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	/* Processor statement declaration type */
424b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	} else if (lsapic->processor_id == acpi_id)
425b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		goto found;
426b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe
427f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	return 0;
428b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowefound:
429b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	*apic_id = tmp;
430b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	return 1;
431f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy}
432f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
433b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowestatic int map_madt_entry(int type, u32 acpi_id)
434f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy{
435f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	unsigned long madt_end, entry;
436f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	int apic_id = -1;
437f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
438f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (!madt)
439f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		return apic_id;
440f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
441f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	entry = (unsigned long)madt;
442f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	madt_end = entry + madt->header.length;
443f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
444f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	/* Parse all entries looking for a match. */
445f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
446f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	entry += sizeof(struct acpi_table_madt);
447f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
448f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		struct acpi_subtable_header *header =
449f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy			(struct acpi_subtable_header *)entry;
450f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
451f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy			if (map_lapic_id(header, acpi_id, &apic_id))
452f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy				break;
4537237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha		} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
4547237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha			if (map_x2apic_id(header, type, acpi_id, &apic_id))
4557237d3de78ff89ec2e18eae5fe962d063024fef5Suresh Siddha				break;
456f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
457b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			if (map_lsapic_id(header, type, acpi_id, &apic_id))
458f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy				break;
459f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		}
460f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		entry += header->length;
461f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	}
462f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	return apic_id;
463f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy}
464f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
465b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowestatic int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
466f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy{
467f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
468f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	union acpi_object *obj;
469f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	struct acpi_subtable_header *header;
470f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	int apic_id = -1;
471f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
472f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
473f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		goto exit;
474f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
475f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (!buffer.length || !buffer.pointer)
476f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		goto exit;
477f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
478f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	obj = buffer.pointer;
479f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (obj->type != ACPI_TYPE_BUFFER ||
480f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
481f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		goto exit;
482f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	}
483f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
484f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	header = (struct acpi_subtable_header *)obj->buffer.pointer;
485f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
486f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		map_lapic_id(header, acpi_id, &apic_id);
487f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
488b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		map_lsapic_id(header, type, acpi_id, &apic_id);
489f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	}
490f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
491f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiyexit:
492f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (buffer.pointer)
493f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		kfree(buffer.pointer);
494f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	return apic_id;
495f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy}
496f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy
497b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowestatic int get_cpu_id(acpi_handle handle, int type, u32 acpi_id)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4994a35a46bf1cda4737c428380d1db5d15e2590d18Len Brown	int i;
500f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	int apic_id = -1;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
502b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	apic_id = map_mat_entry(handle, type, acpi_id);
503f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (apic_id == -1)
504b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		apic_id = map_madt_entry(type, acpi_id);
505f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (apic_id == -1)
506f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy		return apic_id;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
508fbb43ab03c1fa7587476910d346ee11882b4cc62Christoph Lameter	for_each_possible_cpu(i) {
50971b31233a215be27e2efbcc0e739cbebb0bde078Mike Travis		if (cpu_physical_id(i) == apic_id)
5104a35a46bf1cda4737c428380d1db5d15e2590d18Len Brown			return i;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* --------------------------------------------------------------------------
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                 Driver Interface
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   -------------------------------------------------------------------------- */
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
520b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowestatic int acpi_processor_get_info(struct acpi_device *device)
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status = 0;
5234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	union acpi_object object = { 0 };
5244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
525b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	struct acpi_processor *pr;
526b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	int cpu_index, device_declaration = 0;
5274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static int cpu0_initialized;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
529b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	pr = acpi_driver_data(device);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pr)
531d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EINVAL;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (num_online_cpus() > 1)
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		errata.smp = TRUE;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_errata(pr);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Check to see if we have bus mastering arbitration control.  This
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is required for proper C3 usage (to maintain cache coherency).
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
542cee324b145a1e5488b34191de670e5ed1d346ebbAlexey Starikovskiy	if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr->flags.bm_control = 1;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
5454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Bus mastering arbitration control present\n"));
5464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	} else
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
5484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "No bus mastering arbitration control\n"));
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5506cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas	if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
5516cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		/* Declared with "Processor" statement; match ProcessorID */
5526cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
5536cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		if (ACPI_FAILURE(status)) {
5546cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas			printk(KERN_ERR PREFIX "Evaluating processor object\n");
5556cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas			return -ENODEV;
5566cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		}
5576cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas
5586cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		/*
5596cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
5606cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		 *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
5616cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		 *      arch/xxx/acpi.c
5626cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		 */
5636cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas		pr->acpi_id = object.processor.proc_id;
5646cc73b4806c07b4207780f6d85c456b4c5b29d71Bjorn Helgaas	} else {
565b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		/*
566b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		 * Declared with "Device" statement; match _UID.
567b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		 * Note that we don't handle string _UIDs yet.
568b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		 */
56927663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox		unsigned long long value;
57011bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy		status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
57111bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy						NULL, &value);
57211bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy		if (ACPI_FAILURE(status)) {
573b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			printk(KERN_ERR PREFIX
574b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe			    "Evaluating processor _UID [%#x]\n", status);
57511bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy			return -ENODEV;
57611bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy		}
577b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe		device_declaration = 1;
57811bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy		pr->acpi_id = value;
57911bf04c44fd284a5f4e2348a04da6f749cace250Alexey Starikovskiy	}
580b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5824be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	/* Handle UP system running SMP kernel, with no LAPIC in MADT */
583df42baa0d8e54df18dd9366dd7c93d6be7d5d063Ashok Raj	if (!cpu0_initialized && (cpu_index == -1) &&
5844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	    (num_online_cpus() == 1)) {
5854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		cpu_index = 0;
5864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	}
5874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
5884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	cpu0_initialized = 1;
5894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
5904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	pr->id = cpu_index;
5914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
5924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	/*
5934be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	 *  Extra Processor objects may be enumerated on MP systems with
5944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	 *  less than the max # of CPUs. They should be ignored _iff
5954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	 *  they are physically not present.
5964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	 */
597f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (pr->id == -1) {
5984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE
5994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
600d550d98d3317378d93a4869db204725d270ec812Patrick Mochel			return -ENODEV;
6014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		}
6024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	}
6037a04b8491a077471a34938b8ca060c37220953beZhao Yakui	/*
6047a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * On some boxes several processors use the same processor bus id.
6057a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * But they are located in different scope. For example:
6067a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * \_SB.SCK0.CPU0
6077a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * \_SB.SCK1.CPU0
6087a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * Rename the processor device bus id. And the new bus id will be
6097a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * generated as the following format:
6107a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 * CPU+CPU ID.
6117a04b8491a077471a34938b8ca060c37220953beZhao Yakui	 */
6127a04b8491a077471a34938b8ca060c37220953beZhao Yakui	sprintf(acpi_device_bid(device), "CPU%X", pr->id);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
6144be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  pr->acpi_id));
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!object.processor.pblk_address)
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (object.processor.pblk_length != 6)
6196468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown		printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
6206468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown			    object.processor.pblk_length);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr->throttling.address = object.processor.pblk_address;
623cee324b145a1e5488b34191de670e5ed1d346ebbAlexey Starikovskiy		pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
624cee324b145a1e5488b34191de670e5ed1d346ebbAlexey Starikovskiy		pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr->pblk = object.processor.pblk_address;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We don't care about error returns - we just try to mark
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * these reserved so that nobody else is confused into thinking
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * that this region might be unused..
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * (In particular, allocating the IO range for Cardbus)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
638fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	/*
639fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	 * If ACPI describes a slot number for this CPU, we can use it
640fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	 * ensure we get the right value in the "physical id" field
641fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	 * of /proc/cpuinfo
642fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	 */
643fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
644fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang	if (ACPI_SUCCESS(status))
645fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang		arch_fix_phys_package_id(pr->id, object.integer.value);
646fe086a7bea7ab714930bd48addba961ceeef7634Alex Chiang
647d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
650706546d02384b64e083bd9130c56eaa599c66038Mike Travisstatic DEFINE_PER_CPU(void *, processor_device_array);
651cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi
6527ec0a7290797f57b780f792d12f4bcc19c83aa4fBjorn Helgaasstatic void acpi_processor_notify(struct acpi_device *device, u32 event)
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6547ec0a7290797f57b780f792d12f4bcc19c83aa4fBjorn Helgaas	struct acpi_processor *pr = acpi_driver_data(device);
655e790cc8bbb990df900eabdda18a5a480d22a60c8Alexey Starikovskiy	int saved;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pr)
658d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
662e790cc8bbb990df900eabdda18a5a480d22a60c8Alexey Starikovskiy		saved = pr->performance_platform_limit;
663d81c45e1c9369855901420f79114852eba2ea16aZhao Yakui		acpi_processor_ppc_has_changed(pr, 1);
664e790cc8bbb990df900eabdda18a5a480d22a60c8Alexey Starikovskiy		if (saved == pr->performance_platform_limit)
665e790cc8bbb990df900eabdda18a5a480d22a60c8Alexey Starikovskiy			break;
66614e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown		acpi_bus_generate_proc_event(device, event,
6674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					pr->performance_platform_limit);
668962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui		acpi_bus_generate_netlink_event(device->pnp.device_class,
6690794469da3f7b2093575cbdfc1108308dd3641ceKay Sievers						  dev_name(&device->dev), event,
670962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui						  pr->performance_platform_limit);
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_PROCESSOR_NOTIFY_POWER:
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpi_processor_cst_has_changed(pr);
67414e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown		acpi_bus_generate_proc_event(device, event, 0);
675962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui		acpi_bus_generate_netlink_event(device->pnp.device_class,
6760794469da3f7b2093575cbdfc1108308dd3641ceKay Sievers						  dev_name(&device->dev), event, 0);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
67801854e697a77a434104b2f7e6d7fd463a978af32Luming Yu	case ACPI_PROCESSOR_NOTIFY_THROTTLING:
67901854e697a77a434104b2f7e6d7fd463a978af32Luming Yu		acpi_processor_tstate_has_changed(pr);
68014e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown		acpi_bus_generate_proc_event(device, event, 0);
681962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui		acpi_bus_generate_netlink_event(device->pnp.device_class,
6820794469da3f7b2093575cbdfc1108308dd3641ceKay Sievers						  dev_name(&device->dev), event, 0);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
6854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Unsupported event [0x%x]\n", event));
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
689d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
692729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadistatic int acpi_cpu_soft_notify(struct notifier_block *nfb,
693729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi		unsigned long action, void *hcpu)
694729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi{
695729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	unsigned int cpu = (unsigned long)hcpu;
696706546d02384b64e083bd9130c56eaa599c66038Mike Travis	struct acpi_processor *pr = per_cpu(processors, cpu);
697729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi
698729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	if (action == CPU_ONLINE && pr) {
699d81c45e1c9369855901420f79114852eba2ea16aZhao Yakui		acpi_processor_ppc_has_changed(pr, 0);
700729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi		acpi_processor_cst_has_changed(pr);
701729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi		acpi_processor_tstate_has_changed(pr);
702729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	}
703729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	return NOTIFY_OK;
704729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi}
705729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi
706729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadistatic struct notifier_block acpi_cpu_notifier =
707729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi{
708729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	    .notifier_call = acpi_cpu_soft_notify,
709729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi};
710729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi
711941b10fab2cbd90ac7ad6bc2338ffe30e1d3ce53Rakib Mullickstatic int __cpuinit acpi_processor_add(struct acpi_device *device)
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_processor *pr = NULL;
714970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaas	int result = 0;
715970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaas	struct sys_device *sysdev;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71736bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pr)
719d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -ENOMEM;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721eaa958402ea40851097d051f52ba1bb7a885efe9Yinghai Lu	if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
7222fdf66b491ac706657946442789ec644cc317e1aRusty Russell		kfree(pr);
7232fdf66b491ac706657946442789ec644cc317e1aRusty Russell		return -ENOMEM;
7242fdf66b491ac706657946442789ec644cc317e1aRusty Russell	}
7252fdf66b491ac706657946442789ec644cc317e1aRusty Russell
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pr->handle = device->handle;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
729db89b4f0dbab837d0f3de2c3e9427a8d5393afa3Pavel Machek	device->driver_data = pr;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731b26e9286fb438eb78bcdb68b67a3dbb8bc539125Myron Stowe	result = acpi_processor_get_info(device);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result) {
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Processor is physically not present */
734d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return 0;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
737fbb43ab03c1fa7587476910d346ee11882b4cc62Christoph Lameter	BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
739cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi	/*
740cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi	 * Buggy BIOS check
741cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi	 * ACPI id of processors can be reported wrongly by the BIOS.
742cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi	 * Don't trust it blindly
743cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi	 */
744706546d02384b64e083bd9130c56eaa599c66038Mike Travis	if (per_cpu(processor_device_array, pr->id) != NULL &&
745706546d02384b64e083bd9130c56eaa599c66038Mike Travis	    per_cpu(processor_device_array, pr->id) != device) {
7464fdb2a05ef5703553fdd28f1b96ebdd79f173657Joe Perches		printk(KERN_WARNING "BIOS reported wrong ACPI id "
7470eacee585a89ce5827b572a73a024931506bef48Len Brown			"for the processor\n");
748970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaas		result = -ENODEV;
749970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaas		goto err_free_cpumask;
750cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi	}
751706546d02384b64e083bd9130c56eaa599c66038Mike Travis	per_cpu(processor_device_array, pr->id) = device;
752cd8e2b48daee891011a4f21e2c62b210d24dcc9eVenkatesh Pallipadi
753706546d02384b64e083bd9130c56eaa599c66038Mike Travis	per_cpu(processors, pr->id) = pr;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = acpi_processor_add_fs(device);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result)
757970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaas		goto err_free_cpumask;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7599f1eb99c757939b0b1783f926130993e9c298baeZhang Rui	sysdev = get_cpu_sysdev(pr->id);
760d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
761d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas		result = -EFAULT;
762d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas		goto err_remove_fs;
763d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	}
7649f1eb99c757939b0b1783f926130993e9c298baeZhang Rui
76505131ecc99ea9da7f45ba3058fe8a2c1d0ceeab8Venkatesh Pallipadi	/* _PDC call should be done before doing anything else (if reqd.). */
76605131ecc99ea9da7f45ba3058fe8a2c1d0ceeab8Venkatesh Pallipadi	acpi_processor_set_pdc(pr);
7677b768f07dce463a054c9dd84862d15ccc3d2b712Pallipadi, Venkatesh
7680ac3c571315a53c14d2733564f14ebdb911fe903Zhao Yakui#ifdef CONFIG_CPU_FREQ
769d81c45e1c9369855901420f79114852eba2ea16aZhao Yakui	acpi_processor_ppc_has_changed(pr, 0);
7700ac3c571315a53c14d2733564f14ebdb911fe903Zhao Yakui#endif
7710ac3c571315a53c14d2733564f14ebdb911fe903Zhao Yakui	acpi_processor_get_throttling_info(pr);
7720ac3c571315a53c14d2733564f14ebdb911fe903Zhao Yakui	acpi_processor_get_limit_info(pr);
7730ac3c571315a53c14d2733564f14ebdb911fe903Zhao Yakui
77405131ecc99ea9da7f45ba3058fe8a2c1d0ceeab8Venkatesh Pallipadi
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_power_init(pr, device);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
777d9460fd227ed2ce52941b6a12ad4de05c195f6aaZhang Rui	pr->cdev = thermal_cooling_device_register("Processor", device,
778d9460fd227ed2ce52941b6a12ad4de05c195f6aaZhang Rui						&processor_cooling_ops);
779d76628c67cdeebf84766a19c67c821c2e518baa4Thomas Sujith	if (IS_ERR(pr->cdev)) {
780d76628c67cdeebf84766a19c67c821c2e518baa4Thomas Sujith		result = PTR_ERR(pr->cdev);
781d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas		goto err_power_exit;
782d76628c67cdeebf84766a19c67c821c2e518baa4Thomas Sujith	}
7839030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall
78413c41157096f05d5037a99152b4cf9d68ef00ef7Mike Travis	dev_dbg(&device->dev, "registered as cooling_device%d\n",
785fc3a8828b139c24aade3f9d608775e36c248f8f5Greg Kroah-Hartman		 pr->cdev->id);
7869030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall
7879030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall	result = sysfs_create_link(&device->dev.kobj,
7889030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall				   &pr->cdev->device.kobj,
7899030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall				   "thermal_cooling");
790d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	if (result) {
7919030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall		printk(KERN_ERR PREFIX "Create sysfs link\n");
792d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas		goto err_thermal_unregister;
793d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	}
7949030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall	result = sysfs_create_link(&pr->cdev->device.kobj,
7959030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall				   &device->dev.kobj,
7969030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall				   "device");
797d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	if (result) {
7989030062f3d61f87c1e787b3aa134fa3a8e4b2d25Julia Lawall		printk(KERN_ERR PREFIX "Create sysfs link\n");
799d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas		goto err_remove_sysfs;
800d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	}
801d9460fd227ed2ce52941b6a12ad4de05c195f6aaZhang Rui
802d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
803d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas
804d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaaserr_remove_sysfs:
805d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
806d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaaserr_thermal_unregister:
807d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	thermal_cooling_device_unregister(pr->cdev);
808d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaaserr_power_exit:
809d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	acpi_processor_power_exit(pr, device);
810d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaaserr_remove_fs:
811d4e0526184199e23ac1460fe59b8a3741b17a8b5Bjorn Helgaas	acpi_processor_remove_fs(device);
812970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaaserr_free_cpumask:
813970b04929a68134acca17878b1d93e115e58c12aBjorn Helgaas	free_cpumask_var(pr->throttling.shared_cpu_map);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
815d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return result;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_remove(struct acpi_device *device, int type)
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8204be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_processor *pr = NULL;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!device || !acpi_driver_data(device))
824d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EINVAL;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82650dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt	pr = acpi_driver_data(device);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8282fdf66b491ac706657946442789ec644cc317e1aRusty Russell	if (pr->id >= nr_cpu_ids)
8292fdf66b491ac706657946442789ec644cc317e1aRusty Russell		goto free;
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type == ACPI_BUS_REMOVAL_EJECT) {
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (acpi_processor_handle_eject(pr))
833d550d98d3317378d93a4869db204725d270ec812Patrick Mochel			return -EINVAL;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_power_exit(pr, device);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8389f1eb99c757939b0b1783f926130993e9c298baeZhang Rui	sysfs_remove_link(&device->dev.kobj, "sysdev");
8399f1eb99c757939b0b1783f926130993e9c298baeZhang Rui
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_remove_fs(device);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
842f28bb45e2863173a7464d98907677e903f42c68bZhao Yakui	if (pr->cdev) {
843f28bb45e2863173a7464d98907677e903f42c68bZhao Yakui		sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
844f28bb45e2863173a7464d98907677e903f42c68bZhao Yakui		sysfs_remove_link(&pr->cdev->device.kobj, "device");
845f28bb45e2863173a7464d98907677e903f42c68bZhao Yakui		thermal_cooling_device_unregister(pr->cdev);
846f28bb45e2863173a7464d98907677e903f42c68bZhao Yakui		pr->cdev = NULL;
847f28bb45e2863173a7464d98907677e903f42c68bZhao Yakui	}
848d9460fd227ed2ce52941b6a12ad4de05c195f6aaZhang Rui
849706546d02384b64e083bd9130c56eaa599c66038Mike Travis	per_cpu(processors, pr->id) = NULL;
850706546d02384b64e083bd9130c56eaa599c66038Mike Travis	per_cpu(processor_device_array, pr->id) = NULL;
8512fdf66b491ac706657946442789ec644cc317e1aRusty Russell
8522fdf66b491ac706657946442789ec644cc317e1aRusty Russellfree:
8532fdf66b491ac706657946442789ec644cc317e1aRusty Russell	free_cpumask_var(pr->throttling.shared_cpu_map);
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(pr);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
856d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ACPI_HOTPLUG_CPU
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Acpi processor hotplug support 				       	    *
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ****************************************************************************/
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int is_processor_present(acpi_handle handle)
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status;
86727663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long sta = 0;
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
871cfaf3747ff3d431fba33f75083b7f50f58ae22ffZhang Rui
872cfaf3747ff3d431fba33f75083b7f50f58ae22ffZhang Rui	if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
873cfaf3747ff3d431fba33f75083b7f50f58ae22ffZhang Rui		return 1;
874cfaf3747ff3d431fba33f75083b7f50f58ae22ffZhang Rui
875d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui	/*
876d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui	 * _STA is mandatory for a processor that supports hot plug
877d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui	 */
878d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui	if (status == AE_NOT_FOUND)
879d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
880d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui				"Processor does not support hot plug\n"));
881d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui	else
882d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui		ACPI_EXCEPTION((AE_INFO, status,
883d0ce46f550ebbd765881e8c48f43b66285d798b0Zhang Rui				"Processor Device is not present"));
884cfaf3747ff3d431fba33f75083b7f50f58ae22ffZhang Rui	return 0;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic
8884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_handle phandle;
8914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_device *pdev;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_get_parent(handle, &phandle)) {
895d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -ENODEV;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_bus_get_device(phandle, &pdev)) {
899d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -ENODEV;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
903d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -ENODEV;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
906d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
909b95e9e8d94484c2823be67416f25e9756db149dcSam Ravnborgstatic void __ref acpi_processor_hotplug_notify(acpi_handle handle,
910b95e9e8d94484c2823be67416f25e9756db149dcSam Ravnborg						u32 event, void *data)
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_processor *pr;
9134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_device *device = NULL;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_BUS_CHECK:
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_DEVICE_CHECK:
920d6f882e10442c1ea6ed5f93365f48be4cb520be7Glauber Costa		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
921d6f882e10442c1ea6ed5f93365f48be4cb520be7Glauber Costa		"Processor driver received %s event\n",
9224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		       (event == ACPI_NOTIFY_BUS_CHECK) ?
923d6f882e10442c1ea6ed5f93365f48be4cb520be7Glauber Costa		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!is_processor_present(handle))
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (acpi_bus_get_device(handle, &device)) {
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = acpi_processor_device_add(handle, &device);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (result)
9316468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown				printk(KERN_ERR PREFIX
9326468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown					    "Unable to add the device\n");
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9354be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		break;
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_EJECT_REQUEST:
9374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
9384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "received ACPI_NOTIFY_EJECT_REQUEST\n"));
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (acpi_bus_get_device(handle, &device)) {
9416468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown			printk(KERN_ERR PREFIX
9426468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown				    "Device don't exist, dropping EJECT\n");
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr = acpi_driver_data(device);
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!pr) {
9476468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown			printk(KERN_ERR PREFIX
9486468463abd7051fcc29f3ee7c931f9bbbb26f5a4Len Brown				    "Driver data is NULL, dropping EJECT\n");
949d550d98d3317378d93a4869db204725d270ec812Patrick Mochel			return;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
9544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Unsupported event [0x%x]\n", event));
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
958d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic acpi_status
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsprocessor_walk_namespace_cb(acpi_handle handle,
9634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    u32 lvl, void *context, void **rv)
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int *action = context;
9674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_object_type type = 0;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = acpi_get_type(handle, &type);
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_FAILURE(status))
9714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return (AE_OK);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type != ACPI_TYPE_PROCESSOR)
9744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return (AE_OK);
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	switch (*action) {
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case INSTALL_NOTIFY_HANDLER:
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpi_install_notify_handler(handle,
9794be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					    ACPI_SYSTEM_NOTIFY,
9804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					    acpi_processor_hotplug_notify,
9814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					    NULL);
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case UNINSTALL_NOTIFY_HANDLER:
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpi_remove_notify_handler(handle,
9854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					   ACPI_SYSTEM_NOTIFY,
9864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					   acpi_processor_hotplug_notify);
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return (AE_OK);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!is_processor_present(handle)) {
999d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return AE_ERROR;
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_map_lsapic(handle, p_cpu))
1003d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return AE_ERROR;
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (arch_register_cpu(*p_cpu)) {
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpi_unmap_lsapic(*p_cpu);
1007d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return AE_ERROR;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1010d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return AE_OK;
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_handle_eject(struct acpi_processor *pr)
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1015b62b8ef906cdf7115af579ce7378886ce3e0ce00Zhang Rui	if (cpu_online(pr->id))
1016b62b8ef906cdf7115af579ce7378886ce3e0ce00Zhang Rui		cpu_down(pr->id);
1017b62b8ef906cdf7115af579ce7378886ce3e0ce00Zhang Rui
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	arch_unregister_cpu(pr->id);
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_unmap_lsapic(pr->id);
10204be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return (0);
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
10234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return AE_ERROR;
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_processor_handle_eject(struct acpi_processor *pr)
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return (-EINVAL);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid acpi_processor_install_hotplug_notify(void)
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ACPI_HOTPLUG_CPU
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int action = INSTALL_NOTIFY_HANDLER;
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
10394be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    ACPI_ROOT_OBJECT,
10404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    ACPI_UINT32_MAX,
10412263576cfc6e8f6ab038126c3254404b9fcb1c33Lin Ming			    processor_walk_namespace_cb, NULL, &action, NULL);
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1043729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	register_hotcpu_notifier(&acpi_cpu_notifier);
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid acpi_processor_uninstall_hotplug_notify(void)
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ACPI_HOTPLUG_CPU
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int action = UNINSTALL_NOTIFY_HANDLER;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
10524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    ACPI_ROOT_OBJECT,
10534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    ACPI_UINT32_MAX,
10542263576cfc6e8f6ab038126c3254404b9fcb1c33Lin Ming			    processor_walk_namespace_cb, NULL, &action, NULL);
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1056729c6ba334771f28a54efd7e3b8f5ab9414ce7bcVenkatesh Pallipadi	unregister_hotcpu_notifier(&acpi_cpu_notifier);
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We keep the driver loaded even when ACPI is not running.
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is needed for the powernow-k8 driver, that works even without
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACPI, but needs symbols from this driver
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int __init acpi_processor_init(void)
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	int result = 0;
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1069ce8442b55135c679809311997d1446f3bbc05de2Yinghai Lu	if (acpi_disabled)
1070ce8442b55135c679809311997d1446f3bbc05de2Yinghai Lu		return 0;
1071ce8442b55135c679809311997d1446f3bbc05de2Yinghai Lu
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&errata, 0, sizeof(errata));
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1074f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy#ifdef CONFIG_SMP
1075f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy	if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
1076f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy				(struct acpi_table_header **)&madt)))
107770c0846e430881967776582e13aefb81407919f1Randy Dunlap		madt = NULL;
1078f18c5a08bf035b51939281f5b49aa3ae45cea6ceAlexey Starikovskiy#endif
107974cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#ifdef CONFIG_ACPI_PROCFS
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!acpi_processor_dir)
108283822fc9e6ad2e0f3799174f7c6ad3aa285b9488Akinobu Mita		return -ENOMEM;
108374cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#endif
10844f86d3a8e297205780cca027e974fd5f81064780Len Brown	result = cpuidle_register_driver(&acpi_idle_driver);
10854f86d3a8e297205780cca027e974fd5f81064780Len Brown	if (result < 0)
10864f86d3a8e297205780cca027e974fd5f81064780Len Brown		goto out_proc;
10874f86d3a8e297205780cca027e974fd5f81064780Len Brown
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	result = acpi_bus_register_driver(&acpi_processor_driver);
10894f86d3a8e297205780cca027e974fd5f81064780Len Brown	if (result < 0)
10904f86d3a8e297205780cca027e974fd5f81064780Len Brown		goto out_cpuidle;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_install_hotplug_notify();
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_thermal_cpufreq_init();
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_ppc_init();
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981180509f6b3ec3ac2505375a78ccd72d270f2169Zhao Yakui	acpi_processor_throttling_init();
10991180509f6b3ec3ac2505375a78ccd72d270f2169Zhao Yakui
1100d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return 0;
11014f86d3a8e297205780cca027e974fd5f81064780Len Brown
11024f86d3a8e297205780cca027e974fd5f81064780Len Brownout_cpuidle:
11034f86d3a8e297205780cca027e974fd5f81064780Len Brown	cpuidle_unregister_driver(&acpi_idle_driver);
11044f86d3a8e297205780cca027e974fd5f81064780Len Brown
11054f86d3a8e297205780cca027e974fd5f81064780Len Brownout_proc:
110674cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#ifdef CONFIG_ACPI_PROCFS
11074f86d3a8e297205780cca027e974fd5f81064780Len Brown	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
110874cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#endif
11094f86d3a8e297205780cca027e974fd5f81064780Len Brown
11104f86d3a8e297205780cca027e974fd5f81064780Len Brown	return result;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void __exit acpi_processor_exit(void)
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1115ce8442b55135c679809311997d1446f3bbc05de2Yinghai Lu	if (acpi_disabled)
1116ce8442b55135c679809311997d1446f3bbc05de2Yinghai Lu		return;
1117ce8442b55135c679809311997d1446f3bbc05de2Yinghai Lu
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_ppc_exit();
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_thermal_cpufreq_exit();
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_processor_uninstall_hotplug_notify();
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_bus_unregister_driver(&acpi_processor_driver);
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11264f86d3a8e297205780cca027e974fd5f81064780Len Brown	cpuidle_unregister_driver(&acpi_idle_driver);
11274f86d3a8e297205780cca027e974fd5f81064780Len Brown
112874cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#ifdef CONFIG_ACPI_PROCFS
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
113074cad4ee9839669ad920257678ea0bf0a818cd3bZhao Yakui#endif
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1132d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return;
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(acpi_processor_init);
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(acpi_processor_exit);
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(acpi_processor_set_thermal_limit);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_ALIAS("processor");
1141