diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 18 | ||||
-rw-r--r-- | drivers/acpi/Makefile | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxfevnt.c | 19 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 8 | ||||
-rw-r--r-- | drivers/acpi/blacklist.c | 2 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 107 | ||||
-rw-r--r-- | drivers/acpi/ec_sys.c | 160 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 24 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 10 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 35 |
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 | ||
107 | config 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 | |||
107 | config ACPI_PROC_EVENT | 125 | config 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 | |||
60 | obj-$(CONFIG_ACPI_SBS) += sbs.o | 60 | obj-$(CONFIG_ACPI_SBS) += sbs.o |
61 | obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o | 61 | obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o |
62 | obj-$(CONFIG_ACPI_HED) += hed.o | 62 | obj-$(CONFIG_ACPI_HED) += hed.o |
63 | obj-$(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 |
65 | processor-y := processor_driver.o processor_throttling.o | 66 | processor-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, | |||
70 | acpi_status acpi_enable(void) | 70 | acpi_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 | ||
113 | ACPI_EXPORT_SYMBOL(acpi_enable) | 116 | ACPI_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) | |||
868 | static void acpi_battery_notify(struct acpi_device *device, u32 event) | 868 | static 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 | ||
109 | static struct acpi_ec { | 110 | struct acpi_ec *boot_ec, *first_ec; |
110 | acpi_handle handle; | 111 | EXPORT_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 | ||
123 | static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ | 113 | static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ |
124 | static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ | 114 | static 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 | |||
685 | static struct proc_dir_entry *acpi_ec_dir; | ||
686 | |||
687 | static 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 | |||
703 | static 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 | |||
708 | static 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 | |||
716 | static 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 | |||
735 | static 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 | -------------------------------------------------------------------------- */ |
750 | static acpi_status | 674 | static 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 | |||
16 | MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>"); | ||
17 | MODULE_DESCRIPTION("ACPI EC sysfs access driver"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | |||
20 | static bool write_support; | ||
21 | module_param(write_support, bool, 0644); | ||
22 | MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may " | ||
23 | "be needed."); | ||
24 | |||
25 | #define EC_SPACE_SIZE 256 | ||
26 | |||
27 | struct sysdev_class acpi_ec_sysdev_class = { | ||
28 | .name = "ec", | ||
29 | }; | ||
30 | |||
31 | static struct dentry *acpi_ec_debugfs_dir; | ||
32 | |||
33 | static int acpi_ec_open_io(struct inode *i, struct file *f) | ||
34 | { | ||
35 | f->private_data = i->i_private; | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static 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 | |||
68 | static 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 | |||
99 | static 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 | |||
106 | int 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 | |||
139 | error: | ||
140 | debugfs_remove_recursive(acpi_ec_debugfs_dir); | ||
141 | return -ENOMEM; | ||
142 | } | ||
143 | |||
144 | static 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 | |||
154 | static void __exit acpi_ec_sys_exit(void) | ||
155 | { | ||
156 | debugfs_remove_recursive(acpi_ec_debugfs_dir); | ||
157 | } | ||
158 | |||
159 | module_init(acpi_ec_sys_init); | ||
160 | module_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 | ||
23 | int init_acpi_device_notify(void); | 28 | int 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 | -------------------------------------------------------------------------- */ |
54 | struct 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 | |||
69 | extern struct acpi_ec *first_ec; | ||
70 | |||
49 | int acpi_ec_init(void); | 71 | int acpi_ec_init(void); |
50 | int acpi_ec_ecdt_probe(void); | 72 | int acpi_ec_ecdt_probe(void); |
51 | int acpi_boot_ec_enable(void); | 73 | int acpi_boot_ec_enable(void); |
@@ -63,3 +85,5 @@ int acpi_sleep_proc_init(void); | |||
63 | #else | 85 | #else |
64 | static inline int acpi_sleep_proc_init(void) { return 0; } | 86 | static 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; | |||
76 | module_param(max_cstate, uint, 0000); | 76 | module_param(max_cstate, uint, 0000); |
77 | static unsigned int nocst __read_mostly; | 77 | static unsigned int nocst __read_mostly; |
78 | module_param(nocst, uint, 0000); | 78 | module_param(nocst, uint, 0000); |
79 | static int bm_check_disable __read_mostly; | ||
80 | module_param(bm_check_disable, uint, 0000); | ||
79 | 81 | ||
80 | static unsigned int latency_factor __read_mostly = 2; | 82 | static unsigned int latency_factor __read_mostly = 2; |
81 | module_param(latency_factor, uint, 0644); | 83 | module_param(latency_factor, uint, 0644); |
82 | 84 | ||
85 | #ifdef CONFIG_ACPI_PROCFS | ||
83 | static u64 us_to_pm_timer_ticks(s64 t) | 86 | static 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) | |||
82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static 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 | */ | ||
91 | static bool nvs_nosave; | ||
92 | |||
93 | void __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 | */ | ||
398 | static bool s4_no_nvs; | ||
399 | |||
400 | void __init acpi_s4_no_nvs(void) | ||
401 | { | ||
402 | s4_no_nvs = true; | ||
403 | } | ||
404 | |||
405 | static unsigned long s4_hardware_signature; | 404 | static unsigned long s4_hardware_signature; |
406 | static struct acpi_table_facs *facs; | 405 | static struct acpi_table_facs *facs; |
407 | static bool nosigcheck; | 406 | static 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; |