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/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/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c10
-rw-r--r--drivers/acpi/sleep.c35
11 files changed, 263 insertions, 123 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/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d97b8dce1668..18b3f1468b7d 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 5f2027d782e8..1fa0aafebe2a 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 */
@@ -679,72 +669,6 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
679} 669}
680 670
681/* -------------------------------------------------------------------------- 671/* --------------------------------------------------------------------------
682 FS Interface (/proc)
683 -------------------------------------------------------------------------- */
684
685static struct proc_dir_entry *acpi_ec_dir;
686
687static int acpi_ec_read_info(struct seq_file *seq, void *offset)
688{
689 struct acpi_ec *ec = seq->private;
690
691 if (!ec)
692 goto end;
693
694 seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
695 seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
696 (unsigned)ec->command_addr, (unsigned)ec->data_addr);
697 seq_printf(seq, "use global lock:\t%s\n",
698 ec->global_lock ? "yes" : "no");
699 end:
700 return 0;
701}
702
703static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
704{
705 return single_open(file, acpi_ec_read_info, PDE(inode)->data);
706}
707
708static const struct file_operations acpi_ec_info_ops = {
709 .open = acpi_ec_info_open_fs,
710 .read = seq_read,
711 .llseek = seq_lseek,
712 .release = single_release,
713 .owner = THIS_MODULE,
714};
715
716static int acpi_ec_add_fs(struct acpi_device *device)
717{
718 struct proc_dir_entry *entry = NULL;
719
720 if (!acpi_device_dir(device)) {
721 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
722 acpi_ec_dir);
723 if (!acpi_device_dir(device))
724 return -ENODEV;
725 }
726
727 entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
728 acpi_device_dir(device),
729 &acpi_ec_info_ops, acpi_driver_data(device));
730 if (!entry)
731 return -ENODEV;
732 return 0;
733}
734
735static int acpi_ec_remove_fs(struct acpi_device *device)
736{
737
738 if (acpi_device_dir(device)) {
739 remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
740 remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
741 acpi_device_dir(device) = NULL;
742 }
743
744 return 0;
745}
746
747/* --------------------------------------------------------------------------
748 Driver Interface 672 Driver Interface
749 -------------------------------------------------------------------------- */ 673 -------------------------------------------------------------------------- */
750static acpi_status 674static acpi_status
@@ -894,7 +818,12 @@ static int acpi_ec_add(struct acpi_device *device)
894 if (!first_ec) 818 if (!first_ec)
895 first_ec = ec; 819 first_ec = ec;
896 device->driver_data = ec; 820 device->driver_data = ec;
897 acpi_ec_add_fs(device); 821
822 WARN(!request_region(ec->data_addr, 1, "EC data"),
823 "Could not request EC data io port 0x%lx", ec->data_addr);
824 WARN(!request_region(ec->command_addr, 1, "EC cmd"),
825 "Could not request EC cmd io port 0x%lx", ec->command_addr);
826
898 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", 827 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
899 ec->gpe, ec->command_addr, ec->data_addr); 828 ec->gpe, ec->command_addr, ec->data_addr);
900 829
@@ -921,7 +850,8 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
921 kfree(handler); 850 kfree(handler);
922 } 851 }
923 mutex_unlock(&ec->lock); 852 mutex_unlock(&ec->lock);
924 acpi_ec_remove_fs(device); 853 release_region(ec->data_addr, 1);
854 release_region(ec->command_addr, 1);
925 device->driver_data = NULL; 855 device->driver_data = NULL;
926 if (ec == first_ec) 856 if (ec == first_ec)
927 first_ec = NULL; 857 first_ec = NULL;
@@ -1120,16 +1050,10 @@ int __init acpi_ec_init(void)
1120{ 1050{
1121 int result = 0; 1051 int result = 0;
1122 1052
1123 acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
1124 if (!acpi_ec_dir)
1125 return -ENODEV;
1126
1127 /* Now register the driver for the EC */ 1053 /* Now register the driver for the EC */
1128 result = acpi_bus_register_driver(&acpi_ec_driver); 1054 result = acpi_bus_register_driver(&acpi_ec_driver);
1129 if (result < 0) { 1055 if (result < 0)
1130 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1131 return -ENODEV; 1056 return -ENODEV;
1132 }
1133 1057
1134 return result; 1058 return result;
1135} 1059}
@@ -1140,9 +1064,6 @@ static void __exit acpi_ec_exit(void)
1140{ 1064{
1141 1065
1142 acpi_bus_unregister_driver(&acpi_ec_driver); 1066 acpi_bus_unregister_driver(&acpi_ec_driver);
1143
1144 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1145
1146 return; 1067 return;
1147} 1068}
1148#endif /* 0 */ 1069#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/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..e9a8026d39f0 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.
@@ -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 5b7c52e4a00f..2862c781b372 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;