Finalize the splitting of processor.c by moving the rest to processor_core.c

Signed-off-by: Dominik Brodowski <linux@brodo.de>

 drivers/acpi/Makefile         |    8
 drivers/acpi/processor.c      | 1046 ------------------------------------------
 drivers/acpi/processor_core.c | 1046 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1050 insertions(+), 1050 deletions(-)

diff -ruN linux-original/drivers/acpi/Makefile linux/drivers/acpi/Makefile
--- linux-original/drivers/acpi/Makefile	2004-11-27 16:19:40.426694400 +0100
+++ linux/drivers/acpi/Makefile	2004-11-27 16:23:14.855096328 +0100
@@ -31,10 +31,10 @@
 #
 # ACPI Bus and Device Drivers
 #
-processor_tmp-objs	+= processor.o processor_throttling.o processor_idle.o\
-				processor_thermal.o
+processor-objs	+= processor_core.o processor_throttling.o \
+				processor_idle.o processor_thermal.o
 ifdef CONFIG_CPU_FREQ
-processor_tmp-objs	+= processor_perflib.o			
+processor-objs	+= processor_perflib.o			
 endif
 
 obj-$(CONFIG_ACPI_BUS)		+= sleep/
@@ -47,7 +47,7 @@
 obj-$(CONFIG_ACPI_VIDEO)	+= video.o
 obj-$(CONFIG_ACPI_PCI)		+= pci_root.o pci_link.o pci_irq.o pci_bind.o
 obj-$(CONFIG_ACPI_POWER)	+= power.o
-obj-$(CONFIG_ACPI_PROCESSOR)	+= processor_tmp.o
+obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
 obj-$(CONFIG_ACPI_CONTAINER)	+= container.o
 obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
 obj-$(CONFIG_ACPI_SYSTEM)	+= system.o event.o
diff -ruN linux-original/drivers/acpi/processor.c linux/drivers/acpi/processor.c
--- linux-original/drivers/acpi/processor.c	2004-11-27 16:19:40.430693792 +0100
+++ linux/drivers/acpi/processor.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1046 +0,0 @@
-/*
- * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
- *
- *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
- *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
- *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *  			- Added processor hotplug support
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *  TBD:
- *	1. Make # power states dynamic.
- *	2. Support duty_cycle values that span bit 4.
- *	3. Optimize by having scheduler determine business instead of
- *	   having us try to calculate it here.
- *	4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/dmi.h>
-#include <linux/moduleparam.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/cpu.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
-#include <asm/processor.h>
-#include <asm/smp.h>
-#include <asm/acpi.h>
-
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
-
-#define ACPI_PROCESSOR_COMPONENT	0x01000000
-#define ACPI_PROCESSOR_CLASS		"processor"
-#define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
-#define ACPI_PROCESSOR_DEVICE_NAME	"Processor"
-#define ACPI_PROCESSOR_FILE_INFO	"info"
-#define ACPI_PROCESSOR_FILE_POWER	"power"
-#define ACPI_PROCESSOR_FILE_THROTTLING	"throttling"
-#define ACPI_PROCESSOR_FILE_LIMIT	"limit"
-#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
-#define ACPI_PROCESSOR_NOTIFY_POWER	0x81
-
-#define ACPI_PROCESSOR_LIMIT_USER	0
-#define ACPI_PROCESSOR_LIMIT_THERMAL	1
-
-#define ACPI_STA_PRESENT 0x00000001
-
-#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME		("acpi_processor")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
-
-static int acpi_processor_add (struct acpi_device *device);
-static int acpi_processor_start (struct acpi_device *device);
-static int acpi_processor_remove (struct acpi_device *device, int type);
-static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
-static void acpi_processor_notify ( acpi_handle	handle, u32 event, void *data);
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
-static int acpi_processor_handle_eject(struct acpi_processor *pr);
-
-static struct acpi_driver acpi_processor_driver = {
-	.name =		ACPI_PROCESSOR_DRIVER_NAME,
-	.class =	ACPI_PROCESSOR_CLASS,
-	.ids =		ACPI_PROCESSOR_HID,
-	.ops =		{
-				.add =		acpi_processor_add,
-				.remove =	acpi_processor_remove,
-				.start	= 	acpi_processor_start,
-			},
-};
-
-#define INSTALL_NOTIFY_HANDLER		1
-#define UNINSTALL_NOTIFY_HANDLER	2
-
-
-struct file_operations acpi_processor_info_fops = {
-	.open 		= acpi_processor_info_open_fs,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-
-struct acpi_processor	*processors[NR_CPUS];
-struct acpi_processor_errata errata;
-void (*pm_idle_save)(void);
-
-
-/* --------------------------------------------------------------------------
-                                Errata Handling
-   -------------------------------------------------------------------------- */
-
-int
-acpi_processor_errata_piix4 (
-	struct pci_dev		*dev)
-{
-	u8			rev = 0;
-	u8			value1 = 0;
-	u8			value2 = 0;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
-
-	if (!dev)
-		return_VALUE(-EINVAL);
-
-	/*
-	 * Note that 'dev' references the PIIX4 ACPI Controller.
-	 */
-
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-	switch (rev) {
-	case 0:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
-		break;
-	case 1:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
-		break;
-	case 2:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
-		break;
-	case 3:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
-		break;
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
-		break;
-	}
-
-	switch (rev) {
-
-	case 0:		/* PIIX4 A-step */
-	case 1:		/* PIIX4 B-step */
-		/*
-		 * See specification changes #13 ("Manual Throttle Duty Cycle")
-		 * and #14 ("Enabling and Disabling Manual Throttle"), plus
-		 * erratum #5 ("STPCLK# Deassertion Time") from the January 
-		 * 2002 PIIX4 specification update.  Applies to only older 
-		 * PIIX4 models.
-		 */
-		errata.piix4.throttle = 1;
-
-	case 2:		/* PIIX4E */
-	case 3:		/* PIIX4M */
-		/*
-		 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA 
-		 * Livelock") from the January 2002 PIIX4 specification update.
-		 * Applies to all PIIX4 models.
-		 */
-
-		/* 
-		 * BM-IDE
-		 * ------
-		 * Find the PIIX4 IDE Controller and get the Bus Master IDE 
-		 * Status register address.  We'll use this later to read 
-		 * each IDE controller's DMA status to make sure we catch all
-		 * DMA activity.
-		 */
-		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
-		           PCI_DEVICE_ID_INTEL_82371AB, 
-                           PCI_ANY_ID, PCI_ANY_ID, NULL);
-		if (dev) {
-			errata.piix4.bmisx = pci_resource_start(dev, 4);
-			pci_dev_put(dev);
-		}
-
-		/* 
-		 * Type-F DMA
-		 * ----------
-		 * Find the PIIX4 ISA Controller and read the Motherboard
-		 * DMA controller's status to see if Type-F (Fast) DMA mode
-		 * is enabled (bit 7) on either channel.  Note that we'll 
-		 * disable C3 support if this is enabled, as some legacy 
-		 * devices won't operate well if fast DMA is disabled.
-		 */
-		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, 
-			PCI_DEVICE_ID_INTEL_82371AB_0, 
-			PCI_ANY_ID, PCI_ANY_ID, NULL);
-		if (dev) {
-			pci_read_config_byte(dev, 0x76, &value1);
-			pci_read_config_byte(dev, 0x77, &value2);
-			if ((value1 & 0x80) || (value2 & 0x80))
-				errata.piix4.fdma = 1;
-			pci_dev_put(dev);
-		}
-
-		break;
-	}
-
-	if (errata.piix4.bmisx)
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
-			"Bus master activity detection (BM-IDE) erratum enabled\n"));
-	if (errata.piix4.fdma)
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
-			"Type-F DMA livelock erratum (C3 disabled)\n"));
-
-	return_VALUE(0);
-}
-
-
-int
-acpi_processor_errata (
-	struct acpi_processor	*pr)
-{
-	int			result = 0;
-	struct pci_dev		*dev = NULL;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_errata");
-
-	if (!pr)
-		return_VALUE(-EINVAL);
-
-	/*
-	 * PIIX4
-	 */
-	dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, 
-		PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
-	if (dev) {
-		result = acpi_processor_errata_piix4(dev);
-		pci_dev_put(dev);
-	}
-
-	return_VALUE(result);
-}
-
-
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-
-struct proc_dir_entry		*acpi_processor_dir = NULL;
-
-static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
-
-	if (!pr)
-		goto end;
-
-	seq_printf(seq, "processor id:            %d\n"
-			"acpi id:                 %d\n"
-			"bus mastering control:   %s\n"
-			"power management:        %s\n"
-			"throttling control:      %s\n"
-			"limit interface:         %s\n",
-			pr->id,
-			pr->acpi_id,
-			pr->flags.bm_control ? "yes" : "no",
-			pr->flags.power ? "yes" : "no",
-			pr->flags.throttling ? "yes" : "no",
-			pr->flags.limit ? "yes" : "no");
-
-end:
-	return_VALUE(0);
-}
-
-static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_processor_info_seq_show,
-						PDE(inode)->data);
-}
-
-
-static int
-acpi_processor_add_fs (
-	struct acpi_device	*device)
-{
-	struct proc_dir_entry	*entry = NULL;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
-
-	if (!acpi_device_dir(device)) {
-		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-			acpi_processor_dir);
-		if (!acpi_device_dir(device))
-			return_VALUE(-ENODEV);
-	}
-	acpi_device_dir(device)->owner = THIS_MODULE;
-
-	/* 'info' [R] */
-	entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
-		S_IRUGO, acpi_device_dir(device));
-	if (!entry)
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Unable to create '%s' fs entry\n",
-			ACPI_PROCESSOR_FILE_INFO));
-	else {
-		entry->proc_fops = &acpi_processor_info_fops;
-		entry->data = acpi_driver_data(device);
-		entry->owner = THIS_MODULE;
-	}
-
-	/* 'power' [R] */
-	entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
-		S_IRUGO, acpi_device_dir(device));
-	if (!entry)
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Unable to create '%s' fs entry\n",
-			ACPI_PROCESSOR_FILE_POWER));
-	else {
-		entry->proc_fops = &acpi_processor_power_fops;
-		entry->data = acpi_driver_data(device);
-		entry->owner = THIS_MODULE;
-	}
-
-	/* 'throttling' [R/W] */
-	entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
-		S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
-	if (!entry)
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Unable to create '%s' fs entry\n",
-			ACPI_PROCESSOR_FILE_THROTTLING));
-	else {
-		entry->proc_fops = &acpi_processor_throttling_fops;
-		entry->proc_fops->write = acpi_processor_write_throttling;
-		entry->data = acpi_driver_data(device);
-		entry->owner = THIS_MODULE;
-	}
-
-	/* 'limit' [R/W] */
-	entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
-		S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
-	if (!entry)
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Unable to create '%s' fs entry\n",
-			ACPI_PROCESSOR_FILE_LIMIT));
-	else {
-		entry->proc_fops = &acpi_processor_limit_fops;
-		entry->proc_fops->write = acpi_processor_write_limit;
-		entry->data = acpi_driver_data(device);
-		entry->owner = THIS_MODULE;
-	}
-
-	return_VALUE(0);
-}
-
-
-static int
-acpi_processor_remove_fs (
-	struct acpi_device	*device)
-{
-	ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
-
-	if (acpi_device_dir(device)) {
-		remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,acpi_device_dir(device));
-		remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device));
-		remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
-			acpi_device_dir(device));
-		remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,acpi_device_dir(device));
-		remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
-		acpi_device_dir(device) = NULL;
-	}
-
-	return_VALUE(0);
-}
-
-/* Use the acpiid in MADT to map cpus in case of SMP */
-#ifndef CONFIG_SMP
-#define convert_acpiid_to_cpu(acpi_id) (0xff)
-#else
-
-#ifdef CONFIG_IA64
-#define arch_acpiid_to_apicid 	ia64_acpiid_to_sapicid
-#define arch_cpu_to_apicid 	ia64_cpu_to_sapicid
-#define ARCH_BAD_APICID		(0xffff)
-#else
-#define arch_acpiid_to_apicid 	x86_acpiid_to_apicid
-#define arch_cpu_to_apicid 	x86_cpu_to_apicid
-#define ARCH_BAD_APICID		(0xff)
-#endif
-
-static u8 convert_acpiid_to_cpu(u8 acpi_id)
-{
-	u16 apic_id;
-	int i;
-	
-	apic_id = arch_acpiid_to_apicid[acpi_id];
-	if (apic_id == ARCH_BAD_APICID)
-		return -1;
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (arch_cpu_to_apicid[i] == apic_id)
-			return i;
-	}
-	return -1;
-}
-#endif
-
-/* --------------------------------------------------------------------------
-                                 Driver Interface
-   -------------------------------------------------------------------------- */
-
-static int
-acpi_processor_get_info (
-	struct acpi_processor	*pr)
-{
-	acpi_status		status = 0;
-	union acpi_object	object = {0};
-	struct acpi_buffer	buffer = {sizeof(union acpi_object), &object};
-	u8			cpu_index;
-	static int		cpu0_initialized;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_get_info");
-
-	if (!pr)
-		return_VALUE(-EINVAL);
-
-	if (num_online_cpus() > 1)
-		errata.smp = TRUE;
-
-	acpi_processor_errata(pr);
-
-	/*
-	 * Check to see if we have bus mastering arbitration control.  This
-	 * is required for proper C3 usage (to maintain cache coherency).
-	 */
-	if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) {
-		pr->flags.bm_control = 1;
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			"Bus mastering arbitration control present\n"));
-	}
-	else
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			"No bus mastering arbitration control\n"));
-
-	/*
-	 * Evalute the processor object.  Note that it is common on SMP to
-	 * have the first (boot) processor with a valid PBLK address while
-	 * all others have a NULL address.
-	 */
-	status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Error evaluating processor object\n"));
-		return_VALUE(-ENODEV);
-	}
-
-	/*
-	 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
-	 *	>>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
-	 */
-	pr->acpi_id = object.processor.proc_id;
-
-	cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
-
-  	/* Handle UP system running SMP kernel, with no LAPIC in MADT */
-  	if ( !cpu0_initialized && (cpu_index == 0xff) &&
-  		       	(num_online_cpus() == 1)) {
-   		cpu_index = 0;
-   	}
-
-   	cpu0_initialized = 1;
-
-   	pr->id = cpu_index;
-
-  	/*
-  	 *  Extra Processor objects may be enumerated on MP systems with
-  	 *  less than the max # of CPUs. They should be ignored _iff
-  	 *  they are physically not present.
-  	 */
-   	if (cpu_index >=  NR_CPUS) {
-   		if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
-   			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-   				"Error getting cpuindex for acpiid 0x%x\n",
-   				pr->acpi_id));
-   			return_VALUE(-ENODEV);
-   		}
-    	}
- 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, 
-		pr->acpi_id));
-
-	if (!object.processor.pblk_address)
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
-	else if (object.processor.pblk_length != 6)
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n",
-			object.processor.pblk_length));
-	else {
-		pr->throttling.address = object.processor.pblk_address;
-		pr->throttling.duty_offset = acpi_fadt.duty_offset;
-		pr->throttling.duty_width = acpi_fadt.duty_width;
-		pr->power.states[ACPI_STATE_C2].address =
-			object.processor.pblk_address + 4;
-		pr->power.states[ACPI_STATE_C3].address =
-			object.processor.pblk_address + 5;
-
-		/*
-		 * We don't care about error returns - we just try to mark
-		 * these reserved so that nobody else is confused into thinking
-		 * that this region might be unused..
-		 *
-		 * (In particular, allocating the IO range for Cardbus)
-		 */
-		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
-	}
-
-	acpi_processor_get_power_info(pr);
-#ifdef CONFIG_CPU_FREQ
-	acpi_processor_ppc_has_changed(pr);
-#endif
-	acpi_processor_get_throttling_info(pr);
-	acpi_processor_get_limit_info(pr);
-
-	return_VALUE(0);
-}
-
-static int
-acpi_processor_start(
-	struct acpi_device	*device)
-{
-	int			result = 0;
-	acpi_status		status = AE_OK;
-	u32			i = 0;
-	struct acpi_processor	*pr;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_start");
-
-	pr = acpi_driver_data(device);
-
-	result = acpi_processor_get_info(pr);
-	if (result) {
-		/* Processor is physically not present */
-		return_VALUE(0);
-	}
-
-	BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
-
-	processors[pr->id] = pr;
-
-	result = acpi_processor_add_fs(device);
-	if (result)
-		goto end;
-
-	status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
-		acpi_processor_notify, pr);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Error installing device notify handler\n"));
-	}
-
-	/*
-	 * Install the idle handler if processor power management is supported.
-	 * Note that we use previously set idle handler will be used on 
-	 * platforms that only support C1.
-	 */
-	if ((pr->flags.power) && (!boot_option_idle_override)) {
-		printk(KERN_INFO PREFIX "%s [%s] (supports",
-			acpi_device_name(device), acpi_device_bid(device));
-		for (i = 1; i < ACPI_C_STATE_COUNT; i++)
-			if (pr->power.states[i].valid)
-				printk(" C%d", i);
-		printk(")\n");
-		if (pr->id == 0) {
-			pm_idle_save = pm_idle;
-			pm_idle = acpi_processor_idle;
-		}
-	}
-	
-	if (pr->flags.throttling) {
-		printk(KERN_INFO PREFIX "%s [%s] (supports",
-			acpi_device_name(device), acpi_device_bid(device));
-		printk(" %d throttling states", pr->throttling.state_count);
-		printk(")\n");
-	}
-
-end:
-
-	return_VALUE(result);
-}
-
-
-
-static void
-acpi_processor_notify (
-	acpi_handle		handle,
-	u32			event,
-	void			*data)
-{
-	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	struct acpi_device	*device = NULL;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_notify");
-
-	if (!pr)
-		return_VOID;
-
-	if (acpi_bus_get_device(pr->handle, &device))
-		return_VOID;
-
-	switch (event) {
-	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
-		acpi_processor_ppc_has_changed(pr);
-		acpi_bus_generate_event(device, event, 
-			pr->performance_platform_limit);
-		break;
-	case ACPI_PROCESSOR_NOTIFY_POWER:
-		/* TBD */
-		acpi_bus_generate_event(device, event, 0);
-		break;
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			"Unsupported event [0x%x]\n", event));
-		break;
-	}
-
-	return_VOID;
-}
-
-
-static int
-acpi_processor_add (
-	struct acpi_device	*device)
-{
-	struct acpi_processor	*pr = NULL;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_add");
-
-	if (!device)
-		return_VALUE(-EINVAL);
-
-	pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL);
-	if (!pr)
-		return_VALUE(-ENOMEM);
-	memset(pr, 0, sizeof(struct acpi_processor));
-
-	pr->handle = device->handle;
-	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
-	acpi_driver_data(device) = pr;
-
-	return_VALUE(0);
-}
-
-
-static int
-acpi_processor_remove (
-	struct acpi_device	*device,
-	int			type)
-{
-	acpi_status		status = AE_OK;
-	struct acpi_processor	*pr = NULL;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_remove");
-
-	if (!device || !acpi_driver_data(device))
-		return_VALUE(-EINVAL);
-
-	pr = (struct acpi_processor *) acpi_driver_data(device);
-
-	if (pr->id >= NR_CPUS) {
-		kfree(pr);
-		return_VALUE(0);
-	}
-
-	if (type == ACPI_BUS_REMOVAL_EJECT) {
-		if (acpi_processor_handle_eject(pr))
-			return_VALUE(-EINVAL);
-	}
-
-	/* Unregister the idle handler when processor #0 is removed. */
-	if (pr->id == 0) {
-		pm_idle = pm_idle_save;
-		/*
-		 * We are about to unload the current idle thread pm callback
-		 * (pm_idle), Wait for all processors to update cached/local
-		 * copies of pm_idle before proceeding.
-		 */
-		synchronize_kernel();
-	}
-
-	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, 
-		acpi_processor_notify);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
-			"Error removing notify handler\n"));
-	}
-
-	acpi_processor_remove_fs(device);
-
-	processors[pr->id] = NULL;
-
-	kfree(pr);
-
-	return_VALUE(0);
-}
-
-static struct dmi_system_id __initdata processor_dmi_table[] = {
-	{ no_c2c3, "IBM ThinkPad R40e", {
-	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
-	  DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }},
-	{ no_c2c3, "Medion 41700", {
-	  DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
-	  DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }},
-	{},
-};
-
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-/****************************************************************************
- * 	Acpi processor hotplug support 				       	    *
- ****************************************************************************/
-
-static int is_processor_present(acpi_handle handle);
-
-static int
-is_processor_present(
-	acpi_handle handle)
-{
-	acpi_status 		status;
-	unsigned long		sta = 0;
-
-	ACPI_FUNCTION_TRACE("is_processor_present");
-
-	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			"Processor Device is not present\n"));
-		return_VALUE(0);
-	}
-	return_VALUE(1);
-}
-
-
-static
-int acpi_processor_device_add(
-	acpi_handle	handle,
-	struct acpi_device **device)
-{
-	acpi_handle		phandle;
-	struct acpi_device 	*pdev;
-	struct acpi_processor	*pr;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_device_add");
-
-	if (acpi_get_parent(handle, &phandle)) {
-		return_VALUE(-ENODEV);
-	}
-
-	if (acpi_bus_get_device(phandle, &pdev)) {
-		return_VALUE(-ENODEV);
-	}
-
-	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
-		return_VALUE(-ENODEV);
-	}
-
-	acpi_bus_scan(*device);
-
-	pr = acpi_driver_data(*device);
-	if (!pr)
-		return_VALUE(-ENODEV);
-
-	if ((pr->id >=0) && (pr->id < NR_CPUS)) {
-		kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
-	}
-	return_VALUE(0);
-}
-
-
-static void
-acpi_processor_hotplug_notify (
-	acpi_handle		handle,
-	u32			event,
-	void			*data)
-{
-	struct acpi_processor	*pr;
-	struct acpi_device	*device = NULL;
-	int result;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify");
-
-	switch (event) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		printk("Processor driver received %s event\n",
-			(event==ACPI_NOTIFY_BUS_CHECK)?
-			"ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
-
-		if (!is_processor_present(handle))
-			break;
-
-		if (acpi_bus_get_device(handle, &device)) {
-			result = acpi_processor_device_add(handle, &device);
-			if (result)
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					"Unable to add the device\n"));
-			break;
-		}
-
-		pr = acpi_driver_data(device);
-		if (!pr) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				"Driver data is NULL\n"));
-			break;
-		}
-		
-		if (pr->id >= 0 && (pr->id < NR_CPUS)) {
-			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
-			break;
-		}
-
-		result = acpi_processor_start(device);
-		if ((!result) && ((pr->id >=0) && (pr->id < NR_CPUS))) {
-			kobject_hotplug(&device->kobj, KOBJ_ONLINE);
-		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				"Device [%s] failed to start\n",
-				acpi_device_bid(device)));
-		}
-	break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,"received ACPI_NOTIFY_EJECT_REQUEST\n"));
-
-		if (acpi_bus_get_device(handle, &device)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Device don't exist, dropping EJECT\n"));
-			break;
-		}
-		pr = acpi_driver_data(device);
-		if (!pr) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Driver data is NULL, dropping EJECT\n"));
-			return_VOID;
-		}
-
-		if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
-			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
-		break;
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			"Unsupported event [0x%x]\n", event));
-		break;
-	}
-
-	return_VOID;
-}
-
-static acpi_status
-processor_walk_namespace_cb(acpi_handle handle,
-	u32 lvl,
-	void *context,
-	void **rv)
-{
-	acpi_status 			status;
-	int *action = context;
-	acpi_object_type	type = 0;
-
-	status = acpi_get_type(handle, &type);
-	if (ACPI_FAILURE(status))
-		return(AE_OK);
-
-	if (type != ACPI_TYPE_PROCESSOR)
-		return(AE_OK);
-
-	switch(*action) {
-	case INSTALL_NOTIFY_HANDLER:
-		acpi_install_notify_handler(handle,
-			ACPI_SYSTEM_NOTIFY,
-			acpi_processor_hotplug_notify,
-			NULL);
-		break;
-	case UNINSTALL_NOTIFY_HANDLER:
-		acpi_remove_notify_handler(handle,
-			ACPI_SYSTEM_NOTIFY,
-			acpi_processor_hotplug_notify);
-		break;
-	default:
-		break;
-	}
-
-	return(AE_OK);
-}
-
-
-static acpi_status
-acpi_processor_hotadd_init(
-	acpi_handle		handle,
-	int			*p_cpu)
-{
-	ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init");
-	
-	if (!is_processor_present(handle)) {
-		return_VALUE(AE_ERROR);
-	}
-
-	if (acpi_map_lsapic(handle, p_cpu))
-		return_VALUE(AE_ERROR);
-
-	if (arch_register_cpu(*p_cpu)) {
-		acpi_unmap_lsapic(*p_cpu);
-		return_VALUE(AE_ERROR);
-	}
-
-	return_VALUE(AE_OK);
-}
-
-
-static int
-acpi_processor_handle_eject(struct acpi_processor *pr)
-{
-	if (cpu_online(pr->id)) {
-		return(-EINVAL);
-	}
-	arch_unregister_cpu(pr->id);
-	acpi_unmap_lsapic(pr->id);
-	return(0);
-}
-#else
-static acpi_status
-acpi_processor_hotadd_init(
-	acpi_handle		handle,
-	int			*p_cpu)
-{
-	return AE_ERROR;
-}
-static int
-acpi_processor_handle_eject(struct acpi_processor *pr)
-{
-	return(-EINVAL);
-}
-#endif
-
-
-static
-void acpi_processor_install_hotplug_notify(void)
-{
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-	int action = INSTALL_NOTIFY_HANDLER;
-	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
-				     ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX,
-				     processor_walk_namespace_cb,
-				     &action, NULL);
-#endif
-}
-
-
-static
-void acpi_processor_uninstall_hotplug_notify(void)
-{
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-	int action = UNINSTALL_NOTIFY_HANDLER;
-	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
-				     ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX,
-				     processor_walk_namespace_cb,
-				     &action, NULL);
-#endif
-}
-
-/*
- * We keep the driver loaded even when ACPI is not running. 
- * This is needed for the powernow-k8 driver, that works even without
- * ACPI, but needs symbols from this driver
- */
-
-static int __init
-acpi_processor_init (void)
-{
-	int			result = 0;
-
-	ACPI_FUNCTION_TRACE("acpi_processor_init");
-
-	memset(&processors, 0, sizeof(processors));
-	memset(&errata, 0, sizeof(errata));
-
-	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-	if (!acpi_processor_dir)
-		return_VALUE(0);
-	acpi_processor_dir->owner = THIS_MODULE;
-
-	result = acpi_bus_register_driver(&acpi_processor_driver);
-	if (result < 0) {
-		remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-		return_VALUE(0);
-	}
-
-	acpi_processor_install_hotplug_notify();
-
-	acpi_thermal_cpufreq_init();
-
-	acpi_processor_ppc_init();
-
-	dmi_check_system(processor_dmi_table); 
-
-	return_VALUE(0);
-}
-
-
-static void __exit
-acpi_processor_exit (void)
-{
-	ACPI_FUNCTION_TRACE("acpi_processor_exit");
-
-	acpi_processor_ppc_exit();
-
-	acpi_thermal_cpufreq_exit();
-
-	acpi_processor_uninstall_hotplug_notify();
-
-	acpi_bus_unregister_driver(&acpi_processor_driver);
-
-	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-
-	return_VOID;
-}
-
-
-module_init(acpi_processor_init);
-module_exit(acpi_processor_exit);
-
-EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
-
-MODULE_ALIAS("processor");
diff -ruN linux-original/drivers/acpi/processor_core.c linux/drivers/acpi/processor_core.c
--- linux-original/drivers/acpi/processor_core.c	1970-01-01 01:00:00.000000000 +0100
+++ linux/drivers/acpi/processor_core.c	2004-11-27 16:22:24.375770352 +0100
@@ -0,0 +1,1046 @@
+/*
+ * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
+ *
+ *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
+ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
+ *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *  			- Added processor hotplug support
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *  TBD:
+ *	1. Make # power states dynamic.
+ *	2. Support duty_cycle values that span bit 4.
+ *	3. Optimize by having scheduler determine business instead of
+ *	   having us try to calculate it here.
+ *	4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/cpufreq.h>
+#include <linux/cpu.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/dmi.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/cpu.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/smp.h>
+#include <asm/acpi.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/processor.h>
+
+
+#define ACPI_PROCESSOR_COMPONENT	0x01000000
+#define ACPI_PROCESSOR_CLASS		"processor"
+#define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
+#define ACPI_PROCESSOR_DEVICE_NAME	"Processor"
+#define ACPI_PROCESSOR_FILE_INFO	"info"
+#define ACPI_PROCESSOR_FILE_POWER	"power"
+#define ACPI_PROCESSOR_FILE_THROTTLING	"throttling"
+#define ACPI_PROCESSOR_FILE_LIMIT	"limit"
+#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
+#define ACPI_PROCESSOR_NOTIFY_POWER	0x81
+
+#define ACPI_PROCESSOR_LIMIT_USER	0
+#define ACPI_PROCESSOR_LIMIT_THERMAL	1
+
+#define ACPI_STA_PRESENT 0x00000001
+
+#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME		("acpi_processor")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+
+static int acpi_processor_add (struct acpi_device *device);
+static int acpi_processor_start (struct acpi_device *device);
+static int acpi_processor_remove (struct acpi_device *device, int type);
+static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
+static void acpi_processor_notify ( acpi_handle	handle, u32 event, void *data);
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
+static int acpi_processor_handle_eject(struct acpi_processor *pr);
+
+static struct acpi_driver acpi_processor_driver = {
+	.name =		ACPI_PROCESSOR_DRIVER_NAME,
+	.class =	ACPI_PROCESSOR_CLASS,
+	.ids =		ACPI_PROCESSOR_HID,
+	.ops =		{
+				.add =		acpi_processor_add,
+				.remove =	acpi_processor_remove,
+				.start	= 	acpi_processor_start,
+			},
+};
+
+#define INSTALL_NOTIFY_HANDLER		1
+#define UNINSTALL_NOTIFY_HANDLER	2
+
+
+struct file_operations acpi_processor_info_fops = {
+	.open 		= acpi_processor_info_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+
+struct acpi_processor	*processors[NR_CPUS];
+struct acpi_processor_errata errata;
+void (*pm_idle_save)(void);
+
+
+/* --------------------------------------------------------------------------
+                                Errata Handling
+   -------------------------------------------------------------------------- */
+
+int
+acpi_processor_errata_piix4 (
+	struct pci_dev		*dev)
+{
+	u8			rev = 0;
+	u8			value1 = 0;
+	u8			value2 = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
+
+	if (!dev)
+		return_VALUE(-EINVAL);
+
+	/*
+	 * Note that 'dev' references the PIIX4 ACPI Controller.
+	 */
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+	switch (rev) {
+	case 0:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
+		break;
+	case 1:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
+		break;
+	case 2:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
+		break;
+	case 3:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
+		break;
+	}
+
+	switch (rev) {
+
+	case 0:		/* PIIX4 A-step */
+	case 1:		/* PIIX4 B-step */
+		/*
+		 * See specification changes #13 ("Manual Throttle Duty Cycle")
+		 * and #14 ("Enabling and Disabling Manual Throttle"), plus
+		 * erratum #5 ("STPCLK# Deassertion Time") from the January
+		 * 2002 PIIX4 specification update.  Applies to only older
+		 * PIIX4 models.
+		 */
+		errata.piix4.throttle = 1;
+
+	case 2:		/* PIIX4E */
+	case 3:		/* PIIX4M */
+		/*
+		 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
+		 * Livelock") from the January 2002 PIIX4 specification update.
+		 * Applies to all PIIX4 models.
+		 */
+
+		/*
+		 * BM-IDE
+		 * ------
+		 * Find the PIIX4 IDE Controller and get the Bus Master IDE
+		 * Status register address.  We'll use this later to read
+		 * each IDE controller's DMA status to make sure we catch all
+		 * DMA activity.
+		 */
+		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+		           PCI_DEVICE_ID_INTEL_82371AB,
+                           PCI_ANY_ID, PCI_ANY_ID, NULL);
+		if (dev) {
+			errata.piix4.bmisx = pci_resource_start(dev, 4);
+			pci_dev_put(dev);
+		}
+
+		/*
+		 * Type-F DMA
+		 * ----------
+		 * Find the PIIX4 ISA Controller and read the Motherboard
+		 * DMA controller's status to see if Type-F (Fast) DMA mode
+		 * is enabled (bit 7) on either channel.  Note that we'll
+		 * disable C3 support if this is enabled, as some legacy
+		 * devices won't operate well if fast DMA is disabled.
+		 */
+		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+			PCI_DEVICE_ID_INTEL_82371AB_0,
+			PCI_ANY_ID, PCI_ANY_ID, NULL);
+		if (dev) {
+			pci_read_config_byte(dev, 0x76, &value1);
+			pci_read_config_byte(dev, 0x77, &value2);
+			if ((value1 & 0x80) || (value2 & 0x80))
+				errata.piix4.fdma = 1;
+			pci_dev_put(dev);
+		}
+
+		break;
+	}
+
+	if (errata.piix4.bmisx)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Bus master activity detection (BM-IDE) erratum enabled\n"));
+	if (errata.piix4.fdma)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Type-F DMA livelock erratum (C3 disabled)\n"));
+
+	return_VALUE(0);
+}
+
+
+int
+acpi_processor_errata (
+	struct acpi_processor	*pr)
+{
+	int			result = 0;
+	struct pci_dev		*dev = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_errata");
+
+	if (!pr)
+		return_VALUE(-EINVAL);
+
+	/*
+	 * PIIX4
+	 */
+	dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+		PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
+	if (dev) {
+		result = acpi_processor_errata_piix4(dev);
+		pci_dev_put(dev);
+	}
+
+	return_VALUE(result);
+}
+
+
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+
+struct proc_dir_entry		*acpi_processor_dir = NULL;
+
+static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
+{
+	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
+
+	if (!pr)
+		goto end;
+
+	seq_printf(seq, "processor id:            %d\n"
+			"acpi id:                 %d\n"
+			"bus mastering control:   %s\n"
+			"power management:        %s\n"
+			"throttling control:      %s\n"
+			"limit interface:         %s\n",
+			pr->id,
+			pr->acpi_id,
+			pr->flags.bm_control ? "yes" : "no",
+			pr->flags.power ? "yes" : "no",
+			pr->flags.throttling ? "yes" : "no",
+			pr->flags.limit ? "yes" : "no");
+
+end:
+	return_VALUE(0);
+}
+
+static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_processor_info_seq_show,
+						PDE(inode)->data);
+}
+
+
+static int
+acpi_processor_add_fs (
+	struct acpi_device	*device)
+{
+	struct proc_dir_entry	*entry = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
+
+	if (!acpi_device_dir(device)) {
+		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+			acpi_processor_dir);
+		if (!acpi_device_dir(device))
+			return_VALUE(-ENODEV);
+	}
+	acpi_device_dir(device)->owner = THIS_MODULE;
+
+	/* 'info' [R] */
+	entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
+		S_IRUGO, acpi_device_dir(device));
+	if (!entry)
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unable to create '%s' fs entry\n",
+			ACPI_PROCESSOR_FILE_INFO));
+	else {
+		entry->proc_fops = &acpi_processor_info_fops;
+		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
+	}
+
+	/* 'power' [R] */
+	entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
+		S_IRUGO, acpi_device_dir(device));
+	if (!entry)
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unable to create '%s' fs entry\n",
+			ACPI_PROCESSOR_FILE_POWER));
+	else {
+		entry->proc_fops = &acpi_processor_power_fops;
+		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
+	}
+
+	/* 'throttling' [R/W] */
+	entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
+		S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+	if (!entry)
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unable to create '%s' fs entry\n",
+			ACPI_PROCESSOR_FILE_THROTTLING));
+	else {
+		entry->proc_fops = &acpi_processor_throttling_fops;
+		entry->proc_fops->write = acpi_processor_write_throttling;
+		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
+	}
+
+	/* 'limit' [R/W] */
+	entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
+		S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+	if (!entry)
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unable to create '%s' fs entry\n",
+			ACPI_PROCESSOR_FILE_LIMIT));
+	else {
+		entry->proc_fops = &acpi_processor_limit_fops;
+		entry->proc_fops->write = acpi_processor_write_limit;
+		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
+	}
+
+	return_VALUE(0);
+}
+
+
+static int
+acpi_processor_remove_fs (
+	struct acpi_device	*device)
+{
+	ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
+
+	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,acpi_device_dir(device));
+		remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device));
+		remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
+			acpi_device_dir(device));
+		remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,acpi_device_dir(device));
+		remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
+		acpi_device_dir(device) = NULL;
+	}
+
+	return_VALUE(0);
+}
+
+/* Use the acpiid in MADT to map cpus in case of SMP */
+#ifndef CONFIG_SMP
+#define convert_acpiid_to_cpu(acpi_id) (0xff)
+#else
+
+#ifdef CONFIG_IA64
+#define arch_acpiid_to_apicid 	ia64_acpiid_to_sapicid
+#define arch_cpu_to_apicid 	ia64_cpu_to_sapicid
+#define ARCH_BAD_APICID		(0xffff)
+#else
+#define arch_acpiid_to_apicid 	x86_acpiid_to_apicid
+#define arch_cpu_to_apicid 	x86_cpu_to_apicid
+#define ARCH_BAD_APICID		(0xff)
+#endif
+
+static u8 convert_acpiid_to_cpu(u8 acpi_id)
+{
+	u16 apic_id;
+	int i;
+
+	apic_id = arch_acpiid_to_apicid[acpi_id];
+	if (apic_id == ARCH_BAD_APICID)
+		return -1;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (arch_cpu_to_apicid[i] == apic_id)
+			return i;
+	}
+	return -1;
+}
+#endif
+
+/* --------------------------------------------------------------------------
+                                 Driver Interface
+   -------------------------------------------------------------------------- */
+
+static int
+acpi_processor_get_info (
+	struct acpi_processor	*pr)
+{
+	acpi_status		status = 0;
+	union acpi_object	object = {0};
+	struct acpi_buffer	buffer = {sizeof(union acpi_object), &object};
+	u8			cpu_index;
+	static int		cpu0_initialized;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_get_info");
+
+	if (!pr)
+		return_VALUE(-EINVAL);
+
+	if (num_online_cpus() > 1)
+		errata.smp = TRUE;
+
+	acpi_processor_errata(pr);
+
+	/*
+	 * Check to see if we have bus mastering arbitration control.  This
+	 * is required for proper C3 usage (to maintain cache coherency).
+	 */
+	if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) {
+		pr->flags.bm_control = 1;
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Bus mastering arbitration control present\n"));
+	}
+	else
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"No bus mastering arbitration control\n"));
+
+	/*
+	 * Evalute the processor object.  Note that it is common on SMP to
+	 * have the first (boot) processor with a valid PBLK address while
+	 * all others have a NULL address.
+	 */
+	status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Error evaluating processor object\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	/*
+	 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+	 *	>>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
+	 */
+	pr->acpi_id = object.processor.proc_id;
+
+	cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
+
+  	/* Handle UP system running SMP kernel, with no LAPIC in MADT */
+  	if ( !cpu0_initialized && (cpu_index == 0xff) &&
+  		       	(num_online_cpus() == 1)) {
+   		cpu_index = 0;
+   	}
+
+   	cpu0_initialized = 1;
+
+   	pr->id = cpu_index;
+
+  	/*
+  	 *  Extra Processor objects may be enumerated on MP systems with
+  	 *  less than the max # of CPUs. They should be ignored _iff
+  	 *  they are physically not present.
+  	 */
+   	if (cpu_index >=  NR_CPUS) {
+   		if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+   			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+   				"Error getting cpuindex for acpiid 0x%x\n",
+   				pr->acpi_id));
+   			return_VALUE(-ENODEV);
+   		}
+    	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+		pr->acpi_id));
+
+	if (!object.processor.pblk_address)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
+	else if (object.processor.pblk_length != 6)
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n",
+			object.processor.pblk_length));
+	else {
+		pr->throttling.address = object.processor.pblk_address;
+		pr->throttling.duty_offset = acpi_fadt.duty_offset;
+		pr->throttling.duty_width = acpi_fadt.duty_width;
+		pr->power.states[ACPI_STATE_C2].address =
+			object.processor.pblk_address + 4;
+		pr->power.states[ACPI_STATE_C3].address =
+			object.processor.pblk_address + 5;
+
+		/*
+		 * We don't care about error returns - we just try to mark
+		 * these reserved so that nobody else is confused into thinking
+		 * that this region might be unused..
+		 *
+		 * (In particular, allocating the IO range for Cardbus)
+		 */
+		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+	}
+
+	acpi_processor_get_power_info(pr);
+#ifdef CONFIG_CPU_FREQ
+	acpi_processor_ppc_has_changed(pr);
+#endif
+	acpi_processor_get_throttling_info(pr);
+	acpi_processor_get_limit_info(pr);
+
+	return_VALUE(0);
+}
+
+static int
+acpi_processor_start(
+	struct acpi_device	*device)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	u32			i = 0;
+	struct acpi_processor	*pr;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_start");
+
+	pr = acpi_driver_data(device);
+
+	result = acpi_processor_get_info(pr);
+	if (result) {
+		/* Processor is physically not present */
+		return_VALUE(0);
+	}
+
+	BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
+
+	processors[pr->id] = pr;
+
+	result = acpi_processor_add_fs(device);
+	if (result)
+		goto end;
+
+	status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
+		acpi_processor_notify, pr);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Error installing device notify handler\n"));
+	}
+
+	/*
+	 * Install the idle handler if processor power management is supported.
+	 * Note that we use previously set idle handler will be used on
+	 * platforms that only support C1.
+	 */
+	if ((pr->flags.power) && (!boot_option_idle_override)) {
+		printk(KERN_INFO PREFIX "%s [%s] (supports",
+			acpi_device_name(device), acpi_device_bid(device));
+		for (i = 1; i < ACPI_C_STATE_COUNT; i++)
+			if (pr->power.states[i].valid)
+				printk(" C%d", i);
+		printk(")\n");
+		if (pr->id == 0) {
+			pm_idle_save = pm_idle;
+			pm_idle = acpi_processor_idle;
+		}
+	}
+
+	if (pr->flags.throttling) {
+		printk(KERN_INFO PREFIX "%s [%s] (supports",
+			acpi_device_name(device), acpi_device_bid(device));
+		printk(" %d throttling states", pr->throttling.state_count);
+		printk(")\n");
+	}
+
+end:
+
+	return_VALUE(result);
+}
+
+
+
+static void
+acpi_processor_notify (
+	acpi_handle		handle,
+	u32			event,
+	void			*data)
+{
+	struct acpi_processor	*pr = (struct acpi_processor *) data;
+	struct acpi_device	*device = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_notify");
+
+	if (!pr)
+		return_VOID;
+
+	if (acpi_bus_get_device(pr->handle, &device))
+		return_VOID;
+
+	switch (event) {
+	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
+		acpi_processor_ppc_has_changed(pr);
+		acpi_bus_generate_event(device, event,
+			pr->performance_platform_limit);
+		break;
+	case ACPI_PROCESSOR_NOTIFY_POWER:
+		/* TBD */
+		acpi_bus_generate_event(device, event, 0);
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Unsupported event [0x%x]\n", event));
+		break;
+	}
+
+	return_VOID;
+}
+
+
+static int
+acpi_processor_add (
+	struct acpi_device	*device)
+{
+	struct acpi_processor	*pr = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_add");
+
+	if (!device)
+		return_VALUE(-EINVAL);
+
+	pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+	if (!pr)
+		return_VALUE(-ENOMEM);
+	memset(pr, 0, sizeof(struct acpi_processor));
+
+	pr->handle = device->handle;
+	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+	acpi_driver_data(device) = pr;
+
+	return_VALUE(0);
+}
+
+
+static int
+acpi_processor_remove (
+	struct acpi_device	*device,
+	int			type)
+{
+	acpi_status		status = AE_OK;
+	struct acpi_processor	*pr = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_remove");
+
+	if (!device || !acpi_driver_data(device))
+		return_VALUE(-EINVAL);
+
+	pr = (struct acpi_processor *) acpi_driver_data(device);
+
+	if (pr->id >= NR_CPUS) {
+		kfree(pr);
+		return_VALUE(0);
+	}
+
+	if (type == ACPI_BUS_REMOVAL_EJECT) {
+		if (acpi_processor_handle_eject(pr))
+			return_VALUE(-EINVAL);
+	}
+
+	/* Unregister the idle handler when processor #0 is removed. */
+	if (pr->id == 0) {
+		pm_idle = pm_idle_save;
+		/*
+		 * We are about to unload the current idle thread pm callback
+		 * (pm_idle), Wait for all processors to update cached/local
+		 * copies of pm_idle before proceeding.
+		 */
+		synchronize_kernel();
+	}
+
+	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
+		acpi_processor_notify);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Error removing notify handler\n"));
+	}
+
+	acpi_processor_remove_fs(device);
+
+	processors[pr->id] = NULL;
+
+	kfree(pr);
+
+	return_VALUE(0);
+}
+
+static struct dmi_system_id __initdata processor_dmi_table[] = {
+	{ no_c2c3, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }},
+	{ no_c2c3, "Medion 41700", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }},
+	{},
+};
+
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+/****************************************************************************
+ * 	Acpi processor hotplug support 				       	    *
+ ****************************************************************************/
+
+static int is_processor_present(acpi_handle handle);
+
+static int
+is_processor_present(
+	acpi_handle handle)
+{
+	acpi_status 		status;
+	unsigned long		sta = 0;
+
+	ACPI_FUNCTION_TRACE("is_processor_present");
+
+	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Processor Device is not present\n"));
+		return_VALUE(0);
+	}
+	return_VALUE(1);
+}
+
+
+static
+int acpi_processor_device_add(
+	acpi_handle	handle,
+	struct acpi_device **device)
+{
+	acpi_handle		phandle;
+	struct acpi_device 	*pdev;
+	struct acpi_processor	*pr;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_device_add");
+
+	if (acpi_get_parent(handle, &phandle)) {
+		return_VALUE(-ENODEV);
+	}
+
+	if (acpi_bus_get_device(phandle, &pdev)) {
+		return_VALUE(-ENODEV);
+	}
+
+	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
+		return_VALUE(-ENODEV);
+	}
+
+	acpi_bus_scan(*device);
+
+	pr = acpi_driver_data(*device);
+	if (!pr)
+		return_VALUE(-ENODEV);
+
+	if ((pr->id >=0) && (pr->id < NR_CPUS)) {
+		kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
+	}
+	return_VALUE(0);
+}
+
+
+static void
+acpi_processor_hotplug_notify (
+	acpi_handle		handle,
+	u32			event,
+	void			*data)
+{
+	struct acpi_processor	*pr;
+	struct acpi_device	*device = NULL;
+	int result;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify");
+
+	switch (event) {
+	case ACPI_NOTIFY_BUS_CHECK:
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		printk("Processor driver received %s event\n",
+			(event==ACPI_NOTIFY_BUS_CHECK)?
+			"ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+
+		if (!is_processor_present(handle))
+			break;
+
+		if (acpi_bus_get_device(handle, &device)) {
+			result = acpi_processor_device_add(handle, &device);
+			if (result)
+				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+					"Unable to add the device\n"));
+			break;
+		}
+
+		pr = acpi_driver_data(device);
+		if (!pr) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				"Driver data is NULL\n"));
+			break;
+		}
+
+		if (pr->id >= 0 && (pr->id < NR_CPUS)) {
+			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+			break;
+		}
+
+		result = acpi_processor_start(device);
+		if ((!result) && ((pr->id >=0) && (pr->id < NR_CPUS))) {
+			kobject_hotplug(&device->kobj, KOBJ_ONLINE);
+		} else {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				"Device [%s] failed to start\n",
+				acpi_device_bid(device)));
+		}
+	break;
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,"received ACPI_NOTIFY_EJECT_REQUEST\n"));
+
+		if (acpi_bus_get_device(handle, &device)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Device don't exist, dropping EJECT\n"));
+			break;
+		}
+		pr = acpi_driver_data(device);
+		if (!pr) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Driver data is NULL, dropping EJECT\n"));
+			return_VOID;
+		}
+
+		if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
+			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"Unsupported event [0x%x]\n", event));
+		break;
+	}
+
+	return_VOID;
+}
+
+static acpi_status
+processor_walk_namespace_cb(acpi_handle handle,
+	u32 lvl,
+	void *context,
+	void **rv)
+{
+	acpi_status 			status;
+	int *action = context;
+	acpi_object_type	type = 0;
+
+	status = acpi_get_type(handle, &type);
+	if (ACPI_FAILURE(status))
+		return(AE_OK);
+
+	if (type != ACPI_TYPE_PROCESSOR)
+		return(AE_OK);
+
+	switch(*action) {
+	case INSTALL_NOTIFY_HANDLER:
+		acpi_install_notify_handler(handle,
+			ACPI_SYSTEM_NOTIFY,
+			acpi_processor_hotplug_notify,
+			NULL);
+		break;
+	case UNINSTALL_NOTIFY_HANDLER:
+		acpi_remove_notify_handler(handle,
+			ACPI_SYSTEM_NOTIFY,
+			acpi_processor_hotplug_notify);
+		break;
+	default:
+		break;
+	}
+
+	return(AE_OK);
+}
+
+
+static acpi_status
+acpi_processor_hotadd_init(
+	acpi_handle		handle,
+	int			*p_cpu)
+{
+	ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init");
+
+	if (!is_processor_present(handle)) {
+		return_VALUE(AE_ERROR);
+	}
+
+	if (acpi_map_lsapic(handle, p_cpu))
+		return_VALUE(AE_ERROR);
+
+	if (arch_register_cpu(*p_cpu)) {
+		acpi_unmap_lsapic(*p_cpu);
+		return_VALUE(AE_ERROR);
+	}
+
+	return_VALUE(AE_OK);
+}
+
+
+static int
+acpi_processor_handle_eject(struct acpi_processor *pr)
+{
+	if (cpu_online(pr->id)) {
+		return(-EINVAL);
+	}
+	arch_unregister_cpu(pr->id);
+	acpi_unmap_lsapic(pr->id);
+	return(0);
+}
+#else
+static acpi_status
+acpi_processor_hotadd_init(
+	acpi_handle		handle,
+	int			*p_cpu)
+{
+	return AE_ERROR;
+}
+static int
+acpi_processor_handle_eject(struct acpi_processor *pr)
+{
+	return(-EINVAL);
+}
+#endif
+
+
+static
+void acpi_processor_install_hotplug_notify(void)
+{
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+	int action = INSTALL_NOTIFY_HANDLER;
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+				     ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX,
+				     processor_walk_namespace_cb,
+				     &action, NULL);
+#endif
+}
+
+
+static
+void acpi_processor_uninstall_hotplug_notify(void)
+{
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+	int action = UNINSTALL_NOTIFY_HANDLER;
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+				     ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX,
+				     processor_walk_namespace_cb,
+				     &action, NULL);
+#endif
+}
+
+/*
+ * We keep the driver loaded even when ACPI is not running.
+ * This is needed for the powernow-k8 driver, that works even without
+ * ACPI, but needs symbols from this driver
+ */
+
+static int __init
+acpi_processor_init (void)
+{
+	int			result = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_init");
+
+	memset(&processors, 0, sizeof(processors));
+	memset(&errata, 0, sizeof(errata));
+
+	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+	if (!acpi_processor_dir)
+		return_VALUE(0);
+	acpi_processor_dir->owner = THIS_MODULE;
+
+	result = acpi_bus_register_driver(&acpi_processor_driver);
+	if (result < 0) {
+		remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+		return_VALUE(0);
+	}
+
+	acpi_processor_install_hotplug_notify();
+
+	acpi_thermal_cpufreq_init();
+
+	acpi_processor_ppc_init();
+
+	dmi_check_system(processor_dmi_table);
+
+	return_VALUE(0);
+}
+
+
+static void __exit
+acpi_processor_exit (void)
+{
+	ACPI_FUNCTION_TRACE("acpi_processor_exit");
+
+	acpi_processor_ppc_exit();
+
+	acpi_thermal_cpufreq_exit();
+
+	acpi_processor_uninstall_hotplug_notify();
+
+	acpi_bus_unregister_driver(&acpi_processor_driver);
+
+	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+
+	return_VOID;
+}
+
+
+module_init(acpi_processor_init);
+module_exit(acpi_processor_exit);
+
+EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
+
+MODULE_ALIAS("processor");