aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig18
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_pad.c2
-rw-r--r--drivers/acpi/acpica/evxfevnt.c19
-rw-r--r--drivers/acpi/battery.c8
-rw-r--r--drivers/acpi/blacklist.c2
-rw-r--r--drivers/acpi/ec.c107
-rw-r--r--drivers/acpi/ec_sys.c160
-rw-r--r--drivers/acpi/internal.h24
-rw-r--r--drivers/acpi/osl.c40
-rw-r--r--drivers/acpi/pci_root.c9
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c14
-rw-r--r--drivers/acpi/sleep.c35
14 files changed, 286 insertions, 155 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 746411518802..08e0140920e1 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -104,6 +104,24 @@ config ACPI_SYSFS_POWER
104 help 104 help
105 Say N to disable power /sys interface 105 Say N to disable power /sys interface
106 106
107config ACPI_EC_DEBUGFS
108 tristate "EC read/write access through /sys/kernel/debug/ec"
109 default n
110 help
111 Say N to disable Embedded Controller /sys/kernel/debug interface
112
113 Be aware that using this interface can confuse your Embedded
114 Controller in a way that a normal reboot is not enough. You then
115 have to power of your system, and remove the laptop battery for
116 some seconds.
117 An Embedded Controller typically is available on laptops and reads
118 sensor values like battery state and temperature.
119 The kernel accesses the EC through ACPI parsed code provided by BIOS
120 tables. This option allows to access the EC directly without ACPI
121 code being involved.
122 Thus this option is a debug option that helps to write ACPI drivers
123 and can be used to identify ACPI code or EC firmware bugs.
124
107config ACPI_PROC_EVENT 125config ACPI_PROC_EVENT
108 bool "Deprecated /proc/acpi/event support" 126 bool "Deprecated /proc/acpi/event support"
109 depends on PROC_FS 127 depends on PROC_FS
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 6ee33169e1dc..833b582d1762 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_ACPI_SBS) += sbshc.o
60obj-$(CONFIG_ACPI_SBS) += sbs.o 60obj-$(CONFIG_ACPI_SBS) += sbs.o
61obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o 61obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
62obj-$(CONFIG_ACPI_HED) += hed.o 62obj-$(CONFIG_ACPI_HED) += hed.o
63obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
63 64
64# processor has its own "processor." module_param namespace 65# processor has its own "processor." module_param namespace
65processor-y := processor_driver.o processor_throttling.o 66processor-y := processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 446aced33aff..b76848c80be3 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -77,7 +77,7 @@ static void power_saving_mwait_init(void)
77 power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | 77 power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
78 (highest_subcstate - 1); 78 (highest_subcstate - 1);
79 79
80#if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86) 80#if defined(CONFIG_X86)
81 switch (boot_cpu_data.x86_vendor) { 81 switch (boot_cpu_data.x86_vendor) {
82 case X86_VENDOR_AMD: 82 case X86_VENDOR_AMD:
83 case X86_VENDOR_INTEL: 83 case X86_VENDOR_INTEL:
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 53d591a11138..0ec900da5794 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -70,6 +70,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
70acpi_status acpi_enable(void) 70acpi_status acpi_enable(void)
71{ 71{
72 acpi_status status; 72 acpi_status status;
73 int retry;
73 74
74 ACPI_FUNCTION_TRACE(acpi_enable); 75 ACPI_FUNCTION_TRACE(acpi_enable);
75 76
@@ -98,16 +99,18 @@ acpi_status acpi_enable(void)
98 99
99 /* Sanity check that transition succeeded */ 100 /* Sanity check that transition succeeded */
100 101
101 if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) { 102 for (retry = 0; retry < 30000; ++retry) {
102 ACPI_ERROR((AE_INFO, 103 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
103 "Hardware did not enter ACPI mode")); 104 if (retry != 0)
104 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); 105 ACPI_WARNING((AE_INFO,
106 "Platform took > %d00 usec to enter ACPI mode", retry));
107 return_ACPI_STATUS(AE_OK);
108 }
109 acpi_os_stall(100); /* 100 usec */
105 } 110 }
106 111
107 ACPI_DEBUG_PRINT((ACPI_DB_INIT, 112 ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
108 "Transition to ACPI mode successful\n")); 113 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
109
110 return_ACPI_STATUS(AE_OK);
111} 114}
112 115
113ACPI_EXPORT_SYMBOL(acpi_enable) 116ACPI_EXPORT_SYMBOL(acpi_enable)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 3026e3fa83ef..dc58402b0a17 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -868,9 +868,15 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
868static void acpi_battery_notify(struct acpi_device *device, u32 event) 868static void acpi_battery_notify(struct acpi_device *device, u32 event)
869{ 869{
870 struct acpi_battery *battery = acpi_driver_data(device); 870 struct acpi_battery *battery = acpi_driver_data(device);
871#ifdef CONFIG_ACPI_SYSFS_POWER
872 struct device *old;
873#endif
871 874
872 if (!battery) 875 if (!battery)
873 return; 876 return;
877#ifdef CONFIG_ACPI_SYSFS_POWER
878 old = battery->bat.dev;
879#endif
874 acpi_battery_update(battery); 880 acpi_battery_update(battery);
875 acpi_bus_generate_proc_event(device, event, 881 acpi_bus_generate_proc_event(device, event,
876 acpi_battery_present(battery)); 882 acpi_battery_present(battery));
@@ -879,7 +885,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
879 acpi_battery_present(battery)); 885 acpi_battery_present(battery));
880#ifdef CONFIG_ACPI_SYSFS_POWER 886#ifdef CONFIG_ACPI_SYSFS_POWER
881 /* acpi_battery_update could remove power_supply object */ 887 /* acpi_battery_update could remove power_supply object */
882 if (battery->bat.dev) 888 if (old && battery->bat.dev)
883 power_supply_changed(&battery->bat); 889 power_supply_changed(&battery->bat);
884#endif 890#endif
885} 891}
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 01381be05e96..2bb28b9d91c4 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -214,7 +214,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
214 .ident = "Sony VGN-SR290J", 214 .ident = "Sony VGN-SR290J",
215 .matches = { 215 .matches = {
216 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 216 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
217 DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), 217 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
218 }, 218 },
219 }, 219 },
220 { 220 {
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 1e6d4184f0ea..f31291ba94d0 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -34,8 +34,6 @@
34#include <linux/init.h> 34#include <linux/init.h>
35#include <linux/types.h> 35#include <linux/types.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/proc_fs.h>
38#include <linux/seq_file.h>
39#include <linux/interrupt.h> 37#include <linux/interrupt.h>
40#include <linux/list.h> 38#include <linux/list.h>
41#include <linux/spinlock.h> 39#include <linux/spinlock.h>
@@ -45,10 +43,13 @@
45#include <acpi/acpi_drivers.h> 43#include <acpi/acpi_drivers.h>
46#include <linux/dmi.h> 44#include <linux/dmi.h>
47 45
46#include "internal.h"
47
48#define ACPI_EC_CLASS "embedded_controller" 48#define ACPI_EC_CLASS "embedded_controller"
49#define ACPI_EC_DEVICE_NAME "Embedded Controller" 49#define ACPI_EC_DEVICE_NAME "Embedded Controller"
50#define ACPI_EC_FILE_INFO "info" 50#define ACPI_EC_FILE_INFO "info"
51 51
52#undef PREFIX
52#define PREFIX "ACPI: EC: " 53#define PREFIX "ACPI: EC: "
53 54
54/* EC status register */ 55/* EC status register */
@@ -106,19 +107,8 @@ struct transaction {
106 bool done; 107 bool done;
107}; 108};
108 109
109static struct acpi_ec { 110struct acpi_ec *boot_ec, *first_ec;
110 acpi_handle handle; 111EXPORT_SYMBOL(first_ec);
111 unsigned long gpe;
112 unsigned long command_addr;
113 unsigned long data_addr;
114 unsigned long global_lock;
115 unsigned long flags;
116 struct mutex lock;
117 wait_queue_head_t wait;
118 struct list_head list;
119 struct transaction *curr;
120 spinlock_t curr_lock;
121} *boot_ec, *first_ec;
122 112
123static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ 113static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
124static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ 114static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
@@ -672,72 +662,6 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
672} 662}
673 663
674/* -------------------------------------------------------------------------- 664/* --------------------------------------------------------------------------
675 FS Interface (/proc)
676 -------------------------------------------------------------------------- */
677
678static struct proc_dir_entry *acpi_ec_dir;
679
680static int acpi_ec_read_info(struct seq_file *seq, void *offset)
681{
682 struct acpi_ec *ec = seq->private;
683
684 if (!ec)
685 goto end;
686
687 seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
688 seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
689 (unsigned)ec->command_addr, (unsigned)ec->data_addr);
690 seq_printf(seq, "use global lock:\t%s\n",
691 ec->global_lock ? "yes" : "no");
692 end:
693 return 0;
694}
695
696static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
697{
698 return single_open(file, acpi_ec_read_info, PDE(inode)->data);
699}
700
701static const struct file_operations acpi_ec_info_ops = {
702 .open = acpi_ec_info_open_fs,
703 .read = seq_read,
704 .llseek = seq_lseek,
705 .release = single_release,
706 .owner = THIS_MODULE,
707};
708
709static int acpi_ec_add_fs(struct acpi_device *device)
710{
711 struct proc_dir_entry *entry = NULL;
712
713 if (!acpi_device_dir(device)) {
714 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
715 acpi_ec_dir);
716 if (!acpi_device_dir(device))
717 return -ENODEV;
718 }
719
720 entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
721 acpi_device_dir(device),
722 &acpi_ec_info_ops, acpi_driver_data(device));
723 if (!entry)
724 return -ENODEV;
725 return 0;
726}
727
728static int acpi_ec_remove_fs(struct acpi_device *device)
729{
730
731 if (acpi_device_dir(device)) {
732 remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
733 remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
734 acpi_device_dir(device) = NULL;
735 }
736
737 return 0;
738}
739
740/* --------------------------------------------------------------------------
741 Driver Interface 665 Driver Interface
742 -------------------------------------------------------------------------- */ 666 -------------------------------------------------------------------------- */
743static acpi_status 667static acpi_status
@@ -887,7 +811,12 @@ static int acpi_ec_add(struct acpi_device *device)
887 if (!first_ec) 811 if (!first_ec)
888 first_ec = ec; 812 first_ec = ec;
889 device->driver_data = ec; 813 device->driver_data = ec;
890 acpi_ec_add_fs(device); 814
815 WARN(!request_region(ec->data_addr, 1, "EC data"),
816 "Could not request EC data io port 0x%lx", ec->data_addr);
817 WARN(!request_region(ec->command_addr, 1, "EC cmd"),
818 "Could not request EC cmd io port 0x%lx", ec->command_addr);
819
891 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", 820 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
892 ec->gpe, ec->command_addr, ec->data_addr); 821 ec->gpe, ec->command_addr, ec->data_addr);
893 822
@@ -914,7 +843,8 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
914 kfree(handler); 843 kfree(handler);
915 } 844 }
916 mutex_unlock(&ec->lock); 845 mutex_unlock(&ec->lock);
917 acpi_ec_remove_fs(device); 846 release_region(ec->data_addr, 1);
847 release_region(ec->command_addr, 1);
918 device->driver_data = NULL; 848 device->driver_data = NULL;
919 if (ec == first_ec) 849 if (ec == first_ec)
920 first_ec = NULL; 850 first_ec = NULL;
@@ -1095,16 +1025,10 @@ int __init acpi_ec_init(void)
1095{ 1025{
1096 int result = 0; 1026 int result = 0;
1097 1027
1098 acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
1099 if (!acpi_ec_dir)
1100 return -ENODEV;
1101
1102 /* Now register the driver for the EC */ 1028 /* Now register the driver for the EC */
1103 result = acpi_bus_register_driver(&acpi_ec_driver); 1029 result = acpi_bus_register_driver(&acpi_ec_driver);
1104 if (result < 0) { 1030 if (result < 0)
1105 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1106 return -ENODEV; 1031 return -ENODEV;
1107 }
1108 1032
1109 return result; 1033 return result;
1110} 1034}
@@ -1115,9 +1039,6 @@ static void __exit acpi_ec_exit(void)
1115{ 1039{
1116 1040
1117 acpi_bus_unregister_driver(&acpi_ec_driver); 1041 acpi_bus_unregister_driver(&acpi_ec_driver);
1118
1119 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1120
1121 return; 1042 return;
1122} 1043}
1123#endif /* 0 */ 1044#endif /* 0 */
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
new file mode 100644
index 000000000000..0e869b3f81ca
--- /dev/null
+++ b/drivers/acpi/ec_sys.c
@@ -0,0 +1,160 @@
1/*
2 * ec_sys.c
3 *
4 * Copyright (C) 2010 SUSE Products GmbH/Novell
5 * Author:
6 * Thomas Renninger <trenn@suse.de>
7 *
8 * This work is licensed under the terms of the GNU GPL, version 2.
9 */
10
11#include <linux/kernel.h>
12#include <linux/acpi.h>
13#include <linux/debugfs.h>
14#include "internal.h"
15
16MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
17MODULE_DESCRIPTION("ACPI EC sysfs access driver");
18MODULE_LICENSE("GPL");
19
20static bool write_support;
21module_param(write_support, bool, 0644);
22MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may "
23 "be needed.");
24
25#define EC_SPACE_SIZE 256
26
27struct sysdev_class acpi_ec_sysdev_class = {
28 .name = "ec",
29};
30
31static struct dentry *acpi_ec_debugfs_dir;
32
33static int acpi_ec_open_io(struct inode *i, struct file *f)
34{
35 f->private_data = i->i_private;
36 return 0;
37}
38
39static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
40 size_t count, loff_t *off)
41{
42 /* Use this if support reading/writing multiple ECs exists in ec.c:
43 * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private;
44 */
45 unsigned int size = EC_SPACE_SIZE;
46 u8 *data = (u8 *) buf;
47 loff_t init_off = *off;
48 int err = 0;
49
50 if (*off >= size)
51 return 0;
52 if (*off + count >= size) {
53 size -= *off;
54 count = size;
55 } else
56 size = count;
57
58 while (size) {
59 err = ec_read(*off, &data[*off - init_off]);
60 if (err)
61 return err;
62 *off += 1;
63 size--;
64 }
65 return count;
66}
67
68static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
69 size_t count, loff_t *off)
70{
71 /* Use this if support reading/writing multiple ECs exists in ec.c:
72 * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private;
73 */
74
75 unsigned int size = count;
76 loff_t init_off = *off;
77 u8 *data = (u8 *) buf;
78 int err = 0;
79
80 if (*off >= EC_SPACE_SIZE)
81 return 0;
82 if (*off + count >= EC_SPACE_SIZE) {
83 size = EC_SPACE_SIZE - *off;
84 count = size;
85 }
86
87 while (size) {
88 u8 byte_write = data[*off - init_off];
89 err = ec_write(*off, byte_write);
90 if (err)
91 return err;
92
93 *off += 1;
94 size--;
95 }
96 return count;
97}
98
99static struct file_operations acpi_ec_io_ops = {
100 .owner = THIS_MODULE,
101 .open = acpi_ec_open_io,
102 .read = acpi_ec_read_io,
103 .write = acpi_ec_write_io,
104};
105
106int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
107{
108 struct dentry *dev_dir;
109 char name[64];
110 mode_t mode = 0400;
111
112 if (ec_device_count == 0) {
113 acpi_ec_debugfs_dir = debugfs_create_dir("ec", NULL);
114 if (!acpi_ec_debugfs_dir)
115 return -ENOMEM;
116 }
117
118 sprintf(name, "ec%u", ec_device_count);
119 dev_dir = debugfs_create_dir(name, acpi_ec_debugfs_dir);
120 if (!dev_dir) {
121 if (ec_device_count != 0)
122 goto error;
123 return -ENOMEM;
124 }
125
126 if (!debugfs_create_x32("gpe", 0444, dev_dir, (u32 *)&first_ec->gpe))
127 goto error;
128 if (!debugfs_create_bool("use_global_lock", 0444, dev_dir,
129 (u32 *)&first_ec->global_lock))
130 goto error;
131
132 if (write_support)
133 mode = 0600;
134 if (!debugfs_create_file("io", mode, dev_dir, ec, &acpi_ec_io_ops))
135 goto error;
136
137 return 0;
138
139error:
140 debugfs_remove_recursive(acpi_ec_debugfs_dir);
141 return -ENOMEM;
142}
143
144static int __init acpi_ec_sys_init(void)
145{
146 int err = 0;
147 if (first_ec)
148 err = acpi_ec_add_debugfs(first_ec, 0);
149 else
150 err = -ENODEV;
151 return err;
152}
153
154static void __exit acpi_ec_sys_exit(void)
155{
156 debugfs_remove_recursive(acpi_ec_debugfs_dir);
157}
158
159module_init(acpi_ec_sys_init);
160module_exit(acpi_ec_sys_exit);
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index f8f190ec066e..8ae27264a00e 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -18,6 +18,11 @@
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 */ 19 */
20 20
21#ifndef _ACPI_INTERNAL_H_
22#define _ACPI_INTERNAL_H_
23
24#include <linux/sysdev.h>
25
21#define PREFIX "ACPI: " 26#define PREFIX "ACPI: "
22 27
23int init_acpi_device_notify(void); 28int init_acpi_device_notify(void);
@@ -46,6 +51,23 @@ void acpi_early_processor_set_pdc(void);
46/* -------------------------------------------------------------------------- 51/* --------------------------------------------------------------------------
47 Embedded Controller 52 Embedded Controller
48 -------------------------------------------------------------------------- */ 53 -------------------------------------------------------------------------- */
54struct acpi_ec {
55 acpi_handle handle;
56 unsigned long gpe;
57 unsigned long command_addr;
58 unsigned long data_addr;
59 unsigned long global_lock;
60 unsigned long flags;
61 struct mutex lock;
62 wait_queue_head_t wait;
63 struct list_head list;
64 struct transaction *curr;
65 spinlock_t curr_lock;
66 struct sys_device sysdev;
67};
68
69extern struct acpi_ec *first_ec;
70
49int acpi_ec_init(void); 71int acpi_ec_init(void);
50int acpi_ec_ecdt_probe(void); 72int acpi_ec_ecdt_probe(void);
51int acpi_boot_ec_enable(void); 73int acpi_boot_ec_enable(void);
@@ -63,3 +85,5 @@ int acpi_sleep_proc_init(void);
63#else 85#else
64static inline int acpi_sleep_proc_init(void) { return 0; } 86static inline int acpi_sleep_proc_init(void) { return 0; }
65#endif 87#endif
88
89#endif /* _ACPI_INTERNAL_H_ */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 44bddc5bc6ad..f14d3f251d26 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -191,36 +191,11 @@ acpi_status __init acpi_os_initialize(void)
191 return AE_OK; 191 return AE_OK;
192} 192}
193 193
194static void bind_to_cpu0(struct work_struct *work)
195{
196 set_cpus_allowed_ptr(current, cpumask_of(0));
197 kfree(work);
198}
199
200static void bind_workqueue(struct workqueue_struct *wq)
201{
202 struct work_struct *work;
203
204 work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
205 INIT_WORK(work, bind_to_cpu0);
206 queue_work(wq, work);
207}
208
209acpi_status acpi_os_initialize1(void) 194acpi_status acpi_os_initialize1(void)
210{ 195{
211 /* 196 kacpid_wq = create_workqueue("kacpid");
212 * On some machines, a software-initiated SMI causes corruption unless 197 kacpi_notify_wq = create_workqueue("kacpi_notify");
213 * the SMI runs on CPU 0. An SMI can be initiated by any AML, but 198 kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
214 * typically it's done in GPE-related methods that are run via
215 * workqueues, so we can avoid the known corruption cases by binding
216 * the workqueues to CPU 0.
217 */
218 kacpid_wq = create_singlethread_workqueue("kacpid");
219 bind_workqueue(kacpid_wq);
220 kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
221 bind_workqueue(kacpi_notify_wq);
222 kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");
223 bind_workqueue(kacpi_hotplug_wq);
224 BUG_ON(!kacpid_wq); 199 BUG_ON(!kacpid_wq);
225 BUG_ON(!kacpi_notify_wq); 200 BUG_ON(!kacpi_notify_wq);
226 BUG_ON(!kacpi_hotplug_wq); 201 BUG_ON(!kacpi_hotplug_wq);
@@ -766,7 +741,14 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
766 else 741 else
767 INIT_WORK(&dpc->work, acpi_os_execute_deferred); 742 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
768 743
769 ret = queue_work(queue, &dpc->work); 744 /*
745 * On some machines, a software-initiated SMI causes corruption unless
746 * the SMI runs on CPU 0. An SMI can be initiated by any AML, but
747 * typically it's done in GPE-related methods that are run via
748 * workqueues, so we can avoid the known corruption cases by always
749 * queueing on CPU 0.
750 */
751 ret = queue_work_on(0, queue, &dpc->work);
770 752
771 if (!ret) { 753 if (!ret) {
772 printk(KERN_ERR PREFIX 754 printk(KERN_ERR PREFIX
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 4eac59393edc..1f67057af2a5 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -33,6 +33,7 @@
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/pci.h> 34#include <linux/pci.h>
35#include <linux/pci-acpi.h> 35#include <linux/pci-acpi.h>
36#include <linux/pci-aspm.h>
36#include <linux/acpi.h> 37#include <linux/acpi.h>
37#include <linux/slab.h> 38#include <linux/slab.h>
38#include <acpi/acpi_bus.h> 39#include <acpi/acpi_bus.h>
@@ -543,6 +544,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
543 if (flags != base_flags) 544 if (flags != base_flags)
544 acpi_pci_osc_support(root, flags); 545 acpi_pci_osc_support(root, flags);
545 546
547 status = acpi_pci_osc_control_set(root->device->handle,
548 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
549
550 if (ACPI_FAILURE(status)) {
551 printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
552 pcie_no_aspm();
553 }
554
546 pci_acpi_add_bus_pm_notifier(device, root->bus); 555 pci_acpi_add_bus_pm_notifier(device, root->bus);
547 if (device->wakeup.flags.run_wake) 556 if (device->wakeup.flags.run_wake)
548 device_set_run_wake(root->bus->bridge, true); 557 device_set_run_wake(root->bus->bridge, true);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 51284351418f..e9699aaed109 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -223,7 +223,7 @@ static bool processor_physically_present(acpi_handle handle)
223 type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; 223 type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
224 cpuid = acpi_get_cpuid(handle, type, acpi_id); 224 cpuid = acpi_get_cpuid(handle, type, acpi_id);
225 225
226 if (cpuid == -1) 226 if ((cpuid == -1) && (num_possible_cpus() > 1))
227 return false; 227 return false;
228 228
229 return true; 229 return true;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index b1b385692f46..b4c2f3bdadeb 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -76,14 +76,19 @@ static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
76module_param(max_cstate, uint, 0000); 76module_param(max_cstate, uint, 0000);
77static unsigned int nocst __read_mostly; 77static unsigned int nocst __read_mostly;
78module_param(nocst, uint, 0000); 78module_param(nocst, uint, 0000);
79static int bm_check_disable __read_mostly;
80module_param(bm_check_disable, uint, 0000);
79 81
80static unsigned int latency_factor __read_mostly = 2; 82static unsigned int latency_factor __read_mostly = 2;
81module_param(latency_factor, uint, 0644); 83module_param(latency_factor, uint, 0644);
82 84
85#ifdef CONFIG_ACPI_PROCFS
83static u64 us_to_pm_timer_ticks(s64 t) 86static u64 us_to_pm_timer_ticks(s64 t)
84{ 87{
85 return div64_u64(t * PM_TIMER_FREQUENCY, 1000000); 88 return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);
86} 89}
90#endif
91
87/* 92/*
88 * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. 93 * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
89 * For now disable this. Probably a bug somewhere else. 94 * For now disable this. Probably a bug somewhere else.
@@ -159,7 +164,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
159 if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) 164 if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT))
160 return; 165 return;
161 166
162 if (boot_cpu_has(X86_FEATURE_AMDC1E)) 167 if (c1e_detected)
163 type = ACPI_STATE_C1; 168 type = ACPI_STATE_C1;
164 169
165 /* 170 /*
@@ -259,7 +264,7 @@ int acpi_processor_resume(struct acpi_device * device)
259 return 0; 264 return 0;
260} 265}
261 266
262#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) 267#if defined(CONFIG_X86)
263static void tsc_check_state(int state) 268static void tsc_check_state(int state)
264{ 269{
265 switch (boot_cpu_data.x86_vendor) { 270 switch (boot_cpu_data.x86_vendor) {
@@ -763,6 +768,9 @@ static int acpi_idle_bm_check(void)
763{ 768{
764 u32 bm_status = 0; 769 u32 bm_status = 0;
765 770
771 if (bm_check_disable)
772 return 0;
773
766 acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); 774 acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
767 if (bm_status) 775 if (bm_status)
768 acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); 776 acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
@@ -947,7 +955,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
947 if (acpi_idle_suspend) 955 if (acpi_idle_suspend)
948 return(acpi_idle_enter_c1(dev, state)); 956 return(acpi_idle_enter_c1(dev, state));
949 957
950 if (acpi_idle_bm_check()) { 958 if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
951 if (dev->safe_state) { 959 if (dev->safe_state) {
952 dev->last_state = dev->safe_state; 960 dev->last_state = dev->safe_state;
953 return dev->safe_state->enter(dev, dev->safe_state); 961 return dev->safe_state->enter(dev, dev->safe_state);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index aaa1af55e280..e143203254a4 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -82,6 +82,20 @@ static int acpi_sleep_prepare(u32 acpi_state)
82static u32 acpi_target_sleep_state = ACPI_STATE_S0; 82static u32 acpi_target_sleep_state = ACPI_STATE_S0;
83 83
84/* 84/*
85 * The ACPI specification wants us to save NVS memory regions during hibernation
86 * and to restore them during the subsequent resume. Windows does that also for
87 * suspend to RAM. However, it is known that this mechanism does not work on
88 * all machines, so we allow the user to disable it with the help of the
89 * 'acpi_sleep=nonvs' kernel command line option.
90 */
91static bool nvs_nosave;
92
93void __init acpi_nvs_nosave(void)
94{
95 nvs_nosave = true;
96}
97
98/*
85 * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the 99 * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
86 * user to request that behavior by using the 'acpi_old_suspend_ordering' 100 * user to request that behavior by using the 'acpi_old_suspend_ordering'
87 * kernel command line option that causes the following variable to be set. 101 * kernel command line option that causes the following variable to be set.
@@ -197,8 +211,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
197 u32 acpi_state = acpi_suspend_states[pm_state]; 211 u32 acpi_state = acpi_suspend_states[pm_state];
198 int error = 0; 212 int error = 0;
199 213
200 error = suspend_nvs_alloc(); 214 error = nvs_nosave ? 0 : suspend_nvs_alloc();
201
202 if (error) 215 if (error)
203 return error; 216 return error;
204 217
@@ -388,20 +401,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
388#endif /* CONFIG_SUSPEND */ 401#endif /* CONFIG_SUSPEND */
389 402
390#ifdef CONFIG_HIBERNATION 403#ifdef CONFIG_HIBERNATION
391/*
392 * The ACPI specification wants us to save NVS memory regions during hibernation
393 * and to restore them during the subsequent resume. However, it is not certain
394 * if this mechanism is going to work on all machines, so we allow the user to
395 * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
396 * option.
397 */
398static bool s4_no_nvs;
399
400void __init acpi_s4_no_nvs(void)
401{
402 s4_no_nvs = true;
403}
404
405static unsigned long s4_hardware_signature; 404static unsigned long s4_hardware_signature;
406static struct acpi_table_facs *facs; 405static struct acpi_table_facs *facs;
407static bool nosigcheck; 406static bool nosigcheck;
@@ -415,7 +414,7 @@ static int acpi_hibernation_begin(void)
415{ 414{
416 int error; 415 int error;
417 416
418 error = s4_no_nvs ? 0 : suspend_nvs_alloc(); 417 error = nvs_nosave ? 0 : suspend_nvs_alloc();
419 if (!error) { 418 if (!error) {
420 acpi_target_sleep_state = ACPI_STATE_S4; 419 acpi_target_sleep_state = ACPI_STATE_S4;
421 acpi_sleep_tts_switch(acpi_target_sleep_state); 420 acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -510,7 +509,7 @@ static int acpi_hibernation_begin_old(void)
510 error = acpi_sleep_prepare(ACPI_STATE_S4); 509 error = acpi_sleep_prepare(ACPI_STATE_S4);
511 510
512 if (!error) { 511 if (!error) {
513 if (!s4_no_nvs) 512 if (!nvs_nosave)
514 error = suspend_nvs_alloc(); 513 error = suspend_nvs_alloc();
515 if (!error) 514 if (!error)
516 acpi_target_sleep_state = ACPI_STATE_S4; 515 acpi_target_sleep_state = ACPI_STATE_S4;