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