diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/acpi | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/acpi')
198 files changed, 9060 insertions, 7997 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 88681aca88c5..de0e3df76776 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -7,9 +7,7 @@ menuconfig ACPI | |||
7 | depends on !IA64_HP_SIM | 7 | depends on !IA64_HP_SIM |
8 | depends on IA64 || X86 | 8 | depends on IA64 || X86 |
9 | depends on PCI | 9 | depends on PCI |
10 | depends on PM | ||
11 | select PNP | 10 | select PNP |
12 | select CPU_IDLE | ||
13 | default y | 11 | default y |
14 | help | 12 | help |
15 | Advanced Configuration and Power Interface (ACPI) support for | 13 | Advanced Configuration and Power Interface (ACPI) support for |
@@ -52,12 +50,7 @@ config ACPI_PROCFS | |||
52 | For backwards compatibility, this option allows | 50 | For backwards compatibility, this option allows |
53 | deprecated /proc/acpi/ files to exist, even when | 51 | deprecated /proc/acpi/ files to exist, even when |
54 | they have been replaced by functions in /sys. | 52 | they have been replaced by functions in /sys. |
55 | The deprecated files (and their replacements) include: | ||
56 | 53 | ||
57 | /proc/acpi/processor/*/throttling (/sys/class/thermal/ | ||
58 | cooling_device*/*) | ||
59 | /proc/acpi/video/*/brightness (/sys/class/backlight/) | ||
60 | /proc/acpi/thermal_zone/*/* (/sys/class/thermal/) | ||
61 | This option has no effect on /proc/acpi/ files | 54 | This option has no effect on /proc/acpi/ files |
62 | and functions which do not yet exist in /sys. | 55 | and functions which do not yet exist in /sys. |
63 | 56 | ||
@@ -66,7 +59,6 @@ config ACPI_PROCFS | |||
66 | config ACPI_PROCFS_POWER | 59 | config ACPI_PROCFS_POWER |
67 | bool "Deprecated power /proc/acpi directories" | 60 | bool "Deprecated power /proc/acpi directories" |
68 | depends on PROC_FS | 61 | depends on PROC_FS |
69 | default y | ||
70 | help | 62 | help |
71 | For backwards compatibility, this option allows | 63 | For backwards compatibility, this option allows |
72 | deprecated power /proc/acpi/ directories to exist, even when | 64 | deprecated power /proc/acpi/ directories to exist, even when |
@@ -76,27 +68,11 @@ config ACPI_PROCFS_POWER | |||
76 | /proc/acpi/ac_adapter/* (sys/class/power_supply/*) | 68 | /proc/acpi/ac_adapter/* (sys/class/power_supply/*) |
77 | This option has no effect on /proc/acpi/ directories | 69 | This option has no effect on /proc/acpi/ directories |
78 | and functions, which do not yet exist in /sys | 70 | and functions, which do not yet exist in /sys |
71 | This option, together with the proc directories, will be | ||
72 | deleted in 2.6.39. | ||
79 | 73 | ||
80 | Say N to delete power /proc/acpi/ directories that have moved to /sys/ | 74 | Say N to delete power /proc/acpi/ directories that have moved to /sys/ |
81 | 75 | ||
82 | config ACPI_POWER_METER | ||
83 | tristate "ACPI 4.0 power meter" | ||
84 | depends on HWMON | ||
85 | help | ||
86 | This driver exposes ACPI 4.0 power meters as hardware monitoring | ||
87 | devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware | ||
88 | and a power meter. | ||
89 | |||
90 | To compile this driver as a module, choose M here: | ||
91 | the module will be called power-meter. | ||
92 | |||
93 | config ACPI_SYSFS_POWER | ||
94 | bool "Future power /sys interface" | ||
95 | select POWER_SUPPLY | ||
96 | default y | ||
97 | help | ||
98 | Say N to disable power /sys interface | ||
99 | |||
100 | config ACPI_EC_DEBUGFS | 76 | config ACPI_EC_DEBUGFS |
101 | tristate "EC read/write access through /sys/kernel/debug/ec" | 77 | tristate "EC read/write access through /sys/kernel/debug/ec" |
102 | default n | 78 | default n |
@@ -136,6 +112,7 @@ config ACPI_PROC_EVENT | |||
136 | config ACPI_AC | 112 | config ACPI_AC |
137 | tristate "AC Adapter" | 113 | tristate "AC Adapter" |
138 | depends on X86 | 114 | depends on X86 |
115 | select POWER_SUPPLY | ||
139 | default y | 116 | default y |
140 | help | 117 | help |
141 | This driver supports the AC Adapter object, which indicates | 118 | This driver supports the AC Adapter object, which indicates |
@@ -148,6 +125,7 @@ config ACPI_AC | |||
148 | config ACPI_BATTERY | 125 | config ACPI_BATTERY |
149 | tristate "Battery" | 126 | tristate "Battery" |
150 | depends on X86 | 127 | depends on X86 |
128 | select POWER_SUPPLY | ||
151 | default y | 129 | default y |
152 | help | 130 | help |
153 | This driver adds support for battery information through | 131 | This driver adds support for battery information through |
@@ -206,6 +184,7 @@ config ACPI_DOCK | |||
206 | config ACPI_PROCESSOR | 184 | config ACPI_PROCESSOR |
207 | tristate "Processor" | 185 | tristate "Processor" |
208 | select THERMAL | 186 | select THERMAL |
187 | select CPU_IDLE | ||
209 | default y | 188 | default y |
210 | help | 189 | help |
211 | This driver installs ACPI as the idle handler for Linux and uses | 190 | This driver installs ACPI as the idle handler for Linux and uses |
@@ -215,6 +194,17 @@ config ACPI_PROCESSOR | |||
215 | 194 | ||
216 | To compile this driver as a module, choose M here: | 195 | To compile this driver as a module, choose M here: |
217 | the module will be called processor. | 196 | the module will be called processor. |
197 | config ACPI_IPMI | ||
198 | tristate "IPMI" | ||
199 | depends on EXPERIMENTAL && IPMI_SI && IPMI_HANDLER | ||
200 | default n | ||
201 | help | ||
202 | This driver enables the ACPI to access the BMC controller. And it | ||
203 | uses the IPMI request/response message to communicate with BMC | ||
204 | controller, which can be found on on the server. | ||
205 | |||
206 | To compile this driver as a module, choose M here: | ||
207 | the module will be called as acpi_ipmi. | ||
218 | 208 | ||
219 | config ACPI_HOTPLUG_CPU | 209 | config ACPI_HOTPLUG_CPU |
220 | bool | 210 | bool |
@@ -316,7 +306,7 @@ config ACPI_PCI_SLOT | |||
316 | the module will be called pci_slot. | 306 | the module will be called pci_slot. |
317 | 307 | ||
318 | config X86_PM_TIMER | 308 | config X86_PM_TIMER |
319 | bool "Power Management Timer Support" if EMBEDDED | 309 | bool "Power Management Timer Support" if EXPERT |
320 | depends on X86 | 310 | depends on X86 |
321 | default y | 311 | default y |
322 | help | 312 | help |
@@ -364,6 +354,7 @@ config ACPI_HOTPLUG_MEMORY | |||
364 | config ACPI_SBS | 354 | config ACPI_SBS |
365 | tristate "Smart Battery System" | 355 | tristate "Smart Battery System" |
366 | depends on X86 | 356 | depends on X86 |
357 | select POWER_SUPPLY | ||
367 | help | 358 | help |
368 | This driver supports the Smart Battery System, another | 359 | This driver supports the Smart Battery System, another |
369 | type of access to battery information, found on some laptops. | 360 | type of access to battery information, found on some laptops. |
@@ -378,6 +369,21 @@ config ACPI_HED | |||
378 | which is used to report some hardware errors notified via | 369 | which is used to report some hardware errors notified via |
379 | SCI, mainly the corrected errors. | 370 | SCI, mainly the corrected errors. |
380 | 371 | ||
372 | config ACPI_CUSTOM_METHOD | ||
373 | tristate "Allow ACPI methods to be inserted/replaced at run time" | ||
374 | depends on DEBUG_FS | ||
375 | default n | ||
376 | help | ||
377 | This debug facility allows ACPI AML methods to me inserted and/or | ||
378 | replaced without rebooting the system. For details refer to: | ||
379 | Documentation/acpi/method-customizing.txt. | ||
380 | |||
381 | NOTE: This option is security sensitive, because it allows arbitrary | ||
382 | kernel memory to be written to by root (uid=0) users, allowing them | ||
383 | to bypass certain security measures (e.g. if root is not allowed to | ||
384 | load additional kernel modules after boot, this feature may be used | ||
385 | to override that restriction). | ||
386 | |||
381 | source "drivers/acpi/apei/Kconfig" | 387 | source "drivers/acpi/apei/Kconfig" |
382 | 388 | ||
383 | endif # ACPI | 389 | endif # ACPI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 3d031d02e54b..ecb26b4f29a0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -24,7 +24,7 @@ acpi-y += atomicio.o | |||
24 | # sleep related files | 24 | # sleep related files |
25 | acpi-y += wakeup.o | 25 | acpi-y += wakeup.o |
26 | acpi-y += sleep.o | 26 | acpi-y += sleep.o |
27 | acpi-$(CONFIG_ACPI_SLEEP) += proc.o | 27 | acpi-$(CONFIG_ACPI_SLEEP) += proc.o nvs.o |
28 | 28 | ||
29 | 29 | ||
30 | # | 30 | # |
@@ -59,9 +59,9 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o | |||
59 | obj-$(CONFIG_ACPI_BATTERY) += battery.o | 59 | obj-$(CONFIG_ACPI_BATTERY) += battery.o |
60 | obj-$(CONFIG_ACPI_SBS) += sbshc.o | 60 | obj-$(CONFIG_ACPI_SBS) += sbshc.o |
61 | obj-$(CONFIG_ACPI_SBS) += sbs.o | 61 | obj-$(CONFIG_ACPI_SBS) += sbs.o |
62 | obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o | ||
63 | obj-$(CONFIG_ACPI_HED) += hed.o | 62 | obj-$(CONFIG_ACPI_HED) += hed.o |
64 | obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o | 63 | obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o |
64 | obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o | ||
65 | 65 | ||
66 | # processor has its own "processor." module_param namespace | 66 | # processor has its own "processor." module_param namespace |
67 | processor-y := processor_driver.o processor_throttling.o | 67 | processor-y := processor_driver.o processor_throttling.o |
@@ -69,5 +69,6 @@ processor-y += processor_idle.o processor_thermal.o | |||
69 | processor-$(CONFIG_CPU_FREQ) += processor_perflib.o | 69 | processor-$(CONFIG_CPU_FREQ) += processor_perflib.o |
70 | 70 | ||
71 | obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o | 71 | obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o |
72 | obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o | ||
72 | 73 | ||
73 | obj-$(CONFIG_ACPI_APEI) += apei/ | 74 | obj-$(CONFIG_ACPI_APEI) += apei/ |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 56205a0b85df..58c3f74bd84c 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -32,9 +32,7 @@ | |||
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | #endif | 34 | #endif |
35 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
36 | #include <linux/power_supply.h> | 35 | #include <linux/power_supply.h> |
37 | #endif | ||
38 | #include <acpi/acpi_bus.h> | 36 | #include <acpi/acpi_bus.h> |
39 | #include <acpi/acpi_drivers.h> | 37 | #include <acpi/acpi_drivers.h> |
40 | 38 | ||
@@ -86,9 +84,7 @@ static struct acpi_driver acpi_ac_driver = { | |||
86 | }; | 84 | }; |
87 | 85 | ||
88 | struct acpi_ac { | 86 | struct acpi_ac { |
89 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
90 | struct power_supply charger; | 87 | struct power_supply charger; |
91 | #endif | ||
92 | struct acpi_device * device; | 88 | struct acpi_device * device; |
93 | unsigned long long state; | 89 | unsigned long long state; |
94 | }; | 90 | }; |
@@ -104,26 +100,7 @@ static const struct file_operations acpi_ac_fops = { | |||
104 | .release = single_release, | 100 | .release = single_release, |
105 | }; | 101 | }; |
106 | #endif | 102 | #endif |
107 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
108 | static int get_ac_property(struct power_supply *psy, | ||
109 | enum power_supply_property psp, | ||
110 | union power_supply_propval *val) | ||
111 | { | ||
112 | struct acpi_ac *ac = to_acpi_ac(psy); | ||
113 | switch (psp) { | ||
114 | case POWER_SUPPLY_PROP_ONLINE: | ||
115 | val->intval = ac->state; | ||
116 | break; | ||
117 | default: | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | return 0; | ||
121 | } | ||
122 | 103 | ||
123 | static enum power_supply_property ac_props[] = { | ||
124 | POWER_SUPPLY_PROP_ONLINE, | ||
125 | }; | ||
126 | #endif | ||
127 | /* -------------------------------------------------------------------------- | 104 | /* -------------------------------------------------------------------------- |
128 | AC Adapter Management | 105 | AC Adapter Management |
129 | -------------------------------------------------------------------------- */ | 106 | -------------------------------------------------------------------------- */ |
@@ -146,6 +123,35 @@ static int acpi_ac_get_state(struct acpi_ac *ac) | |||
146 | return 0; | 123 | return 0; |
147 | } | 124 | } |
148 | 125 | ||
126 | /* -------------------------------------------------------------------------- | ||
127 | sysfs I/F | ||
128 | -------------------------------------------------------------------------- */ | ||
129 | static int get_ac_property(struct power_supply *psy, | ||
130 | enum power_supply_property psp, | ||
131 | union power_supply_propval *val) | ||
132 | { | ||
133 | struct acpi_ac *ac = to_acpi_ac(psy); | ||
134 | |||
135 | if (!ac) | ||
136 | return -ENODEV; | ||
137 | |||
138 | if (acpi_ac_get_state(ac)) | ||
139 | return -ENODEV; | ||
140 | |||
141 | switch (psp) { | ||
142 | case POWER_SUPPLY_PROP_ONLINE: | ||
143 | val->intval = ac->state; | ||
144 | break; | ||
145 | default: | ||
146 | return -EINVAL; | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static enum power_supply_property ac_props[] = { | ||
152 | POWER_SUPPLY_PROP_ONLINE, | ||
153 | }; | ||
154 | |||
149 | #ifdef CONFIG_ACPI_PROCFS_POWER | 155 | #ifdef CONFIG_ACPI_PROCFS_POWER |
150 | /* -------------------------------------------------------------------------- | 156 | /* -------------------------------------------------------------------------- |
151 | FS Interface (/proc) | 157 | FS Interface (/proc) |
@@ -191,7 +197,8 @@ static int acpi_ac_add_fs(struct acpi_device *device) | |||
191 | { | 197 | { |
192 | struct proc_dir_entry *entry = NULL; | 198 | struct proc_dir_entry *entry = NULL; |
193 | 199 | ||
194 | 200 | printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," | |
201 | " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); | ||
195 | if (!acpi_device_dir(device)) { | 202 | if (!acpi_device_dir(device)) { |
196 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 203 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), |
197 | acpi_ac_dir); | 204 | acpi_ac_dir); |
@@ -247,9 +254,7 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) | |||
247 | dev_name(&device->dev), event, | 254 | dev_name(&device->dev), event, |
248 | (u32) ac->state); | 255 | (u32) ac->state); |
249 | acpi_notifier_call_chain(device, event, (u32) ac->state); | 256 | acpi_notifier_call_chain(device, event, (u32) ac->state); |
250 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
251 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | 257 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); |
252 | #endif | ||
253 | } | 258 | } |
254 | 259 | ||
255 | return; | 260 | return; |
@@ -282,14 +287,12 @@ static int acpi_ac_add(struct acpi_device *device) | |||
282 | #endif | 287 | #endif |
283 | if (result) | 288 | if (result) |
284 | goto end; | 289 | goto end; |
285 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
286 | ac->charger.name = acpi_device_bid(device); | 290 | ac->charger.name = acpi_device_bid(device); |
287 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; | 291 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; |
288 | ac->charger.properties = ac_props; | 292 | ac->charger.properties = ac_props; |
289 | ac->charger.num_properties = ARRAY_SIZE(ac_props); | 293 | ac->charger.num_properties = ARRAY_SIZE(ac_props); |
290 | ac->charger.get_property = get_ac_property; | 294 | ac->charger.get_property = get_ac_property; |
291 | power_supply_register(&ac->device->dev, &ac->charger); | 295 | power_supply_register(&ac->device->dev, &ac->charger); |
292 | #endif | ||
293 | 296 | ||
294 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | 297 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", |
295 | acpi_device_name(device), acpi_device_bid(device), | 298 | acpi_device_name(device), acpi_device_bid(device), |
@@ -316,10 +319,8 @@ static int acpi_ac_resume(struct acpi_device *device) | |||
316 | old_state = ac->state; | 319 | old_state = ac->state; |
317 | if (acpi_ac_get_state(ac)) | 320 | if (acpi_ac_get_state(ac)) |
318 | return 0; | 321 | return 0; |
319 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
320 | if (old_state != ac->state) | 322 | if (old_state != ac->state) |
321 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | 323 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); |
322 | #endif | ||
323 | return 0; | 324 | return 0; |
324 | } | 325 | } |
325 | 326 | ||
@@ -333,10 +334,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type) | |||
333 | 334 | ||
334 | ac = acpi_driver_data(device); | 335 | ac = acpi_driver_data(device); |
335 | 336 | ||
336 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
337 | if (ac->charger.dev) | 337 | if (ac->charger.dev) |
338 | power_supply_unregister(&ac->charger); | 338 | power_supply_unregister(&ac->charger); |
339 | #endif | ||
340 | #ifdef CONFIG_ACPI_PROCFS_POWER | 339 | #ifdef CONFIG_ACPI_PROCFS_POWER |
341 | acpi_ac_remove_fs(device); | 340 | acpi_ac_remove_fs(device); |
342 | #endif | 341 | #endif |
diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c new file mode 100644 index 000000000000..f40acef80269 --- /dev/null +++ b/drivers/acpi/acpi_ipmi.c | |||
@@ -0,0 +1,525 @@ | |||
1 | /* | ||
2 | * acpi_ipmi.c - ACPI IPMI opregion | ||
3 | * | ||
4 | * Copyright (C) 2010 Intel Corporation | ||
5 | * Copyright (C) 2010 Zhao Yakui <yakui.zhao@intel.com> | ||
6 | * | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
12 | * your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
22 | * | ||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/list.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <acpi/acpi_bus.h> | ||
38 | #include <acpi/acpi_drivers.h> | ||
39 | #include <linux/ipmi.h> | ||
40 | #include <linux/device.h> | ||
41 | #include <linux/pnp.h> | ||
42 | |||
43 | MODULE_AUTHOR("Zhao Yakui"); | ||
44 | MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); | ||
45 | MODULE_LICENSE("GPL"); | ||
46 | |||
47 | #define IPMI_FLAGS_HANDLER_INSTALL 0 | ||
48 | |||
49 | #define ACPI_IPMI_OK 0 | ||
50 | #define ACPI_IPMI_TIMEOUT 0x10 | ||
51 | #define ACPI_IPMI_UNKNOWN 0x07 | ||
52 | /* the IPMI timeout is 5s */ | ||
53 | #define IPMI_TIMEOUT (5 * HZ) | ||
54 | |||
55 | struct acpi_ipmi_device { | ||
56 | /* the device list attached to driver_data.ipmi_devices */ | ||
57 | struct list_head head; | ||
58 | /* the IPMI request message list */ | ||
59 | struct list_head tx_msg_list; | ||
60 | struct mutex tx_msg_lock; | ||
61 | acpi_handle handle; | ||
62 | struct pnp_dev *pnp_dev; | ||
63 | ipmi_user_t user_interface; | ||
64 | int ipmi_ifnum; /* IPMI interface number */ | ||
65 | long curr_msgid; | ||
66 | unsigned long flags; | ||
67 | struct ipmi_smi_info smi_data; | ||
68 | }; | ||
69 | |||
70 | struct ipmi_driver_data { | ||
71 | struct list_head ipmi_devices; | ||
72 | struct ipmi_smi_watcher bmc_events; | ||
73 | struct ipmi_user_hndl ipmi_hndlrs; | ||
74 | struct mutex ipmi_lock; | ||
75 | }; | ||
76 | |||
77 | struct acpi_ipmi_msg { | ||
78 | struct list_head head; | ||
79 | /* | ||
80 | * General speaking the addr type should be SI_ADDR_TYPE. And | ||
81 | * the addr channel should be BMC. | ||
82 | * In fact it can also be IPMB type. But we will have to | ||
83 | * parse it from the Netfn command buffer. It is so complex | ||
84 | * that it is skipped. | ||
85 | */ | ||
86 | struct ipmi_addr addr; | ||
87 | long tx_msgid; | ||
88 | /* it is used to track whether the IPMI message is finished */ | ||
89 | struct completion tx_complete; | ||
90 | struct kernel_ipmi_msg tx_message; | ||
91 | int msg_done; | ||
92 | /* tx data . And copy it from ACPI object buffer */ | ||
93 | u8 tx_data[64]; | ||
94 | int tx_len; | ||
95 | u8 rx_data[64]; | ||
96 | int rx_len; | ||
97 | struct acpi_ipmi_device *device; | ||
98 | }; | ||
99 | |||
100 | /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */ | ||
101 | struct acpi_ipmi_buffer { | ||
102 | u8 status; | ||
103 | u8 length; | ||
104 | u8 data[64]; | ||
105 | }; | ||
106 | |||
107 | static void ipmi_register_bmc(int iface, struct device *dev); | ||
108 | static void ipmi_bmc_gone(int iface); | ||
109 | static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); | ||
110 | static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device); | ||
111 | static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device); | ||
112 | |||
113 | static struct ipmi_driver_data driver_data = { | ||
114 | .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices), | ||
115 | .bmc_events = { | ||
116 | .owner = THIS_MODULE, | ||
117 | .new_smi = ipmi_register_bmc, | ||
118 | .smi_gone = ipmi_bmc_gone, | ||
119 | }, | ||
120 | .ipmi_hndlrs = { | ||
121 | .ipmi_recv_hndl = ipmi_msg_handler, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) | ||
126 | { | ||
127 | struct acpi_ipmi_msg *ipmi_msg; | ||
128 | struct pnp_dev *pnp_dev = ipmi->pnp_dev; | ||
129 | |||
130 | ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL); | ||
131 | if (!ipmi_msg) { | ||
132 | dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n"); | ||
133 | return NULL; | ||
134 | } | ||
135 | init_completion(&ipmi_msg->tx_complete); | ||
136 | INIT_LIST_HEAD(&ipmi_msg->head); | ||
137 | ipmi_msg->device = ipmi; | ||
138 | return ipmi_msg; | ||
139 | } | ||
140 | |||
141 | #define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) | ||
142 | #define IPMI_OP_RGN_CMD(offset) (offset & 0xff) | ||
143 | static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, | ||
144 | acpi_physical_address address, | ||
145 | acpi_integer *value) | ||
146 | { | ||
147 | struct kernel_ipmi_msg *msg; | ||
148 | struct acpi_ipmi_buffer *buffer; | ||
149 | struct acpi_ipmi_device *device; | ||
150 | |||
151 | msg = &tx_msg->tx_message; | ||
152 | /* | ||
153 | * IPMI network function and command are encoded in the address | ||
154 | * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3. | ||
155 | */ | ||
156 | msg->netfn = IPMI_OP_RGN_NETFN(address); | ||
157 | msg->cmd = IPMI_OP_RGN_CMD(address); | ||
158 | msg->data = tx_msg->tx_data; | ||
159 | /* | ||
160 | * value is the parameter passed by the IPMI opregion space handler. | ||
161 | * It points to the IPMI request message buffer | ||
162 | */ | ||
163 | buffer = (struct acpi_ipmi_buffer *)value; | ||
164 | /* copy the tx message data */ | ||
165 | msg->data_len = buffer->length; | ||
166 | memcpy(tx_msg->tx_data, buffer->data, msg->data_len); | ||
167 | /* | ||
168 | * now the default type is SYSTEM_INTERFACE and channel type is BMC. | ||
169 | * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE, | ||
170 | * the addr type should be changed to IPMB. Then we will have to parse | ||
171 | * the IPMI request message buffer to get the IPMB address. | ||
172 | * If so, please fix me. | ||
173 | */ | ||
174 | tx_msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; | ||
175 | tx_msg->addr.channel = IPMI_BMC_CHANNEL; | ||
176 | tx_msg->addr.data[0] = 0; | ||
177 | |||
178 | /* Get the msgid */ | ||
179 | device = tx_msg->device; | ||
180 | mutex_lock(&device->tx_msg_lock); | ||
181 | device->curr_msgid++; | ||
182 | tx_msg->tx_msgid = device->curr_msgid; | ||
183 | mutex_unlock(&device->tx_msg_lock); | ||
184 | } | ||
185 | |||
186 | static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, | ||
187 | acpi_integer *value, int rem_time) | ||
188 | { | ||
189 | struct acpi_ipmi_buffer *buffer; | ||
190 | |||
191 | /* | ||
192 | * value is also used as output parameter. It represents the response | ||
193 | * IPMI message returned by IPMI command. | ||
194 | */ | ||
195 | buffer = (struct acpi_ipmi_buffer *)value; | ||
196 | if (!rem_time && !msg->msg_done) { | ||
197 | buffer->status = ACPI_IPMI_TIMEOUT; | ||
198 | return; | ||
199 | } | ||
200 | /* | ||
201 | * If the flag of msg_done is not set or the recv length is zero, it | ||
202 | * means that the IPMI command is not executed correctly. | ||
203 | * The status code will be ACPI_IPMI_UNKNOWN. | ||
204 | */ | ||
205 | if (!msg->msg_done || !msg->rx_len) { | ||
206 | buffer->status = ACPI_IPMI_UNKNOWN; | ||
207 | return; | ||
208 | } | ||
209 | /* | ||
210 | * If the IPMI response message is obtained correctly, the status code | ||
211 | * will be ACPI_IPMI_OK | ||
212 | */ | ||
213 | buffer->status = ACPI_IPMI_OK; | ||
214 | buffer->length = msg->rx_len; | ||
215 | memcpy(buffer->data, msg->rx_data, msg->rx_len); | ||
216 | } | ||
217 | |||
218 | static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) | ||
219 | { | ||
220 | struct acpi_ipmi_msg *tx_msg, *temp; | ||
221 | int count = HZ / 10; | ||
222 | struct pnp_dev *pnp_dev = ipmi->pnp_dev; | ||
223 | |||
224 | list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { | ||
225 | /* wake up the sleep thread on the Tx msg */ | ||
226 | complete(&tx_msg->tx_complete); | ||
227 | } | ||
228 | |||
229 | /* wait for about 100ms to flush the tx message list */ | ||
230 | while (count--) { | ||
231 | if (list_empty(&ipmi->tx_msg_list)) | ||
232 | break; | ||
233 | schedule_timeout(1); | ||
234 | } | ||
235 | if (!list_empty(&ipmi->tx_msg_list)) | ||
236 | dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n"); | ||
237 | } | ||
238 | |||
239 | static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) | ||
240 | { | ||
241 | struct acpi_ipmi_device *ipmi_device = user_msg_data; | ||
242 | int msg_found = 0; | ||
243 | struct acpi_ipmi_msg *tx_msg; | ||
244 | struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; | ||
245 | |||
246 | if (msg->user != ipmi_device->user_interface) { | ||
247 | dev_warn(&pnp_dev->dev, "Unexpected response is returned. " | ||
248 | "returned user %p, expected user %p\n", | ||
249 | msg->user, ipmi_device->user_interface); | ||
250 | ipmi_free_recv_msg(msg); | ||
251 | return; | ||
252 | } | ||
253 | mutex_lock(&ipmi_device->tx_msg_lock); | ||
254 | list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { | ||
255 | if (msg->msgid == tx_msg->tx_msgid) { | ||
256 | msg_found = 1; | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | mutex_unlock(&ipmi_device->tx_msg_lock); | ||
262 | if (!msg_found) { | ||
263 | dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " | ||
264 | "returned.\n", msg->msgid); | ||
265 | ipmi_free_recv_msg(msg); | ||
266 | return; | ||
267 | } | ||
268 | |||
269 | if (msg->msg.data_len) { | ||
270 | /* copy the response data to Rx_data buffer */ | ||
271 | memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len); | ||
272 | tx_msg->rx_len = msg->msg.data_len; | ||
273 | tx_msg->msg_done = 1; | ||
274 | } | ||
275 | complete(&tx_msg->tx_complete); | ||
276 | ipmi_free_recv_msg(msg); | ||
277 | }; | ||
278 | |||
279 | static void ipmi_register_bmc(int iface, struct device *dev) | ||
280 | { | ||
281 | struct acpi_ipmi_device *ipmi_device, *temp; | ||
282 | struct pnp_dev *pnp_dev; | ||
283 | ipmi_user_t user; | ||
284 | int err; | ||
285 | struct ipmi_smi_info smi_data; | ||
286 | acpi_handle handle; | ||
287 | |||
288 | err = ipmi_get_smi_info(iface, &smi_data); | ||
289 | |||
290 | if (err) | ||
291 | return; | ||
292 | |||
293 | if (smi_data.addr_src != SI_ACPI) { | ||
294 | put_device(smi_data.dev); | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | handle = smi_data.addr_info.acpi_info.acpi_handle; | ||
299 | |||
300 | mutex_lock(&driver_data.ipmi_lock); | ||
301 | list_for_each_entry(temp, &driver_data.ipmi_devices, head) { | ||
302 | /* | ||
303 | * if the corresponding ACPI handle is already added | ||
304 | * to the device list, don't add it again. | ||
305 | */ | ||
306 | if (temp->handle == handle) | ||
307 | goto out; | ||
308 | } | ||
309 | |||
310 | ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL); | ||
311 | |||
312 | if (!ipmi_device) | ||
313 | goto out; | ||
314 | |||
315 | pnp_dev = to_pnp_dev(smi_data.dev); | ||
316 | ipmi_device->handle = handle; | ||
317 | ipmi_device->pnp_dev = pnp_dev; | ||
318 | |||
319 | err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, | ||
320 | ipmi_device, &user); | ||
321 | if (err) { | ||
322 | dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); | ||
323 | kfree(ipmi_device); | ||
324 | goto out; | ||
325 | } | ||
326 | acpi_add_ipmi_device(ipmi_device); | ||
327 | ipmi_device->user_interface = user; | ||
328 | ipmi_device->ipmi_ifnum = iface; | ||
329 | mutex_unlock(&driver_data.ipmi_lock); | ||
330 | memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info)); | ||
331 | return; | ||
332 | |||
333 | out: | ||
334 | mutex_unlock(&driver_data.ipmi_lock); | ||
335 | put_device(smi_data.dev); | ||
336 | return; | ||
337 | } | ||
338 | |||
339 | static void ipmi_bmc_gone(int iface) | ||
340 | { | ||
341 | struct acpi_ipmi_device *ipmi_device, *temp; | ||
342 | |||
343 | mutex_lock(&driver_data.ipmi_lock); | ||
344 | list_for_each_entry_safe(ipmi_device, temp, | ||
345 | &driver_data.ipmi_devices, head) { | ||
346 | if (ipmi_device->ipmi_ifnum != iface) | ||
347 | continue; | ||
348 | |||
349 | acpi_remove_ipmi_device(ipmi_device); | ||
350 | put_device(ipmi_device->smi_data.dev); | ||
351 | kfree(ipmi_device); | ||
352 | break; | ||
353 | } | ||
354 | mutex_unlock(&driver_data.ipmi_lock); | ||
355 | } | ||
356 | /* -------------------------------------------------------------------------- | ||
357 | * Address Space Management | ||
358 | * -------------------------------------------------------------------------- */ | ||
359 | /* | ||
360 | * This is the IPMI opregion space handler. | ||
361 | * @function: indicates the read/write. In fact as the IPMI message is driven | ||
362 | * by command, only write is meaningful. | ||
363 | * @address: This contains the netfn/command of IPMI request message. | ||
364 | * @bits : not used. | ||
365 | * @value : it is an in/out parameter. It points to the IPMI message buffer. | ||
366 | * Before the IPMI message is sent, it represents the actual request | ||
367 | * IPMI message. After the IPMI message is finished, it represents | ||
368 | * the response IPMI message returned by IPMI command. | ||
369 | * @handler_context: IPMI device context. | ||
370 | */ | ||
371 | |||
372 | static acpi_status | ||
373 | acpi_ipmi_space_handler(u32 function, acpi_physical_address address, | ||
374 | u32 bits, acpi_integer *value, | ||
375 | void *handler_context, void *region_context) | ||
376 | { | ||
377 | struct acpi_ipmi_msg *tx_msg; | ||
378 | struct acpi_ipmi_device *ipmi_device = handler_context; | ||
379 | int err, rem_time; | ||
380 | acpi_status status; | ||
381 | /* | ||
382 | * IPMI opregion message. | ||
383 | * IPMI message is firstly written to the BMC and system software | ||
384 | * can get the respsonse. So it is unmeaningful for the read access | ||
385 | * of IPMI opregion. | ||
386 | */ | ||
387 | if ((function & ACPI_IO_MASK) == ACPI_READ) | ||
388 | return AE_TYPE; | ||
389 | |||
390 | if (!ipmi_device->user_interface) | ||
391 | return AE_NOT_EXIST; | ||
392 | |||
393 | tx_msg = acpi_alloc_ipmi_msg(ipmi_device); | ||
394 | if (!tx_msg) | ||
395 | return AE_NO_MEMORY; | ||
396 | |||
397 | acpi_format_ipmi_msg(tx_msg, address, value); | ||
398 | mutex_lock(&ipmi_device->tx_msg_lock); | ||
399 | list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); | ||
400 | mutex_unlock(&ipmi_device->tx_msg_lock); | ||
401 | err = ipmi_request_settime(ipmi_device->user_interface, | ||
402 | &tx_msg->addr, | ||
403 | tx_msg->tx_msgid, | ||
404 | &tx_msg->tx_message, | ||
405 | NULL, 0, 0, 0); | ||
406 | if (err) { | ||
407 | status = AE_ERROR; | ||
408 | goto end_label; | ||
409 | } | ||
410 | rem_time = wait_for_completion_timeout(&tx_msg->tx_complete, | ||
411 | IPMI_TIMEOUT); | ||
412 | acpi_format_ipmi_response(tx_msg, value, rem_time); | ||
413 | status = AE_OK; | ||
414 | |||
415 | end_label: | ||
416 | mutex_lock(&ipmi_device->tx_msg_lock); | ||
417 | list_del(&tx_msg->head); | ||
418 | mutex_unlock(&ipmi_device->tx_msg_lock); | ||
419 | kfree(tx_msg); | ||
420 | return status; | ||
421 | } | ||
422 | |||
423 | static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi) | ||
424 | { | ||
425 | if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags)) | ||
426 | return; | ||
427 | |||
428 | acpi_remove_address_space_handler(ipmi->handle, | ||
429 | ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); | ||
430 | |||
431 | clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags); | ||
432 | } | ||
433 | |||
434 | static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) | ||
435 | { | ||
436 | acpi_status status; | ||
437 | |||
438 | if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags)) | ||
439 | return 0; | ||
440 | |||
441 | status = acpi_install_address_space_handler(ipmi->handle, | ||
442 | ACPI_ADR_SPACE_IPMI, | ||
443 | &acpi_ipmi_space_handler, | ||
444 | NULL, ipmi); | ||
445 | if (ACPI_FAILURE(status)) { | ||
446 | struct pnp_dev *pnp_dev = ipmi->pnp_dev; | ||
447 | dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space " | ||
448 | "handle\n"); | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags); | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device) | ||
456 | { | ||
457 | |||
458 | INIT_LIST_HEAD(&ipmi_device->head); | ||
459 | |||
460 | mutex_init(&ipmi_device->tx_msg_lock); | ||
461 | INIT_LIST_HEAD(&ipmi_device->tx_msg_list); | ||
462 | ipmi_install_space_handler(ipmi_device); | ||
463 | |||
464 | list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); | ||
465 | } | ||
466 | |||
467 | static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device) | ||
468 | { | ||
469 | /* | ||
470 | * If the IPMI user interface is created, it should be | ||
471 | * destroyed. | ||
472 | */ | ||
473 | if (ipmi_device->user_interface) { | ||
474 | ipmi_destroy_user(ipmi_device->user_interface); | ||
475 | ipmi_device->user_interface = NULL; | ||
476 | } | ||
477 | /* flush the Tx_msg list */ | ||
478 | if (!list_empty(&ipmi_device->tx_msg_list)) | ||
479 | ipmi_flush_tx_msg(ipmi_device); | ||
480 | |||
481 | list_del(&ipmi_device->head); | ||
482 | ipmi_remove_space_handler(ipmi_device); | ||
483 | } | ||
484 | |||
485 | static int __init acpi_ipmi_init(void) | ||
486 | { | ||
487 | int result = 0; | ||
488 | |||
489 | if (acpi_disabled) | ||
490 | return result; | ||
491 | |||
492 | mutex_init(&driver_data.ipmi_lock); | ||
493 | |||
494 | result = ipmi_smi_watcher_register(&driver_data.bmc_events); | ||
495 | |||
496 | return result; | ||
497 | } | ||
498 | |||
499 | static void __exit acpi_ipmi_exit(void) | ||
500 | { | ||
501 | struct acpi_ipmi_device *ipmi_device, *temp; | ||
502 | |||
503 | if (acpi_disabled) | ||
504 | return; | ||
505 | |||
506 | ipmi_smi_watcher_unregister(&driver_data.bmc_events); | ||
507 | |||
508 | /* | ||
509 | * When one smi_watcher is unregistered, it is only deleted | ||
510 | * from the smi_watcher list. But the smi_gone callback function | ||
511 | * is not called. So explicitly uninstall the ACPI IPMI oregion | ||
512 | * handler and free it. | ||
513 | */ | ||
514 | mutex_lock(&driver_data.ipmi_lock); | ||
515 | list_for_each_entry_safe(ipmi_device, temp, | ||
516 | &driver_data.ipmi_devices, head) { | ||
517 | acpi_remove_ipmi_device(ipmi_device); | ||
518 | put_device(ipmi_device->smi_data.dev); | ||
519 | kfree(ipmi_device); | ||
520 | } | ||
521 | mutex_unlock(&driver_data.ipmi_lock); | ||
522 | } | ||
523 | |||
524 | module_init(acpi_ipmi_init); | ||
525 | module_exit(acpi_ipmi_exit); | ||
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 6b115f6c4313..a43fa1a57d57 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -30,18 +30,13 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> |
32 | #include <acpi/acpi_drivers.h> | 32 | #include <acpi/acpi_drivers.h> |
33 | #include <asm/mwait.h> | ||
33 | 34 | ||
34 | #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" | 35 | #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" |
35 | #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" | 36 | #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" |
36 | #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 | 37 | #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 |
37 | static DEFINE_MUTEX(isolated_cpus_lock); | 38 | static DEFINE_MUTEX(isolated_cpus_lock); |
38 | 39 | ||
39 | #define MWAIT_SUBSTATE_MASK (0xf) | ||
40 | #define MWAIT_CSTATE_MASK (0xf) | ||
41 | #define MWAIT_SUBSTATE_SIZE (4) | ||
42 | #define CPUID_MWAIT_LEAF (5) | ||
43 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) | ||
44 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) | ||
45 | static unsigned long power_saving_mwait_eax; | 40 | static unsigned long power_saving_mwait_eax; |
46 | 41 | ||
47 | static unsigned char tsc_detected_unstable; | 42 | static unsigned char tsc_detected_unstable; |
@@ -303,7 +298,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev, | |||
303 | static ssize_t acpi_pad_rrtime_show(struct device *dev, | 298 | static ssize_t acpi_pad_rrtime_show(struct device *dev, |
304 | struct device_attribute *attr, char *buf) | 299 | struct device_attribute *attr, char *buf) |
305 | { | 300 | { |
306 | return scnprintf(buf, PAGE_SIZE, "%d", round_robin_time); | 301 | return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time); |
307 | } | 302 | } |
308 | static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR, | 303 | static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR, |
309 | acpi_pad_rrtime_show, | 304 | acpi_pad_rrtime_show, |
@@ -326,7 +321,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev, | |||
326 | static ssize_t acpi_pad_idlepct_show(struct device *dev, | 321 | static ssize_t acpi_pad_idlepct_show(struct device *dev, |
327 | struct device_attribute *attr, char *buf) | 322 | struct device_attribute *attr, char *buf) |
328 | { | 323 | { |
329 | return scnprintf(buf, PAGE_SIZE, "%d", idle_pct); | 324 | return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct); |
330 | } | 325 | } |
331 | static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR, | 326 | static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR, |
332 | acpi_pad_idlepct_show, | 327 | acpi_pad_idlepct_show, |
@@ -347,8 +342,11 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev, | |||
347 | static ssize_t acpi_pad_idlecpus_show(struct device *dev, | 342 | static ssize_t acpi_pad_idlecpus_show(struct device *dev, |
348 | struct device_attribute *attr, char *buf) | 343 | struct device_attribute *attr, char *buf) |
349 | { | 344 | { |
350 | return cpumask_scnprintf(buf, PAGE_SIZE, | 345 | int n = 0; |
351 | to_cpumask(pad_busy_cpus_bits)); | 346 | n = cpumask_scnprintf(buf, PAGE_SIZE-2, to_cpumask(pad_busy_cpus_bits)); |
347 | buf[n++] = '\n'; | ||
348 | buf[n] = '\0'; | ||
349 | return n; | ||
352 | } | 350 | } |
353 | static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR, | 351 | static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR, |
354 | acpi_pad_idlecpus_show, | 352 | acpi_pad_idlecpus_show, |
@@ -458,7 +456,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event, | |||
458 | dev_name(&device->dev), event, 0); | 456 | dev_name(&device->dev), event, 0); |
459 | break; | 457 | break; |
460 | default: | 458 | default: |
461 | printk(KERN_WARNING"Unsupported event [0x%x]\n", event); | 459 | printk(KERN_WARNING "Unsupported event [0x%x]\n", event); |
462 | break; | 460 | break; |
463 | } | 461 | } |
464 | } | 462 | } |
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index d93cc06f4bf8..301bd2d388ad 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile | |||
@@ -10,18 +10,18 @@ obj-y += acpi.o | |||
10 | 10 | ||
11 | acpi-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ | 11 | acpi-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ |
12 | dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \ | 12 | dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \ |
13 | dsinit.o | 13 | dsinit.o dsargs.o dscontrol.o dswload2.o |
14 | 14 | ||
15 | acpi-y += evevent.o evregion.o evsci.o evxfevnt.o \ | 15 | acpi-y += evevent.o evregion.o evsci.o evxfevnt.o \ |
16 | evmisc.o evrgnini.o evxface.o evxfregn.o \ | 16 | evmisc.o evrgnini.o evxface.o evxfregn.o \ |
17 | evgpe.o evgpeblk.o evgpeinit.o evgpeutil.o | 17 | evgpe.o evgpeblk.o evgpeinit.o evgpeutil.o evxfgpe.o evglock.o |
18 | 18 | ||
19 | acpi-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ | 19 | acpi-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ |
20 | exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\ | 20 | exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\ |
21 | excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ | 21 | excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ |
22 | exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o exdebug.o | 22 | exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o exdebug.o |
23 | 23 | ||
24 | acpi-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o | 24 | acpi-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o hwpci.o |
25 | 25 | ||
26 | acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o | 26 | acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o |
27 | 27 | ||
@@ -44,4 +44,5 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o | |||
44 | 44 | ||
45 | acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ | 45 | acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ |
46 | utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ | 46 | utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ |
47 | utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o | 47 | utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \ |
48 | utosi.o utxferror.o utdecode.o | ||
diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h index 3e50c74ed4a1..e0ba17f0a7c8 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h index b17d8de9f6ff..bc533dde16c4 100644 --- a/drivers/acpi/acpica/acconfig.h +++ b/drivers/acpi/acpica/acconfig.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -187,7 +187,6 @@ | |||
187 | 187 | ||
188 | /* Operation regions */ | 188 | /* Operation regions */ |
189 | 189 | ||
190 | #define ACPI_NUM_PREDEFINED_REGIONS 9 | ||
191 | #define ACPI_USER_REGION_BEGIN 0x80 | 190 | #define ACPI_USER_REGION_BEGIN 0x80 |
192 | 191 | ||
193 | /* Maximum space_ids for Operation Regions */ | 192 | /* Maximum space_ids for Operation Regions */ |
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 48faf3eba9fb..eb0b1f8dee6d 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -105,6 +105,8 @@ void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg); | |||
105 | acpi_status | 105 | acpi_status |
106 | acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); | 106 | acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); |
107 | 107 | ||
108 | void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg); | ||
109 | |||
108 | acpi_status acpi_db_find_name_in_namespace(char *name_arg); | 110 | acpi_status acpi_db_find_name_in_namespace(char *name_arg); |
109 | 111 | ||
110 | void acpi_db_set_scope(char *name); | 112 | void acpi_db_set_scope(char *name); |
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index 894a0ff2a946..2d1b7ffa377a 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,7 +48,7 @@ | |||
48 | #define NAMEOF_ARG_NTE "__A0" | 48 | #define NAMEOF_ARG_NTE "__A0" |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * dsopcode - support for late evaluation | 51 | * dsargs - execution of dynamic arguments for static objects |
52 | */ | 52 | */ |
53 | acpi_status | 53 | acpi_status |
54 | acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc); | 54 | acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc); |
@@ -62,6 +62,20 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc); | |||
62 | 62 | ||
63 | acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc); | 63 | acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc); |
64 | 64 | ||
65 | /* | ||
66 | * dscontrol - support for execution control opcodes | ||
67 | */ | ||
68 | acpi_status | ||
69 | acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, | ||
70 | union acpi_parse_object *op); | ||
71 | |||
72 | acpi_status | ||
73 | acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, | ||
74 | union acpi_parse_object *op); | ||
75 | |||
76 | /* | ||
77 | * dsopcode - support for late operand evaluation | ||
78 | */ | ||
65 | acpi_status | 79 | acpi_status |
66 | acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, | 80 | acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, |
67 | union acpi_parse_object *op); | 81 | union acpi_parse_object *op); |
@@ -86,17 +100,6 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | |||
86 | acpi_status acpi_ds_initialize_region(acpi_handle obj_handle); | 100 | acpi_status acpi_ds_initialize_region(acpi_handle obj_handle); |
87 | 101 | ||
88 | /* | 102 | /* |
89 | * dsctrl - Parser/Interpreter interface, control stack routines | ||
90 | */ | ||
91 | acpi_status | ||
92 | acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, | ||
93 | union acpi_parse_object *op); | ||
94 | |||
95 | acpi_status | ||
96 | acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, | ||
97 | union acpi_parse_object *op); | ||
98 | |||
99 | /* | ||
100 | * dsexec - Parser/Interpreter interface, method execution callbacks | 103 | * dsexec - Parser/Interpreter interface, method execution callbacks |
101 | */ | 104 | */ |
102 | acpi_status | 105 | acpi_status |
@@ -136,23 +139,26 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
136 | struct acpi_walk_state *walk_state); | 139 | struct acpi_walk_state *walk_state); |
137 | 140 | ||
138 | /* | 141 | /* |
139 | * dsload - Parser/Interpreter interface, namespace load callbacks | 142 | * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks |
140 | */ | 143 | */ |
141 | acpi_status | 144 | acpi_status |
145 | acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); | ||
146 | |||
147 | acpi_status | ||
142 | acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, | 148 | acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, |
143 | union acpi_parse_object **out_op); | 149 | union acpi_parse_object **out_op); |
144 | 150 | ||
145 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state); | 151 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state); |
146 | 152 | ||
153 | /* | ||
154 | * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks | ||
155 | */ | ||
147 | acpi_status | 156 | acpi_status |
148 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | 157 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, |
149 | union acpi_parse_object **out_op); | 158 | union acpi_parse_object **out_op); |
150 | 159 | ||
151 | acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state); | 160 | acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state); |
152 | 161 | ||
153 | acpi_status | ||
154 | acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); | ||
155 | |||
156 | /* | 162 | /* |
157 | * dsmthdat - method data (locals/args) | 163 | * dsmthdat - method data (locals/args) |
158 | */ | 164 | */ |
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 36867cd70eac..bea3b4899183 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -51,8 +51,6 @@ acpi_status acpi_ev_initialize_events(void); | |||
51 | 51 | ||
52 | acpi_status acpi_ev_install_xrupt_handlers(void); | 52 | acpi_status acpi_ev_install_xrupt_handlers(void); |
53 | 53 | ||
54 | acpi_status acpi_ev_install_fadt_gpes(void); | ||
55 | |||
56 | u32 acpi_ev_fixed_event_detect(void); | 54 | u32 acpi_ev_fixed_event_detect(void); |
57 | 55 | ||
58 | /* | 56 | /* |
@@ -60,12 +58,6 @@ u32 acpi_ev_fixed_event_detect(void); | |||
60 | */ | 58 | */ |
61 | u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node); | 59 | u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node); |
62 | 60 | ||
63 | acpi_status acpi_ev_acquire_global_lock(u16 timeout); | ||
64 | |||
65 | acpi_status acpi_ev_release_global_lock(void); | ||
66 | |||
67 | acpi_status acpi_ev_init_global_lock_handler(void); | ||
68 | |||
69 | u32 acpi_ev_get_gpe_number_index(u32 gpe_number); | 61 | u32 acpi_ev_get_gpe_number_index(u32 gpe_number); |
70 | 62 | ||
71 | acpi_status | 63 | acpi_status |
@@ -73,6 +65,17 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node, | |||
73 | u32 notify_value); | 65 | u32 notify_value); |
74 | 66 | ||
75 | /* | 67 | /* |
68 | * evglock - Global Lock support | ||
69 | */ | ||
70 | acpi_status acpi_ev_init_global_lock_handler(void); | ||
71 | |||
72 | acpi_status acpi_ev_acquire_global_lock(u16 timeout); | ||
73 | |||
74 | acpi_status acpi_ev_release_global_lock(void); | ||
75 | |||
76 | acpi_status acpi_ev_remove_global_lock_handler(void); | ||
77 | |||
78 | /* | ||
76 | * evgpe - Low-level GPE support | 79 | * evgpe - Low-level GPE support |
77 | */ | 80 | */ |
78 | u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); | 81 | u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); |
@@ -82,9 +85,9 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info); | |||
82 | 85 | ||
83 | acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); | 86 | acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); |
84 | 87 | ||
85 | acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); | 88 | acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); |
86 | 89 | ||
87 | acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); | 90 | acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); |
88 | 91 | ||
89 | struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, | 92 | struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, |
90 | u32 gpe_number); | 93 | u32 gpe_number); |
@@ -93,6 +96,8 @@ struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number, | |||
93 | struct acpi_gpe_block_info | 96 | struct acpi_gpe_block_info |
94 | *gpe_block); | 97 | *gpe_block); |
95 | 98 | ||
99 | acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); | ||
100 | |||
96 | /* | 101 | /* |
97 | * evgpeblk - Upper-level GPE block support | 102 | * evgpeblk - Upper-level GPE block support |
98 | */ | 103 | */ |
@@ -105,13 +110,15 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
105 | struct acpi_gpe_block_info **return_gpe_block); | 110 | struct acpi_gpe_block_info **return_gpe_block); |
106 | 111 | ||
107 | acpi_status | 112 | acpi_status |
108 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | 113 | acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, |
109 | struct acpi_gpe_block_info *gpe_block); | 114 | struct acpi_gpe_block_info *gpe_block, |
115 | void *context); | ||
110 | 116 | ||
111 | acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); | 117 | acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); |
112 | 118 | ||
113 | u32 | 119 | u32 |
114 | acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, | 120 | acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, |
121 | struct acpi_gpe_event_info *gpe_event_info, | ||
115 | u32 gpe_number); | 122 | u32 gpe_number); |
116 | 123 | ||
117 | /* | 124 | /* |
@@ -125,10 +132,6 @@ acpi_status | |||
125 | acpi_ev_match_gpe_method(acpi_handle obj_handle, | 132 | acpi_ev_match_gpe_method(acpi_handle obj_handle, |
126 | u32 level, void *context, void **return_value); | 133 | u32 level, void *context, void **return_value); |
127 | 134 | ||
128 | acpi_status | ||
129 | acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | ||
130 | u32 level, void *context, void **return_value); | ||
131 | |||
132 | /* | 135 | /* |
133 | * evgpeutil - GPE utilities | 136 | * evgpeutil - GPE utilities |
134 | */ | 137 | */ |
@@ -137,6 +140,10 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context); | |||
137 | 140 | ||
138 | u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info); | 141 | u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info); |
139 | 142 | ||
143 | acpi_status | ||
144 | acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | ||
145 | struct acpi_gpe_block_info *gpe_block, void *context); | ||
146 | |||
140 | struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number); | 147 | struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number); |
141 | 148 | ||
142 | acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt); | 149 | acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt); |
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 1d192142c691..73863d86f022 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -132,6 +132,7 @@ struct acpi_table_fadt acpi_gbl_FADT; | |||
132 | u32 acpi_current_gpe_count; | 132 | u32 acpi_current_gpe_count; |
133 | u32 acpi_gbl_trace_flags; | 133 | u32 acpi_gbl_trace_flags; |
134 | acpi_name acpi_gbl_trace_method_name; | 134 | acpi_name acpi_gbl_trace_method_name; |
135 | u8 acpi_gbl_system_awake_and_running; | ||
135 | 136 | ||
136 | #endif | 137 | #endif |
137 | 138 | ||
@@ -145,6 +146,9 @@ acpi_name acpi_gbl_trace_method_name; | |||
145 | 146 | ||
146 | extern u32 acpi_gbl_nesting_level; | 147 | extern u32 acpi_gbl_nesting_level; |
147 | 148 | ||
149 | ACPI_EXTERN u32 acpi_gpe_count; | ||
150 | ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; | ||
151 | |||
148 | /* Support for dynamic control method tracing mechanism */ | 152 | /* Support for dynamic control method tracing mechanism */ |
149 | 153 | ||
150 | ACPI_EXTERN u32 acpi_gbl_original_dbg_level; | 154 | ACPI_EXTERN u32 acpi_gbl_original_dbg_level; |
@@ -187,6 +191,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; | |||
187 | ACPI_EXTERN u8 acpi_gbl_integer_byte_width; | 191 | ACPI_EXTERN u8 acpi_gbl_integer_byte_width; |
188 | ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; | 192 | ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; |
189 | 193 | ||
194 | /* Mutex for _OSI support */ | ||
195 | |||
196 | ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; | ||
197 | |||
190 | /* Reader/Writer lock is used for namespace walk and dynamic table unload */ | 198 | /* Reader/Writer lock is used for namespace walk and dynamic table unload */ |
191 | 199 | ||
192 | ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; | 200 | ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; |
@@ -206,22 +214,23 @@ ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; | |||
206 | 214 | ||
207 | /* | 215 | /* |
208 | * Global lock mutex is an actual AML mutex object | 216 | * Global lock mutex is an actual AML mutex object |
209 | * Global lock semaphore works in conjunction with the HW global lock | 217 | * Global lock semaphore works in conjunction with the actual global lock |
218 | * Global lock spinlock is used for "pending" handshake | ||
210 | */ | 219 | */ |
211 | ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; | 220 | ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; |
212 | ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; | 221 | ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; |
222 | ACPI_EXTERN acpi_spinlock acpi_gbl_global_lock_pending_lock; | ||
213 | ACPI_EXTERN u16 acpi_gbl_global_lock_handle; | 223 | ACPI_EXTERN u16 acpi_gbl_global_lock_handle; |
214 | ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; | 224 | ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; |
215 | ACPI_EXTERN u8 acpi_gbl_global_lock_present; | 225 | ACPI_EXTERN u8 acpi_gbl_global_lock_present; |
226 | ACPI_EXTERN u8 acpi_gbl_global_lock_pending; | ||
216 | 227 | ||
217 | /* | 228 | /* |
218 | * Spinlocks are used for interfaces that can be possibly called at | 229 | * Spinlocks are used for interfaces that can be possibly called at |
219 | * interrupt level | 230 | * interrupt level |
220 | */ | 231 | */ |
221 | ACPI_EXTERN spinlock_t _acpi_gbl_gpe_lock; /* For GPE data structs and registers */ | 232 | ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */ |
222 | ACPI_EXTERN spinlock_t _acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ | 233 | ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ |
223 | #define acpi_gbl_gpe_lock &_acpi_gbl_gpe_lock | ||
224 | #define acpi_gbl_hardware_lock &_acpi_gbl_hardware_lock | ||
225 | 234 | ||
226 | /***************************************************************************** | 235 | /***************************************************************************** |
227 | * | 236 | * |
@@ -255,6 +264,7 @@ ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; | |||
255 | ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; | 264 | ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; |
256 | ACPI_EXTERN void *acpi_gbl_table_handler_context; | 265 | ACPI_EXTERN void *acpi_gbl_table_handler_context; |
257 | ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; | 266 | ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; |
267 | ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; | ||
258 | 268 | ||
259 | /* Owner ID support */ | 269 | /* Owner ID support */ |
260 | 270 | ||
@@ -262,6 +272,10 @@ ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; | |||
262 | ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; | 272 | ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; |
263 | ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; | 273 | ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; |
264 | 274 | ||
275 | /* Initialization sequencing */ | ||
276 | |||
277 | ACPI_EXTERN u8 acpi_gbl_reg_methods_executed; | ||
278 | |||
265 | /* Misc */ | 279 | /* Misc */ |
266 | 280 | ||
267 | ACPI_EXTERN u32 acpi_gbl_original_mode; | 281 | ACPI_EXTERN u32 acpi_gbl_original_mode; |
@@ -273,8 +287,8 @@ ACPI_EXTERN u8 acpi_gbl_debugger_configuration; | |||
273 | ACPI_EXTERN u8 acpi_gbl_step_to_next_call; | 287 | ACPI_EXTERN u8 acpi_gbl_step_to_next_call; |
274 | ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; | 288 | ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; |
275 | ACPI_EXTERN u8 acpi_gbl_events_initialized; | 289 | ACPI_EXTERN u8 acpi_gbl_events_initialized; |
276 | ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; | ||
277 | ACPI_EXTERN u8 acpi_gbl_osi_data; | 290 | ACPI_EXTERN u8 acpi_gbl_osi_data; |
291 | ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces; | ||
278 | 292 | ||
279 | #ifndef DEFINE_ACPI_GLOBALS | 293 | #ifndef DEFINE_ACPI_GLOBALS |
280 | 294 | ||
@@ -364,6 +378,9 @@ ACPI_EXTERN struct acpi_fixed_event_handler | |||
364 | ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; | 378 | ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; |
365 | ACPI_EXTERN struct acpi_gpe_block_info | 379 | ACPI_EXTERN struct acpi_gpe_block_info |
366 | *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; | 380 | *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; |
381 | ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; | ||
382 | ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler; | ||
383 | ACPI_EXTERN void *acpi_gbl_global_event_handler_context; | ||
367 | 384 | ||
368 | /***************************************************************************** | 385 | /***************************************************************************** |
369 | * | 386 | * |
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 120b3af56596..e7213beaafc7 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -94,7 +94,7 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, | |||
94 | struct acpi_gpe_register_info *gpe_register_info); | 94 | struct acpi_gpe_register_info *gpe_register_info); |
95 | 95 | ||
96 | acpi_status | 96 | acpi_status |
97 | acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action); | 97 | acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action); |
98 | 98 | ||
99 | acpi_status | 99 | acpi_status |
100 | acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | 100 | acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, |
@@ -121,6 +121,13 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
121 | struct acpi_gpe_block_info *gpe_block, | 121 | struct acpi_gpe_block_info *gpe_block, |
122 | void *context); | 122 | void *context); |
123 | 123 | ||
124 | /* | ||
125 | * hwpci - PCI configuration support | ||
126 | */ | ||
127 | acpi_status | ||
128 | acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, | ||
129 | acpi_handle root_pci_device, acpi_handle pci_region); | ||
130 | |||
124 | #ifdef ACPI_FUTURE_USAGE | 131 | #ifdef ACPI_FUTURE_USAGE |
125 | /* | 132 | /* |
126 | * hwtimer - ACPI Timer prototypes | 133 | * hwtimer - ACPI Timer prototypes |
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index 049e203bd621..3731e1c34b83 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 7dad9160f209..c7f743ca395b 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -89,25 +89,6 @@ union acpi_parse_object; | |||
89 | #define ACPI_MAX_MUTEX 7 | 89 | #define ACPI_MAX_MUTEX 7 |
90 | #define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 | 90 | #define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 |
91 | 91 | ||
92 | #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) | ||
93 | #ifdef DEFINE_ACPI_GLOBALS | ||
94 | |||
95 | /* Debug names for the mutexes above */ | ||
96 | |||
97 | static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { | ||
98 | "ACPI_MTX_Interpreter", | ||
99 | "ACPI_MTX_Namespace", | ||
100 | "ACPI_MTX_Tables", | ||
101 | "ACPI_MTX_Events", | ||
102 | "ACPI_MTX_Caches", | ||
103 | "ACPI_MTX_Memory", | ||
104 | "ACPI_MTX_CommandComplete", | ||
105 | "ACPI_MTX_CommandReady" | ||
106 | }; | ||
107 | |||
108 | #endif | ||
109 | #endif | ||
110 | |||
111 | /* Lock structure for reader/writer interfaces */ | 92 | /* Lock structure for reader/writer interfaces */ |
112 | 93 | ||
113 | struct acpi_rw_lock { | 94 | struct acpi_rw_lock { |
@@ -408,16 +389,23 @@ struct acpi_predefined_data { | |||
408 | 389 | ||
409 | /* Dispatch info for each GPE -- either a method or handler, cannot be both */ | 390 | /* Dispatch info for each GPE -- either a method or handler, cannot be both */ |
410 | 391 | ||
411 | struct acpi_handler_info { | 392 | struct acpi_gpe_handler_info { |
412 | acpi_event_handler address; /* Address of handler, if any */ | 393 | acpi_gpe_handler address; /* Address of handler, if any */ |
413 | void *context; /* Context to be passed to handler */ | 394 | void *context; /* Context to be passed to handler */ |
414 | struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ | 395 | struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ |
415 | u8 orig_flags; /* Original misc info about this GPE */ | 396 | u8 original_flags; /* Original (pre-handler) GPE info */ |
397 | u8 originally_enabled; /* True if GPE was originally enabled */ | ||
398 | }; | ||
399 | |||
400 | struct acpi_gpe_notify_object { | ||
401 | struct acpi_namespace_node *node; | ||
402 | struct acpi_gpe_notify_object *next; | ||
416 | }; | 403 | }; |
417 | 404 | ||
418 | union acpi_gpe_dispatch_info { | 405 | union acpi_gpe_dispatch_info { |
419 | struct acpi_namespace_node *method_node; /* Method node for this GPE level */ | 406 | struct acpi_namespace_node *method_node; /* Method node for this GPE level */ |
420 | struct acpi_handler_info *handler; | 407 | struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ |
408 | struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */ | ||
421 | }; | 409 | }; |
422 | 410 | ||
423 | /* | 411 | /* |
@@ -457,6 +445,7 @@ struct acpi_gpe_block_info { | |||
457 | u32 register_count; /* Number of register pairs in block */ | 445 | u32 register_count; /* Number of register pairs in block */ |
458 | u16 gpe_count; /* Number of individual GPEs in block */ | 446 | u16 gpe_count; /* Number of individual GPEs in block */ |
459 | u8 block_base_number; /* Base GPE number for this block */ | 447 | u8 block_base_number; /* Base GPE number for this block */ |
448 | u8 initialized; /* TRUE if this block is initialized */ | ||
460 | }; | 449 | }; |
461 | 450 | ||
462 | /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ | 451 | /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ |
@@ -473,7 +462,6 @@ struct acpi_gpe_walk_info { | |||
473 | struct acpi_gpe_block_info *gpe_block; | 462 | struct acpi_gpe_block_info *gpe_block; |
474 | u16 count; | 463 | u16 count; |
475 | acpi_owner_id owner_id; | 464 | acpi_owner_id owner_id; |
476 | u8 enable_this_gpe; | ||
477 | u8 execute_by_owner_id; | 465 | u8 execute_by_owner_id; |
478 | }; | 466 | }; |
479 | 467 | ||
@@ -854,7 +842,7 @@ struct acpi_bit_register_info { | |||
854 | ACPI_BITMASK_POWER_BUTTON_STATUS | \ | 842 | ACPI_BITMASK_POWER_BUTTON_STATUS | \ |
855 | ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ | 843 | ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ |
856 | ACPI_BITMASK_RT_CLOCK_STATUS | \ | 844 | ACPI_BITMASK_RT_CLOCK_STATUS | \ |
857 | ACPI_BITMASK_PCIEXP_WAKE_DISABLE | \ | 845 | ACPI_BITMASK_PCIEXP_WAKE_STATUS | \ |
858 | ACPI_BITMASK_WAKE_STATUS) | 846 | ACPI_BITMASK_WAKE_STATUS) |
859 | 847 | ||
860 | #define ACPI_BITMASK_TIMER_ENABLE 0x0001 | 848 | #define ACPI_BITMASK_TIMER_ENABLE 0x0001 |
@@ -909,15 +897,21 @@ struct acpi_bit_register_info { | |||
909 | #define ACPI_OSI_WIN_VISTA 0x07 | 897 | #define ACPI_OSI_WIN_VISTA 0x07 |
910 | #define ACPI_OSI_WINSRV_2008 0x08 | 898 | #define ACPI_OSI_WINSRV_2008 0x08 |
911 | #define ACPI_OSI_WIN_VISTA_SP1 0x09 | 899 | #define ACPI_OSI_WIN_VISTA_SP1 0x09 |
912 | #define ACPI_OSI_WIN_7 0x0A | 900 | #define ACPI_OSI_WIN_VISTA_SP2 0x0A |
901 | #define ACPI_OSI_WIN_7 0x0B | ||
913 | 902 | ||
914 | #define ACPI_ALWAYS_ILLEGAL 0x00 | 903 | #define ACPI_ALWAYS_ILLEGAL 0x00 |
915 | 904 | ||
916 | struct acpi_interface_info { | 905 | struct acpi_interface_info { |
917 | char *name; | 906 | char *name; |
907 | struct acpi_interface_info *next; | ||
908 | u8 flags; | ||
918 | u8 value; | 909 | u8 value; |
919 | }; | 910 | }; |
920 | 911 | ||
912 | #define ACPI_OSI_INVALID 0x01 | ||
913 | #define ACPI_OSI_DYNAMIC 0x02 | ||
914 | |||
921 | struct acpi_port_info { | 915 | struct acpi_port_info { |
922 | char *name; | 916 | char *name; |
923 | u16 start; | 917 | u16 start; |
@@ -997,7 +991,7 @@ struct acpi_port_info { | |||
997 | struct acpi_db_method_info { | 991 | struct acpi_db_method_info { |
998 | acpi_handle main_thread_gate; | 992 | acpi_handle main_thread_gate; |
999 | acpi_handle thread_complete_gate; | 993 | acpi_handle thread_complete_gate; |
1000 | u32 *threads; | 994 | acpi_thread_id *threads; |
1001 | u32 num_threads; | 995 | u32 num_threads; |
1002 | u32 num_created; | 996 | u32 num_created; |
1003 | u32 num_completed; | 997 | u32 num_completed; |
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 9894929a2abb..b7491ee1fba6 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -338,8 +338,8 @@ | |||
338 | * the plist contains a set of parens to allow variable-length lists. | 338 | * the plist contains a set of parens to allow variable-length lists. |
339 | * These macros are used for both the debug and non-debug versions of the code. | 339 | * These macros are used for both the debug and non-debug versions of the code. |
340 | */ | 340 | */ |
341 | #define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e); | 341 | #define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e); |
342 | #define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e); | 342 | #define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e); |
343 | #define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist | 343 | #define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist |
344 | #define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist | 344 | #define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist |
345 | 345 | ||
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 9f60ff002203..79a598c67fe3 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -339,18 +339,6 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node); | |||
339 | u32 acpi_ns_local(acpi_object_type type); | 339 | u32 acpi_ns_local(acpi_object_type type); |
340 | 340 | ||
341 | void | 341 | void |
342 | acpi_ns_report_error(const char *module_name, | ||
343 | u32 line_number, | ||
344 | const char *internal_name, acpi_status lookup_status); | ||
345 | |||
346 | void | ||
347 | acpi_ns_report_method_error(const char *module_name, | ||
348 | u32 line_number, | ||
349 | const char *message, | ||
350 | struct acpi_namespace_node *node, | ||
351 | const char *path, acpi_status lookup_status); | ||
352 | |||
353 | void | ||
354 | acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg); | 342 | acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg); |
355 | 343 | ||
356 | acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info); | 344 | acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info); |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 54857fa87aaf..1055769f2f01 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -93,12 +93,10 @@ | |||
93 | 93 | ||
94 | #define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ | 94 | #define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ |
95 | #define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ | 95 | #define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ |
96 | #define AOPOBJ_DATA_VALID 0x04 /* Object is intialized and data is valid */ | 96 | #define AOPOBJ_DATA_VALID 0x04 /* Object is initialized and data is valid */ |
97 | #define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ | 97 | #define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ |
98 | #define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ | 98 | #define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ |
99 | #define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ | 99 | #define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ |
100 | #define AOPOBJ_MODULE_LEVEL 0x40 /* Method is actually module-level code */ | ||
101 | #define AOPOBJ_MODIFIED_NAMESPACE 0x80 /* Method modified the namespace */ | ||
102 | 100 | ||
103 | /****************************************************************************** | 101 | /****************************************************************************** |
104 | * | 102 | * |
@@ -175,7 +173,7 @@ struct acpi_object_region { | |||
175 | }; | 173 | }; |
176 | 174 | ||
177 | struct acpi_object_method { | 175 | struct acpi_object_method { |
178 | ACPI_OBJECT_COMMON_HEADER u8 method_flags; | 176 | ACPI_OBJECT_COMMON_HEADER u8 info_flags; |
179 | u8 param_count; | 177 | u8 param_count; |
180 | u8 sync_level; | 178 | u8 sync_level; |
181 | union acpi_operand_object *mutex; | 179 | union acpi_operand_object *mutex; |
@@ -183,13 +181,21 @@ struct acpi_object_method { | |||
183 | union { | 181 | union { |
184 | ACPI_INTERNAL_METHOD implementation; | 182 | ACPI_INTERNAL_METHOD implementation; |
185 | union acpi_operand_object *handler; | 183 | union acpi_operand_object *handler; |
186 | } extra; | 184 | } dispatch; |
187 | 185 | ||
188 | u32 aml_length; | 186 | u32 aml_length; |
189 | u8 thread_count; | 187 | u8 thread_count; |
190 | acpi_owner_id owner_id; | 188 | acpi_owner_id owner_id; |
191 | }; | 189 | }; |
192 | 190 | ||
191 | /* Flags for info_flags field above */ | ||
192 | |||
193 | #define ACPI_METHOD_MODULE_LEVEL 0x01 /* Method is actually module-level code */ | ||
194 | #define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */ | ||
195 | #define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */ | ||
196 | #define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */ | ||
197 | #define ACPI_METHOD_MODIFIED_NAMESPACE 0x10 /* Method modified the namespace */ | ||
198 | |||
193 | /****************************************************************************** | 199 | /****************************************************************************** |
194 | * | 200 | * |
195 | * Objects that can be notified. All share a common notify_info area. | 201 | * Objects that can be notified. All share a common notify_info area. |
@@ -248,7 +254,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; | |||
248 | u32 base_byte_offset; /* Byte offset within containing object */\ | 254 | u32 base_byte_offset; /* Byte offset within containing object */\ |
249 | u32 value; /* Value to store into the Bank or Index register */\ | 255 | u32 value; /* Value to store into the Bank or Index register */\ |
250 | u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ | 256 | u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ |
251 | u8 access_bit_width; /* Read/Write size in bits (8-64) */ | 257 | |
252 | 258 | ||
253 | struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ | 259 | struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ |
254 | ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ | 260 | ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ |
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index 8c15ff43f42b..bb2ccfad7376 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index d0bb0fd3e57a..5ea1e06afa20 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 10998d369ad0..94e73c97cf85 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index 528bcbaf4ce7..f08b55b7f3a0 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index 6e5dd97949fe..1623b245dde2 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 62a576e34361..967f08124eba 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 35df755251ce..99c140d8e348 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -312,8 +312,6 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list); | |||
312 | /* | 312 | /* |
313 | * uteval - object evaluation | 313 | * uteval - object evaluation |
314 | */ | 314 | */ |
315 | acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state); | ||
316 | |||
317 | acpi_status | 315 | acpi_status |
318 | acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | 316 | acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, |
319 | char *path, | 317 | char *path, |
@@ -395,6 +393,21 @@ acpi_status | |||
395 | acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length); | 393 | acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length); |
396 | 394 | ||
397 | /* | 395 | /* |
396 | * utosi - Support for the _OSI predefined control method | ||
397 | */ | ||
398 | acpi_status acpi_ut_initialize_interfaces(void); | ||
399 | |||
400 | void acpi_ut_interface_terminate(void); | ||
401 | |||
402 | acpi_status acpi_ut_install_interface(acpi_string interface_name); | ||
403 | |||
404 | acpi_status acpi_ut_remove_interface(acpi_string interface_name); | ||
405 | |||
406 | struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name); | ||
407 | |||
408 | acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state); | ||
409 | |||
410 | /* | ||
398 | * utstate - Generic state creation/cache routines | 411 | * utstate - Generic state creation/cache routines |
399 | */ | 412 | */ |
400 | void | 413 | void |
@@ -473,17 +486,6 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position); | |||
473 | 486 | ||
474 | acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer); | 487 | acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer); |
475 | 488 | ||
476 | void ACPI_INTERNAL_VAR_XFACE | ||
477 | acpi_ut_predefined_warning(const char *module_name, | ||
478 | u32 line_number, | ||
479 | char *pathname, | ||
480 | u8 node_flags, const char *format, ...); | ||
481 | |||
482 | void ACPI_INTERNAL_VAR_XFACE | ||
483 | acpi_ut_predefined_info(const char *module_name, | ||
484 | u32 line_number, | ||
485 | char *pathname, u8 node_flags, const char *format, ...); | ||
486 | |||
487 | /* Values for Base above (16=Hex, 10=Decimal) */ | 489 | /* Values for Base above (16=Hex, 10=Decimal) */ |
488 | 490 | ||
489 | #define ACPI_ANY_BASE 0 | 491 | #define ACPI_ANY_BASE 0 |
@@ -574,6 +576,32 @@ acpi_status | |||
574 | acpi_ut_create_list(char *list_name, | 576 | acpi_ut_create_list(char *list_name, |
575 | u16 object_size, struct acpi_memory_list **return_cache); | 577 | u16 object_size, struct acpi_memory_list **return_cache); |
576 | 578 | ||
577 | #endif | 579 | #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ |
580 | |||
581 | /* | ||
582 | * utxferror - various error/warning output functions | ||
583 | */ | ||
584 | void ACPI_INTERNAL_VAR_XFACE | ||
585 | acpi_ut_predefined_warning(const char *module_name, | ||
586 | u32 line_number, | ||
587 | char *pathname, | ||
588 | u8 node_flags, const char *format, ...); | ||
589 | |||
590 | void ACPI_INTERNAL_VAR_XFACE | ||
591 | acpi_ut_predefined_info(const char *module_name, | ||
592 | u32 line_number, | ||
593 | char *pathname, u8 node_flags, const char *format, ...); | ||
594 | |||
595 | void | ||
596 | acpi_ut_namespace_error(const char *module_name, | ||
597 | u32 line_number, | ||
598 | const char *internal_name, acpi_status lookup_status); | ||
599 | |||
600 | void | ||
601 | acpi_ut_method_error(const char *module_name, | ||
602 | u32 line_number, | ||
603 | const char *message, | ||
604 | struct acpi_namespace_node *node, | ||
605 | const char *path, acpi_status lookup_status); | ||
578 | 606 | ||
579 | #endif /* _ACUTILS_H */ | 607 | #endif /* _ACUTILS_H */ |
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index 1f484ba228fc..1077f17859ed 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h | |||
@@ -7,7 +7,7 @@ | |||
7 | *****************************************************************************/ | 7 | *****************************************************************************/ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Copyright (C) 2000 - 2010, Intel Corp. | 10 | * Copyright (C) 2000 - 2011, Intel Corp. |
11 | * All rights reserved. | 11 | * All rights reserved. |
12 | * | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without |
@@ -394,21 +394,6 @@ | |||
394 | #define AML_CLASS_METHOD_CALL 0x09 | 394 | #define AML_CLASS_METHOD_CALL 0x09 |
395 | #define AML_CLASS_UNKNOWN 0x0A | 395 | #define AML_CLASS_UNKNOWN 0x0A |
396 | 396 | ||
397 | /* Predefined Operation Region space_iDs */ | ||
398 | |||
399 | typedef enum { | ||
400 | REGION_MEMORY = 0, | ||
401 | REGION_IO, | ||
402 | REGION_PCI_CONFIG, | ||
403 | REGION_EC, | ||
404 | REGION_SMBUS, | ||
405 | REGION_CMOS, | ||
406 | REGION_PCI_BAR, | ||
407 | REGION_IPMI, | ||
408 | REGION_DATA_TABLE, /* Internal use only */ | ||
409 | REGION_FIXED_HW = 0x7F | ||
410 | } AML_REGION_TYPES; | ||
411 | |||
412 | /* Comparison operation codes for match_op operator */ | 397 | /* Comparison operation codes for match_op operator */ |
413 | 398 | ||
414 | typedef enum { | 399 | typedef enum { |
@@ -480,16 +465,10 @@ typedef enum { | |||
480 | AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D | 465 | AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D |
481 | } AML_ACCESS_ATTRIBUTE; | 466 | } AML_ACCESS_ATTRIBUTE; |
482 | 467 | ||
483 | /* Bit fields in method_flags byte */ | 468 | /* Bit fields in the AML method_flags byte */ |
484 | 469 | ||
485 | #define AML_METHOD_ARG_COUNT 0x07 | 470 | #define AML_METHOD_ARG_COUNT 0x07 |
486 | #define AML_METHOD_SERIALIZED 0x08 | 471 | #define AML_METHOD_SERIALIZED 0x08 |
487 | #define AML_METHOD_SYNC_LEVEL 0xF0 | 472 | #define AML_METHOD_SYNC_LEVEL 0xF0 |
488 | 473 | ||
489 | /* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */ | ||
490 | |||
491 | #define AML_METHOD_INTERNAL_ONLY 0x01 | ||
492 | #define AML_METHOD_RESERVED1 0x02 | ||
493 | #define AML_METHOD_RESERVED2 0x04 | ||
494 | |||
495 | #endif /* __AMLCODE_H__ */ | 474 | #endif /* __AMLCODE_H__ */ |
diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index 0e5798fcbb19..59122cde247c 100644 --- a/drivers/acpi/acpica/amlresrc.h +++ b/drivers/acpi/acpica/amlresrc.h | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c new file mode 100644 index 000000000000..8c7b99728aa2 --- /dev/null +++ b/drivers/acpi/acpica/dsargs.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dsargs - Support for execution of dynamic arguments for static | ||
4 | * objects (regions, fields, buffer fields, etc.) | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include "accommon.h" | ||
47 | #include "acparser.h" | ||
48 | #include "amlcode.h" | ||
49 | #include "acdispat.h" | ||
50 | #include "acnamesp.h" | ||
51 | |||
52 | #define _COMPONENT ACPI_DISPATCHER | ||
53 | ACPI_MODULE_NAME("dsargs") | ||
54 | |||
55 | /* Local prototypes */ | ||
56 | static acpi_status | ||
57 | acpi_ds_execute_arguments(struct acpi_namespace_node *node, | ||
58 | struct acpi_namespace_node *scope_node, | ||
59 | u32 aml_length, u8 *aml_start); | ||
60 | |||
61 | /******************************************************************************* | ||
62 | * | ||
63 | * FUNCTION: acpi_ds_execute_arguments | ||
64 | * | ||
65 | * PARAMETERS: Node - Object NS node | ||
66 | * scope_node - Parent NS node | ||
67 | * aml_length - Length of executable AML | ||
68 | * aml_start - Pointer to the AML | ||
69 | * | ||
70 | * RETURN: Status. | ||
71 | * | ||
72 | * DESCRIPTION: Late (deferred) execution of region or field arguments | ||
73 | * | ||
74 | ******************************************************************************/ | ||
75 | |||
76 | static acpi_status | ||
77 | acpi_ds_execute_arguments(struct acpi_namespace_node *node, | ||
78 | struct acpi_namespace_node *scope_node, | ||
79 | u32 aml_length, u8 *aml_start) | ||
80 | { | ||
81 | acpi_status status; | ||
82 | union acpi_parse_object *op; | ||
83 | struct acpi_walk_state *walk_state; | ||
84 | |||
85 | ACPI_FUNCTION_TRACE(ds_execute_arguments); | ||
86 | |||
87 | /* Allocate a new parser op to be the root of the parsed tree */ | ||
88 | |||
89 | op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); | ||
90 | if (!op) { | ||
91 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
92 | } | ||
93 | |||
94 | /* Save the Node for use in acpi_ps_parse_aml */ | ||
95 | |||
96 | op->common.node = scope_node; | ||
97 | |||
98 | /* Create and initialize a new parser state */ | ||
99 | |||
100 | walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); | ||
101 | if (!walk_state) { | ||
102 | status = AE_NO_MEMORY; | ||
103 | goto cleanup; | ||
104 | } | ||
105 | |||
106 | status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, | ||
107 | aml_length, NULL, ACPI_IMODE_LOAD_PASS1); | ||
108 | if (ACPI_FAILURE(status)) { | ||
109 | acpi_ds_delete_walk_state(walk_state); | ||
110 | goto cleanup; | ||
111 | } | ||
112 | |||
113 | /* Mark this parse as a deferred opcode */ | ||
114 | |||
115 | walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; | ||
116 | walk_state->deferred_node = node; | ||
117 | |||
118 | /* Pass1: Parse the entire declaration */ | ||
119 | |||
120 | status = acpi_ps_parse_aml(walk_state); | ||
121 | if (ACPI_FAILURE(status)) { | ||
122 | goto cleanup; | ||
123 | } | ||
124 | |||
125 | /* Get and init the Op created above */ | ||
126 | |||
127 | op->common.node = node; | ||
128 | acpi_ps_delete_parse_tree(op); | ||
129 | |||
130 | /* Evaluate the deferred arguments */ | ||
131 | |||
132 | op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); | ||
133 | if (!op) { | ||
134 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
135 | } | ||
136 | |||
137 | op->common.node = scope_node; | ||
138 | |||
139 | /* Create and initialize a new parser state */ | ||
140 | |||
141 | walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); | ||
142 | if (!walk_state) { | ||
143 | status = AE_NO_MEMORY; | ||
144 | goto cleanup; | ||
145 | } | ||
146 | |||
147 | /* Execute the opcode and arguments */ | ||
148 | |||
149 | status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, | ||
150 | aml_length, NULL, ACPI_IMODE_EXECUTE); | ||
151 | if (ACPI_FAILURE(status)) { | ||
152 | acpi_ds_delete_walk_state(walk_state); | ||
153 | goto cleanup; | ||
154 | } | ||
155 | |||
156 | /* Mark this execution as a deferred opcode */ | ||
157 | |||
158 | walk_state->deferred_node = node; | ||
159 | status = acpi_ps_parse_aml(walk_state); | ||
160 | |||
161 | cleanup: | ||
162 | acpi_ps_delete_parse_tree(op); | ||
163 | return_ACPI_STATUS(status); | ||
164 | } | ||
165 | |||
166 | /******************************************************************************* | ||
167 | * | ||
168 | * FUNCTION: acpi_ds_get_buffer_field_arguments | ||
169 | * | ||
170 | * PARAMETERS: obj_desc - A valid buffer_field object | ||
171 | * | ||
172 | * RETURN: Status. | ||
173 | * | ||
174 | * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late | ||
175 | * evaluation of these field attributes. | ||
176 | * | ||
177 | ******************************************************************************/ | ||
178 | |||
179 | acpi_status | ||
180 | acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) | ||
181 | { | ||
182 | union acpi_operand_object *extra_desc; | ||
183 | struct acpi_namespace_node *node; | ||
184 | acpi_status status; | ||
185 | |||
186 | ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); | ||
187 | |||
188 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
189 | return_ACPI_STATUS(AE_OK); | ||
190 | } | ||
191 | |||
192 | /* Get the AML pointer (method object) and buffer_field node */ | ||
193 | |||
194 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
195 | node = obj_desc->buffer_field.node; | ||
196 | |||
197 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD, | ||
198 | node, NULL)); | ||
199 | |||
200 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", | ||
201 | acpi_ut_get_node_name(node))); | ||
202 | |||
203 | /* Execute the AML code for the term_arg arguments */ | ||
204 | |||
205 | status = acpi_ds_execute_arguments(node, node->parent, | ||
206 | extra_desc->extra.aml_length, | ||
207 | extra_desc->extra.aml_start); | ||
208 | return_ACPI_STATUS(status); | ||
209 | } | ||
210 | |||
211 | /******************************************************************************* | ||
212 | * | ||
213 | * FUNCTION: acpi_ds_get_bank_field_arguments | ||
214 | * | ||
215 | * PARAMETERS: obj_desc - A valid bank_field object | ||
216 | * | ||
217 | * RETURN: Status. | ||
218 | * | ||
219 | * DESCRIPTION: Get bank_field bank_value. This implements the late | ||
220 | * evaluation of these field attributes. | ||
221 | * | ||
222 | ******************************************************************************/ | ||
223 | |||
224 | acpi_status | ||
225 | acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) | ||
226 | { | ||
227 | union acpi_operand_object *extra_desc; | ||
228 | struct acpi_namespace_node *node; | ||
229 | acpi_status status; | ||
230 | |||
231 | ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); | ||
232 | |||
233 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
234 | return_ACPI_STATUS(AE_OK); | ||
235 | } | ||
236 | |||
237 | /* Get the AML pointer (method object) and bank_field node */ | ||
238 | |||
239 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
240 | node = obj_desc->bank_field.node; | ||
241 | |||
242 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
243 | (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); | ||
244 | |||
245 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", | ||
246 | acpi_ut_get_node_name(node))); | ||
247 | |||
248 | /* Execute the AML code for the term_arg arguments */ | ||
249 | |||
250 | status = acpi_ds_execute_arguments(node, node->parent, | ||
251 | extra_desc->extra.aml_length, | ||
252 | extra_desc->extra.aml_start); | ||
253 | return_ACPI_STATUS(status); | ||
254 | } | ||
255 | |||
256 | /******************************************************************************* | ||
257 | * | ||
258 | * FUNCTION: acpi_ds_get_buffer_arguments | ||
259 | * | ||
260 | * PARAMETERS: obj_desc - A valid Buffer object | ||
261 | * | ||
262 | * RETURN: Status. | ||
263 | * | ||
264 | * DESCRIPTION: Get Buffer length and initializer byte list. This implements | ||
265 | * the late evaluation of these attributes. | ||
266 | * | ||
267 | ******************************************************************************/ | ||
268 | |||
269 | acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) | ||
270 | { | ||
271 | struct acpi_namespace_node *node; | ||
272 | acpi_status status; | ||
273 | |||
274 | ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); | ||
275 | |||
276 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
277 | return_ACPI_STATUS(AE_OK); | ||
278 | } | ||
279 | |||
280 | /* Get the Buffer node */ | ||
281 | |||
282 | node = obj_desc->buffer.node; | ||
283 | if (!node) { | ||
284 | ACPI_ERROR((AE_INFO, | ||
285 | "No pointer back to namespace node in buffer object %p", | ||
286 | obj_desc)); | ||
287 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
288 | } | ||
289 | |||
290 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); | ||
291 | |||
292 | /* Execute the AML code for the term_arg arguments */ | ||
293 | |||
294 | status = acpi_ds_execute_arguments(node, node, | ||
295 | obj_desc->buffer.aml_length, | ||
296 | obj_desc->buffer.aml_start); | ||
297 | return_ACPI_STATUS(status); | ||
298 | } | ||
299 | |||
300 | /******************************************************************************* | ||
301 | * | ||
302 | * FUNCTION: acpi_ds_get_package_arguments | ||
303 | * | ||
304 | * PARAMETERS: obj_desc - A valid Package object | ||
305 | * | ||
306 | * RETURN: Status. | ||
307 | * | ||
308 | * DESCRIPTION: Get Package length and initializer byte list. This implements | ||
309 | * the late evaluation of these attributes. | ||
310 | * | ||
311 | ******************************************************************************/ | ||
312 | |||
313 | acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) | ||
314 | { | ||
315 | struct acpi_namespace_node *node; | ||
316 | acpi_status status; | ||
317 | |||
318 | ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); | ||
319 | |||
320 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
321 | return_ACPI_STATUS(AE_OK); | ||
322 | } | ||
323 | |||
324 | /* Get the Package node */ | ||
325 | |||
326 | node = obj_desc->package.node; | ||
327 | if (!node) { | ||
328 | ACPI_ERROR((AE_INFO, | ||
329 | "No pointer back to namespace node in package %p", | ||
330 | obj_desc)); | ||
331 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
332 | } | ||
333 | |||
334 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); | ||
335 | |||
336 | /* Execute the AML code for the term_arg arguments */ | ||
337 | |||
338 | status = acpi_ds_execute_arguments(node, node, | ||
339 | obj_desc->package.aml_length, | ||
340 | obj_desc->package.aml_start); | ||
341 | return_ACPI_STATUS(status); | ||
342 | } | ||
343 | |||
344 | /******************************************************************************* | ||
345 | * | ||
346 | * FUNCTION: acpi_ds_get_region_arguments | ||
347 | * | ||
348 | * PARAMETERS: obj_desc - A valid region object | ||
349 | * | ||
350 | * RETURN: Status. | ||
351 | * | ||
352 | * DESCRIPTION: Get region address and length. This implements the late | ||
353 | * evaluation of these region attributes. | ||
354 | * | ||
355 | ******************************************************************************/ | ||
356 | |||
357 | acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) | ||
358 | { | ||
359 | struct acpi_namespace_node *node; | ||
360 | acpi_status status; | ||
361 | union acpi_operand_object *extra_desc; | ||
362 | |||
363 | ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); | ||
364 | |||
365 | if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { | ||
366 | return_ACPI_STATUS(AE_OK); | ||
367 | } | ||
368 | |||
369 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
370 | if (!extra_desc) { | ||
371 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
372 | } | ||
373 | |||
374 | /* Get the Region node */ | ||
375 | |||
376 | node = obj_desc->region.node; | ||
377 | |||
378 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
379 | (ACPI_TYPE_REGION, node, NULL)); | ||
380 | |||
381 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", | ||
382 | acpi_ut_get_node_name(node), | ||
383 | extra_desc->extra.aml_start)); | ||
384 | |||
385 | /* Execute the argument AML */ | ||
386 | |||
387 | status = acpi_ds_execute_arguments(node, node->parent, | ||
388 | extra_desc->extra.aml_length, | ||
389 | extra_desc->extra.aml_start); | ||
390 | return_ACPI_STATUS(status); | ||
391 | } | ||
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c new file mode 100644 index 000000000000..26c49fff58da --- /dev/null +++ b/drivers/acpi/acpica/dscontrol.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dscontrol - Support for execution control opcodes - | ||
4 | * if/else/while/return | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include "accommon.h" | ||
47 | #include "amlcode.h" | ||
48 | #include "acdispat.h" | ||
49 | #include "acinterp.h" | ||
50 | |||
51 | #define _COMPONENT ACPI_DISPATCHER | ||
52 | ACPI_MODULE_NAME("dscontrol") | ||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ds_exec_begin_control_op | ||
57 | * | ||
58 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
59 | * Op - The control Op | ||
60 | * | ||
61 | * RETURN: Status | ||
62 | * | ||
63 | * DESCRIPTION: Handles all control ops encountered during control method | ||
64 | * execution. | ||
65 | * | ||
66 | ******************************************************************************/ | ||
67 | acpi_status | ||
68 | acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, | ||
69 | union acpi_parse_object *op) | ||
70 | { | ||
71 | acpi_status status = AE_OK; | ||
72 | union acpi_generic_state *control_state; | ||
73 | |||
74 | ACPI_FUNCTION_NAME(ds_exec_begin_control_op); | ||
75 | |||
76 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", | ||
77 | op, op->common.aml_opcode, walk_state)); | ||
78 | |||
79 | switch (op->common.aml_opcode) { | ||
80 | case AML_WHILE_OP: | ||
81 | |||
82 | /* | ||
83 | * If this is an additional iteration of a while loop, continue. | ||
84 | * There is no need to allocate a new control state. | ||
85 | */ | ||
86 | if (walk_state->control_state) { | ||
87 | if (walk_state->control_state->control. | ||
88 | aml_predicate_start == | ||
89 | (walk_state->parser_state.aml - 1)) { | ||
90 | |||
91 | /* Reset the state to start-of-loop */ | ||
92 | |||
93 | walk_state->control_state->common.state = | ||
94 | ACPI_CONTROL_CONDITIONAL_EXECUTING; | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /*lint -fallthrough */ | ||
100 | |||
101 | case AML_IF_OP: | ||
102 | |||
103 | /* | ||
104 | * IF/WHILE: Create a new control state to manage these | ||
105 | * constructs. We need to manage these as a stack, in order | ||
106 | * to handle nesting. | ||
107 | */ | ||
108 | control_state = acpi_ut_create_control_state(); | ||
109 | if (!control_state) { | ||
110 | status = AE_NO_MEMORY; | ||
111 | break; | ||
112 | } | ||
113 | /* | ||
114 | * Save a pointer to the predicate for multiple executions | ||
115 | * of a loop | ||
116 | */ | ||
117 | control_state->control.aml_predicate_start = | ||
118 | walk_state->parser_state.aml - 1; | ||
119 | control_state->control.package_end = | ||
120 | walk_state->parser_state.pkg_end; | ||
121 | control_state->control.opcode = op->common.aml_opcode; | ||
122 | |||
123 | /* Push the control state on this walk's control stack */ | ||
124 | |||
125 | acpi_ut_push_generic_state(&walk_state->control_state, | ||
126 | control_state); | ||
127 | break; | ||
128 | |||
129 | case AML_ELSE_OP: | ||
130 | |||
131 | /* Predicate is in the state object */ | ||
132 | /* If predicate is true, the IF was executed, ignore ELSE part */ | ||
133 | |||
134 | if (walk_state->last_predicate) { | ||
135 | status = AE_CTRL_TRUE; | ||
136 | } | ||
137 | |||
138 | break; | ||
139 | |||
140 | case AML_RETURN_OP: | ||
141 | |||
142 | break; | ||
143 | |||
144 | default: | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | return (status); | ||
149 | } | ||
150 | |||
151 | /******************************************************************************* | ||
152 | * | ||
153 | * FUNCTION: acpi_ds_exec_end_control_op | ||
154 | * | ||
155 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
156 | * Op - The control Op | ||
157 | * | ||
158 | * RETURN: Status | ||
159 | * | ||
160 | * DESCRIPTION: Handles all control ops encountered during control method | ||
161 | * execution. | ||
162 | * | ||
163 | ******************************************************************************/ | ||
164 | |||
165 | acpi_status | ||
166 | acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | ||
167 | union acpi_parse_object * op) | ||
168 | { | ||
169 | acpi_status status = AE_OK; | ||
170 | union acpi_generic_state *control_state; | ||
171 | |||
172 | ACPI_FUNCTION_NAME(ds_exec_end_control_op); | ||
173 | |||
174 | switch (op->common.aml_opcode) { | ||
175 | case AML_IF_OP: | ||
176 | |||
177 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); | ||
178 | |||
179 | /* | ||
180 | * Save the result of the predicate in case there is an | ||
181 | * ELSE to come | ||
182 | */ | ||
183 | walk_state->last_predicate = | ||
184 | (u8)walk_state->control_state->common.value; | ||
185 | |||
186 | /* | ||
187 | * Pop the control state that was created at the start | ||
188 | * of the IF and free it | ||
189 | */ | ||
190 | control_state = | ||
191 | acpi_ut_pop_generic_state(&walk_state->control_state); | ||
192 | acpi_ut_delete_generic_state(control_state); | ||
193 | break; | ||
194 | |||
195 | case AML_ELSE_OP: | ||
196 | |||
197 | break; | ||
198 | |||
199 | case AML_WHILE_OP: | ||
200 | |||
201 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); | ||
202 | |||
203 | control_state = walk_state->control_state; | ||
204 | if (control_state->common.value) { | ||
205 | |||
206 | /* Predicate was true, the body of the loop was just executed */ | ||
207 | |||
208 | /* | ||
209 | * This loop counter mechanism allows the interpreter to escape | ||
210 | * possibly infinite loops. This can occur in poorly written AML | ||
211 | * when the hardware does not respond within a while loop and the | ||
212 | * loop does not implement a timeout. | ||
213 | */ | ||
214 | control_state->control.loop_count++; | ||
215 | if (control_state->control.loop_count > | ||
216 | ACPI_MAX_LOOP_ITERATIONS) { | ||
217 | status = AE_AML_INFINITE_LOOP; | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Go back and evaluate the predicate and maybe execute the loop | ||
223 | * another time | ||
224 | */ | ||
225 | status = AE_CTRL_PENDING; | ||
226 | walk_state->aml_last_while = | ||
227 | control_state->control.aml_predicate_start; | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | /* Predicate was false, terminate this while loop */ | ||
232 | |||
233 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
234 | "[WHILE_OP] termination! Op=%p\n", op)); | ||
235 | |||
236 | /* Pop this control state and free it */ | ||
237 | |||
238 | control_state = | ||
239 | acpi_ut_pop_generic_state(&walk_state->control_state); | ||
240 | acpi_ut_delete_generic_state(control_state); | ||
241 | break; | ||
242 | |||
243 | case AML_RETURN_OP: | ||
244 | |||
245 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
246 | "[RETURN_OP] Op=%p Arg=%p\n", op, | ||
247 | op->common.value.arg)); | ||
248 | |||
249 | /* | ||
250 | * One optional operand -- the return value | ||
251 | * It can be either an immediate operand or a result that | ||
252 | * has been bubbled up the tree | ||
253 | */ | ||
254 | if (op->common.value.arg) { | ||
255 | |||
256 | /* Since we have a real Return(), delete any implicit return */ | ||
257 | |||
258 | acpi_ds_clear_implicit_return(walk_state); | ||
259 | |||
260 | /* Return statement has an immediate operand */ | ||
261 | |||
262 | status = | ||
263 | acpi_ds_create_operands(walk_state, | ||
264 | op->common.value.arg); | ||
265 | if (ACPI_FAILURE(status)) { | ||
266 | return (status); | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * If value being returned is a Reference (such as | ||
271 | * an arg or local), resolve it now because it may | ||
272 | * cease to exist at the end of the method. | ||
273 | */ | ||
274 | status = | ||
275 | acpi_ex_resolve_to_value(&walk_state->operands[0], | ||
276 | walk_state); | ||
277 | if (ACPI_FAILURE(status)) { | ||
278 | return (status); | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * Get the return value and save as the last result | ||
283 | * value. This is the only place where walk_state->return_desc | ||
284 | * is set to anything other than zero! | ||
285 | */ | ||
286 | walk_state->return_desc = walk_state->operands[0]; | ||
287 | } else if (walk_state->result_count) { | ||
288 | |||
289 | /* Since we have a real Return(), delete any implicit return */ | ||
290 | |||
291 | acpi_ds_clear_implicit_return(walk_state); | ||
292 | |||
293 | /* | ||
294 | * The return value has come from a previous calculation. | ||
295 | * | ||
296 | * If value being returned is a Reference (such as | ||
297 | * an arg or local), resolve it now because it may | ||
298 | * cease to exist at the end of the method. | ||
299 | * | ||
300 | * Allow references created by the Index operator to return | ||
301 | * unchanged. | ||
302 | */ | ||
303 | if ((ACPI_GET_DESCRIPTOR_TYPE | ||
304 | (walk_state->results->results.obj_desc[0]) == | ||
305 | ACPI_DESC_TYPE_OPERAND) | ||
306 | && ((walk_state->results->results.obj_desc[0])-> | ||
307 | common.type == ACPI_TYPE_LOCAL_REFERENCE) | ||
308 | && ((walk_state->results->results.obj_desc[0])-> | ||
309 | reference.class != ACPI_REFCLASS_INDEX)) { | ||
310 | status = | ||
311 | acpi_ex_resolve_to_value(&walk_state-> | ||
312 | results->results. | ||
313 | obj_desc[0], | ||
314 | walk_state); | ||
315 | if (ACPI_FAILURE(status)) { | ||
316 | return (status); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | walk_state->return_desc = | ||
321 | walk_state->results->results.obj_desc[0]; | ||
322 | } else { | ||
323 | /* No return operand */ | ||
324 | |||
325 | if (walk_state->num_operands) { | ||
326 | acpi_ut_remove_reference(walk_state-> | ||
327 | operands[0]); | ||
328 | } | ||
329 | |||
330 | walk_state->operands[0] = NULL; | ||
331 | walk_state->num_operands = 0; | ||
332 | walk_state->return_desc = NULL; | ||
333 | } | ||
334 | |||
335 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
336 | "Completed RETURN_OP State=%p, RetVal=%p\n", | ||
337 | walk_state, walk_state->return_desc)); | ||
338 | |||
339 | /* End the control method execution right now */ | ||
340 | |||
341 | status = AE_CTRL_TERMINATE; | ||
342 | break; | ||
343 | |||
344 | case AML_NOOP_OP: | ||
345 | |||
346 | /* Just do nothing! */ | ||
347 | break; | ||
348 | |||
349 | case AML_BREAK_POINT_OP: | ||
350 | |||
351 | /* | ||
352 | * Set the single-step flag. This will cause the debugger (if present) | ||
353 | * to break to the console within the AML debugger at the start of the | ||
354 | * next AML instruction. | ||
355 | */ | ||
356 | ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); | ||
357 | ACPI_DEBUGGER_EXEC(acpi_os_printf | ||
358 | ("**break** Executed AML BreakPoint opcode\n")); | ||
359 | |||
360 | /* Call to the OSL in case OS wants a piece of the action */ | ||
361 | |||
362 | status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, | ||
363 | "Executed AML Breakpoint opcode"); | ||
364 | break; | ||
365 | |||
366 | case AML_BREAK_OP: | ||
367 | case AML_CONTINUE_OP: /* ACPI 2.0 */ | ||
368 | |||
369 | /* Pop and delete control states until we find a while */ | ||
370 | |||
371 | while (walk_state->control_state && | ||
372 | (walk_state->control_state->control.opcode != | ||
373 | AML_WHILE_OP)) { | ||
374 | control_state = | ||
375 | acpi_ut_pop_generic_state(&walk_state-> | ||
376 | control_state); | ||
377 | acpi_ut_delete_generic_state(control_state); | ||
378 | } | ||
379 | |||
380 | /* No while found? */ | ||
381 | |||
382 | if (!walk_state->control_state) { | ||
383 | return (AE_AML_NO_WHILE); | ||
384 | } | ||
385 | |||
386 | /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ | ||
387 | |||
388 | walk_state->aml_last_while = | ||
389 | walk_state->control_state->control.package_end; | ||
390 | |||
391 | /* Return status depending on opcode */ | ||
392 | |||
393 | if (op->common.aml_opcode == AML_BREAK_OP) { | ||
394 | status = AE_CTRL_BREAK; | ||
395 | } else { | ||
396 | status = AE_CTRL_CONTINUE; | ||
397 | } | ||
398 | break; | ||
399 | |||
400 | default: | ||
401 | |||
402 | ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p", | ||
403 | op->common.aml_opcode, op)); | ||
404 | |||
405 | status = AE_AML_BAD_OPCODE; | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | return (status); | ||
410 | } | ||
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 347bee1726f1..34be60c0e448 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index cc4a38c57558..a7718bf2b9a1 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 64750ee96e20..5d797751e205 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -43,7 +43,6 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "amlcode.h" | ||
47 | #include "acdispat.h" | 46 | #include "acdispat.h" |
48 | #include "acinterp.h" | 47 | #include "acinterp.h" |
49 | #include "acnamesp.h" | 48 | #include "acnamesp.h" |
@@ -201,7 +200,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
201 | /* | 200 | /* |
202 | * If this method is serialized, we need to acquire the method mutex. | 201 | * If this method is serialized, we need to acquire the method mutex. |
203 | */ | 202 | */ |
204 | if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { | 203 | if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) { |
205 | /* | 204 | /* |
206 | * Create a mutex for the method if it is defined to be Serialized | 205 | * Create a mutex for the method if it is defined to be Serialized |
207 | * and a mutex has not already been created. We defer the mutex creation | 206 | * and a mutex has not already been created. We defer the mutex creation |
@@ -413,8 +412,9 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
413 | 412 | ||
414 | /* Invoke an internal method if necessary */ | 413 | /* Invoke an internal method if necessary */ |
415 | 414 | ||
416 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | 415 | if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) { |
417 | status = obj_desc->method.extra.implementation(next_walk_state); | 416 | status = |
417 | obj_desc->method.dispatch.implementation(next_walk_state); | ||
418 | if (status == AE_OK) { | 418 | if (status == AE_OK) { |
419 | status = AE_CTRL_TERMINATE; | 419 | status = AE_CTRL_TERMINATE; |
420 | } | 420 | } |
@@ -573,17 +573,20 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
573 | 573 | ||
574 | acpi_os_release_mutex(method_desc->method. | 574 | acpi_os_release_mutex(method_desc->method. |
575 | mutex->mutex.os_mutex); | 575 | mutex->mutex.os_mutex); |
576 | method_desc->method.mutex->mutex.thread_id = NULL; | 576 | method_desc->method.mutex->mutex.thread_id = 0; |
577 | } | 577 | } |
578 | } | 578 | } |
579 | 579 | ||
580 | /* | 580 | /* |
581 | * Delete any namespace objects created anywhere within the | 581 | * Delete any namespace objects created anywhere within the |
582 | * namespace by the execution of this method. Unless this method | 582 | * namespace by the execution of this method. Unless: |
583 | * is a module-level executable code method, in which case we | 583 | * 1) This method is a module-level executable code method, in which |
584 | * want make the objects permanent. | 584 | * case we want make the objects permanent. |
585 | * 2) There are other threads executing the method, in which case we | ||
586 | * will wait until the last thread has completed. | ||
585 | */ | 587 | */ |
586 | if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { | 588 | if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) |
589 | && (method_desc->method.thread_count == 1)) { | ||
587 | 590 | ||
588 | /* Delete any direct children of (created by) this method */ | 591 | /* Delete any direct children of (created by) this method */ |
589 | 592 | ||
@@ -593,12 +596,17 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
593 | /* | 596 | /* |
594 | * Delete any objects that were created by this method | 597 | * Delete any objects that were created by this method |
595 | * elsewhere in the namespace (if any were created). | 598 | * elsewhere in the namespace (if any were created). |
599 | * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the | ||
600 | * deletion such that we don't have to perform an entire | ||
601 | * namespace walk for every control method execution. | ||
596 | */ | 602 | */ |
597 | if (method_desc->method. | 603 | if (method_desc->method. |
598 | flags & AOPOBJ_MODIFIED_NAMESPACE) { | 604 | info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) { |
599 | acpi_ns_delete_namespace_by_owner(method_desc-> | 605 | acpi_ns_delete_namespace_by_owner(method_desc-> |
600 | method. | 606 | method. |
601 | owner_id); | 607 | owner_id); |
608 | method_desc->method.info_flags &= | ||
609 | ~ACPI_METHOD_MODIFIED_NAMESPACE; | ||
602 | } | 610 | } |
603 | } | 611 | } |
604 | } | 612 | } |
@@ -629,19 +637,43 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
629 | * Serialized if it appears that the method is incorrectly written and | 637 | * Serialized if it appears that the method is incorrectly written and |
630 | * does not support multiple thread execution. The best example of this | 638 | * does not support multiple thread execution. The best example of this |
631 | * is if such a method creates namespace objects and blocks. A second | 639 | * is if such a method creates namespace objects and blocks. A second |
632 | * thread will fail with an AE_ALREADY_EXISTS exception | 640 | * thread will fail with an AE_ALREADY_EXISTS exception. |
633 | * | 641 | * |
634 | * This code is here because we must wait until the last thread exits | 642 | * This code is here because we must wait until the last thread exits |
635 | * before creating the synchronization semaphore. | 643 | * before marking the method as serialized. |
636 | */ | 644 | */ |
637 | if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) | 645 | if (method_desc->method. |
638 | && (!method_desc->method.mutex)) { | 646 | info_flags & ACPI_METHOD_SERIALIZED_PENDING) { |
639 | (void)acpi_ds_create_method_mutex(method_desc); | 647 | if (walk_state) { |
648 | ACPI_INFO((AE_INFO, | ||
649 | "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", | ||
650 | walk_state->method_node->name. | ||
651 | ascii)); | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Method tried to create an object twice and was marked as | ||
656 | * "pending serialized". The probable cause is that the method | ||
657 | * cannot handle reentrancy. | ||
658 | * | ||
659 | * The method was created as not_serialized, but it tried to create | ||
660 | * a named object and then blocked, causing the second thread | ||
661 | * entrance to begin and then fail. Workaround this problem by | ||
662 | * marking the method permanently as Serialized when the last | ||
663 | * thread exits here. | ||
664 | */ | ||
665 | method_desc->method.info_flags &= | ||
666 | ~ACPI_METHOD_SERIALIZED_PENDING; | ||
667 | method_desc->method.info_flags |= | ||
668 | ACPI_METHOD_SERIALIZED; | ||
669 | method_desc->method.sync_level = 0; | ||
640 | } | 670 | } |
641 | 671 | ||
642 | /* No more threads, we can free the owner_id */ | 672 | /* No more threads, we can free the owner_id */ |
643 | 673 | ||
644 | if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { | 674 | if (! |
675 | (method_desc->method. | ||
676 | info_flags & ACPI_METHOD_MODULE_LEVEL)) { | ||
645 | acpi_ut_release_owner_id(&method_desc->method.owner_id); | 677 | acpi_ut_release_owner_id(&method_desc->method.owner_id); |
646 | } | 678 | } |
647 | } | 679 | } |
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 8095306fcd8c..905ce29a92e1 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 8e85f54a8e0e..f42e17e5c252 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 7c0e74227171..c627a288e027 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c | |||
@@ -1,12 +1,11 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Module Name: dsopcode - Dispatcher Op Region support and handling of | 3 | * Module Name: dsopcode - Dispatcher suport for regions and fields |
4 | * "control" opcodes | ||
5 | * | 4 | * |
6 | *****************************************************************************/ | 5 | *****************************************************************************/ |
7 | 6 | ||
8 | /* | 7 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 9 | * All rights reserved. |
11 | * | 10 | * |
12 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -57,11 +56,6 @@ ACPI_MODULE_NAME("dsopcode") | |||
57 | 56 | ||
58 | /* Local prototypes */ | 57 | /* Local prototypes */ |
59 | static acpi_status | 58 | static acpi_status |
60 | acpi_ds_execute_arguments(struct acpi_namespace_node *node, | ||
61 | struct acpi_namespace_node *scope_node, | ||
62 | u32 aml_length, u8 * aml_start); | ||
63 | |||
64 | static acpi_status | ||
65 | acpi_ds_init_buffer_field(u16 aml_opcode, | 59 | acpi_ds_init_buffer_field(u16 aml_opcode, |
66 | union acpi_operand_object *obj_desc, | 60 | union acpi_operand_object *obj_desc, |
67 | union acpi_operand_object *buffer_desc, | 61 | union acpi_operand_object *buffer_desc, |
@@ -71,361 +65,6 @@ acpi_ds_init_buffer_field(u16 aml_opcode, | |||
71 | 65 | ||
72 | /******************************************************************************* | 66 | /******************************************************************************* |
73 | * | 67 | * |
74 | * FUNCTION: acpi_ds_execute_arguments | ||
75 | * | ||
76 | * PARAMETERS: Node - Object NS node | ||
77 | * scope_node - Parent NS node | ||
78 | * aml_length - Length of executable AML | ||
79 | * aml_start - Pointer to the AML | ||
80 | * | ||
81 | * RETURN: Status. | ||
82 | * | ||
83 | * DESCRIPTION: Late (deferred) execution of region or field arguments | ||
84 | * | ||
85 | ******************************************************************************/ | ||
86 | |||
87 | static acpi_status | ||
88 | acpi_ds_execute_arguments(struct acpi_namespace_node *node, | ||
89 | struct acpi_namespace_node *scope_node, | ||
90 | u32 aml_length, u8 * aml_start) | ||
91 | { | ||
92 | acpi_status status; | ||
93 | union acpi_parse_object *op; | ||
94 | struct acpi_walk_state *walk_state; | ||
95 | |||
96 | ACPI_FUNCTION_TRACE(ds_execute_arguments); | ||
97 | |||
98 | /* | ||
99 | * Allocate a new parser op to be the root of the parsed tree | ||
100 | */ | ||
101 | op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); | ||
102 | if (!op) { | ||
103 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
104 | } | ||
105 | |||
106 | /* Save the Node for use in acpi_ps_parse_aml */ | ||
107 | |||
108 | op->common.node = scope_node; | ||
109 | |||
110 | /* Create and initialize a new parser state */ | ||
111 | |||
112 | walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); | ||
113 | if (!walk_state) { | ||
114 | status = AE_NO_MEMORY; | ||
115 | goto cleanup; | ||
116 | } | ||
117 | |||
118 | status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, | ||
119 | aml_length, NULL, ACPI_IMODE_LOAD_PASS1); | ||
120 | if (ACPI_FAILURE(status)) { | ||
121 | acpi_ds_delete_walk_state(walk_state); | ||
122 | goto cleanup; | ||
123 | } | ||
124 | |||
125 | /* Mark this parse as a deferred opcode */ | ||
126 | |||
127 | walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; | ||
128 | walk_state->deferred_node = node; | ||
129 | |||
130 | /* Pass1: Parse the entire declaration */ | ||
131 | |||
132 | status = acpi_ps_parse_aml(walk_state); | ||
133 | if (ACPI_FAILURE(status)) { | ||
134 | goto cleanup; | ||
135 | } | ||
136 | |||
137 | /* Get and init the Op created above */ | ||
138 | |||
139 | op->common.node = node; | ||
140 | acpi_ps_delete_parse_tree(op); | ||
141 | |||
142 | /* Evaluate the deferred arguments */ | ||
143 | |||
144 | op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); | ||
145 | if (!op) { | ||
146 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
147 | } | ||
148 | |||
149 | op->common.node = scope_node; | ||
150 | |||
151 | /* Create and initialize a new parser state */ | ||
152 | |||
153 | walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); | ||
154 | if (!walk_state) { | ||
155 | status = AE_NO_MEMORY; | ||
156 | goto cleanup; | ||
157 | } | ||
158 | |||
159 | /* Execute the opcode and arguments */ | ||
160 | |||
161 | status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, | ||
162 | aml_length, NULL, ACPI_IMODE_EXECUTE); | ||
163 | if (ACPI_FAILURE(status)) { | ||
164 | acpi_ds_delete_walk_state(walk_state); | ||
165 | goto cleanup; | ||
166 | } | ||
167 | |||
168 | /* Mark this execution as a deferred opcode */ | ||
169 | |||
170 | walk_state->deferred_node = node; | ||
171 | status = acpi_ps_parse_aml(walk_state); | ||
172 | |||
173 | cleanup: | ||
174 | acpi_ps_delete_parse_tree(op); | ||
175 | return_ACPI_STATUS(status); | ||
176 | } | ||
177 | |||
178 | /******************************************************************************* | ||
179 | * | ||
180 | * FUNCTION: acpi_ds_get_buffer_field_arguments | ||
181 | * | ||
182 | * PARAMETERS: obj_desc - A valid buffer_field object | ||
183 | * | ||
184 | * RETURN: Status. | ||
185 | * | ||
186 | * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late | ||
187 | * evaluation of these field attributes. | ||
188 | * | ||
189 | ******************************************************************************/ | ||
190 | |||
191 | acpi_status | ||
192 | acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) | ||
193 | { | ||
194 | union acpi_operand_object *extra_desc; | ||
195 | struct acpi_namespace_node *node; | ||
196 | acpi_status status; | ||
197 | |||
198 | ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); | ||
199 | |||
200 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
201 | return_ACPI_STATUS(AE_OK); | ||
202 | } | ||
203 | |||
204 | /* Get the AML pointer (method object) and buffer_field node */ | ||
205 | |||
206 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
207 | node = obj_desc->buffer_field.node; | ||
208 | |||
209 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
210 | (ACPI_TYPE_BUFFER_FIELD, node, NULL)); | ||
211 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", | ||
212 | acpi_ut_get_node_name(node))); | ||
213 | |||
214 | /* Execute the AML code for the term_arg arguments */ | ||
215 | |||
216 | status = acpi_ds_execute_arguments(node, node->parent, | ||
217 | extra_desc->extra.aml_length, | ||
218 | extra_desc->extra.aml_start); | ||
219 | return_ACPI_STATUS(status); | ||
220 | } | ||
221 | |||
222 | /******************************************************************************* | ||
223 | * | ||
224 | * FUNCTION: acpi_ds_get_bank_field_arguments | ||
225 | * | ||
226 | * PARAMETERS: obj_desc - A valid bank_field object | ||
227 | * | ||
228 | * RETURN: Status. | ||
229 | * | ||
230 | * DESCRIPTION: Get bank_field bank_value. This implements the late | ||
231 | * evaluation of these field attributes. | ||
232 | * | ||
233 | ******************************************************************************/ | ||
234 | |||
235 | acpi_status | ||
236 | acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) | ||
237 | { | ||
238 | union acpi_operand_object *extra_desc; | ||
239 | struct acpi_namespace_node *node; | ||
240 | acpi_status status; | ||
241 | |||
242 | ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); | ||
243 | |||
244 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
245 | return_ACPI_STATUS(AE_OK); | ||
246 | } | ||
247 | |||
248 | /* Get the AML pointer (method object) and bank_field node */ | ||
249 | |||
250 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
251 | node = obj_desc->bank_field.node; | ||
252 | |||
253 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
254 | (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); | ||
255 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", | ||
256 | acpi_ut_get_node_name(node))); | ||
257 | |||
258 | /* Execute the AML code for the term_arg arguments */ | ||
259 | |||
260 | status = acpi_ds_execute_arguments(node, node->parent, | ||
261 | extra_desc->extra.aml_length, | ||
262 | extra_desc->extra.aml_start); | ||
263 | return_ACPI_STATUS(status); | ||
264 | } | ||
265 | |||
266 | /******************************************************************************* | ||
267 | * | ||
268 | * FUNCTION: acpi_ds_get_buffer_arguments | ||
269 | * | ||
270 | * PARAMETERS: obj_desc - A valid Buffer object | ||
271 | * | ||
272 | * RETURN: Status. | ||
273 | * | ||
274 | * DESCRIPTION: Get Buffer length and initializer byte list. This implements | ||
275 | * the late evaluation of these attributes. | ||
276 | * | ||
277 | ******************************************************************************/ | ||
278 | |||
279 | acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) | ||
280 | { | ||
281 | struct acpi_namespace_node *node; | ||
282 | acpi_status status; | ||
283 | |||
284 | ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); | ||
285 | |||
286 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
287 | return_ACPI_STATUS(AE_OK); | ||
288 | } | ||
289 | |||
290 | /* Get the Buffer node */ | ||
291 | |||
292 | node = obj_desc->buffer.node; | ||
293 | if (!node) { | ||
294 | ACPI_ERROR((AE_INFO, | ||
295 | "No pointer back to namespace node in buffer object %p", | ||
296 | obj_desc)); | ||
297 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
298 | } | ||
299 | |||
300 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); | ||
301 | |||
302 | /* Execute the AML code for the term_arg arguments */ | ||
303 | |||
304 | status = acpi_ds_execute_arguments(node, node, | ||
305 | obj_desc->buffer.aml_length, | ||
306 | obj_desc->buffer.aml_start); | ||
307 | return_ACPI_STATUS(status); | ||
308 | } | ||
309 | |||
310 | /******************************************************************************* | ||
311 | * | ||
312 | * FUNCTION: acpi_ds_get_package_arguments | ||
313 | * | ||
314 | * PARAMETERS: obj_desc - A valid Package object | ||
315 | * | ||
316 | * RETURN: Status. | ||
317 | * | ||
318 | * DESCRIPTION: Get Package length and initializer byte list. This implements | ||
319 | * the late evaluation of these attributes. | ||
320 | * | ||
321 | ******************************************************************************/ | ||
322 | |||
323 | acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) | ||
324 | { | ||
325 | struct acpi_namespace_node *node; | ||
326 | acpi_status status; | ||
327 | |||
328 | ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); | ||
329 | |||
330 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
331 | return_ACPI_STATUS(AE_OK); | ||
332 | } | ||
333 | |||
334 | /* Get the Package node */ | ||
335 | |||
336 | node = obj_desc->package.node; | ||
337 | if (!node) { | ||
338 | ACPI_ERROR((AE_INFO, | ||
339 | "No pointer back to namespace node in package %p", | ||
340 | obj_desc)); | ||
341 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
342 | } | ||
343 | |||
344 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); | ||
345 | |||
346 | /* Execute the AML code for the term_arg arguments */ | ||
347 | |||
348 | status = acpi_ds_execute_arguments(node, node, | ||
349 | obj_desc->package.aml_length, | ||
350 | obj_desc->package.aml_start); | ||
351 | return_ACPI_STATUS(status); | ||
352 | } | ||
353 | |||
354 | /***************************************************************************** | ||
355 | * | ||
356 | * FUNCTION: acpi_ds_get_region_arguments | ||
357 | * | ||
358 | * PARAMETERS: obj_desc - A valid region object | ||
359 | * | ||
360 | * RETURN: Status. | ||
361 | * | ||
362 | * DESCRIPTION: Get region address and length. This implements the late | ||
363 | * evaluation of these region attributes. | ||
364 | * | ||
365 | ****************************************************************************/ | ||
366 | |||
367 | acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) | ||
368 | { | ||
369 | struct acpi_namespace_node *node; | ||
370 | acpi_status status; | ||
371 | union acpi_operand_object *extra_desc; | ||
372 | |||
373 | ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); | ||
374 | |||
375 | if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { | ||
376 | return_ACPI_STATUS(AE_OK); | ||
377 | } | ||
378 | |||
379 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
380 | if (!extra_desc) { | ||
381 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
382 | } | ||
383 | |||
384 | /* Get the Region node */ | ||
385 | |||
386 | node = obj_desc->region.node; | ||
387 | |||
388 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
389 | (ACPI_TYPE_REGION, node, NULL)); | ||
390 | |||
391 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", | ||
392 | acpi_ut_get_node_name(node), | ||
393 | extra_desc->extra.aml_start)); | ||
394 | |||
395 | /* Execute the argument AML */ | ||
396 | |||
397 | status = acpi_ds_execute_arguments(node, node->parent, | ||
398 | extra_desc->extra.aml_length, | ||
399 | extra_desc->extra.aml_start); | ||
400 | if (ACPI_FAILURE(status)) { | ||
401 | return_ACPI_STATUS(status); | ||
402 | } | ||
403 | |||
404 | /* Validate the region address/length via the host OS */ | ||
405 | |||
406 | status = acpi_os_validate_address(obj_desc->region.space_id, | ||
407 | obj_desc->region.address, | ||
408 | (acpi_size) obj_desc->region.length, | ||
409 | acpi_ut_get_node_name(node)); | ||
410 | |||
411 | if (ACPI_FAILURE(status)) { | ||
412 | /* | ||
413 | * Invalid address/length. We will emit an error message and mark | ||
414 | * the region as invalid, so that it will cause an additional error if | ||
415 | * it is ever used. Then return AE_OK. | ||
416 | */ | ||
417 | ACPI_EXCEPTION((AE_INFO, status, | ||
418 | "During address validation of OpRegion [%4.4s]", | ||
419 | node->name.ascii)); | ||
420 | obj_desc->common.flags |= AOPOBJ_INVALID; | ||
421 | status = AE_OK; | ||
422 | } | ||
423 | |||
424 | return_ACPI_STATUS(status); | ||
425 | } | ||
426 | |||
427 | /******************************************************************************* | ||
428 | * | ||
429 | * FUNCTION: acpi_ds_initialize_region | 68 | * FUNCTION: acpi_ds_initialize_region |
430 | * | 69 | * |
431 | * PARAMETERS: obj_handle - Region namespace node | 70 | * PARAMETERS: obj_handle - Region namespace node |
@@ -826,8 +465,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, | |||
826 | * | 465 | * |
827 | * RETURN: Status | 466 | * RETURN: Status |
828 | * | 467 | * |
829 | * DESCRIPTION: Get region address and length | 468 | * DESCRIPTION: Get region address and length. |
830 | * Called from acpi_ds_exec_end_op during data_table_region parse tree walk | 469 | * Called from acpi_ds_exec_end_op during data_table_region parse |
470 | * tree walk. | ||
831 | * | 471 | * |
832 | ******************************************************************************/ | 472 | ******************************************************************************/ |
833 | 473 | ||
@@ -1114,360 +754,3 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | |||
1114 | acpi_ut_remove_reference(operand_desc); | 754 | acpi_ut_remove_reference(operand_desc); |
1115 | return_ACPI_STATUS(status); | 755 | return_ACPI_STATUS(status); |
1116 | } | 756 | } |
1117 | |||
1118 | /******************************************************************************* | ||
1119 | * | ||
1120 | * FUNCTION: acpi_ds_exec_begin_control_op | ||
1121 | * | ||
1122 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
1123 | * Op - The control Op | ||
1124 | * | ||
1125 | * RETURN: Status | ||
1126 | * | ||
1127 | * DESCRIPTION: Handles all control ops encountered during control method | ||
1128 | * execution. | ||
1129 | * | ||
1130 | ******************************************************************************/ | ||
1131 | |||
1132 | acpi_status | ||
1133 | acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, | ||
1134 | union acpi_parse_object *op) | ||
1135 | { | ||
1136 | acpi_status status = AE_OK; | ||
1137 | union acpi_generic_state *control_state; | ||
1138 | |||
1139 | ACPI_FUNCTION_NAME(ds_exec_begin_control_op); | ||
1140 | |||
1141 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, | ||
1142 | op->common.aml_opcode, walk_state)); | ||
1143 | |||
1144 | switch (op->common.aml_opcode) { | ||
1145 | case AML_WHILE_OP: | ||
1146 | |||
1147 | /* | ||
1148 | * If this is an additional iteration of a while loop, continue. | ||
1149 | * There is no need to allocate a new control state. | ||
1150 | */ | ||
1151 | if (walk_state->control_state) { | ||
1152 | if (walk_state->control_state->control.aml_predicate_start | ||
1153 | == (walk_state->parser_state.aml - 1)) { | ||
1154 | |||
1155 | /* Reset the state to start-of-loop */ | ||
1156 | |||
1157 | walk_state->control_state->common.state = | ||
1158 | ACPI_CONTROL_CONDITIONAL_EXECUTING; | ||
1159 | break; | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | /*lint -fallthrough */ | ||
1164 | |||
1165 | case AML_IF_OP: | ||
1166 | |||
1167 | /* | ||
1168 | * IF/WHILE: Create a new control state to manage these | ||
1169 | * constructs. We need to manage these as a stack, in order | ||
1170 | * to handle nesting. | ||
1171 | */ | ||
1172 | control_state = acpi_ut_create_control_state(); | ||
1173 | if (!control_state) { | ||
1174 | status = AE_NO_MEMORY; | ||
1175 | break; | ||
1176 | } | ||
1177 | /* | ||
1178 | * Save a pointer to the predicate for multiple executions | ||
1179 | * of a loop | ||
1180 | */ | ||
1181 | control_state->control.aml_predicate_start = | ||
1182 | walk_state->parser_state.aml - 1; | ||
1183 | control_state->control.package_end = | ||
1184 | walk_state->parser_state.pkg_end; | ||
1185 | control_state->control.opcode = op->common.aml_opcode; | ||
1186 | |||
1187 | /* Push the control state on this walk's control stack */ | ||
1188 | |||
1189 | acpi_ut_push_generic_state(&walk_state->control_state, | ||
1190 | control_state); | ||
1191 | break; | ||
1192 | |||
1193 | case AML_ELSE_OP: | ||
1194 | |||
1195 | /* Predicate is in the state object */ | ||
1196 | /* If predicate is true, the IF was executed, ignore ELSE part */ | ||
1197 | |||
1198 | if (walk_state->last_predicate) { | ||
1199 | status = AE_CTRL_TRUE; | ||
1200 | } | ||
1201 | |||
1202 | break; | ||
1203 | |||
1204 | case AML_RETURN_OP: | ||
1205 | |||
1206 | break; | ||
1207 | |||
1208 | default: | ||
1209 | break; | ||
1210 | } | ||
1211 | |||
1212 | return (status); | ||
1213 | } | ||
1214 | |||
1215 | /******************************************************************************* | ||
1216 | * | ||
1217 | * FUNCTION: acpi_ds_exec_end_control_op | ||
1218 | * | ||
1219 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
1220 | * Op - The control Op | ||
1221 | * | ||
1222 | * RETURN: Status | ||
1223 | * | ||
1224 | * DESCRIPTION: Handles all control ops encountered during control method | ||
1225 | * execution. | ||
1226 | * | ||
1227 | ******************************************************************************/ | ||
1228 | |||
1229 | acpi_status | ||
1230 | acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | ||
1231 | union acpi_parse_object * op) | ||
1232 | { | ||
1233 | acpi_status status = AE_OK; | ||
1234 | union acpi_generic_state *control_state; | ||
1235 | |||
1236 | ACPI_FUNCTION_NAME(ds_exec_end_control_op); | ||
1237 | |||
1238 | switch (op->common.aml_opcode) { | ||
1239 | case AML_IF_OP: | ||
1240 | |||
1241 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); | ||
1242 | |||
1243 | /* | ||
1244 | * Save the result of the predicate in case there is an | ||
1245 | * ELSE to come | ||
1246 | */ | ||
1247 | walk_state->last_predicate = | ||
1248 | (u8) walk_state->control_state->common.value; | ||
1249 | |||
1250 | /* | ||
1251 | * Pop the control state that was created at the start | ||
1252 | * of the IF and free it | ||
1253 | */ | ||
1254 | control_state = | ||
1255 | acpi_ut_pop_generic_state(&walk_state->control_state); | ||
1256 | acpi_ut_delete_generic_state(control_state); | ||
1257 | break; | ||
1258 | |||
1259 | case AML_ELSE_OP: | ||
1260 | |||
1261 | break; | ||
1262 | |||
1263 | case AML_WHILE_OP: | ||
1264 | |||
1265 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); | ||
1266 | |||
1267 | control_state = walk_state->control_state; | ||
1268 | if (control_state->common.value) { | ||
1269 | |||
1270 | /* Predicate was true, the body of the loop was just executed */ | ||
1271 | |||
1272 | /* | ||
1273 | * This loop counter mechanism allows the interpreter to escape | ||
1274 | * possibly infinite loops. This can occur in poorly written AML | ||
1275 | * when the hardware does not respond within a while loop and the | ||
1276 | * loop does not implement a timeout. | ||
1277 | */ | ||
1278 | control_state->control.loop_count++; | ||
1279 | if (control_state->control.loop_count > | ||
1280 | ACPI_MAX_LOOP_ITERATIONS) { | ||
1281 | status = AE_AML_INFINITE_LOOP; | ||
1282 | break; | ||
1283 | } | ||
1284 | |||
1285 | /* | ||
1286 | * Go back and evaluate the predicate and maybe execute the loop | ||
1287 | * another time | ||
1288 | */ | ||
1289 | status = AE_CTRL_PENDING; | ||
1290 | walk_state->aml_last_while = | ||
1291 | control_state->control.aml_predicate_start; | ||
1292 | break; | ||
1293 | } | ||
1294 | |||
1295 | /* Predicate was false, terminate this while loop */ | ||
1296 | |||
1297 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1298 | "[WHILE_OP] termination! Op=%p\n", op)); | ||
1299 | |||
1300 | /* Pop this control state and free it */ | ||
1301 | |||
1302 | control_state = | ||
1303 | acpi_ut_pop_generic_state(&walk_state->control_state); | ||
1304 | acpi_ut_delete_generic_state(control_state); | ||
1305 | break; | ||
1306 | |||
1307 | case AML_RETURN_OP: | ||
1308 | |||
1309 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1310 | "[RETURN_OP] Op=%p Arg=%p\n", op, | ||
1311 | op->common.value.arg)); | ||
1312 | |||
1313 | /* | ||
1314 | * One optional operand -- the return value | ||
1315 | * It can be either an immediate operand or a result that | ||
1316 | * has been bubbled up the tree | ||
1317 | */ | ||
1318 | if (op->common.value.arg) { | ||
1319 | |||
1320 | /* Since we have a real Return(), delete any implicit return */ | ||
1321 | |||
1322 | acpi_ds_clear_implicit_return(walk_state); | ||
1323 | |||
1324 | /* Return statement has an immediate operand */ | ||
1325 | |||
1326 | status = | ||
1327 | acpi_ds_create_operands(walk_state, | ||
1328 | op->common.value.arg); | ||
1329 | if (ACPI_FAILURE(status)) { | ||
1330 | return (status); | ||
1331 | } | ||
1332 | |||
1333 | /* | ||
1334 | * If value being returned is a Reference (such as | ||
1335 | * an arg or local), resolve it now because it may | ||
1336 | * cease to exist at the end of the method. | ||
1337 | */ | ||
1338 | status = | ||
1339 | acpi_ex_resolve_to_value(&walk_state->operands[0], | ||
1340 | walk_state); | ||
1341 | if (ACPI_FAILURE(status)) { | ||
1342 | return (status); | ||
1343 | } | ||
1344 | |||
1345 | /* | ||
1346 | * Get the return value and save as the last result | ||
1347 | * value. This is the only place where walk_state->return_desc | ||
1348 | * is set to anything other than zero! | ||
1349 | */ | ||
1350 | walk_state->return_desc = walk_state->operands[0]; | ||
1351 | } else if (walk_state->result_count) { | ||
1352 | |||
1353 | /* Since we have a real Return(), delete any implicit return */ | ||
1354 | |||
1355 | acpi_ds_clear_implicit_return(walk_state); | ||
1356 | |||
1357 | /* | ||
1358 | * The return value has come from a previous calculation. | ||
1359 | * | ||
1360 | * If value being returned is a Reference (such as | ||
1361 | * an arg or local), resolve it now because it may | ||
1362 | * cease to exist at the end of the method. | ||
1363 | * | ||
1364 | * Allow references created by the Index operator to return unchanged. | ||
1365 | */ | ||
1366 | if ((ACPI_GET_DESCRIPTOR_TYPE | ||
1367 | (walk_state->results->results.obj_desc[0]) == | ||
1368 | ACPI_DESC_TYPE_OPERAND) | ||
1369 | && ((walk_state->results->results.obj_desc[0])-> | ||
1370 | common.type == ACPI_TYPE_LOCAL_REFERENCE) | ||
1371 | && ((walk_state->results->results.obj_desc[0])-> | ||
1372 | reference.class != ACPI_REFCLASS_INDEX)) { | ||
1373 | status = | ||
1374 | acpi_ex_resolve_to_value(&walk_state-> | ||
1375 | results->results. | ||
1376 | obj_desc[0], | ||
1377 | walk_state); | ||
1378 | if (ACPI_FAILURE(status)) { | ||
1379 | return (status); | ||
1380 | } | ||
1381 | } | ||
1382 | |||
1383 | walk_state->return_desc = | ||
1384 | walk_state->results->results.obj_desc[0]; | ||
1385 | } else { | ||
1386 | /* No return operand */ | ||
1387 | |||
1388 | if (walk_state->num_operands) { | ||
1389 | acpi_ut_remove_reference(walk_state-> | ||
1390 | operands[0]); | ||
1391 | } | ||
1392 | |||
1393 | walk_state->operands[0] = NULL; | ||
1394 | walk_state->num_operands = 0; | ||
1395 | walk_state->return_desc = NULL; | ||
1396 | } | ||
1397 | |||
1398 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1399 | "Completed RETURN_OP State=%p, RetVal=%p\n", | ||
1400 | walk_state, walk_state->return_desc)); | ||
1401 | |||
1402 | /* End the control method execution right now */ | ||
1403 | |||
1404 | status = AE_CTRL_TERMINATE; | ||
1405 | break; | ||
1406 | |||
1407 | case AML_NOOP_OP: | ||
1408 | |||
1409 | /* Just do nothing! */ | ||
1410 | break; | ||
1411 | |||
1412 | case AML_BREAK_POINT_OP: | ||
1413 | |||
1414 | /* | ||
1415 | * Set the single-step flag. This will cause the debugger (if present) | ||
1416 | * to break to the console within the AML debugger at the start of the | ||
1417 | * next AML instruction. | ||
1418 | */ | ||
1419 | ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); | ||
1420 | ACPI_DEBUGGER_EXEC(acpi_os_printf | ||
1421 | ("**break** Executed AML BreakPoint opcode\n")); | ||
1422 | |||
1423 | /* Call to the OSL in case OS wants a piece of the action */ | ||
1424 | |||
1425 | status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, | ||
1426 | "Executed AML Breakpoint opcode"); | ||
1427 | break; | ||
1428 | |||
1429 | case AML_BREAK_OP: | ||
1430 | case AML_CONTINUE_OP: /* ACPI 2.0 */ | ||
1431 | |||
1432 | /* Pop and delete control states until we find a while */ | ||
1433 | |||
1434 | while (walk_state->control_state && | ||
1435 | (walk_state->control_state->control.opcode != | ||
1436 | AML_WHILE_OP)) { | ||
1437 | control_state = | ||
1438 | acpi_ut_pop_generic_state(&walk_state-> | ||
1439 | control_state); | ||
1440 | acpi_ut_delete_generic_state(control_state); | ||
1441 | } | ||
1442 | |||
1443 | /* No while found? */ | ||
1444 | |||
1445 | if (!walk_state->control_state) { | ||
1446 | return (AE_AML_NO_WHILE); | ||
1447 | } | ||
1448 | |||
1449 | /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ | ||
1450 | |||
1451 | walk_state->aml_last_while = | ||
1452 | walk_state->control_state->control.package_end; | ||
1453 | |||
1454 | /* Return status depending on opcode */ | ||
1455 | |||
1456 | if (op->common.aml_opcode == AML_BREAK_OP) { | ||
1457 | status = AE_CTRL_BREAK; | ||
1458 | } else { | ||
1459 | status = AE_CTRL_CONTINUE; | ||
1460 | } | ||
1461 | break; | ||
1462 | |||
1463 | default: | ||
1464 | |||
1465 | ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p", | ||
1466 | op->common.aml_opcode, op)); | ||
1467 | |||
1468 | status = AE_AML_BAD_OPCODE; | ||
1469 | break; | ||
1470 | } | ||
1471 | |||
1472 | return (status); | ||
1473 | } | ||
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 15135c25aa9b..2c477ce172fa 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index d555b374e314..fe40e4c6554f 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -300,10 +300,25 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, | |||
300 | * we must enter this object into the namespace. The created | 300 | * we must enter this object into the namespace. The created |
301 | * object is temporary and will be deleted upon completion of | 301 | * object is temporary and will be deleted upon completion of |
302 | * the execution of this method. | 302 | * the execution of this method. |
303 | * | ||
304 | * Note 10/2010: Except for the Scope() op. This opcode does | ||
305 | * not actually create a new object, it refers to an existing | ||
306 | * object. However, for Scope(), we want to indeed open a | ||
307 | * new scope. | ||
303 | */ | 308 | */ |
304 | status = acpi_ds_load2_begin_op(walk_state, NULL); | 309 | if (op->common.aml_opcode != AML_SCOPE_OP) { |
310 | status = | ||
311 | acpi_ds_load2_begin_op(walk_state, NULL); | ||
312 | } else { | ||
313 | status = | ||
314 | acpi_ds_scope_stack_push(op->named.node, | ||
315 | op->named.node-> | ||
316 | type, walk_state); | ||
317 | if (ACPI_FAILURE(status)) { | ||
318 | return_ACPI_STATUS(status); | ||
319 | } | ||
320 | } | ||
305 | } | 321 | } |
306 | |||
307 | break; | 322 | break; |
308 | 323 | ||
309 | case AML_CLASS_EXECUTE: | 324 | case AML_CLASS_EXECUTE: |
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 140a9d002959..324acec1179a 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Module Name: dswload - Dispatcher namespace load callbacks | 3 | * Module Name: dswload - Dispatcher first pass namespace load callbacks |
4 | * | 4 | * |
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,7 +48,6 @@ | |||
48 | #include "acdispat.h" | 48 | #include "acdispat.h" |
49 | #include "acinterp.h" | 49 | #include "acinterp.h" |
50 | #include "acnamesp.h" | 50 | #include "acnamesp.h" |
51 | #include "acevents.h" | ||
52 | 51 | ||
53 | #ifdef ACPI_ASL_COMPILER | 52 | #ifdef ACPI_ASL_COMPILER |
54 | #include <acpi/acdisasm.h> | 53 | #include <acpi/acdisasm.h> |
@@ -451,7 +450,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) | |||
451 | status = | 450 | status = |
452 | acpi_ex_create_region(op->named.data, | 451 | acpi_ex_create_region(op->named.data, |
453 | op->named.length, | 452 | op->named.length, |
454 | REGION_DATA_TABLE, | 453 | ACPI_ADR_SPACE_DATA_TABLE, |
455 | walk_state); | 454 | walk_state); |
456 | if (ACPI_FAILURE(status)) { | 455 | if (ACPI_FAILURE(status)) { |
457 | return_ACPI_STATUS(status); | 456 | return_ACPI_STATUS(status); |
@@ -537,670 +536,3 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) | |||
537 | 536 | ||
538 | return_ACPI_STATUS(status); | 537 | return_ACPI_STATUS(status); |
539 | } | 538 | } |
540 | |||
541 | /******************************************************************************* | ||
542 | * | ||
543 | * FUNCTION: acpi_ds_load2_begin_op | ||
544 | * | ||
545 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
546 | * out_op - Wher to return op if a new one is created | ||
547 | * | ||
548 | * RETURN: Status | ||
549 | * | ||
550 | * DESCRIPTION: Descending callback used during the loading of ACPI tables. | ||
551 | * | ||
552 | ******************************************************************************/ | ||
553 | |||
554 | acpi_status | ||
555 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | ||
556 | union acpi_parse_object **out_op) | ||
557 | { | ||
558 | union acpi_parse_object *op; | ||
559 | struct acpi_namespace_node *node; | ||
560 | acpi_status status; | ||
561 | acpi_object_type object_type; | ||
562 | char *buffer_ptr; | ||
563 | u32 flags; | ||
564 | |||
565 | ACPI_FUNCTION_TRACE(ds_load2_begin_op); | ||
566 | |||
567 | op = walk_state->op; | ||
568 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | ||
569 | walk_state)); | ||
570 | |||
571 | if (op) { | ||
572 | if ((walk_state->control_state) && | ||
573 | (walk_state->control_state->common.state == | ||
574 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) { | ||
575 | |||
576 | /* We are executing a while loop outside of a method */ | ||
577 | |||
578 | status = acpi_ds_exec_begin_op(walk_state, out_op); | ||
579 | return_ACPI_STATUS(status); | ||
580 | } | ||
581 | |||
582 | /* We only care about Namespace opcodes here */ | ||
583 | |||
584 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && | ||
585 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || | ||
586 | (!(walk_state->op_info->flags & AML_NAMED))) { | ||
587 | return_ACPI_STATUS(AE_OK); | ||
588 | } | ||
589 | |||
590 | /* Get the name we are going to enter or lookup in the namespace */ | ||
591 | |||
592 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { | ||
593 | |||
594 | /* For Namepath op, get the path string */ | ||
595 | |||
596 | buffer_ptr = op->common.value.string; | ||
597 | if (!buffer_ptr) { | ||
598 | |||
599 | /* No name, just exit */ | ||
600 | |||
601 | return_ACPI_STATUS(AE_OK); | ||
602 | } | ||
603 | } else { | ||
604 | /* Get name from the op */ | ||
605 | |||
606 | buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); | ||
607 | } | ||
608 | } else { | ||
609 | /* Get the namestring from the raw AML */ | ||
610 | |||
611 | buffer_ptr = | ||
612 | acpi_ps_get_next_namestring(&walk_state->parser_state); | ||
613 | } | ||
614 | |||
615 | /* Map the opcode into an internal object type */ | ||
616 | |||
617 | object_type = walk_state->op_info->object_type; | ||
618 | |||
619 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
620 | "State=%p Op=%p Type=%X\n", walk_state, op, | ||
621 | object_type)); | ||
622 | |||
623 | switch (walk_state->opcode) { | ||
624 | case AML_FIELD_OP: | ||
625 | case AML_BANK_FIELD_OP: | ||
626 | case AML_INDEX_FIELD_OP: | ||
627 | |||
628 | node = NULL; | ||
629 | status = AE_OK; | ||
630 | break; | ||
631 | |||
632 | case AML_INT_NAMEPATH_OP: | ||
633 | /* | ||
634 | * The name_path is an object reference to an existing object. | ||
635 | * Don't enter the name into the namespace, but look it up | ||
636 | * for use later. | ||
637 | */ | ||
638 | status = | ||
639 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
640 | object_type, ACPI_IMODE_EXECUTE, | ||
641 | ACPI_NS_SEARCH_PARENT, walk_state, &(node)); | ||
642 | break; | ||
643 | |||
644 | case AML_SCOPE_OP: | ||
645 | |||
646 | /* Special case for Scope(\) -> refers to the Root node */ | ||
647 | |||
648 | if (op && (op->named.node == acpi_gbl_root_node)) { | ||
649 | node = op->named.node; | ||
650 | |||
651 | status = | ||
652 | acpi_ds_scope_stack_push(node, object_type, | ||
653 | walk_state); | ||
654 | if (ACPI_FAILURE(status)) { | ||
655 | return_ACPI_STATUS(status); | ||
656 | } | ||
657 | } else { | ||
658 | /* | ||
659 | * The Path is an object reference to an existing object. | ||
660 | * Don't enter the name into the namespace, but look it up | ||
661 | * for use later. | ||
662 | */ | ||
663 | status = | ||
664 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
665 | object_type, ACPI_IMODE_EXECUTE, | ||
666 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
667 | &(node)); | ||
668 | if (ACPI_FAILURE(status)) { | ||
669 | #ifdef ACPI_ASL_COMPILER | ||
670 | if (status == AE_NOT_FOUND) { | ||
671 | status = AE_OK; | ||
672 | } else { | ||
673 | ACPI_ERROR_NAMESPACE(buffer_ptr, | ||
674 | status); | ||
675 | } | ||
676 | #else | ||
677 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
678 | #endif | ||
679 | return_ACPI_STATUS(status); | ||
680 | } | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * We must check to make sure that the target is | ||
685 | * one of the opcodes that actually opens a scope | ||
686 | */ | ||
687 | switch (node->type) { | ||
688 | case ACPI_TYPE_ANY: | ||
689 | case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ | ||
690 | case ACPI_TYPE_DEVICE: | ||
691 | case ACPI_TYPE_POWER: | ||
692 | case ACPI_TYPE_PROCESSOR: | ||
693 | case ACPI_TYPE_THERMAL: | ||
694 | |||
695 | /* These are acceptable types */ | ||
696 | break; | ||
697 | |||
698 | case ACPI_TYPE_INTEGER: | ||
699 | case ACPI_TYPE_STRING: | ||
700 | case ACPI_TYPE_BUFFER: | ||
701 | |||
702 | /* | ||
703 | * These types we will allow, but we will change the type. | ||
704 | * This enables some existing code of the form: | ||
705 | * | ||
706 | * Name (DEB, 0) | ||
707 | * Scope (DEB) { ... } | ||
708 | */ | ||
709 | ACPI_WARNING((AE_INFO, | ||
710 | "Type override - [%4.4s] had invalid type (%s) " | ||
711 | "for Scope operator, changed to type ANY\n", | ||
712 | acpi_ut_get_node_name(node), | ||
713 | acpi_ut_get_type_name(node->type))); | ||
714 | |||
715 | node->type = ACPI_TYPE_ANY; | ||
716 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; | ||
717 | break; | ||
718 | |||
719 | default: | ||
720 | |||
721 | /* All other types are an error */ | ||
722 | |||
723 | ACPI_ERROR((AE_INFO, | ||
724 | "Invalid type (%s) for target of " | ||
725 | "Scope operator [%4.4s] (Cannot override)", | ||
726 | acpi_ut_get_type_name(node->type), | ||
727 | acpi_ut_get_node_name(node))); | ||
728 | |||
729 | return (AE_AML_OPERAND_TYPE); | ||
730 | } | ||
731 | break; | ||
732 | |||
733 | default: | ||
734 | |||
735 | /* All other opcodes */ | ||
736 | |||
737 | if (op && op->common.node) { | ||
738 | |||
739 | /* This op/node was previously entered into the namespace */ | ||
740 | |||
741 | node = op->common.node; | ||
742 | |||
743 | if (acpi_ns_opens_scope(object_type)) { | ||
744 | status = | ||
745 | acpi_ds_scope_stack_push(node, object_type, | ||
746 | walk_state); | ||
747 | if (ACPI_FAILURE(status)) { | ||
748 | return_ACPI_STATUS(status); | ||
749 | } | ||
750 | } | ||
751 | |||
752 | return_ACPI_STATUS(AE_OK); | ||
753 | } | ||
754 | |||
755 | /* | ||
756 | * Enter the named type into the internal namespace. We enter the name | ||
757 | * as we go downward in the parse tree. Any necessary subobjects that | ||
758 | * involve arguments to the opcode must be created as we go back up the | ||
759 | * parse tree later. | ||
760 | * | ||
761 | * Note: Name may already exist if we are executing a deferred opcode. | ||
762 | */ | ||
763 | if (walk_state->deferred_node) { | ||
764 | |||
765 | /* This name is already in the namespace, get the node */ | ||
766 | |||
767 | node = walk_state->deferred_node; | ||
768 | status = AE_OK; | ||
769 | break; | ||
770 | } | ||
771 | |||
772 | flags = ACPI_NS_NO_UPSEARCH; | ||
773 | if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { | ||
774 | |||
775 | /* Execution mode, node cannot already exist, node is temporary */ | ||
776 | |||
777 | flags |= ACPI_NS_ERROR_IF_FOUND; | ||
778 | |||
779 | if (! | ||
780 | (walk_state-> | ||
781 | parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
782 | flags |= ACPI_NS_TEMPORARY; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | /* Add new entry or lookup existing entry */ | ||
787 | |||
788 | status = | ||
789 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
790 | object_type, ACPI_IMODE_LOAD_PASS2, flags, | ||
791 | walk_state, &node); | ||
792 | |||
793 | if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { | ||
794 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
795 | "***New Node [%4.4s] %p is temporary\n", | ||
796 | acpi_ut_get_node_name(node), node)); | ||
797 | } | ||
798 | break; | ||
799 | } | ||
800 | |||
801 | if (ACPI_FAILURE(status)) { | ||
802 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
803 | return_ACPI_STATUS(status); | ||
804 | } | ||
805 | |||
806 | if (!op) { | ||
807 | |||
808 | /* Create a new op */ | ||
809 | |||
810 | op = acpi_ps_alloc_op(walk_state->opcode); | ||
811 | if (!op) { | ||
812 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
813 | } | ||
814 | |||
815 | /* Initialize the new op */ | ||
816 | |||
817 | if (node) { | ||
818 | op->named.name = node->name.integer; | ||
819 | } | ||
820 | *out_op = op; | ||
821 | } | ||
822 | |||
823 | /* | ||
824 | * Put the Node in the "op" object that the parser uses, so we | ||
825 | * can get it again quickly when this scope is closed | ||
826 | */ | ||
827 | op->common.node = node; | ||
828 | return_ACPI_STATUS(status); | ||
829 | } | ||
830 | |||
831 | /******************************************************************************* | ||
832 | * | ||
833 | * FUNCTION: acpi_ds_load2_end_op | ||
834 | * | ||
835 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
836 | * | ||
837 | * RETURN: Status | ||
838 | * | ||
839 | * DESCRIPTION: Ascending callback used during the loading of the namespace, | ||
840 | * both control methods and everything else. | ||
841 | * | ||
842 | ******************************************************************************/ | ||
843 | |||
844 | acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | ||
845 | { | ||
846 | union acpi_parse_object *op; | ||
847 | acpi_status status = AE_OK; | ||
848 | acpi_object_type object_type; | ||
849 | struct acpi_namespace_node *node; | ||
850 | union acpi_parse_object *arg; | ||
851 | struct acpi_namespace_node *new_node; | ||
852 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
853 | u32 i; | ||
854 | u8 region_space; | ||
855 | #endif | ||
856 | |||
857 | ACPI_FUNCTION_TRACE(ds_load2_end_op); | ||
858 | |||
859 | op = walk_state->op; | ||
860 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", | ||
861 | walk_state->op_info->name, op, walk_state)); | ||
862 | |||
863 | /* Check if opcode had an associated namespace object */ | ||
864 | |||
865 | if (!(walk_state->op_info->flags & AML_NSOBJECT)) { | ||
866 | return_ACPI_STATUS(AE_OK); | ||
867 | } | ||
868 | |||
869 | if (op->common.aml_opcode == AML_SCOPE_OP) { | ||
870 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
871 | "Ending scope Op=%p State=%p\n", op, | ||
872 | walk_state)); | ||
873 | } | ||
874 | |||
875 | object_type = walk_state->op_info->object_type; | ||
876 | |||
877 | /* | ||
878 | * Get the Node/name from the earlier lookup | ||
879 | * (It was saved in the *op structure) | ||
880 | */ | ||
881 | node = op->common.node; | ||
882 | |||
883 | /* | ||
884 | * Put the Node on the object stack (Contains the ACPI Name of | ||
885 | * this object) | ||
886 | */ | ||
887 | walk_state->operands[0] = (void *)node; | ||
888 | walk_state->num_operands = 1; | ||
889 | |||
890 | /* Pop the scope stack */ | ||
891 | |||
892 | if (acpi_ns_opens_scope(object_type) && | ||
893 | (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { | ||
894 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
895 | "(%s) Popping scope for Op %p\n", | ||
896 | acpi_ut_get_type_name(object_type), op)); | ||
897 | |||
898 | status = acpi_ds_scope_stack_pop(walk_state); | ||
899 | if (ACPI_FAILURE(status)) { | ||
900 | goto cleanup; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | /* | ||
905 | * Named operations are as follows: | ||
906 | * | ||
907 | * AML_ALIAS | ||
908 | * AML_BANKFIELD | ||
909 | * AML_CREATEBITFIELD | ||
910 | * AML_CREATEBYTEFIELD | ||
911 | * AML_CREATEDWORDFIELD | ||
912 | * AML_CREATEFIELD | ||
913 | * AML_CREATEQWORDFIELD | ||
914 | * AML_CREATEWORDFIELD | ||
915 | * AML_DATA_REGION | ||
916 | * AML_DEVICE | ||
917 | * AML_EVENT | ||
918 | * AML_FIELD | ||
919 | * AML_INDEXFIELD | ||
920 | * AML_METHOD | ||
921 | * AML_METHODCALL | ||
922 | * AML_MUTEX | ||
923 | * AML_NAME | ||
924 | * AML_NAMEDFIELD | ||
925 | * AML_OPREGION | ||
926 | * AML_POWERRES | ||
927 | * AML_PROCESSOR | ||
928 | * AML_SCOPE | ||
929 | * AML_THERMALZONE | ||
930 | */ | ||
931 | |||
932 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
933 | "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", | ||
934 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
935 | walk_state, op, node)); | ||
936 | |||
937 | /* Decode the opcode */ | ||
938 | |||
939 | arg = op->common.value.arg; | ||
940 | |||
941 | switch (walk_state->op_info->type) { | ||
942 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
943 | |||
944 | case AML_TYPE_CREATE_FIELD: | ||
945 | /* | ||
946 | * Create the field object, but the field buffer and index must | ||
947 | * be evaluated later during the execution phase | ||
948 | */ | ||
949 | status = acpi_ds_create_buffer_field(op, walk_state); | ||
950 | break; | ||
951 | |||
952 | case AML_TYPE_NAMED_FIELD: | ||
953 | /* | ||
954 | * If we are executing a method, initialize the field | ||
955 | */ | ||
956 | if (walk_state->method_node) { | ||
957 | status = acpi_ds_init_field_objects(op, walk_state); | ||
958 | } | ||
959 | |||
960 | switch (op->common.aml_opcode) { | ||
961 | case AML_INDEX_FIELD_OP: | ||
962 | |||
963 | status = | ||
964 | acpi_ds_create_index_field(op, | ||
965 | (acpi_handle) arg-> | ||
966 | common.node, walk_state); | ||
967 | break; | ||
968 | |||
969 | case AML_BANK_FIELD_OP: | ||
970 | |||
971 | status = | ||
972 | acpi_ds_create_bank_field(op, arg->common.node, | ||
973 | walk_state); | ||
974 | break; | ||
975 | |||
976 | case AML_FIELD_OP: | ||
977 | |||
978 | status = | ||
979 | acpi_ds_create_field(op, arg->common.node, | ||
980 | walk_state); | ||
981 | break; | ||
982 | |||
983 | default: | ||
984 | /* All NAMED_FIELD opcodes must be handled above */ | ||
985 | break; | ||
986 | } | ||
987 | break; | ||
988 | |||
989 | case AML_TYPE_NAMED_SIMPLE: | ||
990 | |||
991 | status = acpi_ds_create_operands(walk_state, arg); | ||
992 | if (ACPI_FAILURE(status)) { | ||
993 | goto cleanup; | ||
994 | } | ||
995 | |||
996 | switch (op->common.aml_opcode) { | ||
997 | case AML_PROCESSOR_OP: | ||
998 | |||
999 | status = acpi_ex_create_processor(walk_state); | ||
1000 | break; | ||
1001 | |||
1002 | case AML_POWER_RES_OP: | ||
1003 | |||
1004 | status = acpi_ex_create_power_resource(walk_state); | ||
1005 | break; | ||
1006 | |||
1007 | case AML_MUTEX_OP: | ||
1008 | |||
1009 | status = acpi_ex_create_mutex(walk_state); | ||
1010 | break; | ||
1011 | |||
1012 | case AML_EVENT_OP: | ||
1013 | |||
1014 | status = acpi_ex_create_event(walk_state); | ||
1015 | break; | ||
1016 | |||
1017 | case AML_ALIAS_OP: | ||
1018 | |||
1019 | status = acpi_ex_create_alias(walk_state); | ||
1020 | break; | ||
1021 | |||
1022 | default: | ||
1023 | /* Unknown opcode */ | ||
1024 | |||
1025 | status = AE_OK; | ||
1026 | goto cleanup; | ||
1027 | } | ||
1028 | |||
1029 | /* Delete operands */ | ||
1030 | |||
1031 | for (i = 1; i < walk_state->num_operands; i++) { | ||
1032 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
1033 | walk_state->operands[i] = NULL; | ||
1034 | } | ||
1035 | |||
1036 | break; | ||
1037 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
1038 | |||
1039 | case AML_TYPE_NAMED_COMPLEX: | ||
1040 | |||
1041 | switch (op->common.aml_opcode) { | ||
1042 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
1043 | case AML_REGION_OP: | ||
1044 | case AML_DATA_REGION_OP: | ||
1045 | |||
1046 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
1047 | region_space = (acpi_adr_space_type) | ||
1048 | ((op->common.value.arg)->common.value. | ||
1049 | integer); | ||
1050 | } else { | ||
1051 | region_space = REGION_DATA_TABLE; | ||
1052 | } | ||
1053 | |||
1054 | /* | ||
1055 | * The op_region is not fully parsed at this time. The only valid | ||
1056 | * argument is the space_id. (We must save the address of the | ||
1057 | * AML of the address and length operands) | ||
1058 | * | ||
1059 | * If we have a valid region, initialize it. The namespace is | ||
1060 | * unlocked at this point. | ||
1061 | * | ||
1062 | * Need to unlock interpreter if it is locked (if we are running | ||
1063 | * a control method), in order to allow _REG methods to be run | ||
1064 | * during acpi_ev_initialize_region. | ||
1065 | */ | ||
1066 | if (walk_state->method_node) { | ||
1067 | /* | ||
1068 | * Executing a method: initialize the region and unlock | ||
1069 | * the interpreter | ||
1070 | */ | ||
1071 | status = | ||
1072 | acpi_ex_create_region(op->named.data, | ||
1073 | op->named.length, | ||
1074 | region_space, | ||
1075 | walk_state); | ||
1076 | if (ACPI_FAILURE(status)) { | ||
1077 | return (status); | ||
1078 | } | ||
1079 | |||
1080 | acpi_ex_exit_interpreter(); | ||
1081 | } | ||
1082 | |||
1083 | status = | ||
1084 | acpi_ev_initialize_region | ||
1085 | (acpi_ns_get_attached_object(node), FALSE); | ||
1086 | if (walk_state->method_node) { | ||
1087 | acpi_ex_enter_interpreter(); | ||
1088 | } | ||
1089 | |||
1090 | if (ACPI_FAILURE(status)) { | ||
1091 | /* | ||
1092 | * If AE_NOT_EXIST is returned, it is not fatal | ||
1093 | * because many regions get created before a handler | ||
1094 | * is installed for said region. | ||
1095 | */ | ||
1096 | if (AE_NOT_EXIST == status) { | ||
1097 | status = AE_OK; | ||
1098 | } | ||
1099 | } | ||
1100 | break; | ||
1101 | |||
1102 | case AML_NAME_OP: | ||
1103 | |||
1104 | status = acpi_ds_create_node(walk_state, node, op); | ||
1105 | break; | ||
1106 | |||
1107 | case AML_METHOD_OP: | ||
1108 | /* | ||
1109 | * method_op pkg_length name_string method_flags term_list | ||
1110 | * | ||
1111 | * Note: We must create the method node/object pair as soon as we | ||
1112 | * see the method declaration. This allows later pass1 parsing | ||
1113 | * of invocations of the method (need to know the number of | ||
1114 | * arguments.) | ||
1115 | */ | ||
1116 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1117 | "LOADING-Method: State=%p Op=%p NamedObj=%p\n", | ||
1118 | walk_state, op, op->named.node)); | ||
1119 | |||
1120 | if (!acpi_ns_get_attached_object(op->named.node)) { | ||
1121 | walk_state->operands[0] = | ||
1122 | ACPI_CAST_PTR(void, op->named.node); | ||
1123 | walk_state->num_operands = 1; | ||
1124 | |||
1125 | status = | ||
1126 | acpi_ds_create_operands(walk_state, | ||
1127 | op->common.value. | ||
1128 | arg); | ||
1129 | if (ACPI_SUCCESS(status)) { | ||
1130 | status = | ||
1131 | acpi_ex_create_method(op->named. | ||
1132 | data, | ||
1133 | op->named. | ||
1134 | length, | ||
1135 | walk_state); | ||
1136 | } | ||
1137 | walk_state->operands[0] = NULL; | ||
1138 | walk_state->num_operands = 0; | ||
1139 | |||
1140 | if (ACPI_FAILURE(status)) { | ||
1141 | return_ACPI_STATUS(status); | ||
1142 | } | ||
1143 | } | ||
1144 | break; | ||
1145 | |||
1146 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
1147 | |||
1148 | default: | ||
1149 | /* All NAMED_COMPLEX opcodes must be handled above */ | ||
1150 | break; | ||
1151 | } | ||
1152 | break; | ||
1153 | |||
1154 | case AML_CLASS_INTERNAL: | ||
1155 | |||
1156 | /* case AML_INT_NAMEPATH_OP: */ | ||
1157 | break; | ||
1158 | |||
1159 | case AML_CLASS_METHOD_CALL: | ||
1160 | |||
1161 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1162 | "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", | ||
1163 | walk_state, op, node)); | ||
1164 | |||
1165 | /* | ||
1166 | * Lookup the method name and save the Node | ||
1167 | */ | ||
1168 | status = | ||
1169 | acpi_ns_lookup(walk_state->scope_info, | ||
1170 | arg->common.value.string, ACPI_TYPE_ANY, | ||
1171 | ACPI_IMODE_LOAD_PASS2, | ||
1172 | ACPI_NS_SEARCH_PARENT | | ||
1173 | ACPI_NS_DONT_OPEN_SCOPE, walk_state, | ||
1174 | &(new_node)); | ||
1175 | if (ACPI_SUCCESS(status)) { | ||
1176 | /* | ||
1177 | * Make sure that what we found is indeed a method | ||
1178 | * We didn't search for a method on purpose, to see if the name | ||
1179 | * would resolve | ||
1180 | */ | ||
1181 | if (new_node->type != ACPI_TYPE_METHOD) { | ||
1182 | status = AE_AML_OPERAND_TYPE; | ||
1183 | } | ||
1184 | |||
1185 | /* We could put the returned object (Node) on the object stack for | ||
1186 | * later, but for now, we will put it in the "op" object that the | ||
1187 | * parser uses, so we can get it again at the end of this scope | ||
1188 | */ | ||
1189 | op->common.node = new_node; | ||
1190 | } else { | ||
1191 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
1192 | } | ||
1193 | break; | ||
1194 | |||
1195 | default: | ||
1196 | break; | ||
1197 | } | ||
1198 | |||
1199 | cleanup: | ||
1200 | |||
1201 | /* Remove the Node pushed at the very beginning */ | ||
1202 | |||
1203 | walk_state->operands[0] = NULL; | ||
1204 | walk_state->num_operands = 0; | ||
1205 | return_ACPI_STATUS(status); | ||
1206 | } | ||
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c new file mode 100644 index 000000000000..976318138c56 --- /dev/null +++ b/drivers/acpi/acpica/dswload2.c | |||
@@ -0,0 +1,720 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswload2 - Dispatcher second pass namespace load callbacks | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acparser.h" | ||
47 | #include "amlcode.h" | ||
48 | #include "acdispat.h" | ||
49 | #include "acinterp.h" | ||
50 | #include "acnamesp.h" | ||
51 | #include "acevents.h" | ||
52 | |||
53 | #define _COMPONENT ACPI_DISPATCHER | ||
54 | ACPI_MODULE_NAME("dswload2") | ||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ds_load2_begin_op | ||
59 | * | ||
60 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
61 | * out_op - Wher to return op if a new one is created | ||
62 | * | ||
63 | * RETURN: Status | ||
64 | * | ||
65 | * DESCRIPTION: Descending callback used during the loading of ACPI tables. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | acpi_status | ||
69 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | ||
70 | union acpi_parse_object **out_op) | ||
71 | { | ||
72 | union acpi_parse_object *op; | ||
73 | struct acpi_namespace_node *node; | ||
74 | acpi_status status; | ||
75 | acpi_object_type object_type; | ||
76 | char *buffer_ptr; | ||
77 | u32 flags; | ||
78 | |||
79 | ACPI_FUNCTION_TRACE(ds_load2_begin_op); | ||
80 | |||
81 | op = walk_state->op; | ||
82 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | ||
83 | walk_state)); | ||
84 | |||
85 | if (op) { | ||
86 | if ((walk_state->control_state) && | ||
87 | (walk_state->control_state->common.state == | ||
88 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) { | ||
89 | |||
90 | /* We are executing a while loop outside of a method */ | ||
91 | |||
92 | status = acpi_ds_exec_begin_op(walk_state, out_op); | ||
93 | return_ACPI_STATUS(status); | ||
94 | } | ||
95 | |||
96 | /* We only care about Namespace opcodes here */ | ||
97 | |||
98 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && | ||
99 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || | ||
100 | (!(walk_state->op_info->flags & AML_NAMED))) { | ||
101 | return_ACPI_STATUS(AE_OK); | ||
102 | } | ||
103 | |||
104 | /* Get the name we are going to enter or lookup in the namespace */ | ||
105 | |||
106 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { | ||
107 | |||
108 | /* For Namepath op, get the path string */ | ||
109 | |||
110 | buffer_ptr = op->common.value.string; | ||
111 | if (!buffer_ptr) { | ||
112 | |||
113 | /* No name, just exit */ | ||
114 | |||
115 | return_ACPI_STATUS(AE_OK); | ||
116 | } | ||
117 | } else { | ||
118 | /* Get name from the op */ | ||
119 | |||
120 | buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); | ||
121 | } | ||
122 | } else { | ||
123 | /* Get the namestring from the raw AML */ | ||
124 | |||
125 | buffer_ptr = | ||
126 | acpi_ps_get_next_namestring(&walk_state->parser_state); | ||
127 | } | ||
128 | |||
129 | /* Map the opcode into an internal object type */ | ||
130 | |||
131 | object_type = walk_state->op_info->object_type; | ||
132 | |||
133 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
134 | "State=%p Op=%p Type=%X\n", walk_state, op, | ||
135 | object_type)); | ||
136 | |||
137 | switch (walk_state->opcode) { | ||
138 | case AML_FIELD_OP: | ||
139 | case AML_BANK_FIELD_OP: | ||
140 | case AML_INDEX_FIELD_OP: | ||
141 | |||
142 | node = NULL; | ||
143 | status = AE_OK; | ||
144 | break; | ||
145 | |||
146 | case AML_INT_NAMEPATH_OP: | ||
147 | /* | ||
148 | * The name_path is an object reference to an existing object. | ||
149 | * Don't enter the name into the namespace, but look it up | ||
150 | * for use later. | ||
151 | */ | ||
152 | status = | ||
153 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
154 | object_type, ACPI_IMODE_EXECUTE, | ||
155 | ACPI_NS_SEARCH_PARENT, walk_state, &(node)); | ||
156 | break; | ||
157 | |||
158 | case AML_SCOPE_OP: | ||
159 | |||
160 | /* Special case for Scope(\) -> refers to the Root node */ | ||
161 | |||
162 | if (op && (op->named.node == acpi_gbl_root_node)) { | ||
163 | node = op->named.node; | ||
164 | |||
165 | status = | ||
166 | acpi_ds_scope_stack_push(node, object_type, | ||
167 | walk_state); | ||
168 | if (ACPI_FAILURE(status)) { | ||
169 | return_ACPI_STATUS(status); | ||
170 | } | ||
171 | } else { | ||
172 | /* | ||
173 | * The Path is an object reference to an existing object. | ||
174 | * Don't enter the name into the namespace, but look it up | ||
175 | * for use later. | ||
176 | */ | ||
177 | status = | ||
178 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
179 | object_type, ACPI_IMODE_EXECUTE, | ||
180 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
181 | &(node)); | ||
182 | if (ACPI_FAILURE(status)) { | ||
183 | #ifdef ACPI_ASL_COMPILER | ||
184 | if (status == AE_NOT_FOUND) { | ||
185 | status = AE_OK; | ||
186 | } else { | ||
187 | ACPI_ERROR_NAMESPACE(buffer_ptr, | ||
188 | status); | ||
189 | } | ||
190 | #else | ||
191 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
192 | #endif | ||
193 | return_ACPI_STATUS(status); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * We must check to make sure that the target is | ||
199 | * one of the opcodes that actually opens a scope | ||
200 | */ | ||
201 | switch (node->type) { | ||
202 | case ACPI_TYPE_ANY: | ||
203 | case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ | ||
204 | case ACPI_TYPE_DEVICE: | ||
205 | case ACPI_TYPE_POWER: | ||
206 | case ACPI_TYPE_PROCESSOR: | ||
207 | case ACPI_TYPE_THERMAL: | ||
208 | |||
209 | /* These are acceptable types */ | ||
210 | break; | ||
211 | |||
212 | case ACPI_TYPE_INTEGER: | ||
213 | case ACPI_TYPE_STRING: | ||
214 | case ACPI_TYPE_BUFFER: | ||
215 | |||
216 | /* | ||
217 | * These types we will allow, but we will change the type. | ||
218 | * This enables some existing code of the form: | ||
219 | * | ||
220 | * Name (DEB, 0) | ||
221 | * Scope (DEB) { ... } | ||
222 | */ | ||
223 | ACPI_WARNING((AE_INFO, | ||
224 | "Type override - [%4.4s] had invalid type (%s) " | ||
225 | "for Scope operator, changed to type ANY\n", | ||
226 | acpi_ut_get_node_name(node), | ||
227 | acpi_ut_get_type_name(node->type))); | ||
228 | |||
229 | node->type = ACPI_TYPE_ANY; | ||
230 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; | ||
231 | break; | ||
232 | |||
233 | default: | ||
234 | |||
235 | /* All other types are an error */ | ||
236 | |||
237 | ACPI_ERROR((AE_INFO, | ||
238 | "Invalid type (%s) for target of " | ||
239 | "Scope operator [%4.4s] (Cannot override)", | ||
240 | acpi_ut_get_type_name(node->type), | ||
241 | acpi_ut_get_node_name(node))); | ||
242 | |||
243 | return (AE_AML_OPERAND_TYPE); | ||
244 | } | ||
245 | break; | ||
246 | |||
247 | default: | ||
248 | |||
249 | /* All other opcodes */ | ||
250 | |||
251 | if (op && op->common.node) { | ||
252 | |||
253 | /* This op/node was previously entered into the namespace */ | ||
254 | |||
255 | node = op->common.node; | ||
256 | |||
257 | if (acpi_ns_opens_scope(object_type)) { | ||
258 | status = | ||
259 | acpi_ds_scope_stack_push(node, object_type, | ||
260 | walk_state); | ||
261 | if (ACPI_FAILURE(status)) { | ||
262 | return_ACPI_STATUS(status); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | return_ACPI_STATUS(AE_OK); | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Enter the named type into the internal namespace. We enter the name | ||
271 | * as we go downward in the parse tree. Any necessary subobjects that | ||
272 | * involve arguments to the opcode must be created as we go back up the | ||
273 | * parse tree later. | ||
274 | * | ||
275 | * Note: Name may already exist if we are executing a deferred opcode. | ||
276 | */ | ||
277 | if (walk_state->deferred_node) { | ||
278 | |||
279 | /* This name is already in the namespace, get the node */ | ||
280 | |||
281 | node = walk_state->deferred_node; | ||
282 | status = AE_OK; | ||
283 | break; | ||
284 | } | ||
285 | |||
286 | flags = ACPI_NS_NO_UPSEARCH; | ||
287 | if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { | ||
288 | |||
289 | /* Execution mode, node cannot already exist, node is temporary */ | ||
290 | |||
291 | flags |= ACPI_NS_ERROR_IF_FOUND; | ||
292 | |||
293 | if (! | ||
294 | (walk_state-> | ||
295 | parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
296 | flags |= ACPI_NS_TEMPORARY; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /* Add new entry or lookup existing entry */ | ||
301 | |||
302 | status = | ||
303 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
304 | object_type, ACPI_IMODE_LOAD_PASS2, flags, | ||
305 | walk_state, &node); | ||
306 | |||
307 | if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { | ||
308 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
309 | "***New Node [%4.4s] %p is temporary\n", | ||
310 | acpi_ut_get_node_name(node), node)); | ||
311 | } | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | if (ACPI_FAILURE(status)) { | ||
316 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
317 | return_ACPI_STATUS(status); | ||
318 | } | ||
319 | |||
320 | if (!op) { | ||
321 | |||
322 | /* Create a new op */ | ||
323 | |||
324 | op = acpi_ps_alloc_op(walk_state->opcode); | ||
325 | if (!op) { | ||
326 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
327 | } | ||
328 | |||
329 | /* Initialize the new op */ | ||
330 | |||
331 | if (node) { | ||
332 | op->named.name = node->name.integer; | ||
333 | } | ||
334 | *out_op = op; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Put the Node in the "op" object that the parser uses, so we | ||
339 | * can get it again quickly when this scope is closed | ||
340 | */ | ||
341 | op->common.node = node; | ||
342 | return_ACPI_STATUS(status); | ||
343 | } | ||
344 | |||
345 | /******************************************************************************* | ||
346 | * | ||
347 | * FUNCTION: acpi_ds_load2_end_op | ||
348 | * | ||
349 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
350 | * | ||
351 | * RETURN: Status | ||
352 | * | ||
353 | * DESCRIPTION: Ascending callback used during the loading of the namespace, | ||
354 | * both control methods and everything else. | ||
355 | * | ||
356 | ******************************************************************************/ | ||
357 | |||
358 | acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | ||
359 | { | ||
360 | union acpi_parse_object *op; | ||
361 | acpi_status status = AE_OK; | ||
362 | acpi_object_type object_type; | ||
363 | struct acpi_namespace_node *node; | ||
364 | union acpi_parse_object *arg; | ||
365 | struct acpi_namespace_node *new_node; | ||
366 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
367 | u32 i; | ||
368 | u8 region_space; | ||
369 | #endif | ||
370 | |||
371 | ACPI_FUNCTION_TRACE(ds_load2_end_op); | ||
372 | |||
373 | op = walk_state->op; | ||
374 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", | ||
375 | walk_state->op_info->name, op, walk_state)); | ||
376 | |||
377 | /* Check if opcode had an associated namespace object */ | ||
378 | |||
379 | if (!(walk_state->op_info->flags & AML_NSOBJECT)) { | ||
380 | return_ACPI_STATUS(AE_OK); | ||
381 | } | ||
382 | |||
383 | if (op->common.aml_opcode == AML_SCOPE_OP) { | ||
384 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
385 | "Ending scope Op=%p State=%p\n", op, | ||
386 | walk_state)); | ||
387 | } | ||
388 | |||
389 | object_type = walk_state->op_info->object_type; | ||
390 | |||
391 | /* | ||
392 | * Get the Node/name from the earlier lookup | ||
393 | * (It was saved in the *op structure) | ||
394 | */ | ||
395 | node = op->common.node; | ||
396 | |||
397 | /* | ||
398 | * Put the Node on the object stack (Contains the ACPI Name of | ||
399 | * this object) | ||
400 | */ | ||
401 | walk_state->operands[0] = (void *)node; | ||
402 | walk_state->num_operands = 1; | ||
403 | |||
404 | /* Pop the scope stack */ | ||
405 | |||
406 | if (acpi_ns_opens_scope(object_type) && | ||
407 | (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { | ||
408 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
409 | "(%s) Popping scope for Op %p\n", | ||
410 | acpi_ut_get_type_name(object_type), op)); | ||
411 | |||
412 | status = acpi_ds_scope_stack_pop(walk_state); | ||
413 | if (ACPI_FAILURE(status)) { | ||
414 | goto cleanup; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Named operations are as follows: | ||
420 | * | ||
421 | * AML_ALIAS | ||
422 | * AML_BANKFIELD | ||
423 | * AML_CREATEBITFIELD | ||
424 | * AML_CREATEBYTEFIELD | ||
425 | * AML_CREATEDWORDFIELD | ||
426 | * AML_CREATEFIELD | ||
427 | * AML_CREATEQWORDFIELD | ||
428 | * AML_CREATEWORDFIELD | ||
429 | * AML_DATA_REGION | ||
430 | * AML_DEVICE | ||
431 | * AML_EVENT | ||
432 | * AML_FIELD | ||
433 | * AML_INDEXFIELD | ||
434 | * AML_METHOD | ||
435 | * AML_METHODCALL | ||
436 | * AML_MUTEX | ||
437 | * AML_NAME | ||
438 | * AML_NAMEDFIELD | ||
439 | * AML_OPREGION | ||
440 | * AML_POWERRES | ||
441 | * AML_PROCESSOR | ||
442 | * AML_SCOPE | ||
443 | * AML_THERMALZONE | ||
444 | */ | ||
445 | |||
446 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
447 | "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", | ||
448 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
449 | walk_state, op, node)); | ||
450 | |||
451 | /* Decode the opcode */ | ||
452 | |||
453 | arg = op->common.value.arg; | ||
454 | |||
455 | switch (walk_state->op_info->type) { | ||
456 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
457 | |||
458 | case AML_TYPE_CREATE_FIELD: | ||
459 | /* | ||
460 | * Create the field object, but the field buffer and index must | ||
461 | * be evaluated later during the execution phase | ||
462 | */ | ||
463 | status = acpi_ds_create_buffer_field(op, walk_state); | ||
464 | break; | ||
465 | |||
466 | case AML_TYPE_NAMED_FIELD: | ||
467 | /* | ||
468 | * If we are executing a method, initialize the field | ||
469 | */ | ||
470 | if (walk_state->method_node) { | ||
471 | status = acpi_ds_init_field_objects(op, walk_state); | ||
472 | } | ||
473 | |||
474 | switch (op->common.aml_opcode) { | ||
475 | case AML_INDEX_FIELD_OP: | ||
476 | |||
477 | status = | ||
478 | acpi_ds_create_index_field(op, | ||
479 | (acpi_handle) arg-> | ||
480 | common.node, walk_state); | ||
481 | break; | ||
482 | |||
483 | case AML_BANK_FIELD_OP: | ||
484 | |||
485 | status = | ||
486 | acpi_ds_create_bank_field(op, arg->common.node, | ||
487 | walk_state); | ||
488 | break; | ||
489 | |||
490 | case AML_FIELD_OP: | ||
491 | |||
492 | status = | ||
493 | acpi_ds_create_field(op, arg->common.node, | ||
494 | walk_state); | ||
495 | break; | ||
496 | |||
497 | default: | ||
498 | /* All NAMED_FIELD opcodes must be handled above */ | ||
499 | break; | ||
500 | } | ||
501 | break; | ||
502 | |||
503 | case AML_TYPE_NAMED_SIMPLE: | ||
504 | |||
505 | status = acpi_ds_create_operands(walk_state, arg); | ||
506 | if (ACPI_FAILURE(status)) { | ||
507 | goto cleanup; | ||
508 | } | ||
509 | |||
510 | switch (op->common.aml_opcode) { | ||
511 | case AML_PROCESSOR_OP: | ||
512 | |||
513 | status = acpi_ex_create_processor(walk_state); | ||
514 | break; | ||
515 | |||
516 | case AML_POWER_RES_OP: | ||
517 | |||
518 | status = acpi_ex_create_power_resource(walk_state); | ||
519 | break; | ||
520 | |||
521 | case AML_MUTEX_OP: | ||
522 | |||
523 | status = acpi_ex_create_mutex(walk_state); | ||
524 | break; | ||
525 | |||
526 | case AML_EVENT_OP: | ||
527 | |||
528 | status = acpi_ex_create_event(walk_state); | ||
529 | break; | ||
530 | |||
531 | case AML_ALIAS_OP: | ||
532 | |||
533 | status = acpi_ex_create_alias(walk_state); | ||
534 | break; | ||
535 | |||
536 | default: | ||
537 | /* Unknown opcode */ | ||
538 | |||
539 | status = AE_OK; | ||
540 | goto cleanup; | ||
541 | } | ||
542 | |||
543 | /* Delete operands */ | ||
544 | |||
545 | for (i = 1; i < walk_state->num_operands; i++) { | ||
546 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
547 | walk_state->operands[i] = NULL; | ||
548 | } | ||
549 | |||
550 | break; | ||
551 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
552 | |||
553 | case AML_TYPE_NAMED_COMPLEX: | ||
554 | |||
555 | switch (op->common.aml_opcode) { | ||
556 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
557 | case AML_REGION_OP: | ||
558 | case AML_DATA_REGION_OP: | ||
559 | |||
560 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
561 | region_space = (acpi_adr_space_type) | ||
562 | ((op->common.value.arg)->common.value. | ||
563 | integer); | ||
564 | } else { | ||
565 | region_space = ACPI_ADR_SPACE_DATA_TABLE; | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * The op_region is not fully parsed at this time. The only valid | ||
570 | * argument is the space_id. (We must save the address of the | ||
571 | * AML of the address and length operands) | ||
572 | * | ||
573 | * If we have a valid region, initialize it. The namespace is | ||
574 | * unlocked at this point. | ||
575 | * | ||
576 | * Need to unlock interpreter if it is locked (if we are running | ||
577 | * a control method), in order to allow _REG methods to be run | ||
578 | * during acpi_ev_initialize_region. | ||
579 | */ | ||
580 | if (walk_state->method_node) { | ||
581 | /* | ||
582 | * Executing a method: initialize the region and unlock | ||
583 | * the interpreter | ||
584 | */ | ||
585 | status = | ||
586 | acpi_ex_create_region(op->named.data, | ||
587 | op->named.length, | ||
588 | region_space, | ||
589 | walk_state); | ||
590 | if (ACPI_FAILURE(status)) { | ||
591 | return (status); | ||
592 | } | ||
593 | |||
594 | acpi_ex_exit_interpreter(); | ||
595 | } | ||
596 | |||
597 | status = | ||
598 | acpi_ev_initialize_region | ||
599 | (acpi_ns_get_attached_object(node), FALSE); | ||
600 | if (walk_state->method_node) { | ||
601 | acpi_ex_enter_interpreter(); | ||
602 | } | ||
603 | |||
604 | if (ACPI_FAILURE(status)) { | ||
605 | /* | ||
606 | * If AE_NOT_EXIST is returned, it is not fatal | ||
607 | * because many regions get created before a handler | ||
608 | * is installed for said region. | ||
609 | */ | ||
610 | if (AE_NOT_EXIST == status) { | ||
611 | status = AE_OK; | ||
612 | } | ||
613 | } | ||
614 | break; | ||
615 | |||
616 | case AML_NAME_OP: | ||
617 | |||
618 | status = acpi_ds_create_node(walk_state, node, op); | ||
619 | break; | ||
620 | |||
621 | case AML_METHOD_OP: | ||
622 | /* | ||
623 | * method_op pkg_length name_string method_flags term_list | ||
624 | * | ||
625 | * Note: We must create the method node/object pair as soon as we | ||
626 | * see the method declaration. This allows later pass1 parsing | ||
627 | * of invocations of the method (need to know the number of | ||
628 | * arguments.) | ||
629 | */ | ||
630 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
631 | "LOADING-Method: State=%p Op=%p NamedObj=%p\n", | ||
632 | walk_state, op, op->named.node)); | ||
633 | |||
634 | if (!acpi_ns_get_attached_object(op->named.node)) { | ||
635 | walk_state->operands[0] = | ||
636 | ACPI_CAST_PTR(void, op->named.node); | ||
637 | walk_state->num_operands = 1; | ||
638 | |||
639 | status = | ||
640 | acpi_ds_create_operands(walk_state, | ||
641 | op->common.value. | ||
642 | arg); | ||
643 | if (ACPI_SUCCESS(status)) { | ||
644 | status = | ||
645 | acpi_ex_create_method(op->named. | ||
646 | data, | ||
647 | op->named. | ||
648 | length, | ||
649 | walk_state); | ||
650 | } | ||
651 | walk_state->operands[0] = NULL; | ||
652 | walk_state->num_operands = 0; | ||
653 | |||
654 | if (ACPI_FAILURE(status)) { | ||
655 | return_ACPI_STATUS(status); | ||
656 | } | ||
657 | } | ||
658 | break; | ||
659 | |||
660 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
661 | |||
662 | default: | ||
663 | /* All NAMED_COMPLEX opcodes must be handled above */ | ||
664 | break; | ||
665 | } | ||
666 | break; | ||
667 | |||
668 | case AML_CLASS_INTERNAL: | ||
669 | |||
670 | /* case AML_INT_NAMEPATH_OP: */ | ||
671 | break; | ||
672 | |||
673 | case AML_CLASS_METHOD_CALL: | ||
674 | |||
675 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
676 | "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", | ||
677 | walk_state, op, node)); | ||
678 | |||
679 | /* | ||
680 | * Lookup the method name and save the Node | ||
681 | */ | ||
682 | status = | ||
683 | acpi_ns_lookup(walk_state->scope_info, | ||
684 | arg->common.value.string, ACPI_TYPE_ANY, | ||
685 | ACPI_IMODE_LOAD_PASS2, | ||
686 | ACPI_NS_SEARCH_PARENT | | ||
687 | ACPI_NS_DONT_OPEN_SCOPE, walk_state, | ||
688 | &(new_node)); | ||
689 | if (ACPI_SUCCESS(status)) { | ||
690 | /* | ||
691 | * Make sure that what we found is indeed a method | ||
692 | * We didn't search for a method on purpose, to see if the name | ||
693 | * would resolve | ||
694 | */ | ||
695 | if (new_node->type != ACPI_TYPE_METHOD) { | ||
696 | status = AE_AML_OPERAND_TYPE; | ||
697 | } | ||
698 | |||
699 | /* We could put the returned object (Node) on the object stack for | ||
700 | * later, but for now, we will put it in the "op" object that the | ||
701 | * parser uses, so we can get it again at the end of this scope | ||
702 | */ | ||
703 | op->common.node = new_node; | ||
704 | } else { | ||
705 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
706 | } | ||
707 | break; | ||
708 | |||
709 | default: | ||
710 | break; | ||
711 | } | ||
712 | |||
713 | cleanup: | ||
714 | |||
715 | /* Remove the Node pushed at the very beginning */ | ||
716 | |||
717 | walk_state->operands[0] = NULL; | ||
718 | walk_state->num_operands = 0; | ||
719 | return_ACPI_STATUS(status); | ||
720 | } | ||
diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index d1e701709dac..76a661fc1e09 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index 83155dd8671e..a6c374ef9914 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 303618889da0..d458b041e651 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -95,47 +95,6 @@ acpi_status acpi_ev_initialize_events(void) | |||
95 | 95 | ||
96 | /******************************************************************************* | 96 | /******************************************************************************* |
97 | * | 97 | * |
98 | * FUNCTION: acpi_ev_install_fadt_gpes | ||
99 | * | ||
100 | * PARAMETERS: None | ||
101 | * | ||
102 | * RETURN: Status | ||
103 | * | ||
104 | * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks | ||
105 | * (0 and 1). The HW must be fully initialized at this point, | ||
106 | * including global lock support. | ||
107 | * | ||
108 | ******************************************************************************/ | ||
109 | |||
110 | acpi_status acpi_ev_install_fadt_gpes(void) | ||
111 | { | ||
112 | acpi_status status; | ||
113 | |||
114 | ACPI_FUNCTION_TRACE(ev_install_fadt_gpes); | ||
115 | |||
116 | /* Namespace must be locked */ | ||
117 | |||
118 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
119 | if (ACPI_FAILURE(status)) { | ||
120 | return (status); | ||
121 | } | ||
122 | |||
123 | /* FADT GPE Block 0 */ | ||
124 | |||
125 | (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, | ||
126 | acpi_gbl_gpe_fadt_blocks[0]); | ||
127 | |||
128 | /* FADT GPE Block 1 */ | ||
129 | |||
130 | (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, | ||
131 | acpi_gbl_gpe_fadt_blocks[1]); | ||
132 | |||
133 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
134 | return_ACPI_STATUS(AE_OK); | ||
135 | } | ||
136 | |||
137 | /******************************************************************************* | ||
138 | * | ||
139 | * FUNCTION: acpi_ev_install_xrupt_handlers | 98 | * FUNCTION: acpi_ev_install_xrupt_handlers |
140 | * | 99 | * |
141 | * PARAMETERS: None | 100 | * PARAMETERS: None |
@@ -258,9 +217,17 @@ u32 acpi_ev_fixed_event_detect(void) | |||
258 | status_bit_mask) | 217 | status_bit_mask) |
259 | && (fixed_enable & acpi_gbl_fixed_event_info[i]. | 218 | && (fixed_enable & acpi_gbl_fixed_event_info[i]. |
260 | enable_bit_mask)) { | 219 | enable_bit_mask)) { |
220 | /* | ||
221 | * Found an active (signalled) event. Invoke global event | ||
222 | * handler if present. | ||
223 | */ | ||
224 | acpi_fixed_event_count[i]++; | ||
225 | if (acpi_gbl_global_event_handler) { | ||
226 | acpi_gbl_global_event_handler | ||
227 | (ACPI_EVENT_TYPE_FIXED, NULL, i, | ||
228 | acpi_gbl_global_event_handler_context); | ||
229 | } | ||
261 | 230 | ||
262 | /* Found an active (signalled) event */ | ||
263 | acpi_os_fixed_event_count(i); | ||
264 | int_status |= acpi_ev_fixed_event_dispatch(i); | 231 | int_status |= acpi_ev_fixed_event_dispatch(i); |
265 | } | 232 | } |
266 | } | 233 | } |
diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c new file mode 100644 index 000000000000..56a562a1e5d7 --- /dev/null +++ b/drivers/acpi/acpica/evglock.c | |||
@@ -0,0 +1,335 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: evglock - Global Lock support | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acevents.h" | ||
47 | #include "acinterp.h" | ||
48 | |||
49 | #define _COMPONENT ACPI_EVENTS | ||
50 | ACPI_MODULE_NAME("evglock") | ||
51 | |||
52 | /* Local prototypes */ | ||
53 | static u32 acpi_ev_global_lock_handler(void *context); | ||
54 | |||
55 | /******************************************************************************* | ||
56 | * | ||
57 | * FUNCTION: acpi_ev_init_global_lock_handler | ||
58 | * | ||
59 | * PARAMETERS: None | ||
60 | * | ||
61 | * RETURN: Status | ||
62 | * | ||
63 | * DESCRIPTION: Install a handler for the global lock release event | ||
64 | * | ||
65 | ******************************************************************************/ | ||
66 | |||
67 | acpi_status acpi_ev_init_global_lock_handler(void) | ||
68 | { | ||
69 | acpi_status status; | ||
70 | |||
71 | ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); | ||
72 | |||
73 | /* Attempt installation of the global lock handler */ | ||
74 | |||
75 | status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, | ||
76 | acpi_ev_global_lock_handler, | ||
77 | NULL); | ||
78 | |||
79 | /* | ||
80 | * If the global lock does not exist on this platform, the attempt to | ||
81 | * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). | ||
82 | * Map to AE_OK, but mark global lock as not present. Any attempt to | ||
83 | * actually use the global lock will be flagged with an error. | ||
84 | */ | ||
85 | acpi_gbl_global_lock_present = FALSE; | ||
86 | if (status == AE_NO_HARDWARE_RESPONSE) { | ||
87 | ACPI_ERROR((AE_INFO, | ||
88 | "No response from Global Lock hardware, disabling lock")); | ||
89 | |||
90 | return_ACPI_STATUS(AE_OK); | ||
91 | } | ||
92 | |||
93 | status = acpi_os_create_lock(&acpi_gbl_global_lock_pending_lock); | ||
94 | if (ACPI_FAILURE(status)) { | ||
95 | return_ACPI_STATUS(status); | ||
96 | } | ||
97 | |||
98 | acpi_gbl_global_lock_pending = FALSE; | ||
99 | acpi_gbl_global_lock_present = TRUE; | ||
100 | return_ACPI_STATUS(status); | ||
101 | } | ||
102 | |||
103 | /******************************************************************************* | ||
104 | * | ||
105 | * FUNCTION: acpi_ev_remove_global_lock_handler | ||
106 | * | ||
107 | * PARAMETERS: None | ||
108 | * | ||
109 | * RETURN: Status | ||
110 | * | ||
111 | * DESCRIPTION: Remove the handler for the Global Lock | ||
112 | * | ||
113 | ******************************************************************************/ | ||
114 | |||
115 | acpi_status acpi_ev_remove_global_lock_handler(void) | ||
116 | { | ||
117 | acpi_status status; | ||
118 | |||
119 | ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); | ||
120 | |||
121 | acpi_gbl_global_lock_present = FALSE; | ||
122 | status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, | ||
123 | acpi_ev_global_lock_handler); | ||
124 | |||
125 | return_ACPI_STATUS(status); | ||
126 | } | ||
127 | |||
128 | /******************************************************************************* | ||
129 | * | ||
130 | * FUNCTION: acpi_ev_global_lock_handler | ||
131 | * | ||
132 | * PARAMETERS: Context - From thread interface, not used | ||
133 | * | ||
134 | * RETURN: ACPI_INTERRUPT_HANDLED | ||
135 | * | ||
136 | * DESCRIPTION: Invoked directly from the SCI handler when a global lock | ||
137 | * release interrupt occurs. If there is actually a pending | ||
138 | * request for the lock, signal the waiting thread. | ||
139 | * | ||
140 | ******************************************************************************/ | ||
141 | |||
142 | static u32 acpi_ev_global_lock_handler(void *context) | ||
143 | { | ||
144 | acpi_status status; | ||
145 | acpi_cpu_flags flags; | ||
146 | |||
147 | flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); | ||
148 | |||
149 | /* | ||
150 | * If a request for the global lock is not actually pending, | ||
151 | * we are done. This handles "spurious" global lock interrupts | ||
152 | * which are possible (and have been seen) with bad BIOSs. | ||
153 | */ | ||
154 | if (!acpi_gbl_global_lock_pending) { | ||
155 | goto cleanup_and_exit; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Send a unit to the global lock semaphore. The actual acquisition | ||
160 | * of the global lock will be performed by the waiting thread. | ||
161 | */ | ||
162 | status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1); | ||
163 | if (ACPI_FAILURE(status)) { | ||
164 | ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); | ||
165 | } | ||
166 | |||
167 | acpi_gbl_global_lock_pending = FALSE; | ||
168 | |||
169 | cleanup_and_exit: | ||
170 | |||
171 | acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); | ||
172 | return (ACPI_INTERRUPT_HANDLED); | ||
173 | } | ||
174 | |||
175 | /****************************************************************************** | ||
176 | * | ||
177 | * FUNCTION: acpi_ev_acquire_global_lock | ||
178 | * | ||
179 | * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. | ||
180 | * | ||
181 | * RETURN: Status | ||
182 | * | ||
183 | * DESCRIPTION: Attempt to gain ownership of the Global Lock. | ||
184 | * | ||
185 | * MUTEX: Interpreter must be locked | ||
186 | * | ||
187 | * Note: The original implementation allowed multiple threads to "acquire" the | ||
188 | * Global Lock, and the OS would hold the lock until the last thread had | ||
189 | * released it. However, this could potentially starve the BIOS out of the | ||
190 | * lock, especially in the case where there is a tight handshake between the | ||
191 | * Embedded Controller driver and the BIOS. Therefore, this implementation | ||
192 | * allows only one thread to acquire the HW Global Lock at a time, and makes | ||
193 | * the global lock appear as a standard mutex on the OS side. | ||
194 | * | ||
195 | *****************************************************************************/ | ||
196 | |||
197 | acpi_status acpi_ev_acquire_global_lock(u16 timeout) | ||
198 | { | ||
199 | acpi_cpu_flags flags; | ||
200 | acpi_status status; | ||
201 | u8 acquired = FALSE; | ||
202 | |||
203 | ACPI_FUNCTION_TRACE(ev_acquire_global_lock); | ||
204 | |||
205 | /* | ||
206 | * Only one thread can acquire the GL at a time, the global_lock_mutex | ||
207 | * enforces this. This interface releases the interpreter if we must wait. | ||
208 | */ | ||
209 | status = | ||
210 | acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex->mutex. | ||
211 | os_mutex, timeout); | ||
212 | if (ACPI_FAILURE(status)) { | ||
213 | return_ACPI_STATUS(status); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Update the global lock handle and check for wraparound. The handle is | ||
218 | * only used for the external global lock interfaces, but it is updated | ||
219 | * here to properly handle the case where a single thread may acquire the | ||
220 | * lock via both the AML and the acpi_acquire_global_lock interfaces. The | ||
221 | * handle is therefore updated on the first acquire from a given thread | ||
222 | * regardless of where the acquisition request originated. | ||
223 | */ | ||
224 | acpi_gbl_global_lock_handle++; | ||
225 | if (acpi_gbl_global_lock_handle == 0) { | ||
226 | acpi_gbl_global_lock_handle = 1; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Make sure that a global lock actually exists. If not, just | ||
231 | * treat the lock as a standard mutex. | ||
232 | */ | ||
233 | if (!acpi_gbl_global_lock_present) { | ||
234 | acpi_gbl_global_lock_acquired = TRUE; | ||
235 | return_ACPI_STATUS(AE_OK); | ||
236 | } | ||
237 | |||
238 | flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); | ||
239 | |||
240 | do { | ||
241 | |||
242 | /* Attempt to acquire the actual hardware lock */ | ||
243 | |||
244 | ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); | ||
245 | if (acquired) { | ||
246 | acpi_gbl_global_lock_acquired = TRUE; | ||
247 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
248 | "Acquired hardware Global Lock\n")); | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * Did not get the lock. The pending bit was set above, and | ||
254 | * we must now wait until we receive the global lock | ||
255 | * released interrupt. | ||
256 | */ | ||
257 | acpi_gbl_global_lock_pending = TRUE; | ||
258 | acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); | ||
259 | |||
260 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
261 | "Waiting for hardware Global Lock\n")); | ||
262 | |||
263 | /* | ||
264 | * Wait for handshake with the global lock interrupt handler. | ||
265 | * This interface releases the interpreter if we must wait. | ||
266 | */ | ||
267 | status = | ||
268 | acpi_ex_system_wait_semaphore | ||
269 | (acpi_gbl_global_lock_semaphore, ACPI_WAIT_FOREVER); | ||
270 | |||
271 | flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); | ||
272 | |||
273 | } while (ACPI_SUCCESS(status)); | ||
274 | |||
275 | acpi_gbl_global_lock_pending = FALSE; | ||
276 | acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); | ||
277 | |||
278 | return_ACPI_STATUS(status); | ||
279 | } | ||
280 | |||
281 | /******************************************************************************* | ||
282 | * | ||
283 | * FUNCTION: acpi_ev_release_global_lock | ||
284 | * | ||
285 | * PARAMETERS: None | ||
286 | * | ||
287 | * RETURN: Status | ||
288 | * | ||
289 | * DESCRIPTION: Releases ownership of the Global Lock. | ||
290 | * | ||
291 | ******************************************************************************/ | ||
292 | |||
293 | acpi_status acpi_ev_release_global_lock(void) | ||
294 | { | ||
295 | u8 pending = FALSE; | ||
296 | acpi_status status = AE_OK; | ||
297 | |||
298 | ACPI_FUNCTION_TRACE(ev_release_global_lock); | ||
299 | |||
300 | /* Lock must be already acquired */ | ||
301 | |||
302 | if (!acpi_gbl_global_lock_acquired) { | ||
303 | ACPI_WARNING((AE_INFO, | ||
304 | "Cannot release the ACPI Global Lock, it has not been acquired")); | ||
305 | return_ACPI_STATUS(AE_NOT_ACQUIRED); | ||
306 | } | ||
307 | |||
308 | if (acpi_gbl_global_lock_present) { | ||
309 | |||
310 | /* Allow any thread to release the lock */ | ||
311 | |||
312 | ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending); | ||
313 | |||
314 | /* | ||
315 | * If the pending bit was set, we must write GBL_RLS to the control | ||
316 | * register | ||
317 | */ | ||
318 | if (pending) { | ||
319 | status = | ||
320 | acpi_write_bit_register | ||
321 | (ACPI_BITREG_GLOBAL_LOCK_RELEASE, | ||
322 | ACPI_ENABLE_EVENT); | ||
323 | } | ||
324 | |||
325 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
326 | "Released hardware Global Lock\n")); | ||
327 | } | ||
328 | |||
329 | acpi_gbl_global_lock_acquired = FALSE; | ||
330 | |||
331 | /* Release the local GL mutex */ | ||
332 | |||
333 | acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); | ||
334 | return_ACPI_STATUS(status); | ||
335 | } | ||
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index f226eac314db..65c79add3b19 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -52,6 +52,8 @@ ACPI_MODULE_NAME("evgpe") | |||
52 | /* Local prototypes */ | 52 | /* Local prototypes */ |
53 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); | 53 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); |
54 | 54 | ||
55 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context); | ||
56 | |||
55 | /******************************************************************************* | 57 | /******************************************************************************* |
56 | * | 58 | * |
57 | * FUNCTION: acpi_ev_update_gpe_enable_mask | 59 | * FUNCTION: acpi_ev_update_gpe_enable_mask |
@@ -102,7 +104,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) | |||
102 | * | 104 | * |
103 | * RETURN: Status | 105 | * RETURN: Status |
104 | * | 106 | * |
105 | * DESCRIPTION: Clear the given GPE from stale events and enable it. | 107 | * DESCRIPTION: Clear a GPE of stale events and enable it. |
106 | * | 108 | * |
107 | ******************************************************************************/ | 109 | ******************************************************************************/ |
108 | acpi_status | 110 | acpi_status |
@@ -113,12 +115,13 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
113 | ACPI_FUNCTION_TRACE(ev_enable_gpe); | 115 | ACPI_FUNCTION_TRACE(ev_enable_gpe); |
114 | 116 | ||
115 | /* | 117 | /* |
116 | * We will only allow a GPE to be enabled if it has either an | 118 | * We will only allow a GPE to be enabled if it has either an associated |
117 | * associated method (_Lxx/_Exx) or a handler. Otherwise, the | 119 | * method (_Lxx/_Exx) or a handler, or is using the implicit notify |
118 | * GPE will be immediately disabled by acpi_ev_gpe_dispatch the | 120 | * feature. Otherwise, the GPE will be immediately disabled by |
119 | * first time it fires. | 121 | * acpi_ev_gpe_dispatch the first time it fires. |
120 | */ | 122 | */ |
121 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { | 123 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == |
124 | ACPI_GPE_DISPATCH_NONE) { | ||
122 | return_ACPI_STATUS(AE_NO_HANDLER); | 125 | return_ACPI_STATUS(AE_NO_HANDLER); |
123 | } | 126 | } |
124 | 127 | ||
@@ -137,9 +140,9 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
137 | 140 | ||
138 | /******************************************************************************* | 141 | /******************************************************************************* |
139 | * | 142 | * |
140 | * FUNCTION: acpi_raw_enable_gpe | 143 | * FUNCTION: acpi_ev_add_gpe_reference |
141 | * | 144 | * |
142 | * PARAMETERS: gpe_event_info - GPE to enable | 145 | * PARAMETERS: gpe_event_info - Add a reference to this GPE |
143 | * | 146 | * |
144 | * RETURN: Status | 147 | * RETURN: Status |
145 | * | 148 | * |
@@ -148,16 +151,21 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
148 | * | 151 | * |
149 | ******************************************************************************/ | 152 | ******************************************************************************/ |
150 | 153 | ||
151 | acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | 154 | acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) |
152 | { | 155 | { |
153 | acpi_status status = AE_OK; | 156 | acpi_status status = AE_OK; |
154 | 157 | ||
158 | ACPI_FUNCTION_TRACE(ev_add_gpe_reference); | ||
159 | |||
155 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { | 160 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { |
156 | return_ACPI_STATUS(AE_LIMIT); | 161 | return_ACPI_STATUS(AE_LIMIT); |
157 | } | 162 | } |
158 | 163 | ||
159 | gpe_event_info->runtime_count++; | 164 | gpe_event_info->runtime_count++; |
160 | if (gpe_event_info->runtime_count == 1) { | 165 | if (gpe_event_info->runtime_count == 1) { |
166 | |||
167 | /* Enable on first reference */ | ||
168 | |||
161 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | 169 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); |
162 | if (ACPI_SUCCESS(status)) { | 170 | if (ACPI_SUCCESS(status)) { |
163 | status = acpi_ev_enable_gpe(gpe_event_info); | 171 | status = acpi_ev_enable_gpe(gpe_event_info); |
@@ -173,9 +181,9 @@ acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
173 | 181 | ||
174 | /******************************************************************************* | 182 | /******************************************************************************* |
175 | * | 183 | * |
176 | * FUNCTION: acpi_raw_disable_gpe | 184 | * FUNCTION: acpi_ev_remove_gpe_reference |
177 | * | 185 | * |
178 | * PARAMETERS: gpe_event_info - GPE to disable | 186 | * PARAMETERS: gpe_event_info - Remove a reference to this GPE |
179 | * | 187 | * |
180 | * RETURN: Status | 188 | * RETURN: Status |
181 | * | 189 | * |
@@ -184,16 +192,21 @@ acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
184 | * | 192 | * |
185 | ******************************************************************************/ | 193 | ******************************************************************************/ |
186 | 194 | ||
187 | acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | 195 | acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) |
188 | { | 196 | { |
189 | acpi_status status = AE_OK; | 197 | acpi_status status = AE_OK; |
190 | 198 | ||
199 | ACPI_FUNCTION_TRACE(ev_remove_gpe_reference); | ||
200 | |||
191 | if (!gpe_event_info->runtime_count) { | 201 | if (!gpe_event_info->runtime_count) { |
192 | return_ACPI_STATUS(AE_LIMIT); | 202 | return_ACPI_STATUS(AE_LIMIT); |
193 | } | 203 | } |
194 | 204 | ||
195 | gpe_event_info->runtime_count--; | 205 | gpe_event_info->runtime_count--; |
196 | if (!gpe_event_info->runtime_count) { | 206 | if (!gpe_event_info->runtime_count) { |
207 | |||
208 | /* Disable on last reference */ | ||
209 | |||
197 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | 210 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); |
198 | if (ACPI_SUCCESS(status)) { | 211 | if (ACPI_SUCCESS(status)) { |
199 | status = acpi_hw_low_set_gpe(gpe_event_info, | 212 | status = acpi_hw_low_set_gpe(gpe_event_info, |
@@ -360,6 +373,15 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
360 | 373 | ||
361 | gpe_register_info = &gpe_block->register_info[i]; | 374 | gpe_register_info = &gpe_block->register_info[i]; |
362 | 375 | ||
376 | /* | ||
377 | * Optimization: If there are no GPEs enabled within this | ||
378 | * register, we can safely ignore the entire register. | ||
379 | */ | ||
380 | if (!(gpe_register_info->enable_for_run | | ||
381 | gpe_register_info->enable_for_wake)) { | ||
382 | continue; | ||
383 | } | ||
384 | |||
363 | /* Read the Status Register */ | 385 | /* Read the Status Register */ |
364 | 386 | ||
365 | status = | 387 | status = |
@@ -379,7 +401,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
379 | } | 401 | } |
380 | 402 | ||
381 | ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, | 403 | ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, |
382 | "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", | 404 | "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", |
383 | gpe_register_info->base_gpe_number, | 405 | gpe_register_info->base_gpe_number, |
384 | status_reg, enable_reg)); | 406 | status_reg, enable_reg)); |
385 | 407 | ||
@@ -405,7 +427,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
405 | * or method. | 427 | * or method. |
406 | */ | 428 | */ |
407 | int_status |= | 429 | int_status |= |
408 | acpi_ev_gpe_dispatch(&gpe_block-> | 430 | acpi_ev_gpe_dispatch(gpe_block-> |
431 | node, | ||
432 | &gpe_block-> | ||
409 | event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); | 433 | event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); |
410 | } | 434 | } |
411 | } | 435 | } |
@@ -435,19 +459,29 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
435 | * an interrupt handler. | 459 | * an interrupt handler. |
436 | * | 460 | * |
437 | ******************************************************************************/ | 461 | ******************************************************************************/ |
438 | static void acpi_ev_asynch_enable_gpe(void *context); | ||
439 | 462 | ||
440 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | 463 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) |
441 | { | 464 | { |
442 | struct acpi_gpe_event_info *gpe_event_info = (void *)context; | 465 | struct acpi_gpe_event_info *gpe_event_info = context; |
443 | acpi_status status; | 466 | acpi_status status; |
444 | struct acpi_gpe_event_info local_gpe_event_info; | 467 | struct acpi_gpe_event_info *local_gpe_event_info; |
445 | struct acpi_evaluate_info *info; | 468 | struct acpi_evaluate_info *info; |
469 | struct acpi_gpe_notify_object *notify_object; | ||
446 | 470 | ||
447 | ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); | 471 | ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); |
448 | 472 | ||
473 | /* Allocate a local GPE block */ | ||
474 | |||
475 | local_gpe_event_info = | ||
476 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_event_info)); | ||
477 | if (!local_gpe_event_info) { | ||
478 | ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "while handling a GPE")); | ||
479 | return_VOID; | ||
480 | } | ||
481 | |||
449 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | 482 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); |
450 | if (ACPI_FAILURE(status)) { | 483 | if (ACPI_FAILURE(status)) { |
484 | ACPI_FREE(local_gpe_event_info); | ||
451 | return_VOID; | 485 | return_VOID; |
452 | } | 486 | } |
453 | 487 | ||
@@ -455,6 +489,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
455 | 489 | ||
456 | if (!acpi_ev_valid_gpe_event(gpe_event_info)) { | 490 | if (!acpi_ev_valid_gpe_event(gpe_event_info)) { |
457 | status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 491 | status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
492 | ACPI_FREE(local_gpe_event_info); | ||
458 | return_VOID; | 493 | return_VOID; |
459 | } | 494 | } |
460 | 495 | ||
@@ -462,7 +497,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
462 | * Take a snapshot of the GPE info for this level - we copy the info to | 497 | * Take a snapshot of the GPE info for this level - we copy the info to |
463 | * prevent a race condition with remove_handler/remove_block. | 498 | * prevent a race condition with remove_handler/remove_block. |
464 | */ | 499 | */ |
465 | ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info, | 500 | ACPI_MEMCPY(local_gpe_event_info, gpe_event_info, |
466 | sizeof(struct acpi_gpe_event_info)); | 501 | sizeof(struct acpi_gpe_event_info)); |
467 | 502 | ||
468 | status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 503 | status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
@@ -470,12 +505,34 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
470 | return_VOID; | 505 | return_VOID; |
471 | } | 506 | } |
472 | 507 | ||
473 | /* | 508 | /* Do the correct dispatch - normal method or implicit notify */ |
474 | * Must check for control method type dispatch one more time to avoid a | 509 | |
475 | * race with ev_gpe_install_handler | 510 | switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { |
476 | */ | 511 | case ACPI_GPE_DISPATCH_NOTIFY: |
477 | if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == | 512 | |
478 | ACPI_GPE_DISPATCH_METHOD) { | 513 | /* |
514 | * Implicit notify. | ||
515 | * Dispatch a DEVICE_WAKE notify to the appropriate handler. | ||
516 | * NOTE: the request is queued for execution after this method | ||
517 | * completes. The notify handlers are NOT invoked synchronously | ||
518 | * from this thread -- because handlers may in turn run other | ||
519 | * control methods. | ||
520 | */ | ||
521 | status = acpi_ev_queue_notify_request( | ||
522 | local_gpe_event_info->dispatch.device.node, | ||
523 | ACPI_NOTIFY_DEVICE_WAKE); | ||
524 | |||
525 | notify_object = local_gpe_event_info->dispatch.device.next; | ||
526 | while (ACPI_SUCCESS(status) && notify_object) { | ||
527 | status = acpi_ev_queue_notify_request( | ||
528 | notify_object->node, | ||
529 | ACPI_NOTIFY_DEVICE_WAKE); | ||
530 | notify_object = notify_object->next; | ||
531 | } | ||
532 | |||
533 | break; | ||
534 | |||
535 | case ACPI_GPE_DISPATCH_METHOD: | ||
479 | 536 | ||
480 | /* Allocate the evaluation information block */ | 537 | /* Allocate the evaluation information block */ |
481 | 538 | ||
@@ -488,7 +545,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
488 | * control method that corresponds to this GPE | 545 | * control method that corresponds to this GPE |
489 | */ | 546 | */ |
490 | info->prefix_node = | 547 | info->prefix_node = |
491 | local_gpe_event_info.dispatch.method_node; | 548 | local_gpe_event_info->dispatch.method_node; |
492 | info->flags = ACPI_IGNORE_RETURN_VALUE; | 549 | info->flags = ACPI_IGNORE_RETURN_VALUE; |
493 | 550 | ||
494 | status = acpi_ns_evaluate(info); | 551 | status = acpi_ns_evaluate(info); |
@@ -499,46 +556,98 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
499 | ACPI_EXCEPTION((AE_INFO, status, | 556 | ACPI_EXCEPTION((AE_INFO, status, |
500 | "while evaluating GPE method [%4.4s]", | 557 | "while evaluating GPE method [%4.4s]", |
501 | acpi_ut_get_node_name | 558 | acpi_ut_get_node_name |
502 | (local_gpe_event_info.dispatch. | 559 | (local_gpe_event_info->dispatch. |
503 | method_node))); | 560 | method_node))); |
504 | } | 561 | } |
562 | |||
563 | break; | ||
564 | |||
565 | default: | ||
566 | return_VOID; /* Should never happen */ | ||
505 | } | 567 | } |
568 | |||
506 | /* Defer enabling of GPE until all notify handlers are done */ | 569 | /* Defer enabling of GPE until all notify handlers are done */ |
507 | acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, | 570 | |
508 | gpe_event_info); | 571 | status = acpi_os_execute(OSL_NOTIFY_HANDLER, |
572 | acpi_ev_asynch_enable_gpe, | ||
573 | local_gpe_event_info); | ||
574 | if (ACPI_FAILURE(status)) { | ||
575 | ACPI_FREE(local_gpe_event_info); | ||
576 | } | ||
509 | return_VOID; | 577 | return_VOID; |
510 | } | 578 | } |
511 | 579 | ||
512 | static void acpi_ev_asynch_enable_gpe(void *context) | 580 | |
581 | /******************************************************************************* | ||
582 | * | ||
583 | * FUNCTION: acpi_ev_asynch_enable_gpe | ||
584 | * | ||
585 | * PARAMETERS: Context (gpe_event_info) - Info for this GPE | ||
586 | * Callback from acpi_os_execute | ||
587 | * | ||
588 | * RETURN: None | ||
589 | * | ||
590 | * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to | ||
591 | * complete (i.e., finish execution of Notify) | ||
592 | * | ||
593 | ******************************************************************************/ | ||
594 | |||
595 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) | ||
513 | { | 596 | { |
514 | struct acpi_gpe_event_info *gpe_event_info = context; | 597 | struct acpi_gpe_event_info *gpe_event_info = context; |
598 | |||
599 | (void)acpi_ev_finish_gpe(gpe_event_info); | ||
600 | |||
601 | ACPI_FREE(gpe_event_info); | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | |||
606 | /******************************************************************************* | ||
607 | * | ||
608 | * FUNCTION: acpi_ev_finish_gpe | ||
609 | * | ||
610 | * PARAMETERS: gpe_event_info - Info for this GPE | ||
611 | * | ||
612 | * RETURN: Status | ||
613 | * | ||
614 | * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution | ||
615 | * of a GPE method or a synchronous or asynchronous GPE handler. | ||
616 | * | ||
617 | ******************************************************************************/ | ||
618 | |||
619 | acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info) | ||
620 | { | ||
515 | acpi_status status; | 621 | acpi_status status; |
622 | |||
516 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == | 623 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
517 | ACPI_GPE_LEVEL_TRIGGERED) { | 624 | ACPI_GPE_LEVEL_TRIGGERED) { |
518 | /* | 625 | /* |
519 | * GPE is level-triggered, we clear the GPE status bit after handling | 626 | * GPE is level-triggered, we clear the GPE status bit after |
520 | * the event. | 627 | * handling the event. |
521 | */ | 628 | */ |
522 | status = acpi_hw_clear_gpe(gpe_event_info); | 629 | status = acpi_hw_clear_gpe(gpe_event_info); |
523 | if (ACPI_FAILURE(status)) { | 630 | if (ACPI_FAILURE(status)) { |
524 | return_VOID; | 631 | return (status); |
525 | } | 632 | } |
526 | } | 633 | } |
527 | 634 | ||
528 | /* | 635 | /* |
529 | * Enable this GPE, conditionally. This means that the GPE will only be | 636 | * Enable this GPE, conditionally. This means that the GPE will |
530 | * physically enabled if the enable_for_run bit is set in the event_info | 637 | * only be physically enabled if the enable_for_run bit is set |
638 | * in the event_info. | ||
531 | */ | 639 | */ |
532 | (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE); | 640 | (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); |
533 | 641 | return (AE_OK); | |
534 | return_VOID; | ||
535 | } | 642 | } |
536 | 643 | ||
644 | |||
537 | /******************************************************************************* | 645 | /******************************************************************************* |
538 | * | 646 | * |
539 | * FUNCTION: acpi_ev_gpe_dispatch | 647 | * FUNCTION: acpi_ev_gpe_dispatch |
540 | * | 648 | * |
541 | * PARAMETERS: gpe_event_info - Info for this GPE | 649 | * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1 |
650 | * gpe_event_info - Info for this GPE | ||
542 | * gpe_number - Number relative to the parent GPE block | 651 | * gpe_number - Number relative to the parent GPE block |
543 | * | 652 | * |
544 | * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED | 653 | * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED |
@@ -551,13 +660,22 @@ static void acpi_ev_asynch_enable_gpe(void *context) | |||
551 | ******************************************************************************/ | 660 | ******************************************************************************/ |
552 | 661 | ||
553 | u32 | 662 | u32 |
554 | acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) | 663 | acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, |
664 | struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) | ||
555 | { | 665 | { |
556 | acpi_status status; | 666 | acpi_status status; |
667 | u32 return_value; | ||
557 | 668 | ||
558 | ACPI_FUNCTION_TRACE(ev_gpe_dispatch); | 669 | ACPI_FUNCTION_TRACE(ev_gpe_dispatch); |
559 | 670 | ||
560 | acpi_os_gpe_count(gpe_number); | 671 | /* Invoke global event handler if present */ |
672 | |||
673 | acpi_gpe_count++; | ||
674 | if (acpi_gbl_global_event_handler) { | ||
675 | acpi_gbl_global_event_handler(ACPI_EVENT_TYPE_GPE, gpe_device, | ||
676 | gpe_number, | ||
677 | acpi_gbl_global_event_handler_context); | ||
678 | } | ||
561 | 679 | ||
562 | /* | 680 | /* |
563 | * If edge-triggered, clear the GPE status bit now. Note that | 681 | * If edge-triggered, clear the GPE status bit now. Note that |
@@ -568,59 +686,55 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) | |||
568 | status = acpi_hw_clear_gpe(gpe_event_info); | 686 | status = acpi_hw_clear_gpe(gpe_event_info); |
569 | if (ACPI_FAILURE(status)) { | 687 | if (ACPI_FAILURE(status)) { |
570 | ACPI_EXCEPTION((AE_INFO, status, | 688 | ACPI_EXCEPTION((AE_INFO, status, |
571 | "Unable to clear GPE[0x%2X]", | 689 | "Unable to clear GPE%02X", gpe_number)); |
572 | gpe_number)); | ||
573 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | 690 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); |
574 | } | 691 | } |
575 | } | 692 | } |
576 | 693 | ||
577 | /* | 694 | /* |
578 | * Dispatch the GPE to either an installed handler, or the control method | 695 | * Always disable the GPE so that it does not keep firing before |
579 | * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke | 696 | * any asynchronous activity completes (either from the execution |
580 | * it and do not attempt to run the method. If there is neither a handler | 697 | * of a GPE method or an asynchronous GPE handler.) |
581 | * nor a method, we disable this GPE to prevent further such pointless | 698 | * |
582 | * events from firing. | 699 | * If there is no handler or method to run, just disable the |
700 | * GPE and leave it disabled permanently to prevent further such | ||
701 | * pointless events from firing. | ||
702 | */ | ||
703 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
704 | if (ACPI_FAILURE(status)) { | ||
705 | ACPI_EXCEPTION((AE_INFO, status, | ||
706 | "Unable to disable GPE%02X", gpe_number)); | ||
707 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
708 | } | ||
709 | |||
710 | /* | ||
711 | * Dispatch the GPE to either an installed handler or the control | ||
712 | * method associated with this GPE (_Lxx or _Exx). If a handler | ||
713 | * exists, we invoke it and do not attempt to run the method. | ||
714 | * If there is neither a handler nor a method, leave the GPE | ||
715 | * disabled. | ||
583 | */ | 716 | */ |
584 | switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { | 717 | switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { |
585 | case ACPI_GPE_DISPATCH_HANDLER: | 718 | case ACPI_GPE_DISPATCH_HANDLER: |
586 | 719 | ||
587 | /* | 720 | /* Invoke the installed handler (at interrupt level) */ |
588 | * Invoke the installed handler (at interrupt level) | ||
589 | * Ignore return status for now. | ||
590 | * TBD: leave GPE disabled on error? | ||
591 | */ | ||
592 | (void)gpe_event_info->dispatch.handler->address(gpe_event_info-> | ||
593 | dispatch. | ||
594 | handler-> | ||
595 | context); | ||
596 | 721 | ||
597 | /* It is now safe to clear level-triggered events. */ | 722 | return_value = |
723 | gpe_event_info->dispatch.handler->address(gpe_device, | ||
724 | gpe_number, | ||
725 | gpe_event_info-> | ||
726 | dispatch.handler-> | ||
727 | context); | ||
598 | 728 | ||
599 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == | 729 | /* If requested, clear (if level-triggered) and reenable the GPE */ |
600 | ACPI_GPE_LEVEL_TRIGGERED) { | 730 | |
601 | status = acpi_hw_clear_gpe(gpe_event_info); | 731 | if (return_value & ACPI_REENABLE_GPE) { |
602 | if (ACPI_FAILURE(status)) { | 732 | (void)acpi_ev_finish_gpe(gpe_event_info); |
603 | ACPI_EXCEPTION((AE_INFO, status, | ||
604 | "Unable to clear GPE[0x%2X]", | ||
605 | gpe_number)); | ||
606 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
607 | } | ||
608 | } | 733 | } |
609 | break; | 734 | break; |
610 | 735 | ||
611 | case ACPI_GPE_DISPATCH_METHOD: | 736 | case ACPI_GPE_DISPATCH_METHOD: |
612 | 737 | case ACPI_GPE_DISPATCH_NOTIFY: | |
613 | /* | ||
614 | * Disable the GPE, so it doesn't keep firing before the method has a | ||
615 | * chance to run (it runs asynchronously with interrupts enabled). | ||
616 | */ | ||
617 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
618 | if (ACPI_FAILURE(status)) { | ||
619 | ACPI_EXCEPTION((AE_INFO, status, | ||
620 | "Unable to disable GPE[0x%2X]", | ||
621 | gpe_number)); | ||
622 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
623 | } | ||
624 | 738 | ||
625 | /* | 739 | /* |
626 | * Execute the method associated with the GPE | 740 | * Execute the method associated with the GPE |
@@ -631,7 +745,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) | |||
631 | gpe_event_info); | 745 | gpe_event_info); |
632 | if (ACPI_FAILURE(status)) { | 746 | if (ACPI_FAILURE(status)) { |
633 | ACPI_EXCEPTION((AE_INFO, status, | 747 | ACPI_EXCEPTION((AE_INFO, status, |
634 | "Unable to queue handler for GPE[0x%2X] - event disabled", | 748 | "Unable to queue handler for GPE%2X - event disabled", |
635 | gpe_number)); | 749 | gpe_number)); |
636 | } | 750 | } |
637 | break; | 751 | break; |
@@ -644,20 +758,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) | |||
644 | * a GPE to be enabled if it has no handler or method. | 758 | * a GPE to be enabled if it has no handler or method. |
645 | */ | 759 | */ |
646 | ACPI_ERROR((AE_INFO, | 760 | ACPI_ERROR((AE_INFO, |
647 | "No handler or method for GPE[0x%2X], disabling event", | 761 | "No handler or method for GPE%02X, disabling event", |
648 | gpe_number)); | 762 | gpe_number)); |
649 | 763 | ||
650 | /* | ||
651 | * Disable the GPE. The GPE will remain disabled a handler | ||
652 | * is installed or ACPICA is restarted. | ||
653 | */ | ||
654 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
655 | if (ACPI_FAILURE(status)) { | ||
656 | ACPI_EXCEPTION((AE_INFO, status, | ||
657 | "Unable to disable GPE[0x%2X]", | ||
658 | gpe_number)); | ||
659 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
660 | } | ||
661 | break; | 764 | break; |
662 | } | 765 | } |
663 | 766 | ||
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 85445fb5844e..ca2c41a53311 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -361,6 +361,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
361 | 361 | ||
362 | gpe_block->node = gpe_device; | 362 | gpe_block->node = gpe_device; |
363 | gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH); | 363 | gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH); |
364 | gpe_block->initialized = FALSE; | ||
364 | gpe_block->register_count = register_count; | 365 | gpe_block->register_count = register_count; |
365 | gpe_block->block_base_number = gpe_block_base_number; | 366 | gpe_block->block_base_number = gpe_block_base_number; |
366 | 367 | ||
@@ -385,11 +386,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
385 | return_ACPI_STATUS(status); | 386 | return_ACPI_STATUS(status); |
386 | } | 387 | } |
387 | 388 | ||
389 | acpi_gbl_all_gpes_initialized = FALSE; | ||
390 | |||
388 | /* Find all GPE methods (_Lxx or_Exx) for this block */ | 391 | /* Find all GPE methods (_Lxx or_Exx) for this block */ |
389 | 392 | ||
390 | walk_info.gpe_block = gpe_block; | 393 | walk_info.gpe_block = gpe_block; |
391 | walk_info.gpe_device = gpe_device; | 394 | walk_info.gpe_device = gpe_device; |
392 | walk_info.enable_this_gpe = FALSE; | ||
393 | walk_info.execute_by_owner_id = FALSE; | 395 | walk_info.execute_by_owner_id = FALSE; |
394 | 396 | ||
395 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, | 397 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, |
@@ -421,48 +423,45 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
421 | * | 423 | * |
422 | * FUNCTION: acpi_ev_initialize_gpe_block | 424 | * FUNCTION: acpi_ev_initialize_gpe_block |
423 | * | 425 | * |
424 | * PARAMETERS: gpe_device - Handle to the parent GPE block | 426 | * PARAMETERS: acpi_gpe_callback |
425 | * gpe_block - Gpe Block info | ||
426 | * | 427 | * |
427 | * RETURN: Status | 428 | * RETURN: Status |
428 | * | 429 | * |
429 | * DESCRIPTION: Initialize and enable a GPE block. First find and run any | 430 | * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have |
430 | * _PRT methods associated with the block, then enable the | 431 | * associated methods. |
431 | * appropriate GPEs. | ||
432 | * Note: Assumes namespace is locked. | 432 | * Note: Assumes namespace is locked. |
433 | * | 433 | * |
434 | ******************************************************************************/ | 434 | ******************************************************************************/ |
435 | 435 | ||
436 | acpi_status | 436 | acpi_status |
437 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | 437 | acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, |
438 | struct acpi_gpe_block_info *gpe_block) | 438 | struct acpi_gpe_block_info *gpe_block, |
439 | void *ignored) | ||
439 | { | 440 | { |
440 | acpi_status status; | 441 | acpi_status status; |
441 | struct acpi_gpe_event_info *gpe_event_info; | 442 | struct acpi_gpe_event_info *gpe_event_info; |
442 | u32 gpe_enabled_count; | 443 | u32 gpe_enabled_count; |
443 | u32 gpe_index; | 444 | u32 gpe_index; |
444 | u32 gpe_number; | ||
445 | u32 i; | 445 | u32 i; |
446 | u32 j; | 446 | u32 j; |
447 | 447 | ||
448 | ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); | 448 | ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); |
449 | 449 | ||
450 | /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ | 450 | /* |
451 | 451 | * Ignore a null GPE block (e.g., if no GPE block 1 exists), and | |
452 | if (!gpe_block) { | 452 | * any GPE blocks that have been initialized already. |
453 | */ | ||
454 | if (!gpe_block || gpe_block->initialized) { | ||
453 | return_ACPI_STATUS(AE_OK); | 455 | return_ACPI_STATUS(AE_OK); |
454 | } | 456 | } |
455 | 457 | ||
456 | /* | 458 | /* |
457 | * Enable all GPEs that have a corresponding method. Any other GPEs | 459 | * Enable all GPEs that have a corresponding method and have the |
458 | * within this block must be enabled via the acpi_enable_gpe interface. | 460 | * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block |
461 | * must be enabled via the acpi_enable_gpe() interface. | ||
459 | */ | 462 | */ |
460 | gpe_enabled_count = 0; | 463 | gpe_enabled_count = 0; |
461 | 464 | ||
462 | if (gpe_device == acpi_gbl_fadt_gpe_device) { | ||
463 | gpe_device = NULL; | ||
464 | } | ||
465 | |||
466 | for (i = 0; i < gpe_block->register_count; i++) { | 465 | for (i = 0; i < gpe_block->register_count; i++) { |
467 | for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { | 466 | for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { |
468 | 467 | ||
@@ -470,27 +469,24 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
470 | 469 | ||
471 | gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; | 470 | gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; |
472 | gpe_event_info = &gpe_block->event_info[gpe_index]; | 471 | gpe_event_info = &gpe_block->event_info[gpe_index]; |
473 | gpe_number = gpe_index + gpe_block->block_base_number; | ||
474 | |||
475 | /* Ignore GPEs that have no corresponding _Lxx/_Exx method */ | ||
476 | |||
477 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) { | ||
478 | continue; | ||
479 | } | ||
480 | 472 | ||
481 | /* | 473 | /* |
482 | * If the GPE has already been enabled for runtime | 474 | * Ignore GPEs that have no corresponding _Lxx/_Exx method |
483 | * signaling, make sure it remains enabled, but do not | 475 | * and GPEs that are used to wake the system |
484 | * increment its reference counter. | ||
485 | */ | 476 | */ |
486 | status = gpe_event_info->runtime_count ? | 477 | if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == |
487 | acpi_ev_enable_gpe(gpe_event_info) : | 478 | ACPI_GPE_DISPATCH_NONE) |
488 | acpi_enable_gpe(gpe_device, gpe_number); | 479 | || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) |
480 | == ACPI_GPE_DISPATCH_HANDLER) | ||
481 | || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | ||
482 | continue; | ||
483 | } | ||
489 | 484 | ||
485 | status = acpi_ev_add_gpe_reference(gpe_event_info); | ||
490 | if (ACPI_FAILURE(status)) { | 486 | if (ACPI_FAILURE(status)) { |
491 | ACPI_EXCEPTION((AE_INFO, status, | 487 | ACPI_EXCEPTION((AE_INFO, status, |
492 | "Could not enable GPE 0x%02X", | 488 | "Could not enable GPE 0x%02X", |
493 | gpe_number)); | 489 | gpe_index + gpe_block->block_base_number)); |
494 | continue; | 490 | continue; |
495 | } | 491 | } |
496 | 492 | ||
@@ -504,5 +500,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
504 | gpe_enabled_count)); | 500 | gpe_enabled_count)); |
505 | } | 501 | } |
506 | 502 | ||
503 | gpe_block->initialized = TRUE; | ||
504 | |||
507 | return_ACPI_STATUS(AE_OK); | 505 | return_ACPI_STATUS(AE_OK); |
508 | } | 506 | } |
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 3084c5de1bba..ce9aa9f9a972 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -45,11 +45,27 @@ | |||
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "acevents.h" | 46 | #include "acevents.h" |
47 | #include "acnamesp.h" | 47 | #include "acnamesp.h" |
48 | #include "acinterp.h" | ||
49 | 48 | ||
50 | #define _COMPONENT ACPI_EVENTS | 49 | #define _COMPONENT ACPI_EVENTS |
51 | ACPI_MODULE_NAME("evgpeinit") | 50 | ACPI_MODULE_NAME("evgpeinit") |
52 | 51 | ||
52 | /* | ||
53 | * Note: History of _PRW support in ACPICA | ||
54 | * | ||
55 | * Originally (2000 - 2010), the GPE initialization code performed a walk of | ||
56 | * the entire namespace to execute the _PRW methods and detect all GPEs | ||
57 | * capable of waking the system. | ||
58 | * | ||
59 | * As of 10/2010, the _PRW method execution has been removed since it is | ||
60 | * actually unnecessary. The host OS must in fact execute all _PRW methods | ||
61 | * in order to identify the device/power-resource dependencies. We now put | ||
62 | * the onus on the host OS to identify the wake GPEs as part of this process | ||
63 | * and to inform ACPICA of these GPEs via the acpi_setup_gpe_for_wake interface. This | ||
64 | * not only reduces the complexity of the ACPICA initialization code, but in | ||
65 | * some cases (on systems with very large namespaces) it should reduce the | ||
66 | * kernel boot time as well. | ||
67 | */ | ||
68 | |||
53 | /******************************************************************************* | 69 | /******************************************************************************* |
54 | * | 70 | * |
55 | * FUNCTION: acpi_ev_gpe_initialize | 71 | * FUNCTION: acpi_ev_gpe_initialize |
@@ -210,8 +226,7 @@ acpi_status acpi_ev_gpe_initialize(void) | |||
210 | * | 226 | * |
211 | * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a | 227 | * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a |
212 | * result of a Load() or load_table() operation. If new GPE | 228 | * result of a Load() or load_table() operation. If new GPE |
213 | * methods have been installed, register the new methods and | 229 | * methods have been installed, register the new methods. |
214 | * enable and runtime GPEs that are associated with them. | ||
215 | * | 230 | * |
216 | ******************************************************************************/ | 231 | ******************************************************************************/ |
217 | 232 | ||
@@ -223,7 +238,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id) | |||
223 | acpi_status status = AE_OK; | 238 | acpi_status status = AE_OK; |
224 | 239 | ||
225 | /* | 240 | /* |
226 | * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. | 241 | * Find any _Lxx/_Exx GPE methods that have just been loaded. |
227 | * | 242 | * |
228 | * Any GPEs that correspond to new _Lxx/_Exx methods are immediately | 243 | * Any GPEs that correspond to new _Lxx/_Exx methods are immediately |
229 | * enabled. | 244 | * enabled. |
@@ -236,10 +251,9 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id) | |||
236 | return; | 251 | return; |
237 | } | 252 | } |
238 | 253 | ||
254 | walk_info.count = 0; | ||
239 | walk_info.owner_id = table_owner_id; | 255 | walk_info.owner_id = table_owner_id; |
240 | walk_info.execute_by_owner_id = TRUE; | 256 | walk_info.execute_by_owner_id = TRUE; |
241 | walk_info.count = 0; | ||
242 | walk_info.enable_this_gpe = TRUE; | ||
243 | 257 | ||
244 | /* Walk the interrupt level descriptor list */ | 258 | /* Walk the interrupt level descriptor list */ |
245 | 259 | ||
@@ -300,9 +314,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id) | |||
300 | * xx - is the GPE number [in HEX] | 314 | * xx - is the GPE number [in HEX] |
301 | * | 315 | * |
302 | * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods | 316 | * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods |
303 | * with that owner. | 317 | * with that owner. |
304 | * If walk_info->enable_this_gpe is TRUE, the GPE that is referred to by a GPE | ||
305 | * method is immediately enabled (Used for Load/load_table operators) | ||
306 | * | 318 | * |
307 | ******************************************************************************/ | 319 | ******************************************************************************/ |
308 | 320 | ||
@@ -315,8 +327,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, | |||
315 | struct acpi_gpe_walk_info *walk_info = | 327 | struct acpi_gpe_walk_info *walk_info = |
316 | ACPI_CAST_PTR(struct acpi_gpe_walk_info, context); | 328 | ACPI_CAST_PTR(struct acpi_gpe_walk_info, context); |
317 | struct acpi_gpe_event_info *gpe_event_info; | 329 | struct acpi_gpe_event_info *gpe_event_info; |
318 | struct acpi_namespace_node *gpe_device; | ||
319 | acpi_status status; | ||
320 | u32 gpe_number; | 330 | u32 gpe_number; |
321 | char name[ACPI_NAME_SIZE + 1]; | 331 | char name[ACPI_NAME_SIZE + 1]; |
322 | u8 type; | 332 | u8 type; |
@@ -414,36 +424,17 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, | |||
414 | return_ACPI_STATUS(AE_OK); | 424 | return_ACPI_STATUS(AE_OK); |
415 | } | 425 | } |
416 | 426 | ||
427 | /* Disable the GPE in case it's been enabled already. */ | ||
428 | (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
429 | |||
417 | /* | 430 | /* |
418 | * Add the GPE information from above to the gpe_event_info block for | 431 | * Add the GPE information from above to the gpe_event_info block for |
419 | * use during dispatch of this GPE. | 432 | * use during dispatch of this GPE. |
420 | */ | 433 | */ |
434 | gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK); | ||
421 | gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); | 435 | gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); |
422 | gpe_event_info->dispatch.method_node = method_node; | 436 | gpe_event_info->dispatch.method_node = method_node; |
423 | 437 | ||
424 | /* | ||
425 | * Enable this GPE if requested. This only happens when during the | ||
426 | * execution of a Load or load_table operator. We have found a new | ||
427 | * GPE method and want to immediately enable the GPE if it is a | ||
428 | * runtime GPE. | ||
429 | */ | ||
430 | if (walk_info->enable_this_gpe) { | ||
431 | |||
432 | walk_info->count++; | ||
433 | gpe_device = walk_info->gpe_device; | ||
434 | |||
435 | if (gpe_device == acpi_gbl_fadt_gpe_device) { | ||
436 | gpe_device = NULL; | ||
437 | } | ||
438 | |||
439 | status = acpi_enable_gpe(gpe_device, gpe_number); | ||
440 | if (ACPI_FAILURE(status)) { | ||
441 | ACPI_EXCEPTION((AE_INFO, status, | ||
442 | "Could not enable GPE 0x%02X", | ||
443 | gpe_number)); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, | 438 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, |
448 | "Registered GPE method %s as GPE number 0x%.2X\n", | 439 | "Registered GPE method %s as GPE number 0x%.2X\n", |
449 | name, gpe_number)); | 440 | name, gpe_number)); |
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index 19a0e513ea48..80a81d0c4a80 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -154,6 +154,45 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) | |||
154 | 154 | ||
155 | /******************************************************************************* | 155 | /******************************************************************************* |
156 | * | 156 | * |
157 | * FUNCTION: acpi_ev_get_gpe_device | ||
158 | * | ||
159 | * PARAMETERS: GPE_WALK_CALLBACK | ||
160 | * | ||
161 | * RETURN: Status | ||
162 | * | ||
163 | * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE | ||
164 | * block device. NULL if the GPE is one of the FADT-defined GPEs. | ||
165 | * | ||
166 | ******************************************************************************/ | ||
167 | |||
168 | acpi_status | ||
169 | acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | ||
170 | struct acpi_gpe_block_info *gpe_block, void *context) | ||
171 | { | ||
172 | struct acpi_gpe_device_info *info = context; | ||
173 | |||
174 | /* Increment Index by the number of GPEs in this block */ | ||
175 | |||
176 | info->next_block_base_index += gpe_block->gpe_count; | ||
177 | |||
178 | if (info->index < info->next_block_base_index) { | ||
179 | /* | ||
180 | * The GPE index is within this block, get the node. Leave the node | ||
181 | * NULL for the FADT-defined GPEs | ||
182 | */ | ||
183 | if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) { | ||
184 | info->gpe_device = gpe_block->node; | ||
185 | } | ||
186 | |||
187 | info->status = AE_OK; | ||
188 | return (AE_CTRL_END); | ||
189 | } | ||
190 | |||
191 | return (AE_OK); | ||
192 | } | ||
193 | |||
194 | /******************************************************************************* | ||
195 | * | ||
157 | * FUNCTION: acpi_ev_get_gpe_xrupt_block | 196 | * FUNCTION: acpi_ev_get_gpe_xrupt_block |
158 | * | 197 | * |
159 | * PARAMETERS: interrupt_number - Interrupt for a GPE block | 198 | * PARAMETERS: interrupt_number - Interrupt for a GPE block |
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index df0aea9a8cfd..d0b331844427 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -45,7 +45,6 @@ | |||
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "acevents.h" | 46 | #include "acevents.h" |
47 | #include "acnamesp.h" | 47 | #include "acnamesp.h" |
48 | #include "acinterp.h" | ||
49 | 48 | ||
50 | #define _COMPONENT ACPI_EVENTS | 49 | #define _COMPONENT ACPI_EVENTS |
51 | ACPI_MODULE_NAME("evmisc") | 50 | ACPI_MODULE_NAME("evmisc") |
@@ -53,10 +52,6 @@ ACPI_MODULE_NAME("evmisc") | |||
53 | /* Local prototypes */ | 52 | /* Local prototypes */ |
54 | static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); | 53 | static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); |
55 | 54 | ||
56 | static u32 acpi_ev_global_lock_handler(void *context); | ||
57 | |||
58 | static acpi_status acpi_ev_remove_global_lock_handler(void); | ||
59 | |||
60 | /******************************************************************************* | 55 | /******************************************************************************* |
61 | * | 56 | * |
62 | * FUNCTION: acpi_ev_is_notify_object | 57 | * FUNCTION: acpi_ev_is_notify_object |
@@ -275,290 +270,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) | |||
275 | acpi_ut_delete_generic_state(notify_info); | 270 | acpi_ut_delete_generic_state(notify_info); |
276 | } | 271 | } |
277 | 272 | ||
278 | /******************************************************************************* | ||
279 | * | ||
280 | * FUNCTION: acpi_ev_global_lock_handler | ||
281 | * | ||
282 | * PARAMETERS: Context - From thread interface, not used | ||
283 | * | ||
284 | * RETURN: ACPI_INTERRUPT_HANDLED | ||
285 | * | ||
286 | * DESCRIPTION: Invoked directly from the SCI handler when a global lock | ||
287 | * release interrupt occurs. Attempt to acquire the global lock, | ||
288 | * if successful, signal the thread waiting for the lock. | ||
289 | * | ||
290 | * NOTE: Assumes that the semaphore can be signaled from interrupt level. If | ||
291 | * this is not possible for some reason, a separate thread will have to be | ||
292 | * scheduled to do this. | ||
293 | * | ||
294 | ******************************************************************************/ | ||
295 | |||
296 | static u32 acpi_ev_global_lock_handler(void *context) | ||
297 | { | ||
298 | u8 acquired = FALSE; | ||
299 | |||
300 | /* | ||
301 | * Attempt to get the lock. | ||
302 | * | ||
303 | * If we don't get it now, it will be marked pending and we will | ||
304 | * take another interrupt when it becomes free. | ||
305 | */ | ||
306 | ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); | ||
307 | if (acquired) { | ||
308 | |||
309 | /* Got the lock, now wake all threads waiting for it */ | ||
310 | |||
311 | acpi_gbl_global_lock_acquired = TRUE; | ||
312 | /* Send a unit to the semaphore */ | ||
313 | |||
314 | if (ACPI_FAILURE | ||
315 | (acpi_os_signal_semaphore | ||
316 | (acpi_gbl_global_lock_semaphore, 1))) { | ||
317 | ACPI_ERROR((AE_INFO, | ||
318 | "Could not signal Global Lock semaphore")); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | return (ACPI_INTERRUPT_HANDLED); | ||
323 | } | ||
324 | |||
325 | /******************************************************************************* | ||
326 | * | ||
327 | * FUNCTION: acpi_ev_init_global_lock_handler | ||
328 | * | ||
329 | * PARAMETERS: None | ||
330 | * | ||
331 | * RETURN: Status | ||
332 | * | ||
333 | * DESCRIPTION: Install a handler for the global lock release event | ||
334 | * | ||
335 | ******************************************************************************/ | ||
336 | |||
337 | acpi_status acpi_ev_init_global_lock_handler(void) | ||
338 | { | ||
339 | acpi_status status; | ||
340 | |||
341 | ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); | ||
342 | |||
343 | /* Attempt installation of the global lock handler */ | ||
344 | |||
345 | status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, | ||
346 | acpi_ev_global_lock_handler, | ||
347 | NULL); | ||
348 | |||
349 | /* | ||
350 | * If the global lock does not exist on this platform, the attempt to | ||
351 | * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). | ||
352 | * Map to AE_OK, but mark global lock as not present. Any attempt to | ||
353 | * actually use the global lock will be flagged with an error. | ||
354 | */ | ||
355 | if (status == AE_NO_HARDWARE_RESPONSE) { | ||
356 | ACPI_ERROR((AE_INFO, | ||
357 | "No response from Global Lock hardware, disabling lock")); | ||
358 | |||
359 | acpi_gbl_global_lock_present = FALSE; | ||
360 | return_ACPI_STATUS(AE_OK); | ||
361 | } | ||
362 | |||
363 | acpi_gbl_global_lock_present = TRUE; | ||
364 | return_ACPI_STATUS(status); | ||
365 | } | ||
366 | |||
367 | /******************************************************************************* | ||
368 | * | ||
369 | * FUNCTION: acpi_ev_remove_global_lock_handler | ||
370 | * | ||
371 | * PARAMETERS: None | ||
372 | * | ||
373 | * RETURN: Status | ||
374 | * | ||
375 | * DESCRIPTION: Remove the handler for the Global Lock | ||
376 | * | ||
377 | ******************************************************************************/ | ||
378 | |||
379 | static acpi_status acpi_ev_remove_global_lock_handler(void) | ||
380 | { | ||
381 | acpi_status status; | ||
382 | |||
383 | ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); | ||
384 | |||
385 | acpi_gbl_global_lock_present = FALSE; | ||
386 | status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, | ||
387 | acpi_ev_global_lock_handler); | ||
388 | |||
389 | return_ACPI_STATUS(status); | ||
390 | } | ||
391 | |||
392 | /****************************************************************************** | ||
393 | * | ||
394 | * FUNCTION: acpi_ev_acquire_global_lock | ||
395 | * | ||
396 | * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. | ||
397 | * | ||
398 | * RETURN: Status | ||
399 | * | ||
400 | * DESCRIPTION: Attempt to gain ownership of the Global Lock. | ||
401 | * | ||
402 | * MUTEX: Interpreter must be locked | ||
403 | * | ||
404 | * Note: The original implementation allowed multiple threads to "acquire" the | ||
405 | * Global Lock, and the OS would hold the lock until the last thread had | ||
406 | * released it. However, this could potentially starve the BIOS out of the | ||
407 | * lock, especially in the case where there is a tight handshake between the | ||
408 | * Embedded Controller driver and the BIOS. Therefore, this implementation | ||
409 | * allows only one thread to acquire the HW Global Lock at a time, and makes | ||
410 | * the global lock appear as a standard mutex on the OS side. | ||
411 | * | ||
412 | *****************************************************************************/ | ||
413 | static acpi_thread_id acpi_ev_global_lock_thread_id; | ||
414 | static int acpi_ev_global_lock_acquired; | ||
415 | |||
416 | acpi_status acpi_ev_acquire_global_lock(u16 timeout) | ||
417 | { | ||
418 | acpi_status status = AE_OK; | ||
419 | u8 acquired = FALSE; | ||
420 | |||
421 | ACPI_FUNCTION_TRACE(ev_acquire_global_lock); | ||
422 | |||
423 | /* | ||
424 | * Only one thread can acquire the GL at a time, the global_lock_mutex | ||
425 | * enforces this. This interface releases the interpreter if we must wait. | ||
426 | */ | ||
427 | status = acpi_ex_system_wait_mutex( | ||
428 | acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); | ||
429 | if (status == AE_TIME) { | ||
430 | if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { | ||
431 | acpi_ev_global_lock_acquired++; | ||
432 | return AE_OK; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | if (ACPI_FAILURE(status)) { | ||
437 | status = acpi_ex_system_wait_mutex( | ||
438 | acpi_gbl_global_lock_mutex->mutex.os_mutex, | ||
439 | timeout); | ||
440 | } | ||
441 | if (ACPI_FAILURE(status)) { | ||
442 | return_ACPI_STATUS(status); | ||
443 | } | ||
444 | |||
445 | acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); | ||
446 | acpi_ev_global_lock_acquired++; | ||
447 | |||
448 | /* | ||
449 | * Update the global lock handle and check for wraparound. The handle is | ||
450 | * only used for the external global lock interfaces, but it is updated | ||
451 | * here to properly handle the case where a single thread may acquire the | ||
452 | * lock via both the AML and the acpi_acquire_global_lock interfaces. The | ||
453 | * handle is therefore updated on the first acquire from a given thread | ||
454 | * regardless of where the acquisition request originated. | ||
455 | */ | ||
456 | acpi_gbl_global_lock_handle++; | ||
457 | if (acpi_gbl_global_lock_handle == 0) { | ||
458 | acpi_gbl_global_lock_handle = 1; | ||
459 | } | ||
460 | |||
461 | /* | ||
462 | * Make sure that a global lock actually exists. If not, just treat the | ||
463 | * lock as a standard mutex. | ||
464 | */ | ||
465 | if (!acpi_gbl_global_lock_present) { | ||
466 | acpi_gbl_global_lock_acquired = TRUE; | ||
467 | return_ACPI_STATUS(AE_OK); | ||
468 | } | ||
469 | |||
470 | /* Attempt to acquire the actual hardware lock */ | ||
471 | |||
472 | ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); | ||
473 | if (acquired) { | ||
474 | |||
475 | /* We got the lock */ | ||
476 | |||
477 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
478 | "Acquired hardware Global Lock\n")); | ||
479 | |||
480 | acpi_gbl_global_lock_acquired = TRUE; | ||
481 | return_ACPI_STATUS(AE_OK); | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * Did not get the lock. The pending bit was set above, and we must now | ||
486 | * wait until we get the global lock released interrupt. | ||
487 | */ | ||
488 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); | ||
489 | |||
490 | /* | ||
491 | * Wait for handshake with the global lock interrupt handler. | ||
492 | * This interface releases the interpreter if we must wait. | ||
493 | */ | ||
494 | status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, | ||
495 | ACPI_WAIT_FOREVER); | ||
496 | |||
497 | return_ACPI_STATUS(status); | ||
498 | } | ||
499 | |||
500 | /******************************************************************************* | ||
501 | * | ||
502 | * FUNCTION: acpi_ev_release_global_lock | ||
503 | * | ||
504 | * PARAMETERS: None | ||
505 | * | ||
506 | * RETURN: Status | ||
507 | * | ||
508 | * DESCRIPTION: Releases ownership of the Global Lock. | ||
509 | * | ||
510 | ******************************************************************************/ | ||
511 | |||
512 | acpi_status acpi_ev_release_global_lock(void) | ||
513 | { | ||
514 | u8 pending = FALSE; | ||
515 | acpi_status status = AE_OK; | ||
516 | |||
517 | ACPI_FUNCTION_TRACE(ev_release_global_lock); | ||
518 | |||
519 | /* Lock must be already acquired */ | ||
520 | |||
521 | if (!acpi_gbl_global_lock_acquired) { | ||
522 | ACPI_WARNING((AE_INFO, | ||
523 | "Cannot release the ACPI Global Lock, it has not been acquired")); | ||
524 | return_ACPI_STATUS(AE_NOT_ACQUIRED); | ||
525 | } | ||
526 | |||
527 | acpi_ev_global_lock_acquired--; | ||
528 | if (acpi_ev_global_lock_acquired > 0) { | ||
529 | return AE_OK; | ||
530 | } | ||
531 | |||
532 | if (acpi_gbl_global_lock_present) { | ||
533 | |||
534 | /* Allow any thread to release the lock */ | ||
535 | |||
536 | ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending); | ||
537 | |||
538 | /* | ||
539 | * If the pending bit was set, we must write GBL_RLS to the control | ||
540 | * register | ||
541 | */ | ||
542 | if (pending) { | ||
543 | status = | ||
544 | acpi_write_bit_register | ||
545 | (ACPI_BITREG_GLOBAL_LOCK_RELEASE, | ||
546 | ACPI_ENABLE_EVENT); | ||
547 | } | ||
548 | |||
549 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
550 | "Released hardware Global Lock\n")); | ||
551 | } | ||
552 | |||
553 | acpi_gbl_global_lock_acquired = FALSE; | ||
554 | |||
555 | /* Release the local GL mutex */ | ||
556 | acpi_ev_global_lock_thread_id = NULL; | ||
557 | acpi_ev_global_lock_acquired = 0; | ||
558 | acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); | ||
559 | return_ACPI_STATUS(status); | ||
560 | } | ||
561 | |||
562 | /****************************************************************************** | 273 | /****************************************************************************** |
563 | * | 274 | * |
564 | * FUNCTION: acpi_ev_terminate | 275 | * FUNCTION: acpi_ev_terminate |
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 98fd210e87b2..f0edf5c43c03 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -55,6 +55,8 @@ static u8 | |||
55 | acpi_ev_has_default_handler(struct acpi_namespace_node *node, | 55 | acpi_ev_has_default_handler(struct acpi_namespace_node *node, |
56 | acpi_adr_space_type space_id); | 56 | acpi_adr_space_type space_id); |
57 | 57 | ||
58 | static void acpi_ev_orphan_ec_reg_method(void); | ||
59 | |||
58 | static acpi_status | 60 | static acpi_status |
59 | acpi_ev_reg_run(acpi_handle obj_handle, | 61 | acpi_ev_reg_run(acpi_handle obj_handle, |
60 | u32 level, void *context, void **return_value); | 62 | u32 level, void *context, void **return_value); |
@@ -231,6 +233,8 @@ acpi_status acpi_ev_initialize_op_regions(void) | |||
231 | } | 233 | } |
232 | } | 234 | } |
233 | 235 | ||
236 | acpi_gbl_reg_methods_executed = TRUE; | ||
237 | |||
234 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 238 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
235 | return_ACPI_STATUS(status); | 239 | return_ACPI_STATUS(status); |
236 | } | 240 | } |
@@ -559,7 +563,9 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, | |||
559 | 563 | ||
560 | /* Now stop region accesses by executing the _REG method */ | 564 | /* Now stop region accesses by executing the _REG method */ |
561 | 565 | ||
562 | status = acpi_ev_execute_reg_method(region_obj, 0); | 566 | status = |
567 | acpi_ev_execute_reg_method(region_obj, | ||
568 | ACPI_REG_DISCONNECT); | ||
563 | if (ACPI_FAILURE(status)) { | 569 | if (ACPI_FAILURE(status)) { |
564 | ACPI_EXCEPTION((AE_INFO, status, | 570 | ACPI_EXCEPTION((AE_INFO, status, |
565 | "from region _REG, [%s]", | 571 | "from region _REG, [%s]", |
@@ -1060,6 +1066,12 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, | |||
1060 | ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, | 1066 | ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, |
1061 | NULL, &space_id, NULL); | 1067 | NULL, &space_id, NULL); |
1062 | 1068 | ||
1069 | /* Special case for EC: handle "orphan" _REG methods with no region */ | ||
1070 | |||
1071 | if (space_id == ACPI_ADR_SPACE_EC) { | ||
1072 | acpi_ev_orphan_ec_reg_method(); | ||
1073 | } | ||
1074 | |||
1063 | return_ACPI_STATUS(status); | 1075 | return_ACPI_STATUS(status); |
1064 | } | 1076 | } |
1065 | 1077 | ||
@@ -1118,6 +1130,113 @@ acpi_ev_reg_run(acpi_handle obj_handle, | |||
1118 | return (AE_OK); | 1130 | return (AE_OK); |
1119 | } | 1131 | } |
1120 | 1132 | ||
1121 | status = acpi_ev_execute_reg_method(obj_desc, 1); | 1133 | status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT); |
1122 | return (status); | 1134 | return (status); |
1123 | } | 1135 | } |
1136 | |||
1137 | /******************************************************************************* | ||
1138 | * | ||
1139 | * FUNCTION: acpi_ev_orphan_ec_reg_method | ||
1140 | * | ||
1141 | * PARAMETERS: None | ||
1142 | * | ||
1143 | * RETURN: None | ||
1144 | * | ||
1145 | * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC | ||
1146 | * device. This is a _REG method that has no corresponding region | ||
1147 | * within the EC device scope. The orphan _REG method appears to | ||
1148 | * have been enabled by the description of the ECDT in the ACPI | ||
1149 | * specification: "The availability of the region space can be | ||
1150 | * detected by providing a _REG method object underneath the | ||
1151 | * Embedded Controller device." | ||
1152 | * | ||
1153 | * To quickly access the EC device, we use the EC_ID that appears | ||
1154 | * within the ECDT. Otherwise, we would need to perform a time- | ||
1155 | * consuming namespace walk, executing _HID methods to find the | ||
1156 | * EC device. | ||
1157 | * | ||
1158 | ******************************************************************************/ | ||
1159 | |||
1160 | static void acpi_ev_orphan_ec_reg_method(void) | ||
1161 | { | ||
1162 | struct acpi_table_ecdt *table; | ||
1163 | acpi_status status; | ||
1164 | struct acpi_object_list args; | ||
1165 | union acpi_object objects[2]; | ||
1166 | struct acpi_namespace_node *ec_device_node; | ||
1167 | struct acpi_namespace_node *reg_method; | ||
1168 | struct acpi_namespace_node *next_node; | ||
1169 | |||
1170 | ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method); | ||
1171 | |||
1172 | /* Get the ECDT (if present in system) */ | ||
1173 | |||
1174 | status = acpi_get_table(ACPI_SIG_ECDT, 0, | ||
1175 | ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, | ||
1176 | &table)); | ||
1177 | if (ACPI_FAILURE(status)) { | ||
1178 | return_VOID; | ||
1179 | } | ||
1180 | |||
1181 | /* We need a valid EC_ID string */ | ||
1182 | |||
1183 | if (!(*table->id)) { | ||
1184 | return_VOID; | ||
1185 | } | ||
1186 | |||
1187 | /* Namespace is currently locked, must release */ | ||
1188 | |||
1189 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
1190 | |||
1191 | /* Get a handle to the EC device referenced in the ECDT */ | ||
1192 | |||
1193 | status = acpi_get_handle(NULL, | ||
1194 | ACPI_CAST_PTR(char, table->id), | ||
1195 | ACPI_CAST_PTR(acpi_handle, &ec_device_node)); | ||
1196 | if (ACPI_FAILURE(status)) { | ||
1197 | goto exit; | ||
1198 | } | ||
1199 | |||
1200 | /* Get a handle to a _REG method immediately under the EC device */ | ||
1201 | |||
1202 | status = acpi_get_handle(ec_device_node, | ||
1203 | METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle, | ||
1204 | ®_method)); | ||
1205 | if (ACPI_FAILURE(status)) { | ||
1206 | goto exit; | ||
1207 | } | ||
1208 | |||
1209 | /* | ||
1210 | * Execute the _REG method only if there is no Operation Region in | ||
1211 | * this scope with the Embedded Controller space ID. Otherwise, it | ||
1212 | * will already have been executed. Note, this allows for Regions | ||
1213 | * with other space IDs to be present; but the code below will then | ||
1214 | * execute the _REG method with the EC space ID argument. | ||
1215 | */ | ||
1216 | next_node = acpi_ns_get_next_node(ec_device_node, NULL); | ||
1217 | while (next_node) { | ||
1218 | if ((next_node->type == ACPI_TYPE_REGION) && | ||
1219 | (next_node->object) && | ||
1220 | (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) { | ||
1221 | goto exit; /* Do not execute _REG */ | ||
1222 | } | ||
1223 | next_node = acpi_ns_get_next_node(ec_device_node, next_node); | ||
1224 | } | ||
1225 | |||
1226 | /* Evaluate the _REG(EC,Connect) method */ | ||
1227 | |||
1228 | args.count = 2; | ||
1229 | args.pointer = objects; | ||
1230 | objects[0].type = ACPI_TYPE_INTEGER; | ||
1231 | objects[0].integer.value = ACPI_ADR_SPACE_EC; | ||
1232 | objects[1].type = ACPI_TYPE_INTEGER; | ||
1233 | objects[1].integer.value = ACPI_REG_CONNECT; | ||
1234 | |||
1235 | status = acpi_evaluate_object(reg_method, NULL, &args, NULL); | ||
1236 | |||
1237 | exit: | ||
1238 | /* We ignore all errors from above, don't care */ | ||
1239 | |||
1240 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
1241 | return_VOID; | ||
1242 | } | ||
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index f40d271bf568..55a5d35ef34a 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -289,8 +289,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
289 | } | 289 | } |
290 | 290 | ||
291 | /* | 291 | /* |
292 | * Get the PCI device and function numbers from the _ADR object contained | 292 | * Get the PCI device and function numbers from the _ADR object |
293 | * in the parent's scope. | 293 | * contained in the parent's scope. |
294 | */ | 294 | */ |
295 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, | 295 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, |
296 | pci_device_node, &pci_value); | 296 | pci_device_node, &pci_value); |
@@ -320,9 +320,15 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
320 | pci_id->bus = ACPI_LOWORD(pci_value); | 320 | pci_id->bus = ACPI_LOWORD(pci_value); |
321 | } | 321 | } |
322 | 322 | ||
323 | /* Complete this device's pci_id */ | 323 | /* Complete/update the PCI ID for this device */ |
324 | 324 | ||
325 | acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); | 325 | status = |
326 | acpi_hw_derive_pci_id(pci_id, pci_root_node, | ||
327 | region_obj->region.node); | ||
328 | if (ACPI_FAILURE(status)) { | ||
329 | ACPI_FREE(pci_id); | ||
330 | return_ACPI_STATUS(status); | ||
331 | } | ||
326 | 332 | ||
327 | *region_context = pci_id; | 333 | *region_context = pci_id; |
328 | return_ACPI_STATUS(AE_OK); | 334 | return_ACPI_STATUS(AE_OK); |
@@ -584,9 +590,9 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, | |||
584 | * See acpi_ns_exec_module_code | 590 | * See acpi_ns_exec_module_code |
585 | */ | 591 | */ |
586 | if (obj_desc->method. | 592 | if (obj_desc->method. |
587 | flags & AOPOBJ_MODULE_LEVEL) { | 593 | info_flags & ACPI_METHOD_MODULE_LEVEL) { |
588 | handler_obj = | 594 | handler_obj = |
589 | obj_desc->method.extra.handler; | 595 | obj_desc->method.dispatch.handler; |
590 | } | 596 | } |
591 | break; | 597 | break; |
592 | 598 | ||
@@ -631,7 +637,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, | |||
631 | 637 | ||
632 | status = | 638 | status = |
633 | acpi_ev_execute_reg_method | 639 | acpi_ev_execute_reg_method |
634 | (region_obj, 1); | 640 | (region_obj, ACPI_REG_CONNECT); |
635 | 641 | ||
636 | if (acpi_ns_locked) { | 642 | if (acpi_ns_locked) { |
637 | status = | 643 | status = |
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 8dfbaa96e422..2ebd40e1a3ef 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 14e48add32fa..e1141402dbed 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -92,6 +92,57 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) | |||
92 | 92 | ||
93 | ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) | 93 | ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) |
94 | #endif /* ACPI_FUTURE_USAGE */ | 94 | #endif /* ACPI_FUTURE_USAGE */ |
95 | |||
96 | /******************************************************************************* | ||
97 | * | ||
98 | * FUNCTION: acpi_install_global_event_handler | ||
99 | * | ||
100 | * PARAMETERS: Handler - Pointer to the global event handler function | ||
101 | * Context - Value passed to the handler on each event | ||
102 | * | ||
103 | * RETURN: Status | ||
104 | * | ||
105 | * DESCRIPTION: Saves the pointer to the handler function. The global handler | ||
106 | * is invoked upon each incoming GPE and Fixed Event. It is | ||
107 | * invoked at interrupt level at the time of the event dispatch. | ||
108 | * Can be used to update event counters, etc. | ||
109 | * | ||
110 | ******************************************************************************/ | ||
111 | acpi_status | ||
112 | acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context) | ||
113 | { | ||
114 | acpi_status status; | ||
115 | |||
116 | ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); | ||
117 | |||
118 | /* Parameter validation */ | ||
119 | |||
120 | if (!handler) { | ||
121 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
122 | } | ||
123 | |||
124 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
125 | if (ACPI_FAILURE(status)) { | ||
126 | return_ACPI_STATUS(status); | ||
127 | } | ||
128 | |||
129 | /* Don't allow two handlers. */ | ||
130 | |||
131 | if (acpi_gbl_global_event_handler) { | ||
132 | status = AE_ALREADY_EXISTS; | ||
133 | goto cleanup; | ||
134 | } | ||
135 | |||
136 | acpi_gbl_global_event_handler = handler; | ||
137 | acpi_gbl_global_event_handler_context = context; | ||
138 | |||
139 | cleanup: | ||
140 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
141 | return_ACPI_STATUS(status); | ||
142 | } | ||
143 | |||
144 | ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) | ||
145 | |||
95 | /******************************************************************************* | 146 | /******************************************************************************* |
96 | * | 147 | * |
97 | * FUNCTION: acpi_install_fixed_event_handler | 148 | * FUNCTION: acpi_install_fixed_event_handler |
@@ -671,10 +722,10 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) | |||
671 | acpi_status | 722 | acpi_status |
672 | acpi_install_gpe_handler(acpi_handle gpe_device, | 723 | acpi_install_gpe_handler(acpi_handle gpe_device, |
673 | u32 gpe_number, | 724 | u32 gpe_number, |
674 | u32 type, acpi_event_handler address, void *context) | 725 | u32 type, acpi_gpe_handler address, void *context) |
675 | { | 726 | { |
676 | struct acpi_gpe_event_info *gpe_event_info; | 727 | struct acpi_gpe_event_info *gpe_event_info; |
677 | struct acpi_handler_info *handler; | 728 | struct acpi_gpe_handler_info *handler; |
678 | acpi_status status; | 729 | acpi_status status; |
679 | acpi_cpu_flags flags; | 730 | acpi_cpu_flags flags; |
680 | 731 | ||
@@ -693,7 +744,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, | |||
693 | 744 | ||
694 | /* Allocate memory for the handler object */ | 745 | /* Allocate memory for the handler object */ |
695 | 746 | ||
696 | handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); | 747 | handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); |
697 | if (!handler) { | 748 | if (!handler) { |
698 | status = AE_NO_MEMORY; | 749 | status = AE_NO_MEMORY; |
699 | goto unlock_and_exit; | 750 | goto unlock_and_exit; |
@@ -722,19 +773,20 @@ acpi_install_gpe_handler(acpi_handle gpe_device, | |||
722 | handler->address = address; | 773 | handler->address = address; |
723 | handler->context = context; | 774 | handler->context = context; |
724 | handler->method_node = gpe_event_info->dispatch.method_node; | 775 | handler->method_node = gpe_event_info->dispatch.method_node; |
725 | handler->orig_flags = gpe_event_info->flags & | 776 | handler->original_flags = gpe_event_info->flags & |
726 | (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); | 777 | (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
727 | 778 | ||
728 | /* | 779 | /* |
729 | * If the GPE is associated with a method and it cannot wake up the | 780 | * If the GPE is associated with a method, it might have been enabled |
730 | * system from sleep states, it was enabled automatically during | 781 | * automatically during initialization, in which case it has to be |
731 | * initialization, so it has to be disabled now to avoid spurious | 782 | * disabled now to avoid spurious execution of the handler. |
732 | * execution of the handler. | ||
733 | */ | 783 | */ |
734 | 784 | ||
735 | if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) | 785 | if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) |
736 | && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) | 786 | && gpe_event_info->runtime_count) { |
737 | (void)acpi_raw_disable_gpe(gpe_event_info); | 787 | handler->originally_enabled = 1; |
788 | (void)acpi_ev_remove_gpe_reference(gpe_event_info); | ||
789 | } | ||
738 | 790 | ||
739 | /* Install the handler */ | 791 | /* Install the handler */ |
740 | 792 | ||
@@ -776,10 +828,10 @@ ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) | |||
776 | ******************************************************************************/ | 828 | ******************************************************************************/ |
777 | acpi_status | 829 | acpi_status |
778 | acpi_remove_gpe_handler(acpi_handle gpe_device, | 830 | acpi_remove_gpe_handler(acpi_handle gpe_device, |
779 | u32 gpe_number, acpi_event_handler address) | 831 | u32 gpe_number, acpi_gpe_handler address) |
780 | { | 832 | { |
781 | struct acpi_gpe_event_info *gpe_event_info; | 833 | struct acpi_gpe_event_info *gpe_event_info; |
782 | struct acpi_handler_info *handler; | 834 | struct acpi_gpe_handler_info *handler; |
783 | acpi_status status; | 835 | acpi_status status; |
784 | acpi_cpu_flags flags; | 836 | acpi_cpu_flags flags; |
785 | 837 | ||
@@ -834,17 +886,17 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, | |||
834 | gpe_event_info->dispatch.method_node = handler->method_node; | 886 | gpe_event_info->dispatch.method_node = handler->method_node; |
835 | gpe_event_info->flags &= | 887 | gpe_event_info->flags &= |
836 | ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); | 888 | ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
837 | gpe_event_info->flags |= handler->orig_flags; | 889 | gpe_event_info->flags |= handler->original_flags; |
838 | 890 | ||
839 | /* | 891 | /* |
840 | * If the GPE was previously associated with a method and it cannot wake | 892 | * If the GPE was previously associated with a method and it was |
841 | * up the system from sleep states, it should be enabled at this point | 893 | * enabled, it should be enabled at this point to restore the |
842 | * to restore the post-initialization configuration. | 894 | * post-initialization configuration. |
843 | */ | 895 | */ |
844 | 896 | ||
845 | if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) | 897 | if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) |
846 | && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) | 898 | && handler->originally_enabled) |
847 | (void)acpi_raw_enable_gpe(gpe_event_info); | 899 | (void)acpi_ev_add_gpe_reference(gpe_event_info); |
848 | 900 | ||
849 | /* Now we can free the handler object */ | 901 | /* Now we can free the handler object */ |
850 | 902 | ||
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 304825528d48..c57b5c707a77 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -43,18 +43,11 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "acevents.h" | ||
47 | #include "acnamesp.h" | ||
48 | #include "actables.h" | 46 | #include "actables.h" |
49 | 47 | ||
50 | #define _COMPONENT ACPI_EVENTS | 48 | #define _COMPONENT ACPI_EVENTS |
51 | ACPI_MODULE_NAME("evxfevnt") | 49 | ACPI_MODULE_NAME("evxfevnt") |
52 | 50 | ||
53 | /* Local prototypes */ | ||
54 | static acpi_status | ||
55 | acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | ||
56 | struct acpi_gpe_block_info *gpe_block, void *context); | ||
57 | |||
58 | /******************************************************************************* | 51 | /******************************************************************************* |
59 | * | 52 | * |
60 | * FUNCTION: acpi_enable | 53 | * FUNCTION: acpi_enable |
@@ -213,194 +206,6 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) | |||
213 | 206 | ||
214 | /******************************************************************************* | 207 | /******************************************************************************* |
215 | * | 208 | * |
216 | * FUNCTION: acpi_gpe_wakeup | ||
217 | * | ||
218 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
219 | * gpe_number - GPE level within the GPE block | ||
220 | * Action - Enable or Disable | ||
221 | * | ||
222 | * RETURN: Status | ||
223 | * | ||
224 | * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. | ||
225 | * | ||
226 | ******************************************************************************/ | ||
227 | acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action) | ||
228 | { | ||
229 | acpi_status status = AE_OK; | ||
230 | struct acpi_gpe_event_info *gpe_event_info; | ||
231 | struct acpi_gpe_register_info *gpe_register_info; | ||
232 | acpi_cpu_flags flags; | ||
233 | u32 register_bit; | ||
234 | |||
235 | ACPI_FUNCTION_TRACE(acpi_gpe_wakeup); | ||
236 | |||
237 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
238 | |||
239 | /* Ensure that we have a valid GPE number */ | ||
240 | |||
241 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
242 | if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | ||
243 | status = AE_BAD_PARAMETER; | ||
244 | goto unlock_and_exit; | ||
245 | } | ||
246 | |||
247 | gpe_register_info = gpe_event_info->register_info; | ||
248 | if (!gpe_register_info) { | ||
249 | status = AE_NOT_EXIST; | ||
250 | goto unlock_and_exit; | ||
251 | } | ||
252 | |||
253 | register_bit = | ||
254 | acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); | ||
255 | |||
256 | /* Perform the action */ | ||
257 | |||
258 | switch (action) { | ||
259 | case ACPI_GPE_ENABLE: | ||
260 | ACPI_SET_BIT(gpe_register_info->enable_for_wake, | ||
261 | (u8)register_bit); | ||
262 | break; | ||
263 | |||
264 | case ACPI_GPE_DISABLE: | ||
265 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, | ||
266 | (u8)register_bit); | ||
267 | break; | ||
268 | |||
269 | default: | ||
270 | ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); | ||
271 | status = AE_BAD_PARAMETER; | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | unlock_and_exit: | ||
276 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
277 | return_ACPI_STATUS(status); | ||
278 | } | ||
279 | |||
280 | ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup) | ||
281 | |||
282 | /******************************************************************************* | ||
283 | * | ||
284 | * FUNCTION: acpi_enable_gpe | ||
285 | * | ||
286 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
287 | * gpe_number - GPE level within the GPE block | ||
288 | * | ||
289 | * RETURN: Status | ||
290 | * | ||
291 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is | ||
292 | * hardware-enabled. | ||
293 | * | ||
294 | ******************************************************************************/ | ||
295 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
296 | { | ||
297 | acpi_status status = AE_BAD_PARAMETER; | ||
298 | struct acpi_gpe_event_info *gpe_event_info; | ||
299 | acpi_cpu_flags flags; | ||
300 | |||
301 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | ||
302 | |||
303 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
304 | |||
305 | /* Ensure that we have a valid GPE number */ | ||
306 | |||
307 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
308 | if (gpe_event_info) { | ||
309 | status = acpi_raw_enable_gpe(gpe_event_info); | ||
310 | } | ||
311 | |||
312 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
313 | return_ACPI_STATUS(status); | ||
314 | } | ||
315 | ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | ||
316 | |||
317 | /******************************************************************************* | ||
318 | * | ||
319 | * FUNCTION: acpi_disable_gpe | ||
320 | * | ||
321 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
322 | * gpe_number - GPE level within the GPE block | ||
323 | * | ||
324 | * RETURN: Status | ||
325 | * | ||
326 | * DESCRIPTION: Remove a reference to a GPE. When the last reference is | ||
327 | * removed, only then is the GPE disabled (for runtime GPEs), or | ||
328 | * the GPE mask bit disabled (for wake GPEs) | ||
329 | * | ||
330 | ******************************************************************************/ | ||
331 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
332 | { | ||
333 | acpi_status status = AE_BAD_PARAMETER; | ||
334 | struct acpi_gpe_event_info *gpe_event_info; | ||
335 | acpi_cpu_flags flags; | ||
336 | |||
337 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | ||
338 | |||
339 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
340 | |||
341 | /* Ensure that we have a valid GPE number */ | ||
342 | |||
343 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
344 | if (gpe_event_info) { | ||
345 | status = acpi_raw_disable_gpe(gpe_event_info) ; | ||
346 | } | ||
347 | |||
348 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
349 | return_ACPI_STATUS(status); | ||
350 | } | ||
351 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | ||
352 | |||
353 | /******************************************************************************* | ||
354 | * | ||
355 | * FUNCTION: acpi_gpe_can_wake | ||
356 | * | ||
357 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
358 | * gpe_number - GPE level within the GPE block | ||
359 | * | ||
360 | * RETURN: Status | ||
361 | * | ||
362 | * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE | ||
363 | * has a corresponding method and is currently enabled, disable it | ||
364 | * (GPEs with corresponding methods are enabled unconditionally | ||
365 | * during initialization, but GPEs that can wake up are expected | ||
366 | * to be initially disabled). | ||
367 | * | ||
368 | ******************************************************************************/ | ||
369 | acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) | ||
370 | { | ||
371 | acpi_status status = AE_OK; | ||
372 | struct acpi_gpe_event_info *gpe_event_info; | ||
373 | acpi_cpu_flags flags; | ||
374 | |||
375 | ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); | ||
376 | |||
377 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
378 | |||
379 | /* Ensure that we have a valid GPE number */ | ||
380 | |||
381 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
382 | if (!gpe_event_info) { | ||
383 | status = AE_BAD_PARAMETER; | ||
384 | goto unlock_and_exit; | ||
385 | } | ||
386 | |||
387 | if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { | ||
388 | goto unlock_and_exit; | ||
389 | } | ||
390 | |||
391 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | ||
392 | if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) { | ||
393 | (void)acpi_raw_disable_gpe(gpe_event_info); | ||
394 | } | ||
395 | |||
396 | unlock_and_exit: | ||
397 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
398 | return_ACPI_STATUS(status); | ||
399 | } | ||
400 | ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) | ||
401 | |||
402 | /******************************************************************************* | ||
403 | * | ||
404 | * FUNCTION: acpi_disable_event | 209 | * FUNCTION: acpi_disable_event |
405 | * | 210 | * |
406 | * PARAMETERS: Event - The fixed eventto be enabled | 211 | * PARAMETERS: Event - The fixed eventto be enabled |
@@ -492,44 +297,6 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event) | |||
492 | 297 | ||
493 | /******************************************************************************* | 298 | /******************************************************************************* |
494 | * | 299 | * |
495 | * FUNCTION: acpi_clear_gpe | ||
496 | * | ||
497 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
498 | * gpe_number - GPE level within the GPE block | ||
499 | * | ||
500 | * RETURN: Status | ||
501 | * | ||
502 | * DESCRIPTION: Clear an ACPI event (general purpose) | ||
503 | * | ||
504 | ******************************************************************************/ | ||
505 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
506 | { | ||
507 | acpi_status status = AE_OK; | ||
508 | struct acpi_gpe_event_info *gpe_event_info; | ||
509 | acpi_cpu_flags flags; | ||
510 | |||
511 | ACPI_FUNCTION_TRACE(acpi_clear_gpe); | ||
512 | |||
513 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
514 | |||
515 | /* Ensure that we have a valid GPE number */ | ||
516 | |||
517 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
518 | if (!gpe_event_info) { | ||
519 | status = AE_BAD_PARAMETER; | ||
520 | goto unlock_and_exit; | ||
521 | } | ||
522 | |||
523 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
524 | |||
525 | unlock_and_exit: | ||
526 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
527 | return_ACPI_STATUS(status); | ||
528 | } | ||
529 | |||
530 | ACPI_EXPORT_SYMBOL(acpi_clear_gpe) | ||
531 | /******************************************************************************* | ||
532 | * | ||
533 | * FUNCTION: acpi_get_event_status | 300 | * FUNCTION: acpi_get_event_status |
534 | * | 301 | * |
535 | * PARAMETERS: Event - The fixed event | 302 | * PARAMETERS: Event - The fixed event |
@@ -584,343 +351,3 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) | |||
584 | } | 351 | } |
585 | 352 | ||
586 | ACPI_EXPORT_SYMBOL(acpi_get_event_status) | 353 | ACPI_EXPORT_SYMBOL(acpi_get_event_status) |
587 | |||
588 | /******************************************************************************* | ||
589 | * | ||
590 | * FUNCTION: acpi_get_gpe_status | ||
591 | * | ||
592 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
593 | * gpe_number - GPE level within the GPE block | ||
594 | * event_status - Where the current status of the event will | ||
595 | * be returned | ||
596 | * | ||
597 | * RETURN: Status | ||
598 | * | ||
599 | * DESCRIPTION: Get status of an event (general purpose) | ||
600 | * | ||
601 | ******************************************************************************/ | ||
602 | acpi_status | ||
603 | acpi_get_gpe_status(acpi_handle gpe_device, | ||
604 | u32 gpe_number, acpi_event_status *event_status) | ||
605 | { | ||
606 | acpi_status status = AE_OK; | ||
607 | struct acpi_gpe_event_info *gpe_event_info; | ||
608 | acpi_cpu_flags flags; | ||
609 | |||
610 | ACPI_FUNCTION_TRACE(acpi_get_gpe_status); | ||
611 | |||
612 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
613 | |||
614 | /* Ensure that we have a valid GPE number */ | ||
615 | |||
616 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
617 | if (!gpe_event_info) { | ||
618 | status = AE_BAD_PARAMETER; | ||
619 | goto unlock_and_exit; | ||
620 | } | ||
621 | |||
622 | /* Obtain status on the requested GPE number */ | ||
623 | |||
624 | status = acpi_hw_get_gpe_status(gpe_event_info, event_status); | ||
625 | |||
626 | if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) | ||
627 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | ||
628 | |||
629 | unlock_and_exit: | ||
630 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
631 | return_ACPI_STATUS(status); | ||
632 | } | ||
633 | |||
634 | ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) | ||
635 | /******************************************************************************* | ||
636 | * | ||
637 | * FUNCTION: acpi_install_gpe_block | ||
638 | * | ||
639 | * PARAMETERS: gpe_device - Handle to the parent GPE Block Device | ||
640 | * gpe_block_address - Address and space_iD | ||
641 | * register_count - Number of GPE register pairs in the block | ||
642 | * interrupt_number - H/W interrupt for the block | ||
643 | * | ||
644 | * RETURN: Status | ||
645 | * | ||
646 | * DESCRIPTION: Create and Install a block of GPE registers | ||
647 | * | ||
648 | ******************************************************************************/ | ||
649 | acpi_status | ||
650 | acpi_install_gpe_block(acpi_handle gpe_device, | ||
651 | struct acpi_generic_address *gpe_block_address, | ||
652 | u32 register_count, u32 interrupt_number) | ||
653 | { | ||
654 | acpi_status status; | ||
655 | union acpi_operand_object *obj_desc; | ||
656 | struct acpi_namespace_node *node; | ||
657 | struct acpi_gpe_block_info *gpe_block; | ||
658 | |||
659 | ACPI_FUNCTION_TRACE(acpi_install_gpe_block); | ||
660 | |||
661 | if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { | ||
662 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
663 | } | ||
664 | |||
665 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
666 | if (ACPI_FAILURE(status)) { | ||
667 | return (status); | ||
668 | } | ||
669 | |||
670 | node = acpi_ns_validate_handle(gpe_device); | ||
671 | if (!node) { | ||
672 | status = AE_BAD_PARAMETER; | ||
673 | goto unlock_and_exit; | ||
674 | } | ||
675 | |||
676 | /* | ||
677 | * For user-installed GPE Block Devices, the gpe_block_base_number | ||
678 | * is always zero | ||
679 | */ | ||
680 | status = | ||
681 | acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, | ||
682 | interrupt_number, &gpe_block); | ||
683 | if (ACPI_FAILURE(status)) { | ||
684 | goto unlock_and_exit; | ||
685 | } | ||
686 | |||
687 | /* Install block in the device_object attached to the node */ | ||
688 | |||
689 | obj_desc = acpi_ns_get_attached_object(node); | ||
690 | if (!obj_desc) { | ||
691 | |||
692 | /* | ||
693 | * No object, create a new one (Device nodes do not always have | ||
694 | * an attached object) | ||
695 | */ | ||
696 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); | ||
697 | if (!obj_desc) { | ||
698 | status = AE_NO_MEMORY; | ||
699 | goto unlock_and_exit; | ||
700 | } | ||
701 | |||
702 | status = | ||
703 | acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); | ||
704 | |||
705 | /* Remove local reference to the object */ | ||
706 | |||
707 | acpi_ut_remove_reference(obj_desc); | ||
708 | |||
709 | if (ACPI_FAILURE(status)) { | ||
710 | goto unlock_and_exit; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | /* Now install the GPE block in the device_object */ | ||
715 | |||
716 | obj_desc->device.gpe_block = gpe_block; | ||
717 | |||
718 | /* Enable the runtime GPEs in the new block */ | ||
719 | |||
720 | status = acpi_ev_initialize_gpe_block(node, gpe_block); | ||
721 | |||
722 | unlock_and_exit: | ||
723 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
724 | return_ACPI_STATUS(status); | ||
725 | } | ||
726 | |||
727 | ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) | ||
728 | |||
729 | /******************************************************************************* | ||
730 | * | ||
731 | * FUNCTION: acpi_remove_gpe_block | ||
732 | * | ||
733 | * PARAMETERS: gpe_device - Handle to the parent GPE Block Device | ||
734 | * | ||
735 | * RETURN: Status | ||
736 | * | ||
737 | * DESCRIPTION: Remove a previously installed block of GPE registers | ||
738 | * | ||
739 | ******************************************************************************/ | ||
740 | acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) | ||
741 | { | ||
742 | union acpi_operand_object *obj_desc; | ||
743 | acpi_status status; | ||
744 | struct acpi_namespace_node *node; | ||
745 | |||
746 | ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); | ||
747 | |||
748 | if (!gpe_device) { | ||
749 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
750 | } | ||
751 | |||
752 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
753 | if (ACPI_FAILURE(status)) { | ||
754 | return (status); | ||
755 | } | ||
756 | |||
757 | node = acpi_ns_validate_handle(gpe_device); | ||
758 | if (!node) { | ||
759 | status = AE_BAD_PARAMETER; | ||
760 | goto unlock_and_exit; | ||
761 | } | ||
762 | |||
763 | /* Get the device_object attached to the node */ | ||
764 | |||
765 | obj_desc = acpi_ns_get_attached_object(node); | ||
766 | if (!obj_desc || !obj_desc->device.gpe_block) { | ||
767 | return_ACPI_STATUS(AE_NULL_OBJECT); | ||
768 | } | ||
769 | |||
770 | /* Delete the GPE block (but not the device_object) */ | ||
771 | |||
772 | status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); | ||
773 | if (ACPI_SUCCESS(status)) { | ||
774 | obj_desc->device.gpe_block = NULL; | ||
775 | } | ||
776 | |||
777 | unlock_and_exit: | ||
778 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
779 | return_ACPI_STATUS(status); | ||
780 | } | ||
781 | |||
782 | ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) | ||
783 | |||
784 | /******************************************************************************* | ||
785 | * | ||
786 | * FUNCTION: acpi_get_gpe_device | ||
787 | * | ||
788 | * PARAMETERS: Index - System GPE index (0-current_gpe_count) | ||
789 | * gpe_device - Where the parent GPE Device is returned | ||
790 | * | ||
791 | * RETURN: Status | ||
792 | * | ||
793 | * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL | ||
794 | * gpe device indicates that the gpe number is contained in one of | ||
795 | * the FADT-defined gpe blocks. Otherwise, the GPE block device. | ||
796 | * | ||
797 | ******************************************************************************/ | ||
798 | acpi_status | ||
799 | acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) | ||
800 | { | ||
801 | struct acpi_gpe_device_info info; | ||
802 | acpi_status status; | ||
803 | |||
804 | ACPI_FUNCTION_TRACE(acpi_get_gpe_device); | ||
805 | |||
806 | if (!gpe_device) { | ||
807 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
808 | } | ||
809 | |||
810 | if (index >= acpi_current_gpe_count) { | ||
811 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
812 | } | ||
813 | |||
814 | /* Setup and walk the GPE list */ | ||
815 | |||
816 | info.index = index; | ||
817 | info.status = AE_NOT_EXIST; | ||
818 | info.gpe_device = NULL; | ||
819 | info.next_block_base_index = 0; | ||
820 | |||
821 | status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); | ||
822 | if (ACPI_FAILURE(status)) { | ||
823 | return_ACPI_STATUS(status); | ||
824 | } | ||
825 | |||
826 | *gpe_device = info.gpe_device; | ||
827 | return_ACPI_STATUS(info.status); | ||
828 | } | ||
829 | |||
830 | ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) | ||
831 | |||
832 | /******************************************************************************* | ||
833 | * | ||
834 | * FUNCTION: acpi_ev_get_gpe_device | ||
835 | * | ||
836 | * PARAMETERS: GPE_WALK_CALLBACK | ||
837 | * | ||
838 | * RETURN: Status | ||
839 | * | ||
840 | * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE | ||
841 | * block device. NULL if the GPE is one of the FADT-defined GPEs. | ||
842 | * | ||
843 | ******************************************************************************/ | ||
844 | static acpi_status | ||
845 | acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | ||
846 | struct acpi_gpe_block_info *gpe_block, void *context) | ||
847 | { | ||
848 | struct acpi_gpe_device_info *info = context; | ||
849 | |||
850 | /* Increment Index by the number of GPEs in this block */ | ||
851 | |||
852 | info->next_block_base_index += gpe_block->gpe_count; | ||
853 | |||
854 | if (info->index < info->next_block_base_index) { | ||
855 | /* | ||
856 | * The GPE index is within this block, get the node. Leave the node | ||
857 | * NULL for the FADT-defined GPEs | ||
858 | */ | ||
859 | if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) { | ||
860 | info->gpe_device = gpe_block->node; | ||
861 | } | ||
862 | |||
863 | info->status = AE_OK; | ||
864 | return (AE_CTRL_END); | ||
865 | } | ||
866 | |||
867 | return (AE_OK); | ||
868 | } | ||
869 | |||
870 | /****************************************************************************** | ||
871 | * | ||
872 | * FUNCTION: acpi_disable_all_gpes | ||
873 | * | ||
874 | * PARAMETERS: None | ||
875 | * | ||
876 | * RETURN: Status | ||
877 | * | ||
878 | * DESCRIPTION: Disable and clear all GPEs in all GPE blocks | ||
879 | * | ||
880 | ******************************************************************************/ | ||
881 | |||
882 | acpi_status acpi_disable_all_gpes(void) | ||
883 | { | ||
884 | acpi_status status; | ||
885 | |||
886 | ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); | ||
887 | |||
888 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
889 | if (ACPI_FAILURE(status)) { | ||
890 | return_ACPI_STATUS(status); | ||
891 | } | ||
892 | |||
893 | status = acpi_hw_disable_all_gpes(); | ||
894 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
895 | |||
896 | return_ACPI_STATUS(status); | ||
897 | } | ||
898 | |||
899 | /****************************************************************************** | ||
900 | * | ||
901 | * FUNCTION: acpi_enable_all_runtime_gpes | ||
902 | * | ||
903 | * PARAMETERS: None | ||
904 | * | ||
905 | * RETURN: Status | ||
906 | * | ||
907 | * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks | ||
908 | * | ||
909 | ******************************************************************************/ | ||
910 | |||
911 | acpi_status acpi_enable_all_runtime_gpes(void) | ||
912 | { | ||
913 | acpi_status status; | ||
914 | |||
915 | ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); | ||
916 | |||
917 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
918 | if (ACPI_FAILURE(status)) { | ||
919 | return_ACPI_STATUS(status); | ||
920 | } | ||
921 | |||
922 | status = acpi_hw_enable_all_runtime_gpes(); | ||
923 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
924 | |||
925 | return_ACPI_STATUS(status); | ||
926 | } | ||
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c new file mode 100644 index 000000000000..52aaff3df562 --- /dev/null +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -0,0 +1,696 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acevents.h" | ||
47 | #include "acnamesp.h" | ||
48 | |||
49 | #define _COMPONENT ACPI_EVENTS | ||
50 | ACPI_MODULE_NAME("evxfgpe") | ||
51 | |||
52 | /****************************************************************************** | ||
53 | * | ||
54 | * FUNCTION: acpi_update_all_gpes | ||
55 | * | ||
56 | * PARAMETERS: None | ||
57 | * | ||
58 | * RETURN: Status | ||
59 | * | ||
60 | * DESCRIPTION: Complete GPE initialization and enable all GPEs that have | ||
61 | * associated _Lxx or _Exx methods and are not pointed to by any | ||
62 | * device _PRW methods (this indicates that these GPEs are | ||
63 | * generally intended for system or device wakeup. Such GPEs | ||
64 | * have to be enabled directly when the devices whose _PRW | ||
65 | * methods point to them are set up for wakeup signaling.) | ||
66 | * | ||
67 | * NOTE: Should be called after any GPEs are added to the system. Primarily, | ||
68 | * after the system _PRW methods have been run, but also after a GPE Block | ||
69 | * Device has been added or if any new GPE methods have been added via a | ||
70 | * dynamic table load. | ||
71 | * | ||
72 | ******************************************************************************/ | ||
73 | |||
74 | acpi_status acpi_update_all_gpes(void) | ||
75 | { | ||
76 | acpi_status status; | ||
77 | |||
78 | ACPI_FUNCTION_TRACE(acpi_update_all_gpes); | ||
79 | |||
80 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
81 | if (ACPI_FAILURE(status)) { | ||
82 | return_ACPI_STATUS(status); | ||
83 | } | ||
84 | |||
85 | if (acpi_gbl_all_gpes_initialized) { | ||
86 | goto unlock_and_exit; | ||
87 | } | ||
88 | |||
89 | status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL); | ||
90 | if (ACPI_SUCCESS(status)) { | ||
91 | acpi_gbl_all_gpes_initialized = TRUE; | ||
92 | } | ||
93 | |||
94 | unlock_and_exit: | ||
95 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
96 | |||
97 | return_ACPI_STATUS(status); | ||
98 | } | ||
99 | |||
100 | ACPI_EXPORT_SYMBOL(acpi_update_all_gpes) | ||
101 | |||
102 | /******************************************************************************* | ||
103 | * | ||
104 | * FUNCTION: acpi_enable_gpe | ||
105 | * | ||
106 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
107 | * gpe_number - GPE level within the GPE block | ||
108 | * | ||
109 | * RETURN: Status | ||
110 | * | ||
111 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is | ||
112 | * hardware-enabled. | ||
113 | * | ||
114 | ******************************************************************************/ | ||
115 | |||
116 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
117 | { | ||
118 | acpi_status status = AE_BAD_PARAMETER; | ||
119 | struct acpi_gpe_event_info *gpe_event_info; | ||
120 | acpi_cpu_flags flags; | ||
121 | |||
122 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | ||
123 | |||
124 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
125 | |||
126 | /* Ensure that we have a valid GPE number */ | ||
127 | |||
128 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
129 | if (gpe_event_info) { | ||
130 | status = acpi_ev_add_gpe_reference(gpe_event_info); | ||
131 | } | ||
132 | |||
133 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
134 | return_ACPI_STATUS(status); | ||
135 | } | ||
136 | ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | ||
137 | |||
138 | /******************************************************************************* | ||
139 | * | ||
140 | * FUNCTION: acpi_disable_gpe | ||
141 | * | ||
142 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
143 | * gpe_number - GPE level within the GPE block | ||
144 | * | ||
145 | * RETURN: Status | ||
146 | * | ||
147 | * DESCRIPTION: Remove a reference to a GPE. When the last reference is | ||
148 | * removed, only then is the GPE disabled (for runtime GPEs), or | ||
149 | * the GPE mask bit disabled (for wake GPEs) | ||
150 | * | ||
151 | ******************************************************************************/ | ||
152 | |||
153 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
154 | { | ||
155 | acpi_status status = AE_BAD_PARAMETER; | ||
156 | struct acpi_gpe_event_info *gpe_event_info; | ||
157 | acpi_cpu_flags flags; | ||
158 | |||
159 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | ||
160 | |||
161 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
162 | |||
163 | /* Ensure that we have a valid GPE number */ | ||
164 | |||
165 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
166 | if (gpe_event_info) { | ||
167 | status = acpi_ev_remove_gpe_reference(gpe_event_info) ; | ||
168 | } | ||
169 | |||
170 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
171 | return_ACPI_STATUS(status); | ||
172 | } | ||
173 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | ||
174 | |||
175 | |||
176 | /******************************************************************************* | ||
177 | * | ||
178 | * FUNCTION: acpi_setup_gpe_for_wake | ||
179 | * | ||
180 | * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) | ||
181 | * gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
182 | * gpe_number - GPE level within the GPE block | ||
183 | * | ||
184 | * RETURN: Status | ||
185 | * | ||
186 | * DESCRIPTION: Mark a GPE as having the ability to wake the system. This | ||
187 | * interface is intended to be used as the host executes the | ||
188 | * _PRW methods (Power Resources for Wake) in the system tables. | ||
189 | * Each _PRW appears under a Device Object (The wake_device), and | ||
190 | * contains the info for the wake GPE associated with the | ||
191 | * wake_device. | ||
192 | * | ||
193 | ******************************************************************************/ | ||
194 | acpi_status | ||
195 | acpi_setup_gpe_for_wake(acpi_handle wake_device, | ||
196 | acpi_handle gpe_device, u32 gpe_number) | ||
197 | { | ||
198 | acpi_status status = AE_BAD_PARAMETER; | ||
199 | struct acpi_gpe_event_info *gpe_event_info; | ||
200 | struct acpi_namespace_node *device_node; | ||
201 | struct acpi_gpe_notify_object *notify_object; | ||
202 | acpi_cpu_flags flags; | ||
203 | u8 gpe_dispatch_mask; | ||
204 | |||
205 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); | ||
206 | |||
207 | /* Parameter Validation */ | ||
208 | |||
209 | if (!wake_device) { | ||
210 | /* | ||
211 | * By forcing wake_device to be valid, we automatically enable the | ||
212 | * implicit notify feature on all hosts. | ||
213 | */ | ||
214 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
215 | } | ||
216 | |||
217 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
218 | |||
219 | /* Ensure that we have a valid GPE number */ | ||
220 | |||
221 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
222 | if (!gpe_event_info) { | ||
223 | goto unlock_and_exit; | ||
224 | } | ||
225 | |||
226 | if (wake_device == ACPI_ROOT_OBJECT) { | ||
227 | goto out; | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * If there is no method or handler for this GPE, then the | ||
232 | * wake_device will be notified whenever this GPE fires (aka | ||
233 | * "implicit notify") Note: The GPE is assumed to be | ||
234 | * level-triggered (for windows compatibility). | ||
235 | */ | ||
236 | gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; | ||
237 | if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE | ||
238 | && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { | ||
239 | goto out; | ||
240 | } | ||
241 | |||
242 | /* Validate wake_device is of type Device */ | ||
243 | |||
244 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); | ||
245 | if (device_node->type != ACPI_TYPE_DEVICE) { | ||
246 | goto unlock_and_exit; | ||
247 | } | ||
248 | |||
249 | if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { | ||
250 | gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | | ||
251 | ACPI_GPE_LEVEL_TRIGGERED); | ||
252 | gpe_event_info->dispatch.device.node = device_node; | ||
253 | gpe_event_info->dispatch.device.next = NULL; | ||
254 | } else { | ||
255 | /* There are multiple devices to notify implicitly. */ | ||
256 | |||
257 | notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); | ||
258 | if (!notify_object) { | ||
259 | status = AE_NO_MEMORY; | ||
260 | goto unlock_and_exit; | ||
261 | } | ||
262 | |||
263 | notify_object->node = device_node; | ||
264 | notify_object->next = gpe_event_info->dispatch.device.next; | ||
265 | gpe_event_info->dispatch.device.next = notify_object; | ||
266 | } | ||
267 | |||
268 | out: | ||
269 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | ||
270 | status = AE_OK; | ||
271 | |||
272 | unlock_and_exit: | ||
273 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
274 | return_ACPI_STATUS(status); | ||
275 | } | ||
276 | ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) | ||
277 | |||
278 | /******************************************************************************* | ||
279 | * | ||
280 | * FUNCTION: acpi_set_gpe_wake_mask | ||
281 | * | ||
282 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
283 | * gpe_number - GPE level within the GPE block | ||
284 | * Action - Enable or Disable | ||
285 | * | ||
286 | * RETURN: Status | ||
287 | * | ||
288 | * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must | ||
289 | * already be marked as a WAKE GPE. | ||
290 | * | ||
291 | ******************************************************************************/ | ||
292 | |||
293 | acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) | ||
294 | { | ||
295 | acpi_status status = AE_OK; | ||
296 | struct acpi_gpe_event_info *gpe_event_info; | ||
297 | struct acpi_gpe_register_info *gpe_register_info; | ||
298 | acpi_cpu_flags flags; | ||
299 | u32 register_bit; | ||
300 | |||
301 | ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask); | ||
302 | |||
303 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
304 | |||
305 | /* | ||
306 | * Ensure that we have a valid GPE number and that this GPE is in | ||
307 | * fact a wake GPE | ||
308 | */ | ||
309 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
310 | if (!gpe_event_info) { | ||
311 | status = AE_BAD_PARAMETER; | ||
312 | goto unlock_and_exit; | ||
313 | } | ||
314 | |||
315 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | ||
316 | status = AE_TYPE; | ||
317 | goto unlock_and_exit; | ||
318 | } | ||
319 | |||
320 | gpe_register_info = gpe_event_info->register_info; | ||
321 | if (!gpe_register_info) { | ||
322 | status = AE_NOT_EXIST; | ||
323 | goto unlock_and_exit; | ||
324 | } | ||
325 | |||
326 | register_bit = | ||
327 | acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); | ||
328 | |||
329 | /* Perform the action */ | ||
330 | |||
331 | switch (action) { | ||
332 | case ACPI_GPE_ENABLE: | ||
333 | ACPI_SET_BIT(gpe_register_info->enable_for_wake, | ||
334 | (u8)register_bit); | ||
335 | break; | ||
336 | |||
337 | case ACPI_GPE_DISABLE: | ||
338 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, | ||
339 | (u8)register_bit); | ||
340 | break; | ||
341 | |||
342 | default: | ||
343 | ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); | ||
344 | status = AE_BAD_PARAMETER; | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | unlock_and_exit: | ||
349 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
350 | return_ACPI_STATUS(status); | ||
351 | } | ||
352 | |||
353 | ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask) | ||
354 | |||
355 | /******************************************************************************* | ||
356 | * | ||
357 | * FUNCTION: acpi_clear_gpe | ||
358 | * | ||
359 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
360 | * gpe_number - GPE level within the GPE block | ||
361 | * | ||
362 | * RETURN: Status | ||
363 | * | ||
364 | * DESCRIPTION: Clear an ACPI event (general purpose) | ||
365 | * | ||
366 | ******************************************************************************/ | ||
367 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
368 | { | ||
369 | acpi_status status = AE_OK; | ||
370 | struct acpi_gpe_event_info *gpe_event_info; | ||
371 | acpi_cpu_flags flags; | ||
372 | |||
373 | ACPI_FUNCTION_TRACE(acpi_clear_gpe); | ||
374 | |||
375 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
376 | |||
377 | /* Ensure that we have a valid GPE number */ | ||
378 | |||
379 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
380 | if (!gpe_event_info) { | ||
381 | status = AE_BAD_PARAMETER; | ||
382 | goto unlock_and_exit; | ||
383 | } | ||
384 | |||
385 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
386 | |||
387 | unlock_and_exit: | ||
388 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
389 | return_ACPI_STATUS(status); | ||
390 | } | ||
391 | |||
392 | ACPI_EXPORT_SYMBOL(acpi_clear_gpe) | ||
393 | |||
394 | /******************************************************************************* | ||
395 | * | ||
396 | * FUNCTION: acpi_get_gpe_status | ||
397 | * | ||
398 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
399 | * gpe_number - GPE level within the GPE block | ||
400 | * event_status - Where the current status of the event will | ||
401 | * be returned | ||
402 | * | ||
403 | * RETURN: Status | ||
404 | * | ||
405 | * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) | ||
406 | * | ||
407 | ******************************************************************************/ | ||
408 | acpi_status | ||
409 | acpi_get_gpe_status(acpi_handle gpe_device, | ||
410 | u32 gpe_number, acpi_event_status *event_status) | ||
411 | { | ||
412 | acpi_status status = AE_OK; | ||
413 | struct acpi_gpe_event_info *gpe_event_info; | ||
414 | acpi_cpu_flags flags; | ||
415 | |||
416 | ACPI_FUNCTION_TRACE(acpi_get_gpe_status); | ||
417 | |||
418 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
419 | |||
420 | /* Ensure that we have a valid GPE number */ | ||
421 | |||
422 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
423 | if (!gpe_event_info) { | ||
424 | status = AE_BAD_PARAMETER; | ||
425 | goto unlock_and_exit; | ||
426 | } | ||
427 | |||
428 | /* Obtain status on the requested GPE number */ | ||
429 | |||
430 | status = acpi_hw_get_gpe_status(gpe_event_info, event_status); | ||
431 | |||
432 | if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) | ||
433 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | ||
434 | |||
435 | unlock_and_exit: | ||
436 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
437 | return_ACPI_STATUS(status); | ||
438 | } | ||
439 | |||
440 | ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) | ||
441 | |||
442 | /****************************************************************************** | ||
443 | * | ||
444 | * FUNCTION: acpi_disable_all_gpes | ||
445 | * | ||
446 | * PARAMETERS: None | ||
447 | * | ||
448 | * RETURN: Status | ||
449 | * | ||
450 | * DESCRIPTION: Disable and clear all GPEs in all GPE blocks | ||
451 | * | ||
452 | ******************************************************************************/ | ||
453 | |||
454 | acpi_status acpi_disable_all_gpes(void) | ||
455 | { | ||
456 | acpi_status status; | ||
457 | |||
458 | ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); | ||
459 | |||
460 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
461 | if (ACPI_FAILURE(status)) { | ||
462 | return_ACPI_STATUS(status); | ||
463 | } | ||
464 | |||
465 | status = acpi_hw_disable_all_gpes(); | ||
466 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
467 | |||
468 | return_ACPI_STATUS(status); | ||
469 | } | ||
470 | |||
471 | ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes) | ||
472 | |||
473 | /****************************************************************************** | ||
474 | * | ||
475 | * FUNCTION: acpi_enable_all_runtime_gpes | ||
476 | * | ||
477 | * PARAMETERS: None | ||
478 | * | ||
479 | * RETURN: Status | ||
480 | * | ||
481 | * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks | ||
482 | * | ||
483 | ******************************************************************************/ | ||
484 | |||
485 | acpi_status acpi_enable_all_runtime_gpes(void) | ||
486 | { | ||
487 | acpi_status status; | ||
488 | |||
489 | ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); | ||
490 | |||
491 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
492 | if (ACPI_FAILURE(status)) { | ||
493 | return_ACPI_STATUS(status); | ||
494 | } | ||
495 | |||
496 | status = acpi_hw_enable_all_runtime_gpes(); | ||
497 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
498 | |||
499 | return_ACPI_STATUS(status); | ||
500 | } | ||
501 | |||
502 | ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) | ||
503 | |||
504 | /******************************************************************************* | ||
505 | * | ||
506 | * FUNCTION: acpi_install_gpe_block | ||
507 | * | ||
508 | * PARAMETERS: gpe_device - Handle to the parent GPE Block Device | ||
509 | * gpe_block_address - Address and space_iD | ||
510 | * register_count - Number of GPE register pairs in the block | ||
511 | * interrupt_number - H/W interrupt for the block | ||
512 | * | ||
513 | * RETURN: Status | ||
514 | * | ||
515 | * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not | ||
516 | * enabled here. | ||
517 | * | ||
518 | ******************************************************************************/ | ||
519 | acpi_status | ||
520 | acpi_install_gpe_block(acpi_handle gpe_device, | ||
521 | struct acpi_generic_address *gpe_block_address, | ||
522 | u32 register_count, u32 interrupt_number) | ||
523 | { | ||
524 | acpi_status status; | ||
525 | union acpi_operand_object *obj_desc; | ||
526 | struct acpi_namespace_node *node; | ||
527 | struct acpi_gpe_block_info *gpe_block; | ||
528 | |||
529 | ACPI_FUNCTION_TRACE(acpi_install_gpe_block); | ||
530 | |||
531 | if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { | ||
532 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
533 | } | ||
534 | |||
535 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
536 | if (ACPI_FAILURE(status)) { | ||
537 | return (status); | ||
538 | } | ||
539 | |||
540 | node = acpi_ns_validate_handle(gpe_device); | ||
541 | if (!node) { | ||
542 | status = AE_BAD_PARAMETER; | ||
543 | goto unlock_and_exit; | ||
544 | } | ||
545 | |||
546 | /* | ||
547 | * For user-installed GPE Block Devices, the gpe_block_base_number | ||
548 | * is always zero | ||
549 | */ | ||
550 | status = | ||
551 | acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, | ||
552 | interrupt_number, &gpe_block); | ||
553 | if (ACPI_FAILURE(status)) { | ||
554 | goto unlock_and_exit; | ||
555 | } | ||
556 | |||
557 | /* Install block in the device_object attached to the node */ | ||
558 | |||
559 | obj_desc = acpi_ns_get_attached_object(node); | ||
560 | if (!obj_desc) { | ||
561 | |||
562 | /* | ||
563 | * No object, create a new one (Device nodes do not always have | ||
564 | * an attached object) | ||
565 | */ | ||
566 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); | ||
567 | if (!obj_desc) { | ||
568 | status = AE_NO_MEMORY; | ||
569 | goto unlock_and_exit; | ||
570 | } | ||
571 | |||
572 | status = | ||
573 | acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); | ||
574 | |||
575 | /* Remove local reference to the object */ | ||
576 | |||
577 | acpi_ut_remove_reference(obj_desc); | ||
578 | |||
579 | if (ACPI_FAILURE(status)) { | ||
580 | goto unlock_and_exit; | ||
581 | } | ||
582 | } | ||
583 | |||
584 | /* Now install the GPE block in the device_object */ | ||
585 | |||
586 | obj_desc->device.gpe_block = gpe_block; | ||
587 | |||
588 | unlock_and_exit: | ||
589 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
590 | return_ACPI_STATUS(status); | ||
591 | } | ||
592 | |||
593 | ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) | ||
594 | |||
595 | /******************************************************************************* | ||
596 | * | ||
597 | * FUNCTION: acpi_remove_gpe_block | ||
598 | * | ||
599 | * PARAMETERS: gpe_device - Handle to the parent GPE Block Device | ||
600 | * | ||
601 | * RETURN: Status | ||
602 | * | ||
603 | * DESCRIPTION: Remove a previously installed block of GPE registers | ||
604 | * | ||
605 | ******************************************************************************/ | ||
606 | acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) | ||
607 | { | ||
608 | union acpi_operand_object *obj_desc; | ||
609 | acpi_status status; | ||
610 | struct acpi_namespace_node *node; | ||
611 | |||
612 | ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); | ||
613 | |||
614 | if (!gpe_device) { | ||
615 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
616 | } | ||
617 | |||
618 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
619 | if (ACPI_FAILURE(status)) { | ||
620 | return (status); | ||
621 | } | ||
622 | |||
623 | node = acpi_ns_validate_handle(gpe_device); | ||
624 | if (!node) { | ||
625 | status = AE_BAD_PARAMETER; | ||
626 | goto unlock_and_exit; | ||
627 | } | ||
628 | |||
629 | /* Get the device_object attached to the node */ | ||
630 | |||
631 | obj_desc = acpi_ns_get_attached_object(node); | ||
632 | if (!obj_desc || !obj_desc->device.gpe_block) { | ||
633 | return_ACPI_STATUS(AE_NULL_OBJECT); | ||
634 | } | ||
635 | |||
636 | /* Delete the GPE block (but not the device_object) */ | ||
637 | |||
638 | status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); | ||
639 | if (ACPI_SUCCESS(status)) { | ||
640 | obj_desc->device.gpe_block = NULL; | ||
641 | } | ||
642 | |||
643 | unlock_and_exit: | ||
644 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
645 | return_ACPI_STATUS(status); | ||
646 | } | ||
647 | |||
648 | ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) | ||
649 | |||
650 | /******************************************************************************* | ||
651 | * | ||
652 | * FUNCTION: acpi_get_gpe_device | ||
653 | * | ||
654 | * PARAMETERS: Index - System GPE index (0-current_gpe_count) | ||
655 | * gpe_device - Where the parent GPE Device is returned | ||
656 | * | ||
657 | * RETURN: Status | ||
658 | * | ||
659 | * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL | ||
660 | * gpe device indicates that the gpe number is contained in one of | ||
661 | * the FADT-defined gpe blocks. Otherwise, the GPE block device. | ||
662 | * | ||
663 | ******************************************************************************/ | ||
664 | acpi_status | ||
665 | acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) | ||
666 | { | ||
667 | struct acpi_gpe_device_info info; | ||
668 | acpi_status status; | ||
669 | |||
670 | ACPI_FUNCTION_TRACE(acpi_get_gpe_device); | ||
671 | |||
672 | if (!gpe_device) { | ||
673 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
674 | } | ||
675 | |||
676 | if (index >= acpi_current_gpe_count) { | ||
677 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
678 | } | ||
679 | |||
680 | /* Setup and walk the GPE list */ | ||
681 | |||
682 | info.index = index; | ||
683 | info.status = AE_NOT_EXIST; | ||
684 | info.gpe_device = NULL; | ||
685 | info.next_block_base_index = 0; | ||
686 | |||
687 | status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); | ||
688 | if (ACPI_FAILURE(status)) { | ||
689 | return_ACPI_STATUS(status); | ||
690 | } | ||
691 | |||
692 | *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device); | ||
693 | return_ACPI_STATUS(info.status); | ||
694 | } | ||
695 | |||
696 | ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) | ||
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 541cbc1544d5..00cd95692a91 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -64,6 +64,12 @@ ACPI_MODULE_NAME("evxfregn") | |||
64 | * | 64 | * |
65 | * DESCRIPTION: Install a handler for all op_regions of a given space_id. | 65 | * DESCRIPTION: Install a handler for all op_regions of a given space_id. |
66 | * | 66 | * |
67 | * NOTE: This function should only be called after acpi_enable_subsystem has | ||
68 | * been called. This is because any _REG methods associated with the Space ID | ||
69 | * are executed here, and these methods can only be safely executed after | ||
70 | * the default handlers have been installed and the hardware has been | ||
71 | * initialized (via acpi_enable_subsystem.) | ||
72 | * | ||
67 | ******************************************************************************/ | 73 | ******************************************************************************/ |
68 | acpi_status | 74 | acpi_status |
69 | acpi_install_address_space_handler(acpi_handle device, | 75 | acpi_install_address_space_handler(acpi_handle device, |
@@ -104,6 +110,37 @@ acpi_install_address_space_handler(acpi_handle device, | |||
104 | goto unlock_and_exit; | 110 | goto unlock_and_exit; |
105 | } | 111 | } |
106 | 112 | ||
113 | /* | ||
114 | * For the default space_iDs, (the IDs for which there are default region handlers | ||
115 | * installed) Only execute the _REG methods if the global initialization _REG | ||
116 | * methods have already been run (via acpi_initialize_objects). In other words, | ||
117 | * we will defer the execution of the _REG methods for these space_iDs until | ||
118 | * execution of acpi_initialize_objects. This is done because we need the handlers | ||
119 | * for the default spaces (mem/io/pci/table) to be installed before we can run | ||
120 | * any control methods (or _REG methods). There is known BIOS code that depends | ||
121 | * on this. | ||
122 | * | ||
123 | * For all other space_iDs, we can safely execute the _REG methods immediately. | ||
124 | * This means that for IDs like embedded_controller, this function should be called | ||
125 | * only after acpi_enable_subsystem has been called. | ||
126 | */ | ||
127 | switch (space_id) { | ||
128 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | ||
129 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
130 | case ACPI_ADR_SPACE_PCI_CONFIG: | ||
131 | case ACPI_ADR_SPACE_DATA_TABLE: | ||
132 | |||
133 | if (!acpi_gbl_reg_methods_executed) { | ||
134 | |||
135 | /* We will defer execution of the _REG methods for this space */ | ||
136 | goto unlock_and_exit; | ||
137 | } | ||
138 | break; | ||
139 | |||
140 | default: | ||
141 | break; | ||
142 | } | ||
143 | |||
107 | /* Run all _REG methods for this address space */ | 144 | /* Run all _REG methods for this address space */ |
108 | 145 | ||
109 | status = acpi_ev_execute_reg_methods(node, space_id); | 146 | status = acpi_ev_execute_reg_methods(node, space_id); |
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 18832205b631..745a42b401f5 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index b73bc50c5b76..74162a11817d 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 3c61b48c73f5..110711afada8 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -305,7 +305,8 @@ acpi_ex_create_region(u8 * aml_start, | |||
305 | * range | 305 | * range |
306 | */ | 306 | */ |
307 | if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && | 307 | if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && |
308 | (region_space < ACPI_USER_REGION_BEGIN)) { | 308 | (region_space < ACPI_USER_REGION_BEGIN) && |
309 | (region_space != ACPI_ADR_SPACE_DATA_TABLE)) { | ||
309 | ACPI_ERROR((AE_INFO, "Invalid AddressSpace type 0x%X", | 310 | ACPI_ERROR((AE_INFO, "Invalid AddressSpace type 0x%X", |
310 | region_space)); | 311 | region_space)); |
311 | return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); | 312 | return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); |
@@ -482,13 +483,11 @@ acpi_ex_create_method(u8 * aml_start, | |||
482 | obj_desc->method.aml_length = aml_length; | 483 | obj_desc->method.aml_length = aml_length; |
483 | 484 | ||
484 | /* | 485 | /* |
485 | * Disassemble the method flags. Split off the Arg Count | 486 | * Disassemble the method flags. Split off the arg_count, Serialized |
486 | * for efficiency | 487 | * flag, and sync_level for efficiency. |
487 | */ | 488 | */ |
488 | method_flags = (u8) operand[1]->integer.value; | 489 | method_flags = (u8) operand[1]->integer.value; |
489 | 490 | ||
490 | obj_desc->method.method_flags = | ||
491 | (u8) (method_flags & ~AML_METHOD_ARG_COUNT); | ||
492 | obj_desc->method.param_count = | 491 | obj_desc->method.param_count = |
493 | (u8) (method_flags & AML_METHOD_ARG_COUNT); | 492 | (u8) (method_flags & AML_METHOD_ARG_COUNT); |
494 | 493 | ||
@@ -497,6 +496,8 @@ acpi_ex_create_method(u8 * aml_start, | |||
497 | * created for this method when it is parsed. | 496 | * created for this method when it is parsed. |
498 | */ | 497 | */ |
499 | if (method_flags & AML_METHOD_SERIALIZED) { | 498 | if (method_flags & AML_METHOD_SERIALIZED) { |
499 | obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED; | ||
500 | |||
500 | /* | 501 | /* |
501 | * ACPI 1.0: sync_level = 0 | 502 | * ACPI 1.0: sync_level = 0 |
502 | * ACPI 2.0: sync_level = sync_level in method declaration | 503 | * ACPI 2.0: sync_level = sync_level in method declaration |
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index be8c98b480d7..c7a2f1edd282 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index f067bbb0d961..61b8c0e8b74d 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -122,7 +122,7 @@ static struct acpi_exdump_info acpi_ex_dump_event[2] = { | |||
122 | 122 | ||
123 | static struct acpi_exdump_info acpi_ex_dump_method[9] = { | 123 | static struct acpi_exdump_info acpi_ex_dump_method[9] = { |
124 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, | 124 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, |
125 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.method_flags), "Method Flags"}, | 125 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.info_flags), "Info Flags"}, |
126 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), | 126 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), |
127 | "Parameter Count"}, | 127 | "Parameter Count"}, |
128 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"}, | 128 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"}, |
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index f17d2ff0031b..0bde2230c028 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 047217303a4b..f915a7f3f921 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
119 | } | 119 | } |
120 | 120 | ||
121 | /* | 121 | /* |
122 | * Exit now for SMBus or IPMI address space, it has a non-linear address space | 122 | * Exit now for SMBus or IPMI address space, it has a non-linear |
123 | * and the request cannot be directly validated | 123 | * address space and the request cannot be directly validated |
124 | */ | 124 | */ |
125 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || | 125 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || |
126 | rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { | 126 | rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { |
@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
147 | * (Region length is specified in bytes) | 147 | * (Region length is specified in bytes) |
148 | */ | 148 | */ |
149 | if (rgn_desc->region.length < | 149 | if (rgn_desc->region.length < |
150 | (obj_desc->common_field.base_byte_offset + | 150 | (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + |
151 | field_datum_byte_offset + | ||
152 | obj_desc->common_field.access_byte_width)) { | 151 | obj_desc->common_field.access_byte_width)) { |
153 | if (acpi_gbl_enable_interpreter_slack) { | 152 | if (acpi_gbl_enable_interpreter_slack) { |
154 | /* | 153 | /* |
@@ -281,13 +280,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, | |||
281 | if (ACPI_FAILURE(status)) { | 280 | if (ACPI_FAILURE(status)) { |
282 | if (status == AE_NOT_IMPLEMENTED) { | 281 | if (status == AE_NOT_IMPLEMENTED) { |
283 | ACPI_ERROR((AE_INFO, | 282 | ACPI_ERROR((AE_INFO, |
284 | "Region %s(0x%X) not implemented", | 283 | "Region %s (ID=%u) not implemented", |
285 | acpi_ut_get_region_name(rgn_desc->region. | 284 | acpi_ut_get_region_name(rgn_desc->region. |
286 | space_id), | 285 | space_id), |
287 | rgn_desc->region.space_id)); | 286 | rgn_desc->region.space_id)); |
288 | } else if (status == AE_NOT_EXIST) { | 287 | } else if (status == AE_NOT_EXIST) { |
289 | ACPI_ERROR((AE_INFO, | 288 | ACPI_ERROR((AE_INFO, |
290 | "Region %s(0x%X) has no handler", | 289 | "Region %s (ID=%u) has no handler", |
291 | acpi_ut_get_region_name(rgn_desc->region. | 290 | acpi_ut_get_region_name(rgn_desc->region. |
292 | space_id), | 291 | space_id), |
293 | rgn_desc->region.space_id)); | 292 | rgn_desc->region.space_id)); |
@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, | |||
680 | u32 buffer_tail_bits; | 679 | u32 buffer_tail_bits; |
681 | u32 datum_count; | 680 | u32 datum_count; |
682 | u32 field_datum_count; | 681 | u32 field_datum_count; |
682 | u32 access_bit_width; | ||
683 | u32 i; | 683 | u32 i; |
684 | 684 | ||
685 | ACPI_FUNCTION_TRACE(ex_extract_from_field); | 685 | ACPI_FUNCTION_TRACE(ex_extract_from_field); |
@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, | |||
694 | 694 | ||
695 | return_ACPI_STATUS(AE_BUFFER_OVERFLOW); | 695 | return_ACPI_STATUS(AE_BUFFER_OVERFLOW); |
696 | } | 696 | } |
697 | |||
697 | ACPI_MEMSET(buffer, 0, buffer_length); | 698 | ACPI_MEMSET(buffer, 0, buffer_length); |
699 | access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width); | ||
700 | |||
701 | /* Handle the simple case here */ | ||
702 | |||
703 | if ((obj_desc->common_field.start_field_bit_offset == 0) && | ||
704 | (obj_desc->common_field.bit_length == access_bit_width)) { | ||
705 | status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ); | ||
706 | return_ACPI_STATUS(status); | ||
707 | } | ||
708 | |||
709 | /* TBD: Move to common setup code */ | ||
710 | |||
711 | /* Field algorithm is limited to sizeof(u64), truncate if needed */ | ||
712 | |||
713 | if (obj_desc->common_field.access_byte_width > sizeof(u64)) { | ||
714 | obj_desc->common_field.access_byte_width = sizeof(u64); | ||
715 | access_bit_width = sizeof(u64) * 8; | ||
716 | } | ||
698 | 717 | ||
699 | /* Compute the number of datums (access width data items) */ | 718 | /* Compute the number of datums (access width data items) */ |
700 | 719 | ||
701 | datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, | 720 | datum_count = |
702 | obj_desc->common_field.access_bit_width); | 721 | ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, |
722 | access_bit_width); | ||
723 | |||
703 | field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + | 724 | field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + |
704 | obj_desc->common_field. | 725 | obj_desc->common_field. |
705 | start_field_bit_offset, | 726 | start_field_bit_offset, |
706 | obj_desc->common_field. | ||
707 | access_bit_width); | 727 | access_bit_width); |
708 | 728 | ||
709 | /* Priming read from the field */ | 729 | /* Priming read from the field */ |
@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, | |||
738 | * This avoids the differences in behavior between different compilers | 758 | * This avoids the differences in behavior between different compilers |
739 | * concerning shift values larger than the target data width. | 759 | * concerning shift values larger than the target data width. |
740 | */ | 760 | */ |
741 | if ((obj_desc->common_field.access_bit_width - | 761 | if (access_bit_width - |
742 | obj_desc->common_field.start_field_bit_offset) < | 762 | obj_desc->common_field.start_field_bit_offset < |
743 | ACPI_INTEGER_BIT_SIZE) { | 763 | ACPI_INTEGER_BIT_SIZE) { |
744 | merged_datum |= | 764 | merged_datum |= |
745 | raw_datum << (obj_desc->common_field. | 765 | raw_datum << (access_bit_width - |
746 | access_bit_width - | ||
747 | obj_desc->common_field. | 766 | obj_desc->common_field. |
748 | start_field_bit_offset); | 767 | start_field_bit_offset); |
749 | } | 768 | } |
@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, | |||
765 | 784 | ||
766 | /* Mask off any extra bits in the last datum */ | 785 | /* Mask off any extra bits in the last datum */ |
767 | 786 | ||
768 | buffer_tail_bits = obj_desc->common_field.bit_length % | 787 | buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width; |
769 | obj_desc->common_field.access_bit_width; | ||
770 | if (buffer_tail_bits) { | 788 | if (buffer_tail_bits) { |
771 | merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); | 789 | merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); |
772 | } | 790 | } |
@@ -798,6 +816,7 @@ acpi_status | |||
798 | acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | 816 | acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, |
799 | void *buffer, u32 buffer_length) | 817 | void *buffer, u32 buffer_length) |
800 | { | 818 | { |
819 | void *new_buffer; | ||
801 | acpi_status status; | 820 | acpi_status status; |
802 | u64 mask; | 821 | u64 mask; |
803 | u64 width_mask; | 822 | u64 width_mask; |
@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
808 | u32 buffer_tail_bits; | 827 | u32 buffer_tail_bits; |
809 | u32 datum_count; | 828 | u32 datum_count; |
810 | u32 field_datum_count; | 829 | u32 field_datum_count; |
811 | u32 i; | 830 | u32 access_bit_width; |
812 | u32 required_length; | 831 | u32 required_length; |
813 | void *new_buffer; | 832 | u32 i; |
814 | 833 | ||
815 | ACPI_FUNCTION_TRACE(ex_insert_into_field); | 834 | ACPI_FUNCTION_TRACE(ex_insert_into_field); |
816 | 835 | ||
@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
844 | buffer_length = required_length; | 863 | buffer_length = required_length; |
845 | } | 864 | } |
846 | 865 | ||
866 | /* TBD: Move to common setup code */ | ||
867 | |||
868 | /* Algo is limited to sizeof(u64), so cut the access_byte_width */ | ||
869 | if (obj_desc->common_field.access_byte_width > sizeof(u64)) { | ||
870 | obj_desc->common_field.access_byte_width = sizeof(u64); | ||
871 | } | ||
872 | |||
873 | access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width); | ||
874 | |||
847 | /* | 875 | /* |
848 | * Create the bitmasks used for bit insertion. | 876 | * Create the bitmasks used for bit insertion. |
849 | * Note: This if/else is used to bypass compiler differences with the | 877 | * Note: This if/else is used to bypass compiler differences with the |
850 | * shift operator | 878 | * shift operator |
851 | */ | 879 | */ |
852 | if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) { | 880 | if (access_bit_width == ACPI_INTEGER_BIT_SIZE) { |
853 | width_mask = ACPI_UINT64_MAX; | 881 | width_mask = ACPI_UINT64_MAX; |
854 | } else { | 882 | } else { |
855 | width_mask = | 883 | width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width); |
856 | ACPI_MASK_BITS_ABOVE(obj_desc->common_field. | ||
857 | access_bit_width); | ||
858 | } | 884 | } |
859 | 885 | ||
860 | mask = width_mask & | 886 | mask = width_mask & |
@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
863 | /* Compute the number of datums (access width data items) */ | 889 | /* Compute the number of datums (access width data items) */ |
864 | 890 | ||
865 | datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, | 891 | datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, |
866 | obj_desc->common_field.access_bit_width); | 892 | access_bit_width); |
867 | 893 | ||
868 | field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + | 894 | field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + |
869 | obj_desc->common_field. | 895 | obj_desc->common_field. |
870 | start_field_bit_offset, | 896 | start_field_bit_offset, |
871 | obj_desc->common_field. | ||
872 | access_bit_width); | 897 | access_bit_width); |
873 | 898 | ||
874 | /* Get initial Datum from the input buffer */ | 899 | /* Get initial Datum from the input buffer */ |
@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
905 | * This avoids the differences in behavior between different compilers | 930 | * This avoids the differences in behavior between different compilers |
906 | * concerning shift values larger than the target data width. | 931 | * concerning shift values larger than the target data width. |
907 | */ | 932 | */ |
908 | if ((obj_desc->common_field.access_bit_width - | 933 | if ((access_bit_width - |
909 | obj_desc->common_field.start_field_bit_offset) < | 934 | obj_desc->common_field.start_field_bit_offset) < |
910 | ACPI_INTEGER_BIT_SIZE) { | 935 | ACPI_INTEGER_BIT_SIZE) { |
911 | merged_datum = | 936 | merged_datum = |
912 | raw_datum >> (obj_desc->common_field. | 937 | raw_datum >> (access_bit_width - |
913 | access_bit_width - | ||
914 | obj_desc->common_field. | 938 | obj_desc->common_field. |
915 | start_field_bit_offset); | 939 | start_field_bit_offset); |
916 | } else { | 940 | } else { |
@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
929 | ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, | 953 | ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, |
930 | ACPI_MIN(obj_desc->common_field.access_byte_width, | 954 | ACPI_MIN(obj_desc->common_field.access_byte_width, |
931 | buffer_length - buffer_offset)); | 955 | buffer_length - buffer_offset)); |
956 | |||
932 | merged_datum |= | 957 | merged_datum |= |
933 | raw_datum << obj_desc->common_field.start_field_bit_offset; | 958 | raw_datum << obj_desc->common_field.start_field_bit_offset; |
934 | } | 959 | } |
@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
937 | 962 | ||
938 | buffer_tail_bits = (obj_desc->common_field.bit_length + | 963 | buffer_tail_bits = (obj_desc->common_field.bit_length + |
939 | obj_desc->common_field.start_field_bit_offset) % | 964 | obj_desc->common_field.start_field_bit_offset) % |
940 | obj_desc->common_field.access_bit_width; | 965 | access_bit_width; |
941 | if (buffer_tail_bits) { | 966 | if (buffer_tail_bits) { |
942 | mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); | 967 | mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); |
943 | } | 968 | } |
diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 95db4be0877b..703d88ed0b3d 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index f73be97043c0..be1c56ead653 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -336,7 +336,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) | |||
336 | 336 | ||
337 | /* Clear mutex info */ | 337 | /* Clear mutex info */ |
338 | 338 | ||
339 | obj_desc->mutex.thread_id = NULL; | 339 | obj_desc->mutex.thread_id = 0; |
340 | return_ACPI_STATUS(status); | 340 | return_ACPI_STATUS(status); |
341 | } | 341 | } |
342 | 342 | ||
@@ -393,10 +393,10 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
393 | if ((owner_thread->thread_id != walk_state->thread->thread_id) && | 393 | if ((owner_thread->thread_id != walk_state->thread->thread_id) && |
394 | (obj_desc != acpi_gbl_global_lock_mutex)) { | 394 | (obj_desc != acpi_gbl_global_lock_mutex)) { |
395 | ACPI_ERROR((AE_INFO, | 395 | ACPI_ERROR((AE_INFO, |
396 | "Thread %p cannot release Mutex [%4.4s] acquired by thread %p", | 396 | "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", |
397 | ACPI_CAST_PTR(void, walk_state->thread->thread_id), | 397 | (u32)walk_state->thread->thread_id, |
398 | acpi_ut_get_node_name(obj_desc->mutex.node), | 398 | acpi_ut_get_node_name(obj_desc->mutex.node), |
399 | ACPI_CAST_PTR(void, owner_thread->thread_id))); | 399 | (u32)owner_thread->thread_id)); |
400 | return_ACPI_STATUS(AE_AML_NOT_OWNER); | 400 | return_ACPI_STATUS(AE_AML_NOT_OWNER); |
401 | } | 401 | } |
402 | 402 | ||
@@ -488,7 +488,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) | |||
488 | /* Mark mutex unowned */ | 488 | /* Mark mutex unowned */ |
489 | 489 | ||
490 | obj_desc->mutex.owner_thread = NULL; | 490 | obj_desc->mutex.owner_thread = NULL; |
491 | obj_desc->mutex.thread_id = NULL; | 491 | obj_desc->mutex.thread_id = 0; |
492 | 492 | ||
493 | /* Update Thread sync_level (Last mutex is the important one) */ | 493 | /* Update Thread sync_level (Last mutex is the important one) */ |
494 | 494 | ||
diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index d11e539ef763..49ec049c157e 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 84e4d185aa25..236ead14b7f7 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index 10e104cf0fb9..2571b4a310f4 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 7a08d23befcd..1b48d9d28c9a 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 4b50730cf9a0..f4a2787e8e92 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 98a331d2249b..cc95e2000406 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -355,12 +355,10 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, | |||
355 | return_ACPI_STATUS(AE_AML_OPERAND_VALUE); | 355 | return_ACPI_STATUS(AE_AML_OPERAND_VALUE); |
356 | } | 356 | } |
357 | 357 | ||
358 | /* Setup width (access granularity) fields */ | 358 | /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */ |
359 | 359 | ||
360 | obj_desc->common_field.access_byte_width = (u8) | 360 | obj_desc->common_field.access_byte_width = (u8) |
361 | ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */ | 361 | ACPI_DIV_8(access_bit_width); |
362 | |||
363 | obj_desc->common_field.access_bit_width = (u8) access_bit_width; | ||
364 | 362 | ||
365 | /* | 363 | /* |
366 | * base_byte_offset is the address of the start of the field within the | 364 | * base_byte_offset is the address of the start of the field within the |
@@ -405,8 +403,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | |||
405 | { | 403 | { |
406 | union acpi_operand_object *obj_desc; | 404 | union acpi_operand_object *obj_desc; |
407 | union acpi_operand_object *second_desc = NULL; | 405 | union acpi_operand_object *second_desc = NULL; |
408 | u32 type; | ||
409 | acpi_status status; | 406 | acpi_status status; |
407 | u32 access_byte_width; | ||
408 | u32 type; | ||
410 | 409 | ||
411 | ACPI_FUNCTION_TRACE(ex_prep_field_value); | 410 | ACPI_FUNCTION_TRACE(ex_prep_field_value); |
412 | 411 | ||
@@ -421,8 +420,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | |||
421 | type = acpi_ns_get_type(info->region_node); | 420 | type = acpi_ns_get_type(info->region_node); |
422 | if (type != ACPI_TYPE_REGION) { | 421 | if (type != ACPI_TYPE_REGION) { |
423 | ACPI_ERROR((AE_INFO, | 422 | ACPI_ERROR((AE_INFO, |
424 | "Needed Region, found type 0x%X (%s)", | 423 | "Needed Region, found type 0x%X (%s)", type, |
425 | type, acpi_ut_get_type_name(type))); | 424 | acpi_ut_get_type_name(type))); |
426 | 425 | ||
427 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 426 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
428 | } | 427 | } |
@@ -438,7 +437,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | |||
438 | /* Initialize areas of the object that are common to all fields */ | 437 | /* Initialize areas of the object that are common to all fields */ |
439 | 438 | ||
440 | obj_desc->common_field.node = info->field_node; | 439 | obj_desc->common_field.node = info->field_node; |
441 | status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, | 440 | status = acpi_ex_prep_common_field_object(obj_desc, |
441 | info->field_flags, | ||
442 | info->attribute, | 442 | info->attribute, |
443 | info->field_bit_position, | 443 | info->field_bit_position, |
444 | info->field_bit_length); | 444 | info->field_bit_length); |
@@ -455,26 +455,25 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | |||
455 | obj_desc->field.region_obj = | 455 | obj_desc->field.region_obj = |
456 | acpi_ns_get_attached_object(info->region_node); | 456 | acpi_ns_get_attached_object(info->region_node); |
457 | 457 | ||
458 | /* An additional reference for the container */ | 458 | /* Allow full data read from EC address space */ |
459 | 459 | ||
460 | acpi_ut_add_reference(obj_desc->field.region_obj); | 460 | if ((obj_desc->field.region_obj->region.space_id == |
461 | ACPI_ADR_SPACE_EC) | ||
462 | && (obj_desc->common_field.bit_length > 8)) { | ||
463 | access_byte_width = | ||
464 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field. | ||
465 | bit_length); | ||
466 | |||
467 | /* Maximum byte width supported is 255 */ | ||
461 | 468 | ||
462 | /* allow full data read from EC address space */ | 469 | if (access_byte_width < 256) { |
463 | if (obj_desc->field.region_obj->region.space_id == | ||
464 | ACPI_ADR_SPACE_EC) { | ||
465 | if (obj_desc->common_field.bit_length > 8) { | ||
466 | unsigned width = | ||
467 | ACPI_ROUND_BITS_UP_TO_BYTES( | ||
468 | obj_desc->common_field.bit_length); | ||
469 | // access_bit_width is u8, don't overflow it | ||
470 | if (width > 8) | ||
471 | width = 8; | ||
472 | obj_desc->common_field.access_byte_width = | 470 | obj_desc->common_field.access_byte_width = |
473 | width; | 471 | (u8)access_byte_width; |
474 | obj_desc->common_field.access_bit_width = | ||
475 | 8 * width; | ||
476 | } | 472 | } |
477 | } | 473 | } |
474 | /* An additional reference for the container */ | ||
475 | |||
476 | acpi_ut_add_reference(obj_desc->field.region_obj); | ||
478 | 477 | ||
479 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | 478 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
480 | "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", | 479 | "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", |
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 8819d2ac5aee..f0d5e14f1f2c 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -353,7 +353,6 @@ acpi_ex_pci_config_space_handler(u32 function, | |||
353 | acpi_status status = AE_OK; | 353 | acpi_status status = AE_OK; |
354 | struct acpi_pci_id *pci_id; | 354 | struct acpi_pci_id *pci_id; |
355 | u16 pci_register; | 355 | u16 pci_register; |
356 | u32 value32; | ||
357 | 356 | ||
358 | ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); | 357 | ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); |
359 | 358 | ||
@@ -381,8 +380,7 @@ acpi_ex_pci_config_space_handler(u32 function, | |||
381 | case ACPI_READ: | 380 | case ACPI_READ: |
382 | 381 | ||
383 | status = acpi_os_read_pci_configuration(pci_id, pci_register, | 382 | status = acpi_os_read_pci_configuration(pci_id, pci_register, |
384 | &value32, bit_width); | 383 | value, bit_width); |
385 | *value = value32; | ||
386 | break; | 384 | break; |
387 | 385 | ||
388 | case ACPI_WRITE: | 386 | case ACPI_WRITE: |
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index 1fa4289a687e..55997e46948b 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index 7ca35ea8acea..db502cd7d934 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 8c97cfd6a0fd..e3bb00ccdff5 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 1624436ba4c5..c0c8842dd344 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index d4af684620ca..a979017d56b8 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c | |||
@@ -7,7 +7,7 @@ | |||
7 | *****************************************************************************/ | 7 | *****************************************************************************/ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Copyright (C) 2000 - 2010, Intel Corp. | 10 | * Copyright (C) 2000 - 2011, Intel Corp. |
11 | * All rights reserved. | 11 | * All rights reserved. |
12 | * | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index e972b667b09b..dc665cc554de 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 675aaa91a770..df66e7b686be 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 4093522eed45..8ad93146dd32 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index b44274a0b62c..fc380d3d45ab 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 14750db2a1b8..f610d88a66be 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -62,10 +62,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
62 | * PARAMETERS: gpe_event_info - Info block for the GPE | 62 | * PARAMETERS: gpe_event_info - Info block for the GPE |
63 | * gpe_register_info - Info block for the GPE register | 63 | * gpe_register_info - Info block for the GPE register |
64 | * | 64 | * |
65 | * RETURN: Status | 65 | * RETURN: Register mask with a one in the GPE bit position |
66 | * | 66 | * |
67 | * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given | 67 | * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the |
68 | * GPE set. | 68 | * correct position for the input GPE. |
69 | * | 69 | * |
70 | ******************************************************************************/ | 70 | ******************************************************************************/ |
71 | 71 | ||
@@ -85,12 +85,12 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, | |||
85 | * | 85 | * |
86 | * RETURN: Status | 86 | * RETURN: Status |
87 | * | 87 | * |
88 | * DESCRIPTION: Enable or disable a single GPE in its enable register. | 88 | * DESCRIPTION: Enable or disable a single GPE in the parent enable register. |
89 | * | 89 | * |
90 | ******************************************************************************/ | 90 | ******************************************************************************/ |
91 | 91 | ||
92 | acpi_status | 92 | acpi_status |
93 | acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) | 93 | acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) |
94 | { | 94 | { |
95 | struct acpi_gpe_register_info *gpe_register_info; | 95 | struct acpi_gpe_register_info *gpe_register_info; |
96 | acpi_status status; | 96 | acpi_status status; |
@@ -113,14 +113,20 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) | |||
113 | return (status); | 113 | return (status); |
114 | } | 114 | } |
115 | 115 | ||
116 | /* Set ot clear just the bit that corresponds to this GPE */ | 116 | /* Set or clear just the bit that corresponds to this GPE */ |
117 | 117 | ||
118 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, | 118 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, |
119 | gpe_register_info); | 119 | gpe_register_info); |
120 | switch (action) { | 120 | switch (action) { |
121 | case ACPI_GPE_COND_ENABLE: | 121 | case ACPI_GPE_CONDITIONAL_ENABLE: |
122 | if (!(register_bit & gpe_register_info->enable_for_run)) | 122 | |
123 | /* Only enable if the enable_for_run bit is set */ | ||
124 | |||
125 | if (!(register_bit & gpe_register_info->enable_for_run)) { | ||
123 | return (AE_BAD_PARAMETER); | 126 | return (AE_BAD_PARAMETER); |
127 | } | ||
128 | |||
129 | /*lint -fallthrough */ | ||
124 | 130 | ||
125 | case ACPI_GPE_ENABLE: | 131 | case ACPI_GPE_ENABLE: |
126 | ACPI_SET_BIT(enable_mask, register_bit); | 132 | ACPI_SET_BIT(enable_mask, register_bit); |
@@ -131,7 +137,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) | |||
131 | break; | 137 | break; |
132 | 138 | ||
133 | default: | 139 | default: |
134 | ACPI_ERROR((AE_INFO, "Invalid action\n")); | 140 | ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action)); |
135 | return (AE_BAD_PARAMETER); | 141 | return (AE_BAD_PARAMETER); |
136 | } | 142 | } |
137 | 143 | ||
@@ -168,13 +174,13 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) | |||
168 | return (AE_NOT_EXIST); | 174 | return (AE_NOT_EXIST); |
169 | } | 175 | } |
170 | 176 | ||
171 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, | ||
172 | gpe_register_info); | ||
173 | |||
174 | /* | 177 | /* |
175 | * Write a one to the appropriate bit in the status register to | 178 | * Write a one to the appropriate bit in the status register to |
176 | * clear this GPE. | 179 | * clear this GPE. |
177 | */ | 180 | */ |
181 | register_bit = | ||
182 | acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); | ||
183 | |||
178 | status = acpi_hw_write(register_bit, | 184 | status = acpi_hw_write(register_bit, |
179 | &gpe_register_info->status_address); | 185 | &gpe_register_info->status_address); |
180 | 186 | ||
@@ -201,8 +207,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, | |||
201 | u32 in_byte; | 207 | u32 in_byte; |
202 | u32 register_bit; | 208 | u32 register_bit; |
203 | struct acpi_gpe_register_info *gpe_register_info; | 209 | struct acpi_gpe_register_info *gpe_register_info; |
204 | acpi_status status; | ||
205 | acpi_event_status local_event_status = 0; | 210 | acpi_event_status local_event_status = 0; |
211 | acpi_status status; | ||
206 | 212 | ||
207 | ACPI_FUNCTION_ENTRY(); | 213 | ACPI_FUNCTION_ENTRY(); |
208 | 214 | ||
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c new file mode 100644 index 000000000000..050fd227951b --- /dev/null +++ b/drivers/acpi/acpica/hwpci.c | |||
@@ -0,0 +1,412 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: hwpci - Obtain PCI bus, device, and function numbers | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | |||
47 | #define _COMPONENT ACPI_NAMESPACE | ||
48 | ACPI_MODULE_NAME("hwpci") | ||
49 | |||
50 | /* PCI configuration space values */ | ||
51 | #define PCI_CFG_HEADER_TYPE_REG 0x0E | ||
52 | #define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18 | ||
53 | #define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19 | ||
54 | /* PCI header values */ | ||
55 | #define PCI_HEADER_TYPE_MASK 0x7F | ||
56 | #define PCI_TYPE_BRIDGE 0x01 | ||
57 | #define PCI_TYPE_CARDBUS_BRIDGE 0x02 | ||
58 | typedef struct acpi_pci_device { | ||
59 | acpi_handle device; | ||
60 | struct acpi_pci_device *next; | ||
61 | |||
62 | } acpi_pci_device; | ||
63 | |||
64 | /* Local prototypes */ | ||
65 | |||
66 | static acpi_status | ||
67 | acpi_hw_build_pci_list(acpi_handle root_pci_device, | ||
68 | acpi_handle pci_region, | ||
69 | struct acpi_pci_device **return_list_head); | ||
70 | |||
71 | static acpi_status | ||
72 | acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, | ||
73 | struct acpi_pci_device *list_head); | ||
74 | |||
75 | static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head); | ||
76 | |||
77 | static acpi_status | ||
78 | acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, | ||
79 | acpi_handle pci_device, | ||
80 | u16 *bus_number, u8 *is_bridge); | ||
81 | |||
82 | /******************************************************************************* | ||
83 | * | ||
84 | * FUNCTION: acpi_hw_derive_pci_id | ||
85 | * | ||
86 | * PARAMETERS: pci_id - Initial values for the PCI ID. May be | ||
87 | * modified by this function. | ||
88 | * root_pci_device - A handle to a PCI device object. This | ||
89 | * object must be a PCI Root Bridge having a | ||
90 | * _HID value of either PNP0A03 or PNP0A08 | ||
91 | * pci_region - A handle to a PCI configuration space | ||
92 | * Operation Region being initialized | ||
93 | * | ||
94 | * RETURN: Status | ||
95 | * | ||
96 | * DESCRIPTION: This function derives a full PCI ID for a PCI device, | ||
97 | * consisting of a Segment number, Bus number, Device number, | ||
98 | * and function code. | ||
99 | * | ||
100 | * The PCI hardware dynamically configures PCI bus numbers | ||
101 | * depending on the bus topology discovered during system | ||
102 | * initialization. This function is invoked during configuration | ||
103 | * of a PCI_Config Operation Region in order to (possibly) update | ||
104 | * the Bus/Device/Function numbers in the pci_id with the actual | ||
105 | * values as determined by the hardware and operating system | ||
106 | * configuration. | ||
107 | * | ||
108 | * The pci_id parameter is initially populated during the Operation | ||
109 | * Region initialization. This function is then called, and is | ||
110 | * will make any necessary modifications to the Bus, Device, or | ||
111 | * Function number PCI ID subfields as appropriate for the | ||
112 | * current hardware and OS configuration. | ||
113 | * | ||
114 | * NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id | ||
115 | * interface since this feature is OS-independent. This module | ||
116 | * specifically avoids any use of recursion by building a local | ||
117 | * temporary device list. | ||
118 | * | ||
119 | ******************************************************************************/ | ||
120 | |||
121 | acpi_status | ||
122 | acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, | ||
123 | acpi_handle root_pci_device, acpi_handle pci_region) | ||
124 | { | ||
125 | acpi_status status; | ||
126 | struct acpi_pci_device *list_head = NULL; | ||
127 | |||
128 | ACPI_FUNCTION_TRACE(hw_derive_pci_id); | ||
129 | |||
130 | if (!pci_id) { | ||
131 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
132 | } | ||
133 | |||
134 | /* Build a list of PCI devices, from pci_region up to root_pci_device */ | ||
135 | |||
136 | status = | ||
137 | acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head); | ||
138 | if (ACPI_SUCCESS(status)) { | ||
139 | |||
140 | /* Walk the list, updating the PCI device/function/bus numbers */ | ||
141 | |||
142 | status = acpi_hw_process_pci_list(pci_id, list_head); | ||
143 | } | ||
144 | |||
145 | /* Always delete the list */ | ||
146 | |||
147 | acpi_hw_delete_pci_list(list_head); | ||
148 | return_ACPI_STATUS(status); | ||
149 | } | ||
150 | |||
151 | /******************************************************************************* | ||
152 | * | ||
153 | * FUNCTION: acpi_hw_build_pci_list | ||
154 | * | ||
155 | * PARAMETERS: root_pci_device - A handle to a PCI device object. This | ||
156 | * object is guaranteed to be a PCI Root | ||
157 | * Bridge having a _HID value of either | ||
158 | * PNP0A03 or PNP0A08 | ||
159 | * pci_region - A handle to the PCI configuration space | ||
160 | * Operation Region | ||
161 | * return_list_head - Where the PCI device list is returned | ||
162 | * | ||
163 | * RETURN: Status | ||
164 | * | ||
165 | * DESCRIPTION: Builds a list of devices from the input PCI region up to the | ||
166 | * Root PCI device for this namespace subtree. | ||
167 | * | ||
168 | ******************************************************************************/ | ||
169 | |||
170 | static acpi_status | ||
171 | acpi_hw_build_pci_list(acpi_handle root_pci_device, | ||
172 | acpi_handle pci_region, | ||
173 | struct acpi_pci_device **return_list_head) | ||
174 | { | ||
175 | acpi_handle current_device; | ||
176 | acpi_handle parent_device; | ||
177 | acpi_status status; | ||
178 | struct acpi_pci_device *list_element; | ||
179 | struct acpi_pci_device *list_head = NULL; | ||
180 | |||
181 | /* | ||
182 | * Ascend namespace branch until the root_pci_device is reached, building | ||
183 | * a list of device nodes. Loop will exit when either the PCI device is | ||
184 | * found, or the root of the namespace is reached. | ||
185 | */ | ||
186 | current_device = pci_region; | ||
187 | while (1) { | ||
188 | status = acpi_get_parent(current_device, &parent_device); | ||
189 | if (ACPI_FAILURE(status)) { | ||
190 | return (status); | ||
191 | } | ||
192 | |||
193 | /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ | ||
194 | |||
195 | if (parent_device == root_pci_device) { | ||
196 | *return_list_head = list_head; | ||
197 | return (AE_OK); | ||
198 | } | ||
199 | |||
200 | list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); | ||
201 | if (!list_element) { | ||
202 | return (AE_NO_MEMORY); | ||
203 | } | ||
204 | |||
205 | /* Put new element at the head of the list */ | ||
206 | |||
207 | list_element->next = list_head; | ||
208 | list_element->device = parent_device; | ||
209 | list_head = list_element; | ||
210 | |||
211 | current_device = parent_device; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /******************************************************************************* | ||
216 | * | ||
217 | * FUNCTION: acpi_hw_process_pci_list | ||
218 | * | ||
219 | * PARAMETERS: pci_id - Initial values for the PCI ID. May be | ||
220 | * modified by this function. | ||
221 | * list_head - Device list created by | ||
222 | * acpi_hw_build_pci_list | ||
223 | * | ||
224 | * RETURN: Status | ||
225 | * | ||
226 | * DESCRIPTION: Walk downward through the PCI device list, getting the device | ||
227 | * info for each, via the PCI configuration space and updating | ||
228 | * the PCI ID as necessary. Deletes the list during traversal. | ||
229 | * | ||
230 | ******************************************************************************/ | ||
231 | |||
232 | static acpi_status | ||
233 | acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, | ||
234 | struct acpi_pci_device *list_head) | ||
235 | { | ||
236 | acpi_status status = AE_OK; | ||
237 | struct acpi_pci_device *info; | ||
238 | u16 bus_number; | ||
239 | u8 is_bridge = TRUE; | ||
240 | |||
241 | ACPI_FUNCTION_NAME(hw_process_pci_list); | ||
242 | |||
243 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, | ||
244 | "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", | ||
245 | pci_id->segment, pci_id->bus, pci_id->device, | ||
246 | pci_id->function)); | ||
247 | |||
248 | bus_number = pci_id->bus; | ||
249 | |||
250 | /* | ||
251 | * Descend down the namespace tree, collecting PCI device, function, | ||
252 | * and bus numbers. bus_number is only important for PCI bridges. | ||
253 | * Algorithm: As we descend the tree, use the last valid PCI device, | ||
254 | * function, and bus numbers that are discovered, and assign them | ||
255 | * to the PCI ID for the target device. | ||
256 | */ | ||
257 | info = list_head; | ||
258 | while (info) { | ||
259 | status = acpi_hw_get_pci_device_info(pci_id, info->device, | ||
260 | &bus_number, &is_bridge); | ||
261 | if (ACPI_FAILURE(status)) { | ||
262 | return_ACPI_STATUS(status); | ||
263 | } | ||
264 | |||
265 | info = info->next; | ||
266 | } | ||
267 | |||
268 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, | ||
269 | "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " | ||
270 | "Status %X BusNumber %X IsBridge %X\n", | ||
271 | pci_id->segment, pci_id->bus, pci_id->device, | ||
272 | pci_id->function, status, bus_number, is_bridge)); | ||
273 | |||
274 | return_ACPI_STATUS(AE_OK); | ||
275 | } | ||
276 | |||
277 | /******************************************************************************* | ||
278 | * | ||
279 | * FUNCTION: acpi_hw_delete_pci_list | ||
280 | * | ||
281 | * PARAMETERS: list_head - Device list created by | ||
282 | * acpi_hw_build_pci_list | ||
283 | * | ||
284 | * RETURN: None | ||
285 | * | ||
286 | * DESCRIPTION: Free the entire PCI list. | ||
287 | * | ||
288 | ******************************************************************************/ | ||
289 | |||
290 | static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head) | ||
291 | { | ||
292 | struct acpi_pci_device *next; | ||
293 | struct acpi_pci_device *previous; | ||
294 | |||
295 | next = list_head; | ||
296 | while (next) { | ||
297 | previous = next; | ||
298 | next = previous->next; | ||
299 | ACPI_FREE(previous); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | /******************************************************************************* | ||
304 | * | ||
305 | * FUNCTION: acpi_hw_get_pci_device_info | ||
306 | * | ||
307 | * PARAMETERS: pci_id - Initial values for the PCI ID. May be | ||
308 | * modified by this function. | ||
309 | * pci_device - Handle for the PCI device object | ||
310 | * bus_number - Where a PCI bridge bus number is returned | ||
311 | * is_bridge - Return value, indicates if this PCI | ||
312 | * device is a PCI bridge | ||
313 | * | ||
314 | * RETURN: Status | ||
315 | * | ||
316 | * DESCRIPTION: Get the device info for a single PCI device object. Get the | ||
317 | * _ADR (contains PCI device and function numbers), and for PCI | ||
318 | * bridge devices, get the bus number from PCI configuration | ||
319 | * space. | ||
320 | * | ||
321 | ******************************************************************************/ | ||
322 | |||
323 | static acpi_status | ||
324 | acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, | ||
325 | acpi_handle pci_device, | ||
326 | u16 *bus_number, u8 *is_bridge) | ||
327 | { | ||
328 | acpi_status status; | ||
329 | acpi_object_type object_type; | ||
330 | u64 return_value; | ||
331 | u64 pci_value; | ||
332 | |||
333 | /* We only care about objects of type Device */ | ||
334 | |||
335 | status = acpi_get_type(pci_device, &object_type); | ||
336 | if (ACPI_FAILURE(status)) { | ||
337 | return (status); | ||
338 | } | ||
339 | |||
340 | if (object_type != ACPI_TYPE_DEVICE) { | ||
341 | return (AE_OK); | ||
342 | } | ||
343 | |||
344 | /* We need an _ADR. Ignore device if not present */ | ||
345 | |||
346 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, | ||
347 | pci_device, &return_value); | ||
348 | if (ACPI_FAILURE(status)) { | ||
349 | return (AE_OK); | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * From _ADR, get the PCI Device and Function and | ||
354 | * update the PCI ID. | ||
355 | */ | ||
356 | pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value)); | ||
357 | pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value)); | ||
358 | |||
359 | /* | ||
360 | * If the previous device was a bridge, use the previous | ||
361 | * device bus number | ||
362 | */ | ||
363 | if (*is_bridge) { | ||
364 | pci_id->bus = *bus_number; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Get the bus numbers from PCI Config space: | ||
369 | * | ||
370 | * First, get the PCI header_type | ||
371 | */ | ||
372 | *is_bridge = FALSE; | ||
373 | status = acpi_os_read_pci_configuration(pci_id, | ||
374 | PCI_CFG_HEADER_TYPE_REG, | ||
375 | &pci_value, 8); | ||
376 | if (ACPI_FAILURE(status)) { | ||
377 | return (status); | ||
378 | } | ||
379 | |||
380 | /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */ | ||
381 | |||
382 | pci_value &= PCI_HEADER_TYPE_MASK; | ||
383 | |||
384 | if ((pci_value != PCI_TYPE_BRIDGE) && | ||
385 | (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) { | ||
386 | return (AE_OK); | ||
387 | } | ||
388 | |||
389 | /* Bridge: Get the Primary bus_number */ | ||
390 | |||
391 | status = acpi_os_read_pci_configuration(pci_id, | ||
392 | PCI_CFG_PRIMARY_BUS_NUMBER_REG, | ||
393 | &pci_value, 8); | ||
394 | if (ACPI_FAILURE(status)) { | ||
395 | return (status); | ||
396 | } | ||
397 | |||
398 | *is_bridge = TRUE; | ||
399 | pci_id->bus = (u16)pci_value; | ||
400 | |||
401 | /* Bridge: Get the Secondary bus_number */ | ||
402 | |||
403 | status = acpi_os_read_pci_configuration(pci_id, | ||
404 | PCI_CFG_SECONDARY_BUS_NUMBER_REG, | ||
405 | &pci_value, 8); | ||
406 | if (ACPI_FAILURE(status)) { | ||
407 | return (status); | ||
408 | } | ||
409 | |||
410 | *bus_number = (u16)pci_value; | ||
411 | return (AE_OK); | ||
412 | } | ||
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 5d1273b660ae..55accb7018bb 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
@@ -7,7 +7,7 @@ | |||
7 | ******************************************************************************/ | 7 | ******************************************************************************/ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Copyright (C) 2000 - 2010, Intel Corp. | 10 | * Copyright (C) 2000 - 2011, Intel Corp. |
11 | * All rights reserved. | 11 | * All rights reserved. |
12 | * | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 3796811276ac..2ac28bbe8827 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index 1ef8e0bb250b..9c8eb71a12fb 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index e1d9c777b213..5f1605874655 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 50cc3be77724..f75f81ad15c9 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -80,14 +80,14 @@ acpi_status acpi_reset(void) | |||
80 | 80 | ||
81 | if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { | 81 | if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { |
82 | /* | 82 | /* |
83 | * For I/O space, write directly to the OSL. This bypasses the port | 83 | * For I/O space, write directly to the OSL. This |
84 | * validation mechanism, which may block a valid write to the reset | 84 | * bypasses the port validation mechanism, which may |
85 | * register. | 85 | * block a valid write to the reset register. Spec |
86 | * section 4.7.3.6 requires register width to be 8. | ||
86 | */ | 87 | */ |
87 | status = | 88 | status = |
88 | acpi_os_write_port((acpi_io_address) reset_reg->address, | 89 | acpi_os_write_port((acpi_io_address) reset_reg->address, |
89 | acpi_gbl_FADT.reset_value, | 90 | acpi_gbl_FADT.reset_value, 8); |
90 | reset_reg->bit_width); | ||
91 | } else { | 91 | } else { |
92 | /* Write the reset value to the reset register */ | 92 | /* Write the reset value to the reset register */ |
93 | 93 | ||
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 0cd925be5fc1..d93172fd15a8 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -163,9 +163,9 @@ acpi_status acpi_ns_root_initialize(void) | |||
163 | #else | 163 | #else |
164 | /* Mark this as a very SPECIAL method */ | 164 | /* Mark this as a very SPECIAL method */ |
165 | 165 | ||
166 | obj_desc->method.method_flags = | 166 | obj_desc->method.info_flags = |
167 | AML_METHOD_INTERNAL_ONLY; | 167 | ACPI_METHOD_INTERNAL_ONLY; |
168 | obj_desc->method.extra.implementation = | 168 | obj_desc->method.dispatch.implementation = |
169 | acpi_ut_osi_implementation; | 169 | acpi_ut_osi_implementation; |
170 | #endif | 170 | #endif |
171 | break; | 171 | break; |
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 1e5ff803d9ad..1d0ef15d158f 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -234,8 +234,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
234 | * modified the namespace. This is used for cleanup when the | 234 | * modified the namespace. This is used for cleanup when the |
235 | * method exits. | 235 | * method exits. |
236 | */ | 236 | */ |
237 | walk_state->method_desc->method.flags |= | 237 | walk_state->method_desc->method.info_flags |= |
238 | AOPOBJ_MODIFIED_NAMESPACE; | 238 | ACPI_METHOD_MODIFIED_NAMESPACE; |
239 | } | 239 | } |
240 | } | 240 | } |
241 | 241 | ||
@@ -341,6 +341,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
341 | { | 341 | { |
342 | struct acpi_namespace_node *child_node = NULL; | 342 | struct acpi_namespace_node *child_node = NULL; |
343 | u32 level = 1; | 343 | u32 level = 1; |
344 | acpi_status status; | ||
344 | 345 | ||
345 | ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); | 346 | ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); |
346 | 347 | ||
@@ -348,6 +349,13 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
348 | return_VOID; | 349 | return_VOID; |
349 | } | 350 | } |
350 | 351 | ||
352 | /* Lock namespace for possible update */ | ||
353 | |||
354 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
355 | if (ACPI_FAILURE(status)) { | ||
356 | return_VOID; | ||
357 | } | ||
358 | |||
351 | /* | 359 | /* |
352 | * Traverse the tree of objects until we bubble back up | 360 | * Traverse the tree of objects until we bubble back up |
353 | * to where we started. | 361 | * to where we started. |
@@ -397,6 +405,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
397 | } | 405 | } |
398 | } | 406 | } |
399 | 407 | ||
408 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
400 | return_VOID; | 409 | return_VOID; |
401 | } | 410 | } |
402 | 411 | ||
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index a54dc39e304b..b683cc2ff9d3 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -624,9 +624,22 @@ acpi_ns_dump_objects(acpi_object_type type, | |||
624 | acpi_owner_id owner_id, acpi_handle start_handle) | 624 | acpi_owner_id owner_id, acpi_handle start_handle) |
625 | { | 625 | { |
626 | struct acpi_walk_info info; | 626 | struct acpi_walk_info info; |
627 | acpi_status status; | ||
627 | 628 | ||
628 | ACPI_FUNCTION_ENTRY(); | 629 | ACPI_FUNCTION_ENTRY(); |
629 | 630 | ||
631 | /* | ||
632 | * Just lock the entire namespace for the duration of the dump. | ||
633 | * We don't want any changes to the namespace during this time, | ||
634 | * especially the temporary nodes since we are going to display | ||
635 | * them also. | ||
636 | */ | ||
637 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
638 | if (ACPI_FAILURE(status)) { | ||
639 | acpi_os_printf("Could not acquire namespace mutex\n"); | ||
640 | return; | ||
641 | } | ||
642 | |||
630 | info.debug_level = ACPI_LV_TABLES; | 643 | info.debug_level = ACPI_LV_TABLES; |
631 | info.owner_id = owner_id; | 644 | info.owner_id = owner_id; |
632 | info.display_type = display_type; | 645 | info.display_type = display_type; |
@@ -636,6 +649,8 @@ acpi_ns_dump_objects(acpi_object_type type, | |||
636 | ACPI_NS_WALK_TEMP_NODES, | 649 | ACPI_NS_WALK_TEMP_NODES, |
637 | acpi_ns_dump_one_object, NULL, | 650 | acpi_ns_dump_one_object, NULL, |
638 | (void *)&info, NULL); | 651 | (void *)&info, NULL); |
652 | |||
653 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
639 | } | 654 | } |
640 | #endif /* ACPI_FUTURE_USAGE */ | 655 | #endif /* ACPI_FUTURE_USAGE */ |
641 | 656 | ||
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index d2a97921e249..2ed294b7a4db 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index f52829cc294b..c1bd02b1a058 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -389,7 +389,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | |||
389 | * acpi_gbl_root_node->Object is NULL at PASS1. | 389 | * acpi_gbl_root_node->Object is NULL at PASS1. |
390 | */ | 390 | */ |
391 | if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { | 391 | if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { |
392 | method_obj->method.extra.handler = | 392 | method_obj->method.dispatch.handler = |
393 | parent_node->object->device.handler; | 393 | parent_node->object->device.handler; |
394 | } | 394 | } |
395 | 395 | ||
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 660a2728908d..fd7c6380e294 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -577,9 +577,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, | |||
577 | * as possible (without an NMI being received in the middle of | 577 | * as possible (without an NMI being received in the middle of |
578 | * this) - so disable NMIs and initialize the device: | 578 | * this) - so disable NMIs and initialize the device: |
579 | */ | 579 | */ |
580 | acpi_nmi_disable(); | ||
581 | status = acpi_ns_evaluate(info); | 580 | status = acpi_ns_evaluate(info); |
582 | acpi_nmi_enable(); | ||
583 | 581 | ||
584 | if (ACPI_SUCCESS(status)) { | 582 | if (ACPI_SUCCESS(status)) { |
585 | walk_info->num_INI++; | 583 | walk_info->num_INI++; |
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index df18be94fefe..5f7dc691c183 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index d3104af57e13..d5fa520c3de5 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index 41a9213dd5af..3bb8bf105ea2 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 5808c89e9fac..b3234fa795b8 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 7096bcda0c72..9fb03fa8ffde 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index d1c136692667..ac7b854b0bd7 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -74,7 +74,6 @@ ACPI_MODULE_NAME("nsrepair") | |||
74 | * | 74 | * |
75 | * Additional possible repairs: | 75 | * Additional possible repairs: |
76 | * | 76 | * |
77 | * Optional/unnecessary NULL package elements removed | ||
78 | * Required package elements that are NULL replaced by Integer/String/Buffer | 77 | * Required package elements that are NULL replaced by Integer/String/Buffer |
79 | * Incorrect standalone package wrapped with required outer package | 78 | * Incorrect standalone package wrapped with required outer package |
80 | * | 79 | * |
@@ -623,16 +622,12 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | |||
623 | ACPI_FUNCTION_NAME(ns_remove_null_elements); | 622 | ACPI_FUNCTION_NAME(ns_remove_null_elements); |
624 | 623 | ||
625 | /* | 624 | /* |
626 | * PTYPE1 packages contain no subpackages. | 625 | * We can safely remove all NULL elements from these package types: |
627 | * PTYPE2 packages contain a variable number of sub-packages. We can | 626 | * PTYPE1_VAR packages contain a variable number of simple data types. |
628 | * safely remove all NULL elements from the PTYPE2 packages. | 627 | * PTYPE2 packages contain a variable number of sub-packages. |
629 | */ | 628 | */ |
630 | switch (package_type) { | 629 | switch (package_type) { |
631 | case ACPI_PTYPE1_FIXED: | ||
632 | case ACPI_PTYPE1_VAR: | 630 | case ACPI_PTYPE1_VAR: |
633 | case ACPI_PTYPE1_OPTION: | ||
634 | return; | ||
635 | |||
636 | case ACPI_PTYPE2: | 631 | case ACPI_PTYPE2: |
637 | case ACPI_PTYPE2_COUNT: | 632 | case ACPI_PTYPE2_COUNT: |
638 | case ACPI_PTYPE2_PKG_COUNT: | 633 | case ACPI_PTYPE2_PKG_COUNT: |
@@ -642,6 +637,8 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | |||
642 | break; | 637 | break; |
643 | 638 | ||
644 | default: | 639 | default: |
640 | case ACPI_PTYPE1_FIXED: | ||
641 | case ACPI_PTYPE1_OPTION: | ||
645 | return; | 642 | return; |
646 | } | 643 | } |
647 | 644 | ||
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 4009498fbabd..973883babee1 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -74,10 +74,18 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, | |||
74 | union acpi_operand_object **return_object_ptr); | 74 | union acpi_operand_object **return_object_ptr); |
75 | 75 | ||
76 | static acpi_status | 76 | static acpi_status |
77 | acpi_ns_repair_CID(struct acpi_predefined_data *data, | ||
78 | union acpi_operand_object **return_object_ptr); | ||
79 | |||
80 | static acpi_status | ||
77 | acpi_ns_repair_FDE(struct acpi_predefined_data *data, | 81 | acpi_ns_repair_FDE(struct acpi_predefined_data *data, |
78 | union acpi_operand_object **return_object_ptr); | 82 | union acpi_operand_object **return_object_ptr); |
79 | 83 | ||
80 | static acpi_status | 84 | static acpi_status |
85 | acpi_ns_repair_HID(struct acpi_predefined_data *data, | ||
86 | union acpi_operand_object **return_object_ptr); | ||
87 | |||
88 | static acpi_status | ||
81 | acpi_ns_repair_PSS(struct acpi_predefined_data *data, | 89 | acpi_ns_repair_PSS(struct acpi_predefined_data *data, |
82 | union acpi_operand_object **return_object_ptr); | 90 | union acpi_operand_object **return_object_ptr); |
83 | 91 | ||
@@ -108,8 +116,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements, | |||
108 | * As necessary: | 116 | * As necessary: |
109 | * | 117 | * |
110 | * _ALR: Sort the list ascending by ambient_illuminance | 118 | * _ALR: Sort the list ascending by ambient_illuminance |
119 | * _CID: Strings: uppercase all, remove any leading asterisk | ||
111 | * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs | 120 | * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs |
112 | * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs | 121 | * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs |
122 | * _HID: Strings: uppercase all, remove any leading asterisk | ||
113 | * _PSS: Sort the list descending by Power | 123 | * _PSS: Sort the list descending by Power |
114 | * _TSS: Sort the list descending by Power | 124 | * _TSS: Sort the list descending by Power |
115 | * | 125 | * |
@@ -122,8 +132,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements, | |||
122 | */ | 132 | */ |
123 | static const struct acpi_repair_info acpi_ns_repairable_names[] = { | 133 | static const struct acpi_repair_info acpi_ns_repairable_names[] = { |
124 | {"_ALR", acpi_ns_repair_ALR}, | 134 | {"_ALR", acpi_ns_repair_ALR}, |
135 | {"_CID", acpi_ns_repair_CID}, | ||
125 | {"_FDE", acpi_ns_repair_FDE}, | 136 | {"_FDE", acpi_ns_repair_FDE}, |
126 | {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ | 137 | {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ |
138 | {"_HID", acpi_ns_repair_HID}, | ||
127 | {"_PSS", acpi_ns_repair_PSS}, | 139 | {"_PSS", acpi_ns_repair_PSS}, |
128 | {"_TSS", acpi_ns_repair_TSS}, | 140 | {"_TSS", acpi_ns_repair_TSS}, |
129 | {{0, 0, 0, 0}, NULL} /* Table terminator */ | 141 | {{0, 0, 0, 0}, NULL} /* Table terminator */ |
@@ -321,6 +333,157 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, | |||
321 | 333 | ||
322 | /****************************************************************************** | 334 | /****************************************************************************** |
323 | * | 335 | * |
336 | * FUNCTION: acpi_ns_repair_CID | ||
337 | * | ||
338 | * PARAMETERS: Data - Pointer to validation data structure | ||
339 | * return_object_ptr - Pointer to the object returned from the | ||
340 | * evaluation of a method or object | ||
341 | * | ||
342 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
343 | * | ||
344 | * DESCRIPTION: Repair for the _CID object. If a string, ensure that all | ||
345 | * letters are uppercase and that there is no leading asterisk. | ||
346 | * If a Package, ensure same for all string elements. | ||
347 | * | ||
348 | *****************************************************************************/ | ||
349 | |||
350 | static acpi_status | ||
351 | acpi_ns_repair_CID(struct acpi_predefined_data *data, | ||
352 | union acpi_operand_object **return_object_ptr) | ||
353 | { | ||
354 | acpi_status status; | ||
355 | union acpi_operand_object *return_object = *return_object_ptr; | ||
356 | union acpi_operand_object **element_ptr; | ||
357 | union acpi_operand_object *original_element; | ||
358 | u16 original_ref_count; | ||
359 | u32 i; | ||
360 | |||
361 | /* Check for _CID as a simple string */ | ||
362 | |||
363 | if (return_object->common.type == ACPI_TYPE_STRING) { | ||
364 | status = acpi_ns_repair_HID(data, return_object_ptr); | ||
365 | return (status); | ||
366 | } | ||
367 | |||
368 | /* Exit if not a Package */ | ||
369 | |||
370 | if (return_object->common.type != ACPI_TYPE_PACKAGE) { | ||
371 | return (AE_OK); | ||
372 | } | ||
373 | |||
374 | /* Examine each element of the _CID package */ | ||
375 | |||
376 | element_ptr = return_object->package.elements; | ||
377 | for (i = 0; i < return_object->package.count; i++) { | ||
378 | original_element = *element_ptr; | ||
379 | original_ref_count = original_element->common.reference_count; | ||
380 | |||
381 | status = acpi_ns_repair_HID(data, element_ptr); | ||
382 | if (ACPI_FAILURE(status)) { | ||
383 | return (status); | ||
384 | } | ||
385 | |||
386 | /* Take care with reference counts */ | ||
387 | |||
388 | if (original_element != *element_ptr) { | ||
389 | |||
390 | /* Element was replaced */ | ||
391 | |||
392 | (*element_ptr)->common.reference_count = | ||
393 | original_ref_count; | ||
394 | |||
395 | acpi_ut_remove_reference(original_element); | ||
396 | } | ||
397 | |||
398 | element_ptr++; | ||
399 | } | ||
400 | |||
401 | return (AE_OK); | ||
402 | } | ||
403 | |||
404 | /****************************************************************************** | ||
405 | * | ||
406 | * FUNCTION: acpi_ns_repair_HID | ||
407 | * | ||
408 | * PARAMETERS: Data - Pointer to validation data structure | ||
409 | * return_object_ptr - Pointer to the object returned from the | ||
410 | * evaluation of a method or object | ||
411 | * | ||
412 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
413 | * | ||
414 | * DESCRIPTION: Repair for the _HID object. If a string, ensure that all | ||
415 | * letters are uppercase and that there is no leading asterisk. | ||
416 | * | ||
417 | *****************************************************************************/ | ||
418 | |||
419 | static acpi_status | ||
420 | acpi_ns_repair_HID(struct acpi_predefined_data *data, | ||
421 | union acpi_operand_object **return_object_ptr) | ||
422 | { | ||
423 | union acpi_operand_object *return_object = *return_object_ptr; | ||
424 | union acpi_operand_object *new_string; | ||
425 | char *source; | ||
426 | char *dest; | ||
427 | |||
428 | ACPI_FUNCTION_NAME(ns_repair_HID); | ||
429 | |||
430 | /* We only care about string _HID objects (not integers) */ | ||
431 | |||
432 | if (return_object->common.type != ACPI_TYPE_STRING) { | ||
433 | return (AE_OK); | ||
434 | } | ||
435 | |||
436 | if (return_object->string.length == 0) { | ||
437 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
438 | "Invalid zero-length _HID or _CID string")); | ||
439 | |||
440 | /* Return AE_OK anyway, let driver handle it */ | ||
441 | |||
442 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
443 | return (AE_OK); | ||
444 | } | ||
445 | |||
446 | /* It is simplest to always create a new string object */ | ||
447 | |||
448 | new_string = acpi_ut_create_string_object(return_object->string.length); | ||
449 | if (!new_string) { | ||
450 | return (AE_NO_MEMORY); | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * Remove a leading asterisk if present. For some unknown reason, there | ||
455 | * are many machines in the field that contains IDs like this. | ||
456 | * | ||
457 | * Examples: "*PNP0C03", "*ACPI0003" | ||
458 | */ | ||
459 | source = return_object->string.pointer; | ||
460 | if (*source == '*') { | ||
461 | source++; | ||
462 | new_string->string.length--; | ||
463 | |||
464 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
465 | "%s: Removed invalid leading asterisk\n", | ||
466 | data->pathname)); | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * Copy and uppercase the string. From the ACPI specification: | ||
471 | * | ||
472 | * A valid PNP ID must be of the form "AAA####" where A is an uppercase | ||
473 | * letter and # is a hex digit. A valid ACPI ID must be of the form | ||
474 | * "ACPI####" where # is a hex digit. | ||
475 | */ | ||
476 | for (dest = new_string->string.pointer; *source; dest++, source++) { | ||
477 | *dest = (char)ACPI_TOUPPER(*source); | ||
478 | } | ||
479 | |||
480 | acpi_ut_remove_reference(return_object); | ||
481 | *return_object_ptr = new_string; | ||
482 | return (AE_OK); | ||
483 | } | ||
484 | |||
485 | /****************************************************************************** | ||
486 | * | ||
324 | * FUNCTION: acpi_ns_repair_TSS | 487 | * FUNCTION: acpi_ns_repair_TSS |
325 | * | 488 | * |
326 | * PARAMETERS: Data - Pointer to validation data structure | 489 | * PARAMETERS: Data - Pointer to validation data structure |
diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 41102a84272f..28b0d7a62b99 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index e1add3491b04..cb1b104a69a2 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -60,104 +60,6 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); | |||
60 | 60 | ||
61 | /******************************************************************************* | 61 | /******************************************************************************* |
62 | * | 62 | * |
63 | * FUNCTION: acpi_ns_report_error | ||
64 | * | ||
65 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
66 | * line_number - Caller's line number (for error output) | ||
67 | * internal_name - Name or path of the namespace node | ||
68 | * lookup_status - Exception code from NS lookup | ||
69 | * | ||
70 | * RETURN: None | ||
71 | * | ||
72 | * DESCRIPTION: Print warning message with full pathname | ||
73 | * | ||
74 | ******************************************************************************/ | ||
75 | |||
76 | void | ||
77 | acpi_ns_report_error(const char *module_name, | ||
78 | u32 line_number, | ||
79 | const char *internal_name, acpi_status lookup_status) | ||
80 | { | ||
81 | acpi_status status; | ||
82 | u32 bad_name; | ||
83 | char *name = NULL; | ||
84 | |||
85 | acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); | ||
86 | |||
87 | if (lookup_status == AE_BAD_CHARACTER) { | ||
88 | |||
89 | /* There is a non-ascii character in the name */ | ||
90 | |||
91 | ACPI_MOVE_32_TO_32(&bad_name, | ||
92 | ACPI_CAST_PTR(u32, internal_name)); | ||
93 | acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); | ||
94 | } else { | ||
95 | /* Convert path to external format */ | ||
96 | |||
97 | status = acpi_ns_externalize_name(ACPI_UINT32_MAX, | ||
98 | internal_name, NULL, &name); | ||
99 | |||
100 | /* Print target name */ | ||
101 | |||
102 | if (ACPI_SUCCESS(status)) { | ||
103 | acpi_os_printf("[%s]", name); | ||
104 | } else { | ||
105 | acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); | ||
106 | } | ||
107 | |||
108 | if (name) { | ||
109 | ACPI_FREE(name); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | acpi_os_printf(" Namespace lookup failure, %s\n", | ||
114 | acpi_format_exception(lookup_status)); | ||
115 | } | ||
116 | |||
117 | /******************************************************************************* | ||
118 | * | ||
119 | * FUNCTION: acpi_ns_report_method_error | ||
120 | * | ||
121 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
122 | * line_number - Caller's line number (for error output) | ||
123 | * Message - Error message to use on failure | ||
124 | * prefix_node - Prefix relative to the path | ||
125 | * Path - Path to the node (optional) | ||
126 | * method_status - Execution status | ||
127 | * | ||
128 | * RETURN: None | ||
129 | * | ||
130 | * DESCRIPTION: Print warning message with full pathname | ||
131 | * | ||
132 | ******************************************************************************/ | ||
133 | |||
134 | void | ||
135 | acpi_ns_report_method_error(const char *module_name, | ||
136 | u32 line_number, | ||
137 | const char *message, | ||
138 | struct acpi_namespace_node *prefix_node, | ||
139 | const char *path, acpi_status method_status) | ||
140 | { | ||
141 | acpi_status status; | ||
142 | struct acpi_namespace_node *node = prefix_node; | ||
143 | |||
144 | acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); | ||
145 | |||
146 | if (path) { | ||
147 | status = | ||
148 | acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, | ||
149 | &node); | ||
150 | if (ACPI_FAILURE(status)) { | ||
151 | acpi_os_printf("[Could not get node by pathname]"); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | acpi_ns_print_node_pathname(node, message); | ||
156 | acpi_os_printf(", %s\n", acpi_format_exception(method_status)); | ||
157 | } | ||
158 | |||
159 | /******************************************************************************* | ||
160 | * | ||
161 | * FUNCTION: acpi_ns_print_node_pathname | 63 | * FUNCTION: acpi_ns_print_node_pathname |
162 | * | 64 | * |
163 | * PARAMETERS: Node - Object | 65 | * PARAMETERS: Node - Object |
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 2cd5be8fe10f..345f0c3c6ad2 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index ebef8a7fd707..c53f0040e490 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index b01e45a415e3..3fd4526f3dba 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -603,10 +603,9 @@ acpi_status acpi_install_method(u8 *buffer) | |||
603 | method_obj->method.param_count = (u8) | 603 | method_obj->method.param_count = (u8) |
604 | (method_flags & AML_METHOD_ARG_COUNT); | 604 | (method_flags & AML_METHOD_ARG_COUNT); |
605 | 605 | ||
606 | method_obj->method.method_flags = (u8) | ||
607 | (method_flags & ~AML_METHOD_ARG_COUNT); | ||
608 | |||
609 | if (method_flags & AML_METHOD_SERIALIZED) { | 606 | if (method_flags & AML_METHOD_SERIALIZED) { |
607 | method_obj->method.info_flags = ACPI_METHOD_SERIALIZED; | ||
608 | |||
610 | method_obj->method.sync_level = (u8) | 609 | method_obj->method.sync_level = (u8) |
611 | ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4); | 610 | ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4); |
612 | } | 611 | } |
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index a1f04e9b8030..db7660f8b869 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 7df1a4c95274..e1fad0ee0136 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 2f2e7760938c..01dd70d1de51 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -655,7 +655,7 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, | |||
655 | method_obj->method.aml_start = aml_start; | 655 | method_obj->method.aml_start = aml_start; |
656 | method_obj->method.aml_length = aml_length; | 656 | method_obj->method.aml_length = aml_length; |
657 | method_obj->method.owner_id = owner_id; | 657 | method_obj->method.owner_id = owner_id; |
658 | method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; | 658 | method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL; |
659 | 659 | ||
660 | /* | 660 | /* |
661 | * Save the parent node in next_object. This is cheating, but we | 661 | * Save the parent node in next_object. This is cheating, but we |
diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index 2b0c3be2b1b8..bed08de7528c 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 8d81542194d4..9bb0cbd37b5e 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -55,7 +55,6 @@ | |||
55 | #include "acparser.h" | 55 | #include "acparser.h" |
56 | #include "acdispat.h" | 56 | #include "acdispat.h" |
57 | #include "amlcode.h" | 57 | #include "amlcode.h" |
58 | #include "acnamesp.h" | ||
59 | #include "acinterp.h" | 58 | #include "acinterp.h" |
60 | 59 | ||
61 | #define _COMPONENT ACPI_PARSER | 60 | #define _COMPONENT ACPI_PARSER |
@@ -539,24 +538,16 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) | |||
539 | /* Check for possible multi-thread reentrancy problem */ | 538 | /* Check for possible multi-thread reentrancy problem */ |
540 | 539 | ||
541 | if ((status == AE_ALREADY_EXISTS) && | 540 | if ((status == AE_ALREADY_EXISTS) && |
542 | (!walk_state->method_desc->method.mutex)) { | 541 | (!(walk_state->method_desc->method. |
543 | ACPI_INFO((AE_INFO, | 542 | info_flags & ACPI_METHOD_SERIALIZED))) { |
544 | "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", | ||
545 | walk_state->method_node->name. | ||
546 | ascii)); | ||
547 | |||
548 | /* | 543 | /* |
549 | * Method tried to create an object twice. The probable cause is | 544 | * Method is not serialized and tried to create an object |
550 | * that the method cannot handle reentrancy. | 545 | * twice. The probable cause is that the method cannot |
551 | * | 546 | * handle reentrancy. Mark as "pending serialized" now, and |
552 | * The method is marked not_serialized, but it tried to create | 547 | * then mark "serialized" when the last thread exits. |
553 | * a named object, causing the second thread entrance to fail. | ||
554 | * Workaround this problem by marking the method permanently | ||
555 | * as Serialized. | ||
556 | */ | 548 | */ |
557 | walk_state->method_desc->method.method_flags |= | 549 | walk_state->method_desc->method.info_flags |= |
558 | AML_METHOD_SERIALIZED; | 550 | ACPI_METHOD_SERIALIZED_PENDING; |
559 | walk_state->method_desc->method.sync_level = 0; | ||
560 | } | 551 | } |
561 | } | 552 | } |
562 | 553 | ||
diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index 40e2b279ea12..a5faa1323a02 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index d4b970c3630b..f1464c03aa42 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index fe29eee5adb1..7eda78503422 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index 8abb9629443d..3312d6368bf1 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index c42f067cff9d..8086805d4494 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -47,7 +47,6 @@ | |||
47 | #include "acdispat.h" | 47 | #include "acdispat.h" |
48 | #include "acinterp.h" | 48 | #include "acinterp.h" |
49 | #include "actables.h" | 49 | #include "actables.h" |
50 | #include "amlcode.h" | ||
51 | 50 | ||
52 | #define _COMPONENT ACPI_PARSER | 51 | #define _COMPONENT ACPI_PARSER |
53 | ACPI_MODULE_NAME("psxface") | 52 | ACPI_MODULE_NAME("psxface") |
@@ -285,15 +284,15 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) | |||
285 | goto cleanup; | 284 | goto cleanup; |
286 | } | 285 | } |
287 | 286 | ||
288 | if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) { | 287 | if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) { |
289 | walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL; | 288 | walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL; |
290 | } | 289 | } |
291 | 290 | ||
292 | /* Invoke an internal method if necessary */ | 291 | /* Invoke an internal method if necessary */ |
293 | 292 | ||
294 | if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | 293 | if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) { |
295 | status = | 294 | status = |
296 | info->obj_desc->method.extra.implementation(walk_state); | 295 | info->obj_desc->method.dispatch.implementation(walk_state); |
297 | info->return_object = walk_state->return_desc; | 296 | info->return_object = walk_state->return_desc; |
298 | 297 | ||
299 | /* Cleanup states */ | 298 | /* Cleanup states */ |
diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index 226c806ae986..9e66f9078426 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index d6ebf7ec622d..3a8a89ec2ca4 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index c80a2eea3a01..4ce6e1147e80 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index f859b0386fe4..33db7520c74b 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c index 1fd868b964fd..f9ea60872aa4 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index 33bff17c0bbc..0c7efef008be 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c index 545da40d7fa7..50b8ad211167 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 7335f22aac20..1bfcef736c50 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index 887b8ba8c432..7cc6d8625f1e 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index f8cd9e87d987..410264b22a29 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 491191e6cf69..231811e56939 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 9f6a6e7e1c8e..2ff657a28f26 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 1728cb9bf600..6f5588e62c0a 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -49,7 +49,7 @@ | |||
49 | ACPI_MODULE_NAME("tbfadt") | 49 | ACPI_MODULE_NAME("tbfadt") |
50 | 50 | ||
51 | /* Local prototypes */ | 51 | /* Local prototypes */ |
52 | static inline void | 52 | static ACPI_INLINE void |
53 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | 53 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
54 | u8 space_id, u8 byte_width, u64 address); | 54 | u8 space_id, u8 byte_width, u64 address); |
55 | 55 | ||
@@ -181,7 +181,7 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { | |||
181 | * | 181 | * |
182 | ******************************************************************************/ | 182 | ******************************************************************************/ |
183 | 183 | ||
184 | static inline void | 184 | static ACPI_INLINE void |
185 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | 185 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
186 | u8 space_id, u8 byte_width, u64 address) | 186 | u8 space_id, u8 byte_width, u64 address) |
187 | { | 187 | { |
@@ -384,8 +384,11 @@ static void acpi_tb_convert_fadt(void) | |||
384 | * | 384 | * |
385 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at | 385 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at |
386 | * offset 45, 55, 95, and the word located at offset 109, 110. | 386 | * offset 45, 55, 95, and the word located at offset 109, 110. |
387 | * | ||
388 | * Note: The FADT revision value is unreliable. Only the length can be | ||
389 | * trusted. | ||
387 | */ | 390 | */ |
388 | if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { | 391 | if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) { |
389 | acpi_gbl_FADT.preferred_profile = 0; | 392 | acpi_gbl_FADT.preferred_profile = 0; |
390 | acpi_gbl_FADT.pstate_control = 0; | 393 | acpi_gbl_FADT.pstate_control = 0; |
391 | acpi_gbl_FADT.cst_control = 0; | 394 | acpi_gbl_FADT.cst_control = 0; |
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index 989d5c867864..a55cb2bb5abb 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 83d7af8d0905..48db0944ce4a 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 34f9c2bc5e1f..0f2d395feaba 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 4a8b9e6ea57a..4b7085dfc683 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2010, Intel Corp. | 9 | * Copyright (C) 2000 - 2011, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index fd2c07d1d3ac..7eb6c6cc1edf 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index 8f0896281567..0a697351cf69 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 6fef83f04bcd..aded299a2fa8 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 983510640059..a9bcd816dc29 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -179,9 +179,8 @@ acpi_debug_print(u32 requested_debug_level, | |||
179 | if (thread_id != acpi_gbl_prev_thread_id) { | 179 | if (thread_id != acpi_gbl_prev_thread_id) { |
180 | if (ACPI_LV_THREADS & acpi_dbg_level) { | 180 | if (ACPI_LV_THREADS & acpi_dbg_level) { |
181 | acpi_os_printf | 181 | acpi_os_printf |
182 | ("\n**** Context Switch from TID %p to TID %p ****\n\n", | 182 | ("\n**** Context Switch from TID %u to TID %u ****\n\n", |
183 | ACPI_CAST_PTR(void, acpi_gbl_prev_thread_id), | 183 | (u32)acpi_gbl_prev_thread_id, (u32)thread_id); |
184 | ACPI_CAST_PTR(void, thread_id)); | ||
185 | } | 184 | } |
186 | 185 | ||
187 | acpi_gbl_prev_thread_id = thread_id; | 186 | acpi_gbl_prev_thread_id = thread_id; |
@@ -194,7 +193,7 @@ acpi_debug_print(u32 requested_debug_level, | |||
194 | acpi_os_printf("%8s-%04ld ", module_name, line_number); | 193 | acpi_os_printf("%8s-%04ld ", module_name, line_number); |
195 | 194 | ||
196 | if (ACPI_LV_THREADS & acpi_dbg_level) { | 195 | if (ACPI_LV_THREADS & acpi_dbg_level) { |
197 | acpi_os_printf("[%p] ", ACPI_CAST_PTR(void, thread_id)); | 196 | acpi_os_printf("[%u] ", (u32)thread_id); |
198 | } | 197 | } |
199 | 198 | ||
200 | acpi_os_printf("[%02ld] %-22.22s: ", | 199 | acpi_os_printf("[%02ld] %-22.22s: ", |
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c new file mode 100644 index 000000000000..97cb36f85ce9 --- /dev/null +++ b/drivers/acpi/acpica/utdecode.c | |||
@@ -0,0 +1,549 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: utdecode - Utility decoding routines (value-to-string) | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acnamesp.h" | ||
47 | |||
48 | #define _COMPONENT ACPI_UTILITIES | ||
49 | ACPI_MODULE_NAME("utdecode") | ||
50 | |||
51 | /******************************************************************************* | ||
52 | * | ||
53 | * FUNCTION: acpi_format_exception | ||
54 | * | ||
55 | * PARAMETERS: Status - The acpi_status code to be formatted | ||
56 | * | ||
57 | * RETURN: A string containing the exception text. A valid pointer is | ||
58 | * always returned. | ||
59 | * | ||
60 | * DESCRIPTION: This function translates an ACPI exception into an ASCII string | ||
61 | * It is here instead of utxface.c so it is always present. | ||
62 | * | ||
63 | ******************************************************************************/ | ||
64 | const char *acpi_format_exception(acpi_status status) | ||
65 | { | ||
66 | const char *exception = NULL; | ||
67 | |||
68 | ACPI_FUNCTION_ENTRY(); | ||
69 | |||
70 | exception = acpi_ut_validate_exception(status); | ||
71 | if (!exception) { | ||
72 | |||
73 | /* Exception code was not recognized */ | ||
74 | |||
75 | ACPI_ERROR((AE_INFO, | ||
76 | "Unknown exception code: 0x%8.8X", status)); | ||
77 | |||
78 | exception = "UNKNOWN_STATUS_CODE"; | ||
79 | } | ||
80 | |||
81 | return (ACPI_CAST_PTR(const char, exception)); | ||
82 | } | ||
83 | |||
84 | ACPI_EXPORT_SYMBOL(acpi_format_exception) | ||
85 | |||
86 | /* | ||
87 | * Properties of the ACPI Object Types, both internal and external. | ||
88 | * The table is indexed by values of acpi_object_type | ||
89 | */ | ||
90 | const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = { | ||
91 | ACPI_NS_NORMAL, /* 00 Any */ | ||
92 | ACPI_NS_NORMAL, /* 01 Number */ | ||
93 | ACPI_NS_NORMAL, /* 02 String */ | ||
94 | ACPI_NS_NORMAL, /* 03 Buffer */ | ||
95 | ACPI_NS_NORMAL, /* 04 Package */ | ||
96 | ACPI_NS_NORMAL, /* 05 field_unit */ | ||
97 | ACPI_NS_NEWSCOPE, /* 06 Device */ | ||
98 | ACPI_NS_NORMAL, /* 07 Event */ | ||
99 | ACPI_NS_NEWSCOPE, /* 08 Method */ | ||
100 | ACPI_NS_NORMAL, /* 09 Mutex */ | ||
101 | ACPI_NS_NORMAL, /* 10 Region */ | ||
102 | ACPI_NS_NEWSCOPE, /* 11 Power */ | ||
103 | ACPI_NS_NEWSCOPE, /* 12 Processor */ | ||
104 | ACPI_NS_NEWSCOPE, /* 13 Thermal */ | ||
105 | ACPI_NS_NORMAL, /* 14 buffer_field */ | ||
106 | ACPI_NS_NORMAL, /* 15 ddb_handle */ | ||
107 | ACPI_NS_NORMAL, /* 16 Debug Object */ | ||
108 | ACPI_NS_NORMAL, /* 17 def_field */ | ||
109 | ACPI_NS_NORMAL, /* 18 bank_field */ | ||
110 | ACPI_NS_NORMAL, /* 19 index_field */ | ||
111 | ACPI_NS_NORMAL, /* 20 Reference */ | ||
112 | ACPI_NS_NORMAL, /* 21 Alias */ | ||
113 | ACPI_NS_NORMAL, /* 22 method_alias */ | ||
114 | ACPI_NS_NORMAL, /* 23 Notify */ | ||
115 | ACPI_NS_NORMAL, /* 24 Address Handler */ | ||
116 | ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ | ||
117 | ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ | ||
118 | ACPI_NS_NEWSCOPE, /* 27 Scope */ | ||
119 | ACPI_NS_NORMAL, /* 28 Extra */ | ||
120 | ACPI_NS_NORMAL, /* 29 Data */ | ||
121 | ACPI_NS_NORMAL /* 30 Invalid */ | ||
122 | }; | ||
123 | |||
124 | /******************************************************************************* | ||
125 | * | ||
126 | * FUNCTION: acpi_ut_hex_to_ascii_char | ||
127 | * | ||
128 | * PARAMETERS: Integer - Contains the hex digit | ||
129 | * Position - bit position of the digit within the | ||
130 | * integer (multiple of 4) | ||
131 | * | ||
132 | * RETURN: The converted Ascii character | ||
133 | * | ||
134 | * DESCRIPTION: Convert a hex digit to an Ascii character | ||
135 | * | ||
136 | ******************************************************************************/ | ||
137 | |||
138 | /* Hex to ASCII conversion table */ | ||
139 | |||
140 | static const char acpi_gbl_hex_to_ascii[] = { | ||
141 | '0', '1', '2', '3', '4', '5', '6', '7', | ||
142 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
143 | }; | ||
144 | |||
145 | char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) | ||
146 | { | ||
147 | |||
148 | return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); | ||
149 | } | ||
150 | |||
151 | /******************************************************************************* | ||
152 | * | ||
153 | * FUNCTION: acpi_ut_get_region_name | ||
154 | * | ||
155 | * PARAMETERS: Space ID - ID for the region | ||
156 | * | ||
157 | * RETURN: Decoded region space_id name | ||
158 | * | ||
159 | * DESCRIPTION: Translate a Space ID into a name string (Debug only) | ||
160 | * | ||
161 | ******************************************************************************/ | ||
162 | |||
163 | /* Region type decoding */ | ||
164 | |||
165 | const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { | ||
166 | "SystemMemory", | ||
167 | "SystemIO", | ||
168 | "PCI_Config", | ||
169 | "EmbeddedControl", | ||
170 | "SMBus", | ||
171 | "SystemCMOS", | ||
172 | "PCIBARTarget", | ||
173 | "IPMI" | ||
174 | }; | ||
175 | |||
176 | char *acpi_ut_get_region_name(u8 space_id) | ||
177 | { | ||
178 | |||
179 | if (space_id >= ACPI_USER_REGION_BEGIN) { | ||
180 | return ("UserDefinedRegion"); | ||
181 | } else if (space_id == ACPI_ADR_SPACE_DATA_TABLE) { | ||
182 | return ("DataTable"); | ||
183 | } else if (space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { | ||
184 | return ("FunctionalFixedHW"); | ||
185 | } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { | ||
186 | return ("InvalidSpaceId"); | ||
187 | } | ||
188 | |||
189 | return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); | ||
190 | } | ||
191 | |||
192 | /******************************************************************************* | ||
193 | * | ||
194 | * FUNCTION: acpi_ut_get_event_name | ||
195 | * | ||
196 | * PARAMETERS: event_id - Fixed event ID | ||
197 | * | ||
198 | * RETURN: Decoded event ID name | ||
199 | * | ||
200 | * DESCRIPTION: Translate a Event ID into a name string (Debug only) | ||
201 | * | ||
202 | ******************************************************************************/ | ||
203 | |||
204 | /* Event type decoding */ | ||
205 | |||
206 | static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { | ||
207 | "PM_Timer", | ||
208 | "GlobalLock", | ||
209 | "PowerButton", | ||
210 | "SleepButton", | ||
211 | "RealTimeClock", | ||
212 | }; | ||
213 | |||
214 | char *acpi_ut_get_event_name(u32 event_id) | ||
215 | { | ||
216 | |||
217 | if (event_id > ACPI_EVENT_MAX) { | ||
218 | return ("InvalidEventID"); | ||
219 | } | ||
220 | |||
221 | return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); | ||
222 | } | ||
223 | |||
224 | /******************************************************************************* | ||
225 | * | ||
226 | * FUNCTION: acpi_ut_get_type_name | ||
227 | * | ||
228 | * PARAMETERS: Type - An ACPI object type | ||
229 | * | ||
230 | * RETURN: Decoded ACPI object type name | ||
231 | * | ||
232 | * DESCRIPTION: Translate a Type ID into a name string (Debug only) | ||
233 | * | ||
234 | ******************************************************************************/ | ||
235 | |||
236 | /* | ||
237 | * Elements of acpi_gbl_ns_type_names below must match | ||
238 | * one-to-one with values of acpi_object_type | ||
239 | * | ||
240 | * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; | ||
241 | * when stored in a table it really means that we have thus far seen no | ||
242 | * evidence to indicate what type is actually going to be stored for this entry. | ||
243 | */ | ||
244 | static const char acpi_gbl_bad_type[] = "UNDEFINED"; | ||
245 | |||
246 | /* Printable names of the ACPI object types */ | ||
247 | |||
248 | static const char *acpi_gbl_ns_type_names[] = { | ||
249 | /* 00 */ "Untyped", | ||
250 | /* 01 */ "Integer", | ||
251 | /* 02 */ "String", | ||
252 | /* 03 */ "Buffer", | ||
253 | /* 04 */ "Package", | ||
254 | /* 05 */ "FieldUnit", | ||
255 | /* 06 */ "Device", | ||
256 | /* 07 */ "Event", | ||
257 | /* 08 */ "Method", | ||
258 | /* 09 */ "Mutex", | ||
259 | /* 10 */ "Region", | ||
260 | /* 11 */ "Power", | ||
261 | /* 12 */ "Processor", | ||
262 | /* 13 */ "Thermal", | ||
263 | /* 14 */ "BufferField", | ||
264 | /* 15 */ "DdbHandle", | ||
265 | /* 16 */ "DebugObject", | ||
266 | /* 17 */ "RegionField", | ||
267 | /* 18 */ "BankField", | ||
268 | /* 19 */ "IndexField", | ||
269 | /* 20 */ "Reference", | ||
270 | /* 21 */ "Alias", | ||
271 | /* 22 */ "MethodAlias", | ||
272 | /* 23 */ "Notify", | ||
273 | /* 24 */ "AddrHandler", | ||
274 | /* 25 */ "ResourceDesc", | ||
275 | /* 26 */ "ResourceFld", | ||
276 | /* 27 */ "Scope", | ||
277 | /* 28 */ "Extra", | ||
278 | /* 29 */ "Data", | ||
279 | /* 30 */ "Invalid" | ||
280 | }; | ||
281 | |||
282 | char *acpi_ut_get_type_name(acpi_object_type type) | ||
283 | { | ||
284 | |||
285 | if (type > ACPI_TYPE_INVALID) { | ||
286 | return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); | ||
287 | } | ||
288 | |||
289 | return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); | ||
290 | } | ||
291 | |||
292 | char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) | ||
293 | { | ||
294 | |||
295 | if (!obj_desc) { | ||
296 | return ("[NULL Object Descriptor]"); | ||
297 | } | ||
298 | |||
299 | return (acpi_ut_get_type_name(obj_desc->common.type)); | ||
300 | } | ||
301 | |||
302 | /******************************************************************************* | ||
303 | * | ||
304 | * FUNCTION: acpi_ut_get_node_name | ||
305 | * | ||
306 | * PARAMETERS: Object - A namespace node | ||
307 | * | ||
308 | * RETURN: ASCII name of the node | ||
309 | * | ||
310 | * DESCRIPTION: Validate the node and return the node's ACPI name. | ||
311 | * | ||
312 | ******************************************************************************/ | ||
313 | |||
314 | char *acpi_ut_get_node_name(void *object) | ||
315 | { | ||
316 | struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; | ||
317 | |||
318 | /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ | ||
319 | |||
320 | if (!object) { | ||
321 | return ("NULL"); | ||
322 | } | ||
323 | |||
324 | /* Check for Root node */ | ||
325 | |||
326 | if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { | ||
327 | return ("\"\\\" "); | ||
328 | } | ||
329 | |||
330 | /* Descriptor must be a namespace node */ | ||
331 | |||
332 | if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { | ||
333 | return ("####"); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Ensure name is valid. The name was validated/repaired when the node | ||
338 | * was created, but make sure it has not been corrupted. | ||
339 | */ | ||
340 | acpi_ut_repair_name(node->name.ascii); | ||
341 | |||
342 | /* Return the name */ | ||
343 | |||
344 | return (node->name.ascii); | ||
345 | } | ||
346 | |||
347 | /******************************************************************************* | ||
348 | * | ||
349 | * FUNCTION: acpi_ut_get_descriptor_name | ||
350 | * | ||
351 | * PARAMETERS: Object - An ACPI object | ||
352 | * | ||
353 | * RETURN: Decoded name of the descriptor type | ||
354 | * | ||
355 | * DESCRIPTION: Validate object and return the descriptor type | ||
356 | * | ||
357 | ******************************************************************************/ | ||
358 | |||
359 | /* Printable names of object descriptor types */ | ||
360 | |||
361 | static const char *acpi_gbl_desc_type_names[] = { | ||
362 | /* 00 */ "Not a Descriptor", | ||
363 | /* 01 */ "Cached", | ||
364 | /* 02 */ "State-Generic", | ||
365 | /* 03 */ "State-Update", | ||
366 | /* 04 */ "State-Package", | ||
367 | /* 05 */ "State-Control", | ||
368 | /* 06 */ "State-RootParseScope", | ||
369 | /* 07 */ "State-ParseScope", | ||
370 | /* 08 */ "State-WalkScope", | ||
371 | /* 09 */ "State-Result", | ||
372 | /* 10 */ "State-Notify", | ||
373 | /* 11 */ "State-Thread", | ||
374 | /* 12 */ "Walk", | ||
375 | /* 13 */ "Parser", | ||
376 | /* 14 */ "Operand", | ||
377 | /* 15 */ "Node" | ||
378 | }; | ||
379 | |||
380 | char *acpi_ut_get_descriptor_name(void *object) | ||
381 | { | ||
382 | |||
383 | if (!object) { | ||
384 | return ("NULL OBJECT"); | ||
385 | } | ||
386 | |||
387 | if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { | ||
388 | return ("Not a Descriptor"); | ||
389 | } | ||
390 | |||
391 | return (ACPI_CAST_PTR(char, | ||
392 | acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE | ||
393 | (object)])); | ||
394 | |||
395 | } | ||
396 | |||
397 | /******************************************************************************* | ||
398 | * | ||
399 | * FUNCTION: acpi_ut_get_reference_name | ||
400 | * | ||
401 | * PARAMETERS: Object - An ACPI reference object | ||
402 | * | ||
403 | * RETURN: Decoded name of the type of reference | ||
404 | * | ||
405 | * DESCRIPTION: Decode a reference object sub-type to a string. | ||
406 | * | ||
407 | ******************************************************************************/ | ||
408 | |||
409 | /* Printable names of reference object sub-types */ | ||
410 | |||
411 | static const char *acpi_gbl_ref_class_names[] = { | ||
412 | /* 00 */ "Local", | ||
413 | /* 01 */ "Argument", | ||
414 | /* 02 */ "RefOf", | ||
415 | /* 03 */ "Index", | ||
416 | /* 04 */ "DdbHandle", | ||
417 | /* 05 */ "Named Object", | ||
418 | /* 06 */ "Debug" | ||
419 | }; | ||
420 | |||
421 | const char *acpi_ut_get_reference_name(union acpi_operand_object *object) | ||
422 | { | ||
423 | |||
424 | if (!object) { | ||
425 | return ("NULL Object"); | ||
426 | } | ||
427 | |||
428 | if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { | ||
429 | return ("Not an Operand object"); | ||
430 | } | ||
431 | |||
432 | if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) { | ||
433 | return ("Not a Reference object"); | ||
434 | } | ||
435 | |||
436 | if (object->reference.class > ACPI_REFCLASS_MAX) { | ||
437 | return ("Unknown Reference class"); | ||
438 | } | ||
439 | |||
440 | return (acpi_gbl_ref_class_names[object->reference.class]); | ||
441 | } | ||
442 | |||
443 | #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) | ||
444 | /* | ||
445 | * Strings and procedures used for debug only | ||
446 | */ | ||
447 | |||
448 | /******************************************************************************* | ||
449 | * | ||
450 | * FUNCTION: acpi_ut_get_mutex_name | ||
451 | * | ||
452 | * PARAMETERS: mutex_id - The predefined ID for this mutex. | ||
453 | * | ||
454 | * RETURN: Decoded name of the internal mutex | ||
455 | * | ||
456 | * DESCRIPTION: Translate a mutex ID into a name string (Debug only) | ||
457 | * | ||
458 | ******************************************************************************/ | ||
459 | |||
460 | /* Names for internal mutex objects, used for debug output */ | ||
461 | |||
462 | static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { | ||
463 | "ACPI_MTX_Interpreter", | ||
464 | "ACPI_MTX_Namespace", | ||
465 | "ACPI_MTX_Tables", | ||
466 | "ACPI_MTX_Events", | ||
467 | "ACPI_MTX_Caches", | ||
468 | "ACPI_MTX_Memory", | ||
469 | "ACPI_MTX_CommandComplete", | ||
470 | "ACPI_MTX_CommandReady" | ||
471 | }; | ||
472 | |||
473 | char *acpi_ut_get_mutex_name(u32 mutex_id) | ||
474 | { | ||
475 | |||
476 | if (mutex_id > ACPI_MAX_MUTEX) { | ||
477 | return ("Invalid Mutex ID"); | ||
478 | } | ||
479 | |||
480 | return (acpi_gbl_mutex_names[mutex_id]); | ||
481 | } | ||
482 | |||
483 | /******************************************************************************* | ||
484 | * | ||
485 | * FUNCTION: acpi_ut_get_notify_name | ||
486 | * | ||
487 | * PARAMETERS: notify_value - Value from the Notify() request | ||
488 | * | ||
489 | * RETURN: Decoded name for the notify value | ||
490 | * | ||
491 | * DESCRIPTION: Translate a Notify Value to a notify namestring. | ||
492 | * | ||
493 | ******************************************************************************/ | ||
494 | |||
495 | /* Names for Notify() values, used for debug output */ | ||
496 | |||
497 | static const char *acpi_gbl_notify_value_names[] = { | ||
498 | "Bus Check", | ||
499 | "Device Check", | ||
500 | "Device Wake", | ||
501 | "Eject Request", | ||
502 | "Device Check Light", | ||
503 | "Frequency Mismatch", | ||
504 | "Bus Mode Mismatch", | ||
505 | "Power Fault", | ||
506 | "Capabilities Check", | ||
507 | "Device PLD Check", | ||
508 | "Reserved", | ||
509 | "System Locality Update" | ||
510 | }; | ||
511 | |||
512 | const char *acpi_ut_get_notify_name(u32 notify_value) | ||
513 | { | ||
514 | |||
515 | if (notify_value <= ACPI_NOTIFY_MAX) { | ||
516 | return (acpi_gbl_notify_value_names[notify_value]); | ||
517 | } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { | ||
518 | return ("Reserved"); | ||
519 | } else { /* Greater or equal to 0x80 */ | ||
520 | |||
521 | return ("**Device Specific**"); | ||
522 | } | ||
523 | } | ||
524 | #endif | ||
525 | |||
526 | /******************************************************************************* | ||
527 | * | ||
528 | * FUNCTION: acpi_ut_valid_object_type | ||
529 | * | ||
530 | * PARAMETERS: Type - Object type to be validated | ||
531 | * | ||
532 | * RETURN: TRUE if valid object type, FALSE otherwise | ||
533 | * | ||
534 | * DESCRIPTION: Validate an object type | ||
535 | * | ||
536 | ******************************************************************************/ | ||
537 | |||
538 | u8 acpi_ut_valid_object_type(acpi_object_type type) | ||
539 | { | ||
540 | |||
541 | if (type > ACPI_TYPE_LOCAL_MAX) { | ||
542 | |||
543 | /* Note: Assumes all TYPEs are contiguous (external/local) */ | ||
544 | |||
545 | return (FALSE); | ||
546 | } | ||
547 | |||
548 | return (TRUE); | ||
549 | } | ||
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index ed794cd033ea..31f5a7832ef1 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 6dfdeb653490..18f73c9d10bc 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,153 +48,6 @@ | |||
48 | #define _COMPONENT ACPI_UTILITIES | 48 | #define _COMPONENT ACPI_UTILITIES |
49 | ACPI_MODULE_NAME("uteval") | 49 | ACPI_MODULE_NAME("uteval") |
50 | 50 | ||
51 | /* | ||
52 | * Strings supported by the _OSI predefined (internal) method. | ||
53 | * | ||
54 | * March 2009: Removed "Linux" as this host no longer wants to respond true | ||
55 | * for this string. Basically, the only safe OS strings are windows-related | ||
56 | * and in many or most cases represent the only test path within the | ||
57 | * BIOS-provided ASL code. | ||
58 | * | ||
59 | * The second element of each entry is used to track the newest version of | ||
60 | * Windows that the BIOS has requested. | ||
61 | */ | ||
62 | static struct acpi_interface_info acpi_interfaces_supported[] = { | ||
63 | /* Operating System Vendor Strings */ | ||
64 | |||
65 | {"Windows 2000", ACPI_OSI_WIN_2000}, /* Windows 2000 */ | ||
66 | {"Windows 2001", ACPI_OSI_WIN_XP}, /* Windows XP */ | ||
67 | {"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ | ||
68 | {"Windows 2001.1", ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ | ||
69 | {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ | ||
70 | {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ | ||
71 | {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ | ||
72 | {"Windows 2006.1", ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ | ||
73 | {"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ | ||
74 | {"Windows 2009", ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ | ||
75 | |||
76 | /* Feature Group Strings */ | ||
77 | |||
78 | {"Extended Address Space Descriptor", 0} | ||
79 | |||
80 | /* | ||
81 | * All "optional" feature group strings (features that are implemented | ||
82 | * by the host) should be implemented in the host version of | ||
83 | * acpi_os_validate_interface and should not be added here. | ||
84 | */ | ||
85 | }; | ||
86 | |||
87 | /******************************************************************************* | ||
88 | * | ||
89 | * FUNCTION: acpi_ut_osi_implementation | ||
90 | * | ||
91 | * PARAMETERS: walk_state - Current walk state | ||
92 | * | ||
93 | * RETURN: Status | ||
94 | * | ||
95 | * DESCRIPTION: Implementation of the _OSI predefined control method | ||
96 | * | ||
97 | ******************************************************************************/ | ||
98 | |||
99 | acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) | ||
100 | { | ||
101 | acpi_status status; | ||
102 | union acpi_operand_object *string_desc; | ||
103 | union acpi_operand_object *return_desc; | ||
104 | u32 return_value; | ||
105 | u32 i; | ||
106 | |||
107 | ACPI_FUNCTION_TRACE(ut_osi_implementation); | ||
108 | |||
109 | /* Validate the string input argument */ | ||
110 | |||
111 | string_desc = walk_state->arguments[0].object; | ||
112 | if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) { | ||
113 | return_ACPI_STATUS(AE_TYPE); | ||
114 | } | ||
115 | |||
116 | /* Create a return object */ | ||
117 | |||
118 | return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); | ||
119 | if (!return_desc) { | ||
120 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
121 | } | ||
122 | |||
123 | /* Default return value is 0, NOT SUPPORTED */ | ||
124 | |||
125 | return_value = 0; | ||
126 | |||
127 | /* Compare input string to static table of supported interfaces */ | ||
128 | |||
129 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { | ||
130 | if (!ACPI_STRCMP(string_desc->string.pointer, | ||
131 | acpi_interfaces_supported[i].name)) { | ||
132 | /* | ||
133 | * The interface is supported. | ||
134 | * Update the osi_data if necessary. We keep track of the latest | ||
135 | * version of Windows that has been requested by the BIOS. | ||
136 | */ | ||
137 | if (acpi_interfaces_supported[i].value > | ||
138 | acpi_gbl_osi_data) { | ||
139 | acpi_gbl_osi_data = | ||
140 | acpi_interfaces_supported[i].value; | ||
141 | } | ||
142 | |||
143 | return_value = ACPI_UINT32_MAX; | ||
144 | goto exit; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Did not match the string in the static table, call the host OSL to | ||
150 | * check for a match with one of the optional strings (such as | ||
151 | * "Module Device", "3.0 Thermal Model", etc.) | ||
152 | */ | ||
153 | status = acpi_os_validate_interface(string_desc->string.pointer); | ||
154 | if (ACPI_SUCCESS(status)) { | ||
155 | |||
156 | /* The interface is supported */ | ||
157 | |||
158 | return_value = ACPI_UINT32_MAX; | ||
159 | } | ||
160 | |||
161 | exit: | ||
162 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, | ||
163 | "ACPI: BIOS _OSI(%s) is %ssupported\n", | ||
164 | string_desc->string.pointer, return_value == 0 ? "not " : "")); | ||
165 | |||
166 | /* Complete the return value */ | ||
167 | |||
168 | return_desc->integer.value = return_value; | ||
169 | walk_state->return_desc = return_desc; | ||
170 | return_ACPI_STATUS (AE_OK); | ||
171 | } | ||
172 | |||
173 | /******************************************************************************* | ||
174 | * | ||
175 | * FUNCTION: acpi_osi_invalidate | ||
176 | * | ||
177 | * PARAMETERS: interface_string | ||
178 | * | ||
179 | * RETURN: Status | ||
180 | * | ||
181 | * DESCRIPTION: invalidate string in pre-defiend _OSI string list | ||
182 | * | ||
183 | ******************************************************************************/ | ||
184 | |||
185 | acpi_status acpi_osi_invalidate(char *interface) | ||
186 | { | ||
187 | int i; | ||
188 | |||
189 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { | ||
190 | if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) { | ||
191 | *acpi_interfaces_supported[i].name = '\0'; | ||
192 | return AE_OK; | ||
193 | } | ||
194 | } | ||
195 | return AE_NOT_FOUND; | ||
196 | } | ||
197 | |||
198 | /******************************************************************************* | 51 | /******************************************************************************* |
199 | * | 52 | * |
200 | * FUNCTION: acpi_ut_evaluate_object | 53 | * FUNCTION: acpi_ut_evaluate_object |
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 0558747579ef..833a38a9c905 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -45,7 +45,6 @@ | |||
45 | 45 | ||
46 | #include <acpi/acpi.h> | 46 | #include <acpi/acpi.h> |
47 | #include "accommon.h" | 47 | #include "accommon.h" |
48 | #include "acnamesp.h" | ||
49 | 48 | ||
50 | #define _COMPONENT ACPI_UTILITIES | 49 | #define _COMPONENT ACPI_UTILITIES |
51 | ACPI_MODULE_NAME("utglobal") | 50 | ACPI_MODULE_NAME("utglobal") |
@@ -107,43 +106,6 @@ const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = { | |||
107 | 106 | ||
108 | /******************************************************************************* | 107 | /******************************************************************************* |
109 | * | 108 | * |
110 | * FUNCTION: acpi_format_exception | ||
111 | * | ||
112 | * PARAMETERS: Status - The acpi_status code to be formatted | ||
113 | * | ||
114 | * RETURN: A string containing the exception text. A valid pointer is | ||
115 | * always returned. | ||
116 | * | ||
117 | * DESCRIPTION: This function translates an ACPI exception into an ASCII string | ||
118 | * It is here instead of utxface.c so it is always present. | ||
119 | * | ||
120 | ******************************************************************************/ | ||
121 | |||
122 | const char *acpi_format_exception(acpi_status status) | ||
123 | { | ||
124 | const char *exception = NULL; | ||
125 | |||
126 | ACPI_FUNCTION_ENTRY(); | ||
127 | |||
128 | exception = acpi_ut_validate_exception(status); | ||
129 | if (!exception) { | ||
130 | |||
131 | /* Exception code was not recognized */ | ||
132 | |||
133 | ACPI_ERROR((AE_INFO, | ||
134 | "Unknown exception code: 0x%8.8X", status)); | ||
135 | |||
136 | exception = "UNKNOWN_STATUS_CODE"; | ||
137 | dump_stack(); | ||
138 | } | ||
139 | |||
140 | return (ACPI_CAST_PTR(const char, exception)); | ||
141 | } | ||
142 | |||
143 | ACPI_EXPORT_SYMBOL(acpi_format_exception) | ||
144 | |||
145 | /******************************************************************************* | ||
146 | * | ||
147 | * Namespace globals | 109 | * Namespace globals |
148 | * | 110 | * |
149 | ******************************************************************************/ | 111 | ******************************************************************************/ |
@@ -154,14 +116,16 @@ ACPI_EXPORT_SYMBOL(acpi_format_exception) | |||
154 | * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run | 116 | * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run |
155 | * during the initialization sequence. | 117 | * during the initialization sequence. |
156 | * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to | 118 | * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to |
157 | * perform a Notify() operation on it. | 119 | * perform a Notify() operation on it. 09/2010: Changed to type Device. |
120 | * This still allows notifies, but does not confuse host code that | ||
121 | * searches for valid thermal_zone objects. | ||
158 | */ | 122 | */ |
159 | const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { | 123 | const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { |
160 | {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, | 124 | {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, |
161 | {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, | 125 | {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, |
162 | {"_SB_", ACPI_TYPE_DEVICE, NULL}, | 126 | {"_SB_", ACPI_TYPE_DEVICE, NULL}, |
163 | {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, | 127 | {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, |
164 | {"_TZ_", ACPI_TYPE_THERMAL, NULL}, | 128 | {"_TZ_", ACPI_TYPE_DEVICE, NULL}, |
165 | {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, | 129 | {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, |
166 | {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, | 130 | {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, |
167 | {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, | 131 | {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, |
@@ -175,71 +139,6 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { | |||
175 | {NULL, ACPI_TYPE_ANY, NULL} | 139 | {NULL, ACPI_TYPE_ANY, NULL} |
176 | }; | 140 | }; |
177 | 141 | ||
178 | /* | ||
179 | * Properties of the ACPI Object Types, both internal and external. | ||
180 | * The table is indexed by values of acpi_object_type | ||
181 | */ | ||
182 | const u8 acpi_gbl_ns_properties[] = { | ||
183 | ACPI_NS_NORMAL, /* 00 Any */ | ||
184 | ACPI_NS_NORMAL, /* 01 Number */ | ||
185 | ACPI_NS_NORMAL, /* 02 String */ | ||
186 | ACPI_NS_NORMAL, /* 03 Buffer */ | ||
187 | ACPI_NS_NORMAL, /* 04 Package */ | ||
188 | ACPI_NS_NORMAL, /* 05 field_unit */ | ||
189 | ACPI_NS_NEWSCOPE, /* 06 Device */ | ||
190 | ACPI_NS_NORMAL, /* 07 Event */ | ||
191 | ACPI_NS_NEWSCOPE, /* 08 Method */ | ||
192 | ACPI_NS_NORMAL, /* 09 Mutex */ | ||
193 | ACPI_NS_NORMAL, /* 10 Region */ | ||
194 | ACPI_NS_NEWSCOPE, /* 11 Power */ | ||
195 | ACPI_NS_NEWSCOPE, /* 12 Processor */ | ||
196 | ACPI_NS_NEWSCOPE, /* 13 Thermal */ | ||
197 | ACPI_NS_NORMAL, /* 14 buffer_field */ | ||
198 | ACPI_NS_NORMAL, /* 15 ddb_handle */ | ||
199 | ACPI_NS_NORMAL, /* 16 Debug Object */ | ||
200 | ACPI_NS_NORMAL, /* 17 def_field */ | ||
201 | ACPI_NS_NORMAL, /* 18 bank_field */ | ||
202 | ACPI_NS_NORMAL, /* 19 index_field */ | ||
203 | ACPI_NS_NORMAL, /* 20 Reference */ | ||
204 | ACPI_NS_NORMAL, /* 21 Alias */ | ||
205 | ACPI_NS_NORMAL, /* 22 method_alias */ | ||
206 | ACPI_NS_NORMAL, /* 23 Notify */ | ||
207 | ACPI_NS_NORMAL, /* 24 Address Handler */ | ||
208 | ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ | ||
209 | ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ | ||
210 | ACPI_NS_NEWSCOPE, /* 27 Scope */ | ||
211 | ACPI_NS_NORMAL, /* 28 Extra */ | ||
212 | ACPI_NS_NORMAL, /* 29 Data */ | ||
213 | ACPI_NS_NORMAL /* 30 Invalid */ | ||
214 | }; | ||
215 | |||
216 | /* Hex to ASCII conversion table */ | ||
217 | |||
218 | static const char acpi_gbl_hex_to_ascii[] = { | ||
219 | '0', '1', '2', '3', '4', '5', '6', '7', | ||
220 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
221 | }; | ||
222 | |||
223 | /******************************************************************************* | ||
224 | * | ||
225 | * FUNCTION: acpi_ut_hex_to_ascii_char | ||
226 | * | ||
227 | * PARAMETERS: Integer - Contains the hex digit | ||
228 | * Position - bit position of the digit within the | ||
229 | * integer (multiple of 4) | ||
230 | * | ||
231 | * RETURN: The converted Ascii character | ||
232 | * | ||
233 | * DESCRIPTION: Convert a hex digit to an Ascii character | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) | ||
238 | { | ||
239 | |||
240 | return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); | ||
241 | } | ||
242 | |||
243 | /****************************************************************************** | 142 | /****************************************************************************** |
244 | * | 143 | * |
245 | * Event and Hardware globals | 144 | * Event and Hardware globals |
@@ -339,386 +238,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = | |||
339 | 238 | ||
340 | /******************************************************************************* | 239 | /******************************************************************************* |
341 | * | 240 | * |
342 | * FUNCTION: acpi_ut_get_region_name | ||
343 | * | ||
344 | * PARAMETERS: None. | ||
345 | * | ||
346 | * RETURN: Status | ||
347 | * | ||
348 | * DESCRIPTION: Translate a Space ID into a name string (Debug only) | ||
349 | * | ||
350 | ******************************************************************************/ | ||
351 | |||
352 | /* Region type decoding */ | ||
353 | |||
354 | const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { | ||
355 | "SystemMemory", | ||
356 | "SystemIO", | ||
357 | "PCI_Config", | ||
358 | "EmbeddedControl", | ||
359 | "SMBus", | ||
360 | "SystemCMOS", | ||
361 | "PCIBARTarget", | ||
362 | "IPMI", | ||
363 | "DataTable" | ||
364 | }; | ||
365 | |||
366 | char *acpi_ut_get_region_name(u8 space_id) | ||
367 | { | ||
368 | |||
369 | if (space_id >= ACPI_USER_REGION_BEGIN) { | ||
370 | return ("UserDefinedRegion"); | ||
371 | } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { | ||
372 | return ("InvalidSpaceId"); | ||
373 | } | ||
374 | |||
375 | return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); | ||
376 | } | ||
377 | |||
378 | /******************************************************************************* | ||
379 | * | ||
380 | * FUNCTION: acpi_ut_get_event_name | ||
381 | * | ||
382 | * PARAMETERS: None. | ||
383 | * | ||
384 | * RETURN: Status | ||
385 | * | ||
386 | * DESCRIPTION: Translate a Event ID into a name string (Debug only) | ||
387 | * | ||
388 | ******************************************************************************/ | ||
389 | |||
390 | /* Event type decoding */ | ||
391 | |||
392 | static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { | ||
393 | "PM_Timer", | ||
394 | "GlobalLock", | ||
395 | "PowerButton", | ||
396 | "SleepButton", | ||
397 | "RealTimeClock", | ||
398 | }; | ||
399 | |||
400 | char *acpi_ut_get_event_name(u32 event_id) | ||
401 | { | ||
402 | |||
403 | if (event_id > ACPI_EVENT_MAX) { | ||
404 | return ("InvalidEventID"); | ||
405 | } | ||
406 | |||
407 | return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); | ||
408 | } | ||
409 | |||
410 | /******************************************************************************* | ||
411 | * | ||
412 | * FUNCTION: acpi_ut_get_type_name | ||
413 | * | ||
414 | * PARAMETERS: None. | ||
415 | * | ||
416 | * RETURN: Status | ||
417 | * | ||
418 | * DESCRIPTION: Translate a Type ID into a name string (Debug only) | ||
419 | * | ||
420 | ******************************************************************************/ | ||
421 | |||
422 | /* | ||
423 | * Elements of acpi_gbl_ns_type_names below must match | ||
424 | * one-to-one with values of acpi_object_type | ||
425 | * | ||
426 | * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; | ||
427 | * when stored in a table it really means that we have thus far seen no | ||
428 | * evidence to indicate what type is actually going to be stored for this entry. | ||
429 | */ | ||
430 | static const char acpi_gbl_bad_type[] = "UNDEFINED"; | ||
431 | |||
432 | /* Printable names of the ACPI object types */ | ||
433 | |||
434 | static const char *acpi_gbl_ns_type_names[] = { | ||
435 | /* 00 */ "Untyped", | ||
436 | /* 01 */ "Integer", | ||
437 | /* 02 */ "String", | ||
438 | /* 03 */ "Buffer", | ||
439 | /* 04 */ "Package", | ||
440 | /* 05 */ "FieldUnit", | ||
441 | /* 06 */ "Device", | ||
442 | /* 07 */ "Event", | ||
443 | /* 08 */ "Method", | ||
444 | /* 09 */ "Mutex", | ||
445 | /* 10 */ "Region", | ||
446 | /* 11 */ "Power", | ||
447 | /* 12 */ "Processor", | ||
448 | /* 13 */ "Thermal", | ||
449 | /* 14 */ "BufferField", | ||
450 | /* 15 */ "DdbHandle", | ||
451 | /* 16 */ "DebugObject", | ||
452 | /* 17 */ "RegionField", | ||
453 | /* 18 */ "BankField", | ||
454 | /* 19 */ "IndexField", | ||
455 | /* 20 */ "Reference", | ||
456 | /* 21 */ "Alias", | ||
457 | /* 22 */ "MethodAlias", | ||
458 | /* 23 */ "Notify", | ||
459 | /* 24 */ "AddrHandler", | ||
460 | /* 25 */ "ResourceDesc", | ||
461 | /* 26 */ "ResourceFld", | ||
462 | /* 27 */ "Scope", | ||
463 | /* 28 */ "Extra", | ||
464 | /* 29 */ "Data", | ||
465 | /* 30 */ "Invalid" | ||
466 | }; | ||
467 | |||
468 | char *acpi_ut_get_type_name(acpi_object_type type) | ||
469 | { | ||
470 | |||
471 | if (type > ACPI_TYPE_INVALID) { | ||
472 | return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); | ||
473 | } | ||
474 | |||
475 | return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); | ||
476 | } | ||
477 | |||
478 | char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) | ||
479 | { | ||
480 | |||
481 | if (!obj_desc) { | ||
482 | return ("[NULL Object Descriptor]"); | ||
483 | } | ||
484 | |||
485 | return (acpi_ut_get_type_name(obj_desc->common.type)); | ||
486 | } | ||
487 | |||
488 | /******************************************************************************* | ||
489 | * | ||
490 | * FUNCTION: acpi_ut_get_node_name | ||
491 | * | ||
492 | * PARAMETERS: Object - A namespace node | ||
493 | * | ||
494 | * RETURN: Pointer to a string | ||
495 | * | ||
496 | * DESCRIPTION: Validate the node and return the node's ACPI name. | ||
497 | * | ||
498 | ******************************************************************************/ | ||
499 | |||
500 | char *acpi_ut_get_node_name(void *object) | ||
501 | { | ||
502 | struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; | ||
503 | |||
504 | /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ | ||
505 | |||
506 | if (!object) { | ||
507 | return ("NULL"); | ||
508 | } | ||
509 | |||
510 | /* Check for Root node */ | ||
511 | |||
512 | if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { | ||
513 | return ("\"\\\" "); | ||
514 | } | ||
515 | |||
516 | /* Descriptor must be a namespace node */ | ||
517 | |||
518 | if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { | ||
519 | return ("####"); | ||
520 | } | ||
521 | |||
522 | /* Name must be a valid ACPI name */ | ||
523 | |||
524 | if (!acpi_ut_valid_acpi_name(node->name.integer)) { | ||
525 | node->name.integer = acpi_ut_repair_name(node->name.ascii); | ||
526 | } | ||
527 | |||
528 | /* Return the name */ | ||
529 | |||
530 | return (node->name.ascii); | ||
531 | } | ||
532 | |||
533 | /******************************************************************************* | ||
534 | * | ||
535 | * FUNCTION: acpi_ut_get_descriptor_name | ||
536 | * | ||
537 | * PARAMETERS: Object - An ACPI object | ||
538 | * | ||
539 | * RETURN: Pointer to a string | ||
540 | * | ||
541 | * DESCRIPTION: Validate object and return the descriptor type | ||
542 | * | ||
543 | ******************************************************************************/ | ||
544 | |||
545 | /* Printable names of object descriptor types */ | ||
546 | |||
547 | static const char *acpi_gbl_desc_type_names[] = { | ||
548 | /* 00 */ "Invalid", | ||
549 | /* 01 */ "Cached", | ||
550 | /* 02 */ "State-Generic", | ||
551 | /* 03 */ "State-Update", | ||
552 | /* 04 */ "State-Package", | ||
553 | /* 05 */ "State-Control", | ||
554 | /* 06 */ "State-RootParseScope", | ||
555 | /* 07 */ "State-ParseScope", | ||
556 | /* 08 */ "State-WalkScope", | ||
557 | /* 09 */ "State-Result", | ||
558 | /* 10 */ "State-Notify", | ||
559 | /* 11 */ "State-Thread", | ||
560 | /* 12 */ "Walk", | ||
561 | /* 13 */ "Parser", | ||
562 | /* 14 */ "Operand", | ||
563 | /* 15 */ "Node" | ||
564 | }; | ||
565 | |||
566 | char *acpi_ut_get_descriptor_name(void *object) | ||
567 | { | ||
568 | |||
569 | if (!object) { | ||
570 | return ("NULL OBJECT"); | ||
571 | } | ||
572 | |||
573 | if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { | ||
574 | return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); | ||
575 | } | ||
576 | |||
577 | return (ACPI_CAST_PTR(char, | ||
578 | acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE | ||
579 | (object)])); | ||
580 | |||
581 | } | ||
582 | |||
583 | /******************************************************************************* | ||
584 | * | ||
585 | * FUNCTION: acpi_ut_get_reference_name | ||
586 | * | ||
587 | * PARAMETERS: Object - An ACPI reference object | ||
588 | * | ||
589 | * RETURN: Pointer to a string | ||
590 | * | ||
591 | * DESCRIPTION: Decode a reference object sub-type to a string. | ||
592 | * | ||
593 | ******************************************************************************/ | ||
594 | |||
595 | /* Printable names of reference object sub-types */ | ||
596 | |||
597 | static const char *acpi_gbl_ref_class_names[] = { | ||
598 | /* 00 */ "Local", | ||
599 | /* 01 */ "Argument", | ||
600 | /* 02 */ "RefOf", | ||
601 | /* 03 */ "Index", | ||
602 | /* 04 */ "DdbHandle", | ||
603 | /* 05 */ "Named Object", | ||
604 | /* 06 */ "Debug" | ||
605 | }; | ||
606 | |||
607 | const char *acpi_ut_get_reference_name(union acpi_operand_object *object) | ||
608 | { | ||
609 | if (!object) | ||
610 | return "NULL Object"; | ||
611 | |||
612 | if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) | ||
613 | return "Not an Operand object"; | ||
614 | |||
615 | if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) | ||
616 | return "Not a Reference object"; | ||
617 | |||
618 | if (object->reference.class > ACPI_REFCLASS_MAX) | ||
619 | return "Unknown Reference class"; | ||
620 | |||
621 | return acpi_gbl_ref_class_names[object->reference.class]; | ||
622 | } | ||
623 | |||
624 | #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) | ||
625 | /* | ||
626 | * Strings and procedures used for debug only | ||
627 | */ | ||
628 | |||
629 | /******************************************************************************* | ||
630 | * | ||
631 | * FUNCTION: acpi_ut_get_mutex_name | ||
632 | * | ||
633 | * PARAMETERS: mutex_id - The predefined ID for this mutex. | ||
634 | * | ||
635 | * RETURN: String containing the name of the mutex. Always returns a valid | ||
636 | * pointer. | ||
637 | * | ||
638 | * DESCRIPTION: Translate a mutex ID into a name string (Debug only) | ||
639 | * | ||
640 | ******************************************************************************/ | ||
641 | |||
642 | char *acpi_ut_get_mutex_name(u32 mutex_id) | ||
643 | { | ||
644 | |||
645 | if (mutex_id > ACPI_MAX_MUTEX) { | ||
646 | return ("Invalid Mutex ID"); | ||
647 | } | ||
648 | |||
649 | return (acpi_gbl_mutex_names[mutex_id]); | ||
650 | } | ||
651 | |||
652 | /******************************************************************************* | ||
653 | * | ||
654 | * FUNCTION: acpi_ut_get_notify_name | ||
655 | * | ||
656 | * PARAMETERS: notify_value - Value from the Notify() request | ||
657 | * | ||
658 | * RETURN: String corresponding to the Notify Value. | ||
659 | * | ||
660 | * DESCRIPTION: Translate a Notify Value to a notify namestring. | ||
661 | * | ||
662 | ******************************************************************************/ | ||
663 | |||
664 | /* Names for Notify() values, used for debug output */ | ||
665 | |||
666 | static const char *acpi_gbl_notify_value_names[] = { | ||
667 | "Bus Check", | ||
668 | "Device Check", | ||
669 | "Device Wake", | ||
670 | "Eject Request", | ||
671 | "Device Check Light", | ||
672 | "Frequency Mismatch", | ||
673 | "Bus Mode Mismatch", | ||
674 | "Power Fault", | ||
675 | "Capabilities Check", | ||
676 | "Device PLD Check", | ||
677 | "Reserved", | ||
678 | "System Locality Update" | ||
679 | }; | ||
680 | |||
681 | const char *acpi_ut_get_notify_name(u32 notify_value) | ||
682 | { | ||
683 | |||
684 | if (notify_value <= ACPI_NOTIFY_MAX) { | ||
685 | return (acpi_gbl_notify_value_names[notify_value]); | ||
686 | } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { | ||
687 | return ("Reserved"); | ||
688 | } else { /* Greater or equal to 0x80 */ | ||
689 | |||
690 | return ("**Device Specific**"); | ||
691 | } | ||
692 | } | ||
693 | #endif | ||
694 | |||
695 | /******************************************************************************* | ||
696 | * | ||
697 | * FUNCTION: acpi_ut_valid_object_type | ||
698 | * | ||
699 | * PARAMETERS: Type - Object type to be validated | ||
700 | * | ||
701 | * RETURN: TRUE if valid object type, FALSE otherwise | ||
702 | * | ||
703 | * DESCRIPTION: Validate an object type | ||
704 | * | ||
705 | ******************************************************************************/ | ||
706 | |||
707 | u8 acpi_ut_valid_object_type(acpi_object_type type) | ||
708 | { | ||
709 | |||
710 | if (type > ACPI_TYPE_LOCAL_MAX) { | ||
711 | |||
712 | /* Note: Assumes all TYPEs are contiguous (external/local) */ | ||
713 | |||
714 | return (FALSE); | ||
715 | } | ||
716 | |||
717 | return (TRUE); | ||
718 | } | ||
719 | |||
720 | /******************************************************************************* | ||
721 | * | ||
722 | * FUNCTION: acpi_ut_init_globals | 241 | * FUNCTION: acpi_ut_init_globals |
723 | * | 242 | * |
724 | * PARAMETERS: None | 243 | * PARAMETERS: None |
@@ -766,6 +285,7 @@ acpi_status acpi_ut_init_globals(void) | |||
766 | acpi_gbl_gpe_fadt_blocks[0] = NULL; | 285 | acpi_gbl_gpe_fadt_blocks[0] = NULL; |
767 | acpi_gbl_gpe_fadt_blocks[1] = NULL; | 286 | acpi_gbl_gpe_fadt_blocks[1] = NULL; |
768 | acpi_current_gpe_count = 0; | 287 | acpi_current_gpe_count = 0; |
288 | acpi_gbl_all_gpes_initialized = FALSE; | ||
769 | 289 | ||
770 | /* Global handlers */ | 290 | /* Global handlers */ |
771 | 291 | ||
@@ -774,6 +294,8 @@ acpi_status acpi_ut_init_globals(void) | |||
774 | acpi_gbl_exception_handler = NULL; | 294 | acpi_gbl_exception_handler = NULL; |
775 | acpi_gbl_init_handler = NULL; | 295 | acpi_gbl_init_handler = NULL; |
776 | acpi_gbl_table_handler = NULL; | 296 | acpi_gbl_table_handler = NULL; |
297 | acpi_gbl_interface_handler = NULL; | ||
298 | acpi_gbl_global_event_handler = NULL; | ||
777 | 299 | ||
778 | /* Global Lock support */ | 300 | /* Global Lock support */ |
779 | 301 | ||
@@ -800,6 +322,8 @@ acpi_status acpi_ut_init_globals(void) | |||
800 | acpi_gbl_debugger_configuration = DEBUGGER_THREADING; | 322 | acpi_gbl_debugger_configuration = DEBUGGER_THREADING; |
801 | acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; | 323 | acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; |
802 | acpi_gbl_osi_data = 0; | 324 | acpi_gbl_osi_data = 0; |
325 | acpi_gbl_osi_mutex = NULL; | ||
326 | acpi_gbl_reg_methods_executed = FALSE; | ||
803 | 327 | ||
804 | /* Hardware oriented */ | 328 | /* Hardware oriented */ |
805 | 329 | ||
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index 1397fadd0d4b..b679ea693545 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,42 +48,6 @@ | |||
48 | #define _COMPONENT ACPI_UTILITIES | 48 | #define _COMPONENT ACPI_UTILITIES |
49 | ACPI_MODULE_NAME("utids") | 49 | ACPI_MODULE_NAME("utids") |
50 | 50 | ||
51 | /* Local prototypes */ | ||
52 | static void acpi_ut_copy_id_string(char *destination, char *source); | ||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_ut_copy_id_string | ||
57 | * | ||
58 | * PARAMETERS: Destination - Where to copy the string | ||
59 | * Source - Source string | ||
60 | * | ||
61 | * RETURN: None | ||
62 | * | ||
63 | * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. | ||
64 | * Performs removal of a leading asterisk if present -- workaround | ||
65 | * for a known issue on a bunch of machines. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | |||
69 | static void acpi_ut_copy_id_string(char *destination, char *source) | ||
70 | { | ||
71 | |||
72 | /* | ||
73 | * Workaround for ID strings that have a leading asterisk. This construct | ||
74 | * is not allowed by the ACPI specification (ID strings must be | ||
75 | * alphanumeric), but enough existing machines have this embedded in their | ||
76 | * ID strings that the following code is useful. | ||
77 | */ | ||
78 | if (*source == '*') { | ||
79 | source++; | ||
80 | } | ||
81 | |||
82 | /* Do the actual copy */ | ||
83 | |||
84 | ACPI_STRCPY(destination, source); | ||
85 | } | ||
86 | |||
87 | /******************************************************************************* | 51 | /******************************************************************************* |
88 | * | 52 | * |
89 | * FUNCTION: acpi_ut_execute_HID | 53 | * FUNCTION: acpi_ut_execute_HID |
@@ -101,7 +65,6 @@ static void acpi_ut_copy_id_string(char *destination, char *source) | |||
101 | * NOTE: Internal function, no parameter validation | 65 | * NOTE: Internal function, no parameter validation |
102 | * | 66 | * |
103 | ******************************************************************************/ | 67 | ******************************************************************************/ |
104 | |||
105 | acpi_status | 68 | acpi_status |
106 | acpi_ut_execute_HID(struct acpi_namespace_node *device_node, | 69 | acpi_ut_execute_HID(struct acpi_namespace_node *device_node, |
107 | struct acpica_device_id **return_id) | 70 | struct acpica_device_id **return_id) |
@@ -147,7 +110,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, | |||
147 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | 110 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { |
148 | acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value); | 111 | acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value); |
149 | } else { | 112 | } else { |
150 | acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer); | 113 | ACPI_STRCPY(hid->string, obj_desc->string.pointer); |
151 | } | 114 | } |
152 | 115 | ||
153 | hid->length = length; | 116 | hid->length = length; |
@@ -224,7 +187,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, | |||
224 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | 187 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { |
225 | acpi_ex_integer_to_string(uid->string, obj_desc->integer.value); | 188 | acpi_ex_integer_to_string(uid->string, obj_desc->integer.value); |
226 | } else { | 189 | } else { |
227 | acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer); | 190 | ACPI_STRCPY(uid->string, obj_desc->string.pointer); |
228 | } | 191 | } |
229 | 192 | ||
230 | uid->length = length; | 193 | uid->length = length; |
@@ -357,8 +320,8 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, | |||
357 | 320 | ||
358 | /* Copy the String CID from the returned object */ | 321 | /* Copy the String CID from the returned object */ |
359 | 322 | ||
360 | acpi_ut_copy_id_string(next_id_string, | 323 | ACPI_STRCPY(next_id_string, |
361 | cid_objects[i]->string.pointer); | 324 | cid_objects[i]->string.pointer); |
362 | length = cid_objects[i]->string.length + 1; | 325 | length = cid_objects[i]->string.length + 1; |
363 | } | 326 | } |
364 | 327 | ||
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index a39c93dac719..191b6828cce9 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -117,6 +117,10 @@ void acpi_ut_subsystem_shutdown(void) | |||
117 | /* Close the acpi_event Handling */ | 117 | /* Close the acpi_event Handling */ |
118 | 118 | ||
119 | acpi_ev_terminate(); | 119 | acpi_ev_terminate(); |
120 | |||
121 | /* Delete any dynamic _OSI interfaces */ | ||
122 | |||
123 | acpi_ut_interface_terminate(); | ||
120 | #endif | 124 | #endif |
121 | 125 | ||
122 | /* Close the Namespace */ | 126 | /* Close the Namespace */ |
diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c index b081cd46a15f..f6bb75c6faf5 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 35059a14eb72..ce481da9bb45 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,11 +48,27 @@ | |||
48 | ACPI_MODULE_NAME("utmath") | 48 | ACPI_MODULE_NAME("utmath") |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Support for double-precision integer divide. This code is included here | 51 | * Optional support for 64-bit double-precision integer divide. This code |
52 | * in order to support kernel environments where the double-precision math | 52 | * is configurable and is implemented in order to support 32-bit kernel |
53 | * library is not available. | 53 | * environments where a 64-bit double-precision math library is not available. |
54 | * | ||
55 | * Support for a more normal 64-bit divide/modulo (with check for a divide- | ||
56 | * by-zero) appears after this optional section of code. | ||
54 | */ | 57 | */ |
55 | #ifndef ACPI_USE_NATIVE_DIVIDE | 58 | #ifndef ACPI_USE_NATIVE_DIVIDE |
59 | /* Structures used only for 64-bit divide */ | ||
60 | typedef struct uint64_struct { | ||
61 | u32 lo; | ||
62 | u32 hi; | ||
63 | |||
64 | } uint64_struct; | ||
65 | |||
66 | typedef union uint64_overlay { | ||
67 | u64 full; | ||
68 | struct uint64_struct part; | ||
69 | |||
70 | } uint64_overlay; | ||
71 | |||
56 | /******************************************************************************* | 72 | /******************************************************************************* |
57 | * | 73 | * |
58 | * FUNCTION: acpi_ut_short_divide | 74 | * FUNCTION: acpi_ut_short_divide |
@@ -69,6 +85,7 @@ ACPI_MODULE_NAME("utmath") | |||
69 | * 32-bit remainder. | 85 | * 32-bit remainder. |
70 | * | 86 | * |
71 | ******************************************************************************/ | 87 | ******************************************************************************/ |
88 | |||
72 | acpi_status | 89 | acpi_status |
73 | acpi_ut_short_divide(u64 dividend, | 90 | acpi_ut_short_divide(u64 dividend, |
74 | u32 divisor, u64 *out_quotient, u32 *out_remainder) | 91 | u32 divisor, u64 *out_quotient, u32 *out_remainder) |
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index e8d0724ee403..c33a852d4f42 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -50,11 +50,6 @@ | |||
50 | #define _COMPONENT ACPI_UTILITIES | 50 | #define _COMPONENT ACPI_UTILITIES |
51 | ACPI_MODULE_NAME("utmisc") | 51 | ACPI_MODULE_NAME("utmisc") |
52 | 52 | ||
53 | /* | ||
54 | * Common suffix for messages | ||
55 | */ | ||
56 | #define ACPI_COMMON_MSG_SUFFIX \ | ||
57 | acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) | ||
58 | /******************************************************************************* | 53 | /******************************************************************************* |
59 | * | 54 | * |
60 | * FUNCTION: acpi_ut_validate_exception | 55 | * FUNCTION: acpi_ut_validate_exception |
@@ -1044,160 +1039,3 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, | |||
1044 | 1039 | ||
1045 | return_ACPI_STATUS(AE_AML_INTERNAL); | 1040 | return_ACPI_STATUS(AE_AML_INTERNAL); |
1046 | } | 1041 | } |
1047 | |||
1048 | /******************************************************************************* | ||
1049 | * | ||
1050 | * FUNCTION: acpi_error, acpi_exception, acpi_warning, acpi_info | ||
1051 | * | ||
1052 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
1053 | * line_number - Caller's line number (for error output) | ||
1054 | * Format - Printf format string + additional args | ||
1055 | * | ||
1056 | * RETURN: None | ||
1057 | * | ||
1058 | * DESCRIPTION: Print message with module/line/version info | ||
1059 | * | ||
1060 | ******************************************************************************/ | ||
1061 | |||
1062 | void ACPI_INTERNAL_VAR_XFACE | ||
1063 | acpi_error(const char *module_name, u32 line_number, const char *format, ...) | ||
1064 | { | ||
1065 | va_list args; | ||
1066 | |||
1067 | acpi_os_printf("ACPI Error: "); | ||
1068 | |||
1069 | va_start(args, format); | ||
1070 | acpi_os_vprintf(format, args); | ||
1071 | ACPI_COMMON_MSG_SUFFIX; | ||
1072 | va_end(args); | ||
1073 | } | ||
1074 | |||
1075 | void ACPI_INTERNAL_VAR_XFACE | ||
1076 | acpi_exception(const char *module_name, | ||
1077 | u32 line_number, acpi_status status, const char *format, ...) | ||
1078 | { | ||
1079 | va_list args; | ||
1080 | |||
1081 | acpi_os_printf("ACPI Exception: %s, ", acpi_format_exception(status)); | ||
1082 | |||
1083 | va_start(args, format); | ||
1084 | acpi_os_vprintf(format, args); | ||
1085 | ACPI_COMMON_MSG_SUFFIX; | ||
1086 | va_end(args); | ||
1087 | } | ||
1088 | |||
1089 | void ACPI_INTERNAL_VAR_XFACE | ||
1090 | acpi_warning(const char *module_name, u32 line_number, const char *format, ...) | ||
1091 | { | ||
1092 | va_list args; | ||
1093 | |||
1094 | acpi_os_printf("ACPI Warning: "); | ||
1095 | |||
1096 | va_start(args, format); | ||
1097 | acpi_os_vprintf(format, args); | ||
1098 | ACPI_COMMON_MSG_SUFFIX; | ||
1099 | va_end(args); | ||
1100 | } | ||
1101 | |||
1102 | void ACPI_INTERNAL_VAR_XFACE | ||
1103 | acpi_info(const char *module_name, u32 line_number, const char *format, ...) | ||
1104 | { | ||
1105 | va_list args; | ||
1106 | |||
1107 | acpi_os_printf("ACPI: "); | ||
1108 | |||
1109 | va_start(args, format); | ||
1110 | acpi_os_vprintf(format, args); | ||
1111 | acpi_os_printf("\n"); | ||
1112 | va_end(args); | ||
1113 | } | ||
1114 | |||
1115 | ACPI_EXPORT_SYMBOL(acpi_error) | ||
1116 | ACPI_EXPORT_SYMBOL(acpi_exception) | ||
1117 | ACPI_EXPORT_SYMBOL(acpi_warning) | ||
1118 | ACPI_EXPORT_SYMBOL(acpi_info) | ||
1119 | |||
1120 | /******************************************************************************* | ||
1121 | * | ||
1122 | * FUNCTION: acpi_ut_predefined_warning | ||
1123 | * | ||
1124 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
1125 | * line_number - Caller's line number (for error output) | ||
1126 | * Pathname - Full pathname to the node | ||
1127 | * node_flags - From Namespace node for the method/object | ||
1128 | * Format - Printf format string + additional args | ||
1129 | * | ||
1130 | * RETURN: None | ||
1131 | * | ||
1132 | * DESCRIPTION: Warnings for the predefined validation module. Messages are | ||
1133 | * only emitted the first time a problem with a particular | ||
1134 | * method/object is detected. This prevents a flood of error | ||
1135 | * messages for methods that are repeatedly evaluated. | ||
1136 | * | ||
1137 | ******************************************************************************/ | ||
1138 | |||
1139 | void ACPI_INTERNAL_VAR_XFACE | ||
1140 | acpi_ut_predefined_warning(const char *module_name, | ||
1141 | u32 line_number, | ||
1142 | char *pathname, | ||
1143 | u8 node_flags, const char *format, ...) | ||
1144 | { | ||
1145 | va_list args; | ||
1146 | |||
1147 | /* | ||
1148 | * Warning messages for this method/object will be disabled after the | ||
1149 | * first time a validation fails or an object is successfully repaired. | ||
1150 | */ | ||
1151 | if (node_flags & ANOBJ_EVALUATED) { | ||
1152 | return; | ||
1153 | } | ||
1154 | |||
1155 | acpi_os_printf("ACPI Warning for %s: ", pathname); | ||
1156 | |||
1157 | va_start(args, format); | ||
1158 | acpi_os_vprintf(format, args); | ||
1159 | ACPI_COMMON_MSG_SUFFIX; | ||
1160 | va_end(args); | ||
1161 | } | ||
1162 | |||
1163 | /******************************************************************************* | ||
1164 | * | ||
1165 | * FUNCTION: acpi_ut_predefined_info | ||
1166 | * | ||
1167 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
1168 | * line_number - Caller's line number (for error output) | ||
1169 | * Pathname - Full pathname to the node | ||
1170 | * node_flags - From Namespace node for the method/object | ||
1171 | * Format - Printf format string + additional args | ||
1172 | * | ||
1173 | * RETURN: None | ||
1174 | * | ||
1175 | * DESCRIPTION: Info messages for the predefined validation module. Messages | ||
1176 | * are only emitted the first time a problem with a particular | ||
1177 | * method/object is detected. This prevents a flood of | ||
1178 | * messages for methods that are repeatedly evaluated. | ||
1179 | * | ||
1180 | ******************************************************************************/ | ||
1181 | |||
1182 | void ACPI_INTERNAL_VAR_XFACE | ||
1183 | acpi_ut_predefined_info(const char *module_name, | ||
1184 | u32 line_number, | ||
1185 | char *pathname, u8 node_flags, const char *format, ...) | ||
1186 | { | ||
1187 | va_list args; | ||
1188 | |||
1189 | /* | ||
1190 | * Warning messages for this method/object will be disabled after the | ||
1191 | * first time a validation fails or an object is successfully repaired. | ||
1192 | */ | ||
1193 | if (node_flags & ANOBJ_EVALUATED) { | ||
1194 | return; | ||
1195 | } | ||
1196 | |||
1197 | acpi_os_printf("ACPI Info for %s: ", pathname); | ||
1198 | |||
1199 | va_start(args, format); | ||
1200 | acpi_os_vprintf(format, args); | ||
1201 | ACPI_COMMON_MSG_SUFFIX; | ||
1202 | va_end(args); | ||
1203 | } | ||
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index f5cca3a1300c..7d797e2baecd 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -83,8 +83,21 @@ acpi_status acpi_ut_mutex_initialize(void) | |||
83 | 83 | ||
84 | /* Create the spinlocks for use at interrupt level */ | 84 | /* Create the spinlocks for use at interrupt level */ |
85 | 85 | ||
86 | spin_lock_init(acpi_gbl_gpe_lock); | 86 | status = acpi_os_create_lock (&acpi_gbl_gpe_lock); |
87 | spin_lock_init(acpi_gbl_hardware_lock); | 87 | if (ACPI_FAILURE (status)) { |
88 | return_ACPI_STATUS (status); | ||
89 | } | ||
90 | |||
91 | status = acpi_os_create_lock (&acpi_gbl_hardware_lock); | ||
92 | if (ACPI_FAILURE (status)) { | ||
93 | return_ACPI_STATUS (status); | ||
94 | } | ||
95 | |||
96 | /* Mutex for _OSI support */ | ||
97 | status = acpi_os_create_mutex(&acpi_gbl_osi_mutex); | ||
98 | if (ACPI_FAILURE(status)) { | ||
99 | return_ACPI_STATUS(status); | ||
100 | } | ||
88 | 101 | ||
89 | /* Create the reader/writer lock for namespace access */ | 102 | /* Create the reader/writer lock for namespace access */ |
90 | 103 | ||
@@ -117,6 +130,8 @@ void acpi_ut_mutex_terminate(void) | |||
117 | acpi_ut_delete_mutex(i); | 130 | acpi_ut_delete_mutex(i); |
118 | } | 131 | } |
119 | 132 | ||
133 | acpi_os_delete_mutex(acpi_gbl_osi_mutex); | ||
134 | |||
120 | /* Delete the spinlocks */ | 135 | /* Delete the spinlocks */ |
121 | 136 | ||
122 | acpi_os_delete_lock(acpi_gbl_gpe_lock); | 137 | acpi_os_delete_lock(acpi_gbl_gpe_lock); |
@@ -220,18 +235,17 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) | |||
220 | if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { | 235 | if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { |
221 | if (i == mutex_id) { | 236 | if (i == mutex_id) { |
222 | ACPI_ERROR((AE_INFO, | 237 | ACPI_ERROR((AE_INFO, |
223 | "Mutex [%s] already acquired by this thread [%p]", | 238 | "Mutex [%s] already acquired by this thread [%u]", |
224 | acpi_ut_get_mutex_name | 239 | acpi_ut_get_mutex_name |
225 | (mutex_id), | 240 | (mutex_id), |
226 | ACPI_CAST_PTR(void, | 241 | (u32)this_thread_id)); |
227 | this_thread_id))); | ||
228 | 242 | ||
229 | return (AE_ALREADY_ACQUIRED); | 243 | return (AE_ALREADY_ACQUIRED); |
230 | } | 244 | } |
231 | 245 | ||
232 | ACPI_ERROR((AE_INFO, | 246 | ACPI_ERROR((AE_INFO, |
233 | "Invalid acquire order: Thread %p owns [%s], wants [%s]", | 247 | "Invalid acquire order: Thread %u owns [%s], wants [%s]", |
234 | ACPI_CAST_PTR(void, this_thread_id), | 248 | (u32)this_thread_id, |
235 | acpi_ut_get_mutex_name(i), | 249 | acpi_ut_get_mutex_name(i), |
236 | acpi_ut_get_mutex_name(mutex_id))); | 250 | acpi_ut_get_mutex_name(mutex_id))); |
237 | 251 | ||
@@ -242,24 +256,24 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) | |||
242 | #endif | 256 | #endif |
243 | 257 | ||
244 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, | 258 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, |
245 | "Thread %p attempting to acquire Mutex [%s]\n", | 259 | "Thread %u attempting to acquire Mutex [%s]\n", |
246 | ACPI_CAST_PTR(void, this_thread_id), | 260 | (u32)this_thread_id, |
247 | acpi_ut_get_mutex_name(mutex_id))); | 261 | acpi_ut_get_mutex_name(mutex_id))); |
248 | 262 | ||
249 | status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, | 263 | status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, |
250 | ACPI_WAIT_FOREVER); | 264 | ACPI_WAIT_FOREVER); |
251 | if (ACPI_SUCCESS(status)) { | 265 | if (ACPI_SUCCESS(status)) { |
252 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, | 266 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, |
253 | "Thread %p acquired Mutex [%s]\n", | 267 | "Thread %u acquired Mutex [%s]\n", |
254 | ACPI_CAST_PTR(void, this_thread_id), | 268 | (u32)this_thread_id, |
255 | acpi_ut_get_mutex_name(mutex_id))); | 269 | acpi_ut_get_mutex_name(mutex_id))); |
256 | 270 | ||
257 | acpi_gbl_mutex_info[mutex_id].use_count++; | 271 | acpi_gbl_mutex_info[mutex_id].use_count++; |
258 | acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; | 272 | acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; |
259 | } else { | 273 | } else { |
260 | ACPI_EXCEPTION((AE_INFO, status, | 274 | ACPI_EXCEPTION((AE_INFO, status, |
261 | "Thread %p could not acquire Mutex [0x%X]", | 275 | "Thread %u could not acquire Mutex [0x%X]", |
262 | ACPI_CAST_PTR(void, this_thread_id), mutex_id)); | 276 | (u32)this_thread_id, mutex_id)); |
263 | } | 277 | } |
264 | 278 | ||
265 | return (status); | 279 | return (status); |
@@ -279,10 +293,14 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) | |||
279 | 293 | ||
280 | acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) | 294 | acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) |
281 | { | 295 | { |
296 | acpi_thread_id this_thread_id; | ||
297 | |||
282 | ACPI_FUNCTION_NAME(ut_release_mutex); | 298 | ACPI_FUNCTION_NAME(ut_release_mutex); |
283 | 299 | ||
284 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n", | 300 | this_thread_id = acpi_os_get_thread_id(); |
285 | ACPI_CAST_PTR(void, acpi_os_get_thread_id()), | 301 | |
302 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", | ||
303 | (u32)this_thread_id, | ||
286 | acpi_ut_get_mutex_name(mutex_id))); | 304 | acpi_ut_get_mutex_name(mutex_id))); |
287 | 305 | ||
288 | if (mutex_id > ACPI_MAX_MUTEX) { | 306 | if (mutex_id > ACPI_MAX_MUTEX) { |
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index fd1fa2749ea5..188340a017b4 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c new file mode 100644 index 000000000000..1fb10cb8f11d --- /dev/null +++ b/drivers/acpi/acpica/utosi.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: utosi - Support for the _OSI predefined control method | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | |||
47 | #define _COMPONENT ACPI_UTILITIES | ||
48 | ACPI_MODULE_NAME("utosi") | ||
49 | |||
50 | /* | ||
51 | * Strings supported by the _OSI predefined control method (which is | ||
52 | * implemented internally within this module.) | ||
53 | * | ||
54 | * March 2009: Removed "Linux" as this host no longer wants to respond true | ||
55 | * for this string. Basically, the only safe OS strings are windows-related | ||
56 | * and in many or most cases represent the only test path within the | ||
57 | * BIOS-provided ASL code. | ||
58 | * | ||
59 | * The last element of each entry is used to track the newest version of | ||
60 | * Windows that the BIOS has requested. | ||
61 | */ | ||
62 | static struct acpi_interface_info acpi_default_supported_interfaces[] = { | ||
63 | /* Operating System Vendor Strings */ | ||
64 | |||
65 | {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */ | ||
66 | {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */ | ||
67 | {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ | ||
68 | {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ | ||
69 | {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ | ||
70 | {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ | ||
71 | {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ | ||
72 | {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ | ||
73 | {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ | ||
74 | {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ | ||
75 | {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ | ||
76 | |||
77 | /* Feature Group Strings */ | ||
78 | |||
79 | {"Extended Address Space Descriptor", NULL, 0, 0} | ||
80 | |||
81 | /* | ||
82 | * All "optional" feature group strings (features that are implemented | ||
83 | * by the host) should be dynamically added by the host via | ||
84 | * acpi_install_interface and should not be manually added here. | ||
85 | * | ||
86 | * Examples of optional feature group strings: | ||
87 | * | ||
88 | * "Module Device" | ||
89 | * "Processor Device" | ||
90 | * "3.0 Thermal Model" | ||
91 | * "3.0 _SCP Extensions" | ||
92 | * "Processor Aggregator Device" | ||
93 | */ | ||
94 | }; | ||
95 | |||
96 | /******************************************************************************* | ||
97 | * | ||
98 | * FUNCTION: acpi_ut_initialize_interfaces | ||
99 | * | ||
100 | * PARAMETERS: None | ||
101 | * | ||
102 | * RETURN: Status | ||
103 | * | ||
104 | * DESCRIPTION: Initialize the global _OSI supported interfaces list | ||
105 | * | ||
106 | ******************************************************************************/ | ||
107 | |||
108 | acpi_status acpi_ut_initialize_interfaces(void) | ||
109 | { | ||
110 | u32 i; | ||
111 | |||
112 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); | ||
113 | acpi_gbl_supported_interfaces = acpi_default_supported_interfaces; | ||
114 | |||
115 | /* Link the static list of supported interfaces */ | ||
116 | |||
117 | for (i = 0; | ||
118 | i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1); | ||
119 | i++) { | ||
120 | acpi_default_supported_interfaces[i].next = | ||
121 | &acpi_default_supported_interfaces[(acpi_size) i + 1]; | ||
122 | } | ||
123 | |||
124 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | ||
125 | return (AE_OK); | ||
126 | } | ||
127 | |||
128 | /******************************************************************************* | ||
129 | * | ||
130 | * FUNCTION: acpi_ut_interface_terminate | ||
131 | * | ||
132 | * PARAMETERS: None | ||
133 | * | ||
134 | * RETURN: None | ||
135 | * | ||
136 | * DESCRIPTION: Delete all interfaces in the global list. Sets | ||
137 | * acpi_gbl_supported_interfaces to NULL. | ||
138 | * | ||
139 | ******************************************************************************/ | ||
140 | |||
141 | void acpi_ut_interface_terminate(void) | ||
142 | { | ||
143 | struct acpi_interface_info *next_interface; | ||
144 | |||
145 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); | ||
146 | next_interface = acpi_gbl_supported_interfaces; | ||
147 | |||
148 | while (next_interface) { | ||
149 | acpi_gbl_supported_interfaces = next_interface->next; | ||
150 | |||
151 | /* Only interfaces added at runtime can be freed */ | ||
152 | |||
153 | if (next_interface->flags & ACPI_OSI_DYNAMIC) { | ||
154 | ACPI_FREE(next_interface->name); | ||
155 | ACPI_FREE(next_interface); | ||
156 | } | ||
157 | |||
158 | next_interface = acpi_gbl_supported_interfaces; | ||
159 | } | ||
160 | |||
161 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | ||
162 | } | ||
163 | |||
164 | /******************************************************************************* | ||
165 | * | ||
166 | * FUNCTION: acpi_ut_install_interface | ||
167 | * | ||
168 | * PARAMETERS: interface_name - The interface to install | ||
169 | * | ||
170 | * RETURN: Status | ||
171 | * | ||
172 | * DESCRIPTION: Install the interface into the global interface list. | ||
173 | * Caller MUST hold acpi_gbl_osi_mutex | ||
174 | * | ||
175 | ******************************************************************************/ | ||
176 | |||
177 | acpi_status acpi_ut_install_interface(acpi_string interface_name) | ||
178 | { | ||
179 | struct acpi_interface_info *interface_info; | ||
180 | |||
181 | /* Allocate info block and space for the name string */ | ||
182 | |||
183 | interface_info = | ||
184 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info)); | ||
185 | if (!interface_info) { | ||
186 | return (AE_NO_MEMORY); | ||
187 | } | ||
188 | |||
189 | interface_info->name = | ||
190 | ACPI_ALLOCATE_ZEROED(ACPI_STRLEN(interface_name) + 1); | ||
191 | if (!interface_info->name) { | ||
192 | ACPI_FREE(interface_info); | ||
193 | return (AE_NO_MEMORY); | ||
194 | } | ||
195 | |||
196 | /* Initialize new info and insert at the head of the global list */ | ||
197 | |||
198 | ACPI_STRCPY(interface_info->name, interface_name); | ||
199 | interface_info->flags = ACPI_OSI_DYNAMIC; | ||
200 | interface_info->next = acpi_gbl_supported_interfaces; | ||
201 | |||
202 | acpi_gbl_supported_interfaces = interface_info; | ||
203 | return (AE_OK); | ||
204 | } | ||
205 | |||
206 | /******************************************************************************* | ||
207 | * | ||
208 | * FUNCTION: acpi_ut_remove_interface | ||
209 | * | ||
210 | * PARAMETERS: interface_name - The interface to remove | ||
211 | * | ||
212 | * RETURN: Status | ||
213 | * | ||
214 | * DESCRIPTION: Remove the interface from the global interface list. | ||
215 | * Caller MUST hold acpi_gbl_osi_mutex | ||
216 | * | ||
217 | ******************************************************************************/ | ||
218 | |||
219 | acpi_status acpi_ut_remove_interface(acpi_string interface_name) | ||
220 | { | ||
221 | struct acpi_interface_info *previous_interface; | ||
222 | struct acpi_interface_info *next_interface; | ||
223 | |||
224 | previous_interface = next_interface = acpi_gbl_supported_interfaces; | ||
225 | while (next_interface) { | ||
226 | if (!ACPI_STRCMP(interface_name, next_interface->name)) { | ||
227 | |||
228 | /* Found: name is in either the static list or was added at runtime */ | ||
229 | |||
230 | if (next_interface->flags & ACPI_OSI_DYNAMIC) { | ||
231 | |||
232 | /* Interface was added dynamically, remove and free it */ | ||
233 | |||
234 | if (previous_interface == next_interface) { | ||
235 | acpi_gbl_supported_interfaces = | ||
236 | next_interface->next; | ||
237 | } else { | ||
238 | previous_interface->next = | ||
239 | next_interface->next; | ||
240 | } | ||
241 | |||
242 | ACPI_FREE(next_interface->name); | ||
243 | ACPI_FREE(next_interface); | ||
244 | } else { | ||
245 | /* | ||
246 | * Interface is in static list. If marked invalid, then it | ||
247 | * does not actually exist. Else, mark it invalid. | ||
248 | */ | ||
249 | if (next_interface->flags & ACPI_OSI_INVALID) { | ||
250 | return (AE_NOT_EXIST); | ||
251 | } | ||
252 | |||
253 | next_interface->flags |= ACPI_OSI_INVALID; | ||
254 | } | ||
255 | |||
256 | return (AE_OK); | ||
257 | } | ||
258 | |||
259 | previous_interface = next_interface; | ||
260 | next_interface = next_interface->next; | ||
261 | } | ||
262 | |||
263 | /* Interface was not found */ | ||
264 | |||
265 | return (AE_NOT_EXIST); | ||
266 | } | ||
267 | |||
268 | /******************************************************************************* | ||
269 | * | ||
270 | * FUNCTION: acpi_ut_get_interface | ||
271 | * | ||
272 | * PARAMETERS: interface_name - The interface to find | ||
273 | * | ||
274 | * RETURN: struct acpi_interface_info if found. NULL if not found. | ||
275 | * | ||
276 | * DESCRIPTION: Search for the specified interface name in the global list. | ||
277 | * Caller MUST hold acpi_gbl_osi_mutex | ||
278 | * | ||
279 | ******************************************************************************/ | ||
280 | |||
281 | struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name) | ||
282 | { | ||
283 | struct acpi_interface_info *next_interface; | ||
284 | |||
285 | next_interface = acpi_gbl_supported_interfaces; | ||
286 | while (next_interface) { | ||
287 | if (!ACPI_STRCMP(interface_name, next_interface->name)) { | ||
288 | return (next_interface); | ||
289 | } | ||
290 | |||
291 | next_interface = next_interface->next; | ||
292 | } | ||
293 | |||
294 | return (NULL); | ||
295 | } | ||
296 | |||
297 | /******************************************************************************* | ||
298 | * | ||
299 | * FUNCTION: acpi_ut_osi_implementation | ||
300 | * | ||
301 | * PARAMETERS: walk_state - Current walk state | ||
302 | * | ||
303 | * RETURN: Status | ||
304 | * | ||
305 | * DESCRIPTION: Implementation of the _OSI predefined control method. When | ||
306 | * an invocation of _OSI is encountered in the system AML, | ||
307 | * control is transferred to this function. | ||
308 | * | ||
309 | ******************************************************************************/ | ||
310 | |||
311 | acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state) | ||
312 | { | ||
313 | union acpi_operand_object *string_desc; | ||
314 | union acpi_operand_object *return_desc; | ||
315 | struct acpi_interface_info *interface_info; | ||
316 | acpi_interface_handler interface_handler; | ||
317 | u32 return_value; | ||
318 | |||
319 | ACPI_FUNCTION_TRACE(ut_osi_implementation); | ||
320 | |||
321 | /* Validate the string input argument (from the AML caller) */ | ||
322 | |||
323 | string_desc = walk_state->arguments[0].object; | ||
324 | if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) { | ||
325 | return_ACPI_STATUS(AE_TYPE); | ||
326 | } | ||
327 | |||
328 | /* Create a return object */ | ||
329 | |||
330 | return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); | ||
331 | if (!return_desc) { | ||
332 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
333 | } | ||
334 | |||
335 | /* Default return value is 0, NOT SUPPORTED */ | ||
336 | |||
337 | return_value = 0; | ||
338 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); | ||
339 | |||
340 | /* Lookup the interface in the global _OSI list */ | ||
341 | |||
342 | interface_info = acpi_ut_get_interface(string_desc->string.pointer); | ||
343 | if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) { | ||
344 | /* | ||
345 | * The interface is supported. | ||
346 | * Update the osi_data if necessary. We keep track of the latest | ||
347 | * version of Windows that has been requested by the BIOS. | ||
348 | */ | ||
349 | if (interface_info->value > acpi_gbl_osi_data) { | ||
350 | acpi_gbl_osi_data = interface_info->value; | ||
351 | } | ||
352 | |||
353 | return_value = ACPI_UINT32_MAX; | ||
354 | } | ||
355 | |||
356 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | ||
357 | |||
358 | /* | ||
359 | * Invoke an optional _OSI interface handler. The host OS may wish | ||
360 | * to do some interface-specific handling. For example, warn about | ||
361 | * certain interfaces or override the true/false support value. | ||
362 | */ | ||
363 | interface_handler = acpi_gbl_interface_handler; | ||
364 | if (interface_handler) { | ||
365 | return_value = | ||
366 | interface_handler(string_desc->string.pointer, | ||
367 | return_value); | ||
368 | } | ||
369 | |||
370 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, | ||
371 | "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", | ||
372 | string_desc->string.pointer, | ||
373 | return_value == 0 ? "not " : "")); | ||
374 | |||
375 | /* Complete the return object */ | ||
376 | |||
377 | return_desc->integer.value = return_value; | ||
378 | walk_state->return_desc = return_desc; | ||
379 | return_ACPI_STATUS(AE_OK); | ||
380 | } | ||
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index 7965919000b1..6ffd3a8bdaa5 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -50,7 +50,7 @@ ACPI_MODULE_NAME("utresrc") | |||
50 | #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) | 50 | #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) |
51 | /* | 51 | /* |
52 | * Strings used to decode resource descriptors. | 52 | * Strings used to decode resource descriptors. |
53 | * Used by both the disasssembler and the debugger resource dump routines | 53 | * Used by both the disassembler and the debugger resource dump routines |
54 | */ | 54 | */ |
55 | const char *acpi_gbl_bm_decode[] = { | 55 | const char *acpi_gbl_bm_decode[] = { |
56 | "NotBusMaster", | 56 | "NotBusMaster", |
diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index d35d109b8da2..30c21e1a9360 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 7f8cefcb2b32..98ad125e14ff 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -110,6 +110,15 @@ acpi_status __init acpi_initialize_subsystem(void) | |||
110 | return_ACPI_STATUS(status); | 110 | return_ACPI_STATUS(status); |
111 | } | 111 | } |
112 | 112 | ||
113 | /* Initialize the global OSI interfaces list with the static names */ | ||
114 | |||
115 | status = acpi_ut_initialize_interfaces(); | ||
116 | if (ACPI_FAILURE(status)) { | ||
117 | ACPI_EXCEPTION((AE_INFO, status, | ||
118 | "During OSI interfaces initialization")); | ||
119 | return_ACPI_STATUS(status); | ||
120 | } | ||
121 | |||
113 | /* If configured, initialize the AML debugger */ | 122 | /* If configured, initialize the AML debugger */ |
114 | 123 | ||
115 | ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); | 124 | ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); |
@@ -290,19 +299,6 @@ acpi_status acpi_initialize_objects(u32 flags) | |||
290 | } | 299 | } |
291 | 300 | ||
292 | /* | 301 | /* |
293 | * Complete the GPE initialization for the GPE blocks defined in the FADT | ||
294 | * (GPE block 0 and 1). | ||
295 | * | ||
296 | * NOTE: Currently, there seems to be no need to run the _REG methods | ||
297 | * before enabling the GPEs. | ||
298 | */ | ||
299 | if (!(flags & ACPI_NO_EVENT_INIT)) { | ||
300 | status = acpi_ev_install_fadt_gpes(); | ||
301 | if (ACPI_FAILURE(status)) | ||
302 | return (status); | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * Empty the caches (delete the cached objects) on the assumption that | 302 | * Empty the caches (delete the cached objects) on the assumption that |
307 | * the table load filled them up more than they will be at runtime -- | 303 | * the table load filled them up more than they will be at runtime -- |
308 | * thus wasting non-paged memory. | 304 | * thus wasting non-paged memory. |
@@ -506,6 +502,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) | |||
506 | 502 | ||
507 | ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) | 503 | ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) |
508 | #endif /* ACPI_FUTURE_USAGE */ | 504 | #endif /* ACPI_FUTURE_USAGE */ |
505 | |||
509 | /***************************************************************************** | 506 | /***************************************************************************** |
510 | * | 507 | * |
511 | * FUNCTION: acpi_purge_cached_objects | 508 | * FUNCTION: acpi_purge_cached_objects |
@@ -529,4 +526,117 @@ acpi_status acpi_purge_cached_objects(void) | |||
529 | } | 526 | } |
530 | 527 | ||
531 | ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) | 528 | ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) |
532 | #endif | 529 | |
530 | /***************************************************************************** | ||
531 | * | ||
532 | * FUNCTION: acpi_install_interface | ||
533 | * | ||
534 | * PARAMETERS: interface_name - The interface to install | ||
535 | * | ||
536 | * RETURN: Status | ||
537 | * | ||
538 | * DESCRIPTION: Install an _OSI interface to the global list | ||
539 | * | ||
540 | ****************************************************************************/ | ||
541 | acpi_status acpi_install_interface(acpi_string interface_name) | ||
542 | { | ||
543 | acpi_status status; | ||
544 | struct acpi_interface_info *interface_info; | ||
545 | |||
546 | /* Parameter validation */ | ||
547 | |||
548 | if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) { | ||
549 | return (AE_BAD_PARAMETER); | ||
550 | } | ||
551 | |||
552 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); | ||
553 | |||
554 | /* Check if the interface name is already in the global list */ | ||
555 | |||
556 | interface_info = acpi_ut_get_interface(interface_name); | ||
557 | if (interface_info) { | ||
558 | /* | ||
559 | * The interface already exists in the list. This is OK if the | ||
560 | * interface has been marked invalid -- just clear the bit. | ||
561 | */ | ||
562 | if (interface_info->flags & ACPI_OSI_INVALID) { | ||
563 | interface_info->flags &= ~ACPI_OSI_INVALID; | ||
564 | status = AE_OK; | ||
565 | } else { | ||
566 | status = AE_ALREADY_EXISTS; | ||
567 | } | ||
568 | } else { | ||
569 | /* New interface name, install into the global list */ | ||
570 | |||
571 | status = acpi_ut_install_interface(interface_name); | ||
572 | } | ||
573 | |||
574 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | ||
575 | return (status); | ||
576 | } | ||
577 | |||
578 | ACPI_EXPORT_SYMBOL(acpi_install_interface) | ||
579 | |||
580 | /***************************************************************************** | ||
581 | * | ||
582 | * FUNCTION: acpi_remove_interface | ||
583 | * | ||
584 | * PARAMETERS: interface_name - The interface to remove | ||
585 | * | ||
586 | * RETURN: Status | ||
587 | * | ||
588 | * DESCRIPTION: Remove an _OSI interface from the global list | ||
589 | * | ||
590 | ****************************************************************************/ | ||
591 | acpi_status acpi_remove_interface(acpi_string interface_name) | ||
592 | { | ||
593 | acpi_status status; | ||
594 | |||
595 | /* Parameter validation */ | ||
596 | |||
597 | if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) { | ||
598 | return (AE_BAD_PARAMETER); | ||
599 | } | ||
600 | |||
601 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); | ||
602 | |||
603 | status = acpi_ut_remove_interface(interface_name); | ||
604 | |||
605 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | ||
606 | return (status); | ||
607 | } | ||
608 | |||
609 | ACPI_EXPORT_SYMBOL(acpi_remove_interface) | ||
610 | |||
611 | /***************************************************************************** | ||
612 | * | ||
613 | * FUNCTION: acpi_install_interface_handler | ||
614 | * | ||
615 | * PARAMETERS: Handler - The _OSI interface handler to install | ||
616 | * NULL means "remove existing handler" | ||
617 | * | ||
618 | * RETURN: Status | ||
619 | * | ||
620 | * DESCRIPTION: Install a handler for the predefined _OSI ACPI method. | ||
621 | * invoked during execution of the internal implementation of | ||
622 | * _OSI. A NULL handler simply removes any existing handler. | ||
623 | * | ||
624 | ****************************************************************************/ | ||
625 | acpi_status acpi_install_interface_handler(acpi_interface_handler handler) | ||
626 | { | ||
627 | acpi_status status = AE_OK; | ||
628 | |||
629 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); | ||
630 | |||
631 | if (handler && acpi_gbl_interface_handler) { | ||
632 | status = AE_ALREADY_EXISTS; | ||
633 | } else { | ||
634 | acpi_gbl_interface_handler = handler; | ||
635 | } | ||
636 | |||
637 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | ||
638 | return (status); | ||
639 | } | ||
640 | |||
641 | ACPI_EXPORT_SYMBOL(acpi_install_interface_handler) | ||
642 | #endif /* !ACPI_ASL_COMPILER */ | ||
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c new file mode 100644 index 000000000000..916ae097c43c --- /dev/null +++ b/drivers/acpi/acpica/utxferror.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: utxferror - Various error/warning output functions | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acnamesp.h" | ||
47 | |||
48 | #define _COMPONENT ACPI_UTILITIES | ||
49 | ACPI_MODULE_NAME("utxferror") | ||
50 | |||
51 | /* | ||
52 | * This module is used for the in-kernel ACPICA as well as the ACPICA | ||
53 | * tools/applications. | ||
54 | * | ||
55 | * For the i_aSL compiler case, the output is redirected to stderr so that | ||
56 | * any of the various ACPI errors and warnings do not appear in the output | ||
57 | * files, for either the compiler or disassembler portions of the tool. | ||
58 | */ | ||
59 | #ifdef ACPI_ASL_COMPILER | ||
60 | #include <stdio.h> | ||
61 | extern FILE *acpi_gbl_output_file; | ||
62 | |||
63 | #define ACPI_MSG_REDIRECT_BEGIN \ | ||
64 | FILE *output_file = acpi_gbl_output_file; \ | ||
65 | acpi_os_redirect_output (stderr); | ||
66 | |||
67 | #define ACPI_MSG_REDIRECT_END \ | ||
68 | acpi_os_redirect_output (output_file); | ||
69 | |||
70 | #else | ||
71 | /* | ||
72 | * non-i_aSL case - no redirection, nothing to do | ||
73 | */ | ||
74 | #define ACPI_MSG_REDIRECT_BEGIN | ||
75 | #define ACPI_MSG_REDIRECT_END | ||
76 | #endif | ||
77 | /* | ||
78 | * Common message prefixes | ||
79 | */ | ||
80 | #define ACPI_MSG_ERROR "ACPI Error: " | ||
81 | #define ACPI_MSG_EXCEPTION "ACPI Exception: " | ||
82 | #define ACPI_MSG_WARNING "ACPI Warning: " | ||
83 | #define ACPI_MSG_INFO "ACPI: " | ||
84 | /* | ||
85 | * Common message suffix | ||
86 | */ | ||
87 | #define ACPI_MSG_SUFFIX \ | ||
88 | acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) | ||
89 | /******************************************************************************* | ||
90 | * | ||
91 | * FUNCTION: acpi_error | ||
92 | * | ||
93 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
94 | * line_number - Caller's line number (for error output) | ||
95 | * Format - Printf format string + additional args | ||
96 | * | ||
97 | * RETURN: None | ||
98 | * | ||
99 | * DESCRIPTION: Print "ACPI Error" message with module/line/version info | ||
100 | * | ||
101 | ******************************************************************************/ | ||
102 | void ACPI_INTERNAL_VAR_XFACE | ||
103 | acpi_error(const char *module_name, u32 line_number, const char *format, ...) | ||
104 | { | ||
105 | va_list arg_list; | ||
106 | |||
107 | ACPI_MSG_REDIRECT_BEGIN; | ||
108 | acpi_os_printf(ACPI_MSG_ERROR); | ||
109 | |||
110 | va_start(arg_list, format); | ||
111 | acpi_os_vprintf(format, arg_list); | ||
112 | ACPI_MSG_SUFFIX; | ||
113 | va_end(arg_list); | ||
114 | |||
115 | ACPI_MSG_REDIRECT_END; | ||
116 | } | ||
117 | |||
118 | ACPI_EXPORT_SYMBOL(acpi_error) | ||
119 | |||
120 | /******************************************************************************* | ||
121 | * | ||
122 | * FUNCTION: acpi_exception | ||
123 | * | ||
124 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
125 | * line_number - Caller's line number (for error output) | ||
126 | * Status - Status to be formatted | ||
127 | * Format - Printf format string + additional args | ||
128 | * | ||
129 | * RETURN: None | ||
130 | * | ||
131 | * DESCRIPTION: Print "ACPI Exception" message with module/line/version info | ||
132 | * and decoded acpi_status. | ||
133 | * | ||
134 | ******************************************************************************/ | ||
135 | void ACPI_INTERNAL_VAR_XFACE | ||
136 | acpi_exception(const char *module_name, | ||
137 | u32 line_number, acpi_status status, const char *format, ...) | ||
138 | { | ||
139 | va_list arg_list; | ||
140 | |||
141 | ACPI_MSG_REDIRECT_BEGIN; | ||
142 | acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ", | ||
143 | acpi_format_exception(status)); | ||
144 | |||
145 | va_start(arg_list, format); | ||
146 | acpi_os_vprintf(format, arg_list); | ||
147 | ACPI_MSG_SUFFIX; | ||
148 | va_end(arg_list); | ||
149 | |||
150 | ACPI_MSG_REDIRECT_END; | ||
151 | } | ||
152 | |||
153 | ACPI_EXPORT_SYMBOL(acpi_exception) | ||
154 | |||
155 | /******************************************************************************* | ||
156 | * | ||
157 | * FUNCTION: acpi_warning | ||
158 | * | ||
159 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
160 | * line_number - Caller's line number (for error output) | ||
161 | * Format - Printf format string + additional args | ||
162 | * | ||
163 | * RETURN: None | ||
164 | * | ||
165 | * DESCRIPTION: Print "ACPI Warning" message with module/line/version info | ||
166 | * | ||
167 | ******************************************************************************/ | ||
168 | void ACPI_INTERNAL_VAR_XFACE | ||
169 | acpi_warning(const char *module_name, u32 line_number, const char *format, ...) | ||
170 | { | ||
171 | va_list arg_list; | ||
172 | |||
173 | ACPI_MSG_REDIRECT_BEGIN; | ||
174 | acpi_os_printf(ACPI_MSG_WARNING); | ||
175 | |||
176 | va_start(arg_list, format); | ||
177 | acpi_os_vprintf(format, arg_list); | ||
178 | ACPI_MSG_SUFFIX; | ||
179 | va_end(arg_list); | ||
180 | |||
181 | ACPI_MSG_REDIRECT_END; | ||
182 | } | ||
183 | |||
184 | ACPI_EXPORT_SYMBOL(acpi_warning) | ||
185 | |||
186 | /******************************************************************************* | ||
187 | * | ||
188 | * FUNCTION: acpi_info | ||
189 | * | ||
190 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
191 | * line_number - Caller's line number (for error output) | ||
192 | * Format - Printf format string + additional args | ||
193 | * | ||
194 | * RETURN: None | ||
195 | * | ||
196 | * DESCRIPTION: Print generic "ACPI:" information message. There is no | ||
197 | * module/line/version info in order to keep the message simple. | ||
198 | * | ||
199 | * TBD: module_name and line_number args are not needed, should be removed. | ||
200 | * | ||
201 | ******************************************************************************/ | ||
202 | void ACPI_INTERNAL_VAR_XFACE | ||
203 | acpi_info(const char *module_name, u32 line_number, const char *format, ...) | ||
204 | { | ||
205 | va_list arg_list; | ||
206 | |||
207 | ACPI_MSG_REDIRECT_BEGIN; | ||
208 | acpi_os_printf(ACPI_MSG_INFO); | ||
209 | |||
210 | va_start(arg_list, format); | ||
211 | acpi_os_vprintf(format, arg_list); | ||
212 | acpi_os_printf("\n"); | ||
213 | va_end(arg_list); | ||
214 | |||
215 | ACPI_MSG_REDIRECT_END; | ||
216 | } | ||
217 | |||
218 | ACPI_EXPORT_SYMBOL(acpi_info) | ||
219 | |||
220 | /* | ||
221 | * The remainder of this module contains internal error functions that may | ||
222 | * be configured out. | ||
223 | */ | ||
224 | #if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP) | ||
225 | /******************************************************************************* | ||
226 | * | ||
227 | * FUNCTION: acpi_ut_predefined_warning | ||
228 | * | ||
229 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
230 | * line_number - Caller's line number (for error output) | ||
231 | * Pathname - Full pathname to the node | ||
232 | * node_flags - From Namespace node for the method/object | ||
233 | * Format - Printf format string + additional args | ||
234 | * | ||
235 | * RETURN: None | ||
236 | * | ||
237 | * DESCRIPTION: Warnings for the predefined validation module. Messages are | ||
238 | * only emitted the first time a problem with a particular | ||
239 | * method/object is detected. This prevents a flood of error | ||
240 | * messages for methods that are repeatedly evaluated. | ||
241 | * | ||
242 | ******************************************************************************/ | ||
243 | void ACPI_INTERNAL_VAR_XFACE | ||
244 | acpi_ut_predefined_warning(const char *module_name, | ||
245 | u32 line_number, | ||
246 | char *pathname, | ||
247 | u8 node_flags, const char *format, ...) | ||
248 | { | ||
249 | va_list arg_list; | ||
250 | |||
251 | /* | ||
252 | * Warning messages for this method/object will be disabled after the | ||
253 | * first time a validation fails or an object is successfully repaired. | ||
254 | */ | ||
255 | if (node_flags & ANOBJ_EVALUATED) { | ||
256 | return; | ||
257 | } | ||
258 | |||
259 | acpi_os_printf(ACPI_MSG_WARNING "For %s: ", pathname); | ||
260 | |||
261 | va_start(arg_list, format); | ||
262 | acpi_os_vprintf(format, arg_list); | ||
263 | ACPI_MSG_SUFFIX; | ||
264 | va_end(arg_list); | ||
265 | } | ||
266 | |||
267 | /******************************************************************************* | ||
268 | * | ||
269 | * FUNCTION: acpi_ut_predefined_info | ||
270 | * | ||
271 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
272 | * line_number - Caller's line number (for error output) | ||
273 | * Pathname - Full pathname to the node | ||
274 | * node_flags - From Namespace node for the method/object | ||
275 | * Format - Printf format string + additional args | ||
276 | * | ||
277 | * RETURN: None | ||
278 | * | ||
279 | * DESCRIPTION: Info messages for the predefined validation module. Messages | ||
280 | * are only emitted the first time a problem with a particular | ||
281 | * method/object is detected. This prevents a flood of | ||
282 | * messages for methods that are repeatedly evaluated. | ||
283 | * | ||
284 | ******************************************************************************/ | ||
285 | |||
286 | void ACPI_INTERNAL_VAR_XFACE | ||
287 | acpi_ut_predefined_info(const char *module_name, | ||
288 | u32 line_number, | ||
289 | char *pathname, u8 node_flags, const char *format, ...) | ||
290 | { | ||
291 | va_list arg_list; | ||
292 | |||
293 | /* | ||
294 | * Warning messages for this method/object will be disabled after the | ||
295 | * first time a validation fails or an object is successfully repaired. | ||
296 | */ | ||
297 | if (node_flags & ANOBJ_EVALUATED) { | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | acpi_os_printf(ACPI_MSG_INFO "For %s: ", pathname); | ||
302 | |||
303 | va_start(arg_list, format); | ||
304 | acpi_os_vprintf(format, arg_list); | ||
305 | ACPI_MSG_SUFFIX; | ||
306 | va_end(arg_list); | ||
307 | } | ||
308 | |||
309 | /******************************************************************************* | ||
310 | * | ||
311 | * FUNCTION: acpi_ut_namespace_error | ||
312 | * | ||
313 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
314 | * line_number - Caller's line number (for error output) | ||
315 | * internal_name - Name or path of the namespace node | ||
316 | * lookup_status - Exception code from NS lookup | ||
317 | * | ||
318 | * RETURN: None | ||
319 | * | ||
320 | * DESCRIPTION: Print error message with the full pathname for the NS node. | ||
321 | * | ||
322 | ******************************************************************************/ | ||
323 | |||
324 | void | ||
325 | acpi_ut_namespace_error(const char *module_name, | ||
326 | u32 line_number, | ||
327 | const char *internal_name, acpi_status lookup_status) | ||
328 | { | ||
329 | acpi_status status; | ||
330 | u32 bad_name; | ||
331 | char *name = NULL; | ||
332 | |||
333 | ACPI_MSG_REDIRECT_BEGIN; | ||
334 | acpi_os_printf(ACPI_MSG_ERROR); | ||
335 | |||
336 | if (lookup_status == AE_BAD_CHARACTER) { | ||
337 | |||
338 | /* There is a non-ascii character in the name */ | ||
339 | |||
340 | ACPI_MOVE_32_TO_32(&bad_name, | ||
341 | ACPI_CAST_PTR(u32, internal_name)); | ||
342 | acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); | ||
343 | } else { | ||
344 | /* Convert path to external format */ | ||
345 | |||
346 | status = acpi_ns_externalize_name(ACPI_UINT32_MAX, | ||
347 | internal_name, NULL, &name); | ||
348 | |||
349 | /* Print target name */ | ||
350 | |||
351 | if (ACPI_SUCCESS(status)) { | ||
352 | acpi_os_printf("[%s]", name); | ||
353 | } else { | ||
354 | acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); | ||
355 | } | ||
356 | |||
357 | if (name) { | ||
358 | ACPI_FREE(name); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | acpi_os_printf(" Namespace lookup failure, %s", | ||
363 | acpi_format_exception(lookup_status)); | ||
364 | |||
365 | ACPI_MSG_SUFFIX; | ||
366 | ACPI_MSG_REDIRECT_END; | ||
367 | } | ||
368 | |||
369 | /******************************************************************************* | ||
370 | * | ||
371 | * FUNCTION: acpi_ut_method_error | ||
372 | * | ||
373 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
374 | * line_number - Caller's line number (for error output) | ||
375 | * Message - Error message to use on failure | ||
376 | * prefix_node - Prefix relative to the path | ||
377 | * Path - Path to the node (optional) | ||
378 | * method_status - Execution status | ||
379 | * | ||
380 | * RETURN: None | ||
381 | * | ||
382 | * DESCRIPTION: Print error message with the full pathname for the method. | ||
383 | * | ||
384 | ******************************************************************************/ | ||
385 | |||
386 | void | ||
387 | acpi_ut_method_error(const char *module_name, | ||
388 | u32 line_number, | ||
389 | const char *message, | ||
390 | struct acpi_namespace_node *prefix_node, | ||
391 | const char *path, acpi_status method_status) | ||
392 | { | ||
393 | acpi_status status; | ||
394 | struct acpi_namespace_node *node = prefix_node; | ||
395 | |||
396 | ACPI_MSG_REDIRECT_BEGIN; | ||
397 | acpi_os_printf(ACPI_MSG_ERROR); | ||
398 | |||
399 | if (path) { | ||
400 | status = | ||
401 | acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, | ||
402 | &node); | ||
403 | if (ACPI_FAILURE(status)) { | ||
404 | acpi_os_printf("[Could not get node by pathname]"); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | acpi_ns_print_node_pathname(node, message); | ||
409 | acpi_os_printf(", %s", acpi_format_exception(method_status)); | ||
410 | |||
411 | ACPI_MSG_SUFFIX; | ||
412 | ACPI_MSG_REDIRECT_END; | ||
413 | } | ||
414 | |||
415 | #endif /* ACPI_NO_ERROR_MESSAGES */ | ||
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index fca34ccfd294..f739a70b1c70 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig | |||
@@ -1,5 +1,7 @@ | |||
1 | config ACPI_APEI | 1 | config ACPI_APEI |
2 | bool "ACPI Platform Error Interface (APEI)" | 2 | bool "ACPI Platform Error Interface (APEI)" |
3 | select MISC_FILESYSTEMS | ||
4 | select PSTORE | ||
3 | depends on X86 | 5 | depends on X86 |
4 | help | 6 | help |
5 | APEI allows to report errors (for example from the chipset) | 7 | APEI allows to report errors (for example from the chipset) |
@@ -21,6 +23,13 @@ config ACPI_APEI_GHES | |||
21 | by firmware to produce more valuable hardware error | 23 | by firmware to produce more valuable hardware error |
22 | information for Linux. | 24 | information for Linux. |
23 | 25 | ||
26 | config ACPI_APEI_PCIEAER | ||
27 | bool "APEI PCIe AER logging/recovering support" | ||
28 | depends on ACPI_APEI && PCIEAER | ||
29 | help | ||
30 | PCIe AER errors may be reported via APEI firmware first mode. | ||
31 | Turn on this option to enable the corresponding support. | ||
32 | |||
24 | config ACPI_APEI_EINJ | 33 | config ACPI_APEI_EINJ |
25 | tristate "APEI Error INJection (EINJ)" | 34 | tristate "APEI Error INJection (EINJ)" |
26 | depends on ACPI_APEI && DEBUG_FS | 35 | depends on ACPI_APEI && DEBUG_FS |
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index 18df1e940276..ef0581f2094d 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h | |||
@@ -109,6 +109,8 @@ static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus) | |||
109 | return sizeof(*estatus) + estatus->data_length; | 109 | return sizeof(*estatus) + estatus->data_length; |
110 | } | 110 | } |
111 | 111 | ||
112 | void apei_estatus_print(const char *pfx, | ||
113 | const struct acpi_hest_generic_status *estatus); | ||
112 | int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus); | 114 | int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus); |
113 | int apei_estatus_check(const struct acpi_hest_generic_status *estatus); | 115 | int apei_estatus_check(const struct acpi_hest_generic_status *estatus); |
114 | #endif | 116 | #endif |
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index f4cf2fc4c8c1..5d4189464d63 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/time.h> | 29 | #include <linux/time.h> |
30 | #include <linux/cper.h> | 30 | #include <linux/cper.h> |
31 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
32 | #include <linux/aer.h> | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * CPER record ID need to be unique even after reboot, because record | 35 | * CPER record ID need to be unique even after reboot, because record |
@@ -46,6 +47,326 @@ u64 cper_next_record_id(void) | |||
46 | } | 47 | } |
47 | EXPORT_SYMBOL_GPL(cper_next_record_id); | 48 | EXPORT_SYMBOL_GPL(cper_next_record_id); |
48 | 49 | ||
50 | static const char *cper_severity_strs[] = { | ||
51 | "recoverable", | ||
52 | "fatal", | ||
53 | "corrected", | ||
54 | "info", | ||
55 | }; | ||
56 | |||
57 | static const char *cper_severity_str(unsigned int severity) | ||
58 | { | ||
59 | return severity < ARRAY_SIZE(cper_severity_strs) ? | ||
60 | cper_severity_strs[severity] : "unknown"; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * cper_print_bits - print strings for set bits | ||
65 | * @pfx: prefix for each line, including log level and prefix string | ||
66 | * @bits: bit mask | ||
67 | * @strs: string array, indexed by bit position | ||
68 | * @strs_size: size of the string array: @strs | ||
69 | * | ||
70 | * For each set bit in @bits, print the corresponding string in @strs. | ||
71 | * If the output length is longer than 80, multiple line will be | ||
72 | * printed, with @pfx is printed at the beginning of each line. | ||
73 | */ | ||
74 | void cper_print_bits(const char *pfx, unsigned int bits, | ||
75 | const char *strs[], unsigned int strs_size) | ||
76 | { | ||
77 | int i, len = 0; | ||
78 | const char *str; | ||
79 | char buf[84]; | ||
80 | |||
81 | for (i = 0; i < strs_size; i++) { | ||
82 | if (!(bits & (1U << i))) | ||
83 | continue; | ||
84 | str = strs[i]; | ||
85 | if (!str) | ||
86 | continue; | ||
87 | if (len && len + strlen(str) + 2 > 80) { | ||
88 | printk("%s\n", buf); | ||
89 | len = 0; | ||
90 | } | ||
91 | if (!len) | ||
92 | len = snprintf(buf, sizeof(buf), "%s%s", pfx, str); | ||
93 | else | ||
94 | len += snprintf(buf+len, sizeof(buf)-len, ", %s", str); | ||
95 | } | ||
96 | if (len) | ||
97 | printk("%s\n", buf); | ||
98 | } | ||
99 | |||
100 | static const char *cper_proc_type_strs[] = { | ||
101 | "IA32/X64", | ||
102 | "IA64", | ||
103 | }; | ||
104 | |||
105 | static const char *cper_proc_isa_strs[] = { | ||
106 | "IA32", | ||
107 | "IA64", | ||
108 | "X64", | ||
109 | }; | ||
110 | |||
111 | static const char *cper_proc_error_type_strs[] = { | ||
112 | "cache error", | ||
113 | "TLB error", | ||
114 | "bus error", | ||
115 | "micro-architectural error", | ||
116 | }; | ||
117 | |||
118 | static const char *cper_proc_op_strs[] = { | ||
119 | "unknown or generic", | ||
120 | "data read", | ||
121 | "data write", | ||
122 | "instruction execution", | ||
123 | }; | ||
124 | |||
125 | static const char *cper_proc_flag_strs[] = { | ||
126 | "restartable", | ||
127 | "precise IP", | ||
128 | "overflow", | ||
129 | "corrected", | ||
130 | }; | ||
131 | |||
132 | static void cper_print_proc_generic(const char *pfx, | ||
133 | const struct cper_sec_proc_generic *proc) | ||
134 | { | ||
135 | if (proc->validation_bits & CPER_PROC_VALID_TYPE) | ||
136 | printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type, | ||
137 | proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ? | ||
138 | cper_proc_type_strs[proc->proc_type] : "unknown"); | ||
139 | if (proc->validation_bits & CPER_PROC_VALID_ISA) | ||
140 | printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa, | ||
141 | proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ? | ||
142 | cper_proc_isa_strs[proc->proc_isa] : "unknown"); | ||
143 | if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) { | ||
144 | printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type); | ||
145 | cper_print_bits(pfx, proc->proc_error_type, | ||
146 | cper_proc_error_type_strs, | ||
147 | ARRAY_SIZE(cper_proc_error_type_strs)); | ||
148 | } | ||
149 | if (proc->validation_bits & CPER_PROC_VALID_OPERATION) | ||
150 | printk("%s""operation: %d, %s\n", pfx, proc->operation, | ||
151 | proc->operation < ARRAY_SIZE(cper_proc_op_strs) ? | ||
152 | cper_proc_op_strs[proc->operation] : "unknown"); | ||
153 | if (proc->validation_bits & CPER_PROC_VALID_FLAGS) { | ||
154 | printk("%s""flags: 0x%02x\n", pfx, proc->flags); | ||
155 | cper_print_bits(pfx, proc->flags, cper_proc_flag_strs, | ||
156 | ARRAY_SIZE(cper_proc_flag_strs)); | ||
157 | } | ||
158 | if (proc->validation_bits & CPER_PROC_VALID_LEVEL) | ||
159 | printk("%s""level: %d\n", pfx, proc->level); | ||
160 | if (proc->validation_bits & CPER_PROC_VALID_VERSION) | ||
161 | printk("%s""version_info: 0x%016llx\n", pfx, proc->cpu_version); | ||
162 | if (proc->validation_bits & CPER_PROC_VALID_ID) | ||
163 | printk("%s""processor_id: 0x%016llx\n", pfx, proc->proc_id); | ||
164 | if (proc->validation_bits & CPER_PROC_VALID_TARGET_ADDRESS) | ||
165 | printk("%s""target_address: 0x%016llx\n", | ||
166 | pfx, proc->target_addr); | ||
167 | if (proc->validation_bits & CPER_PROC_VALID_REQUESTOR_ID) | ||
168 | printk("%s""requestor_id: 0x%016llx\n", | ||
169 | pfx, proc->requestor_id); | ||
170 | if (proc->validation_bits & CPER_PROC_VALID_RESPONDER_ID) | ||
171 | printk("%s""responder_id: 0x%016llx\n", | ||
172 | pfx, proc->responder_id); | ||
173 | if (proc->validation_bits & CPER_PROC_VALID_IP) | ||
174 | printk("%s""IP: 0x%016llx\n", pfx, proc->ip); | ||
175 | } | ||
176 | |||
177 | static const char *cper_mem_err_type_strs[] = { | ||
178 | "unknown", | ||
179 | "no error", | ||
180 | "single-bit ECC", | ||
181 | "multi-bit ECC", | ||
182 | "single-symbol chipkill ECC", | ||
183 | "multi-symbol chipkill ECC", | ||
184 | "master abort", | ||
185 | "target abort", | ||
186 | "parity error", | ||
187 | "watchdog timeout", | ||
188 | "invalid address", | ||
189 | "mirror Broken", | ||
190 | "memory sparing", | ||
191 | "scrub corrected error", | ||
192 | "scrub uncorrected error", | ||
193 | }; | ||
194 | |||
195 | static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) | ||
196 | { | ||
197 | if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) | ||
198 | printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); | ||
199 | if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) | ||
200 | printk("%s""physical_address: 0x%016llx\n", | ||
201 | pfx, mem->physical_addr); | ||
202 | if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK) | ||
203 | printk("%s""physical_address_mask: 0x%016llx\n", | ||
204 | pfx, mem->physical_addr_mask); | ||
205 | if (mem->validation_bits & CPER_MEM_VALID_NODE) | ||
206 | printk("%s""node: %d\n", pfx, mem->node); | ||
207 | if (mem->validation_bits & CPER_MEM_VALID_CARD) | ||
208 | printk("%s""card: %d\n", pfx, mem->card); | ||
209 | if (mem->validation_bits & CPER_MEM_VALID_MODULE) | ||
210 | printk("%s""module: %d\n", pfx, mem->module); | ||
211 | if (mem->validation_bits & CPER_MEM_VALID_BANK) | ||
212 | printk("%s""bank: %d\n", pfx, mem->bank); | ||
213 | if (mem->validation_bits & CPER_MEM_VALID_DEVICE) | ||
214 | printk("%s""device: %d\n", pfx, mem->device); | ||
215 | if (mem->validation_bits & CPER_MEM_VALID_ROW) | ||
216 | printk("%s""row: %d\n", pfx, mem->row); | ||
217 | if (mem->validation_bits & CPER_MEM_VALID_COLUMN) | ||
218 | printk("%s""column: %d\n", pfx, mem->column); | ||
219 | if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) | ||
220 | printk("%s""bit_position: %d\n", pfx, mem->bit_pos); | ||
221 | if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) | ||
222 | printk("%s""requestor_id: 0x%016llx\n", pfx, mem->requestor_id); | ||
223 | if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) | ||
224 | printk("%s""responder_id: 0x%016llx\n", pfx, mem->responder_id); | ||
225 | if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) | ||
226 | printk("%s""target_id: 0x%016llx\n", pfx, mem->target_id); | ||
227 | if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { | ||
228 | u8 etype = mem->error_type; | ||
229 | printk("%s""error_type: %d, %s\n", pfx, etype, | ||
230 | etype < ARRAY_SIZE(cper_mem_err_type_strs) ? | ||
231 | cper_mem_err_type_strs[etype] : "unknown"); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | static const char *cper_pcie_port_type_strs[] = { | ||
236 | "PCIe end point", | ||
237 | "legacy PCI end point", | ||
238 | "unknown", | ||
239 | "unknown", | ||
240 | "root port", | ||
241 | "upstream switch port", | ||
242 | "downstream switch port", | ||
243 | "PCIe to PCI/PCI-X bridge", | ||
244 | "PCI/PCI-X to PCIe bridge", | ||
245 | "root complex integrated endpoint device", | ||
246 | "root complex event collector", | ||
247 | }; | ||
248 | |||
249 | static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, | ||
250 | const struct acpi_hest_generic_data *gdata) | ||
251 | { | ||
252 | if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) | ||
253 | printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, | ||
254 | pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? | ||
255 | cper_pcie_port_type_strs[pcie->port_type] : "unknown"); | ||
256 | if (pcie->validation_bits & CPER_PCIE_VALID_VERSION) | ||
257 | printk("%s""version: %d.%d\n", pfx, | ||
258 | pcie->version.major, pcie->version.minor); | ||
259 | if (pcie->validation_bits & CPER_PCIE_VALID_COMMAND_STATUS) | ||
260 | printk("%s""command: 0x%04x, status: 0x%04x\n", pfx, | ||
261 | pcie->command, pcie->status); | ||
262 | if (pcie->validation_bits & CPER_PCIE_VALID_DEVICE_ID) { | ||
263 | const __u8 *p; | ||
264 | printk("%s""device_id: %04x:%02x:%02x.%x\n", pfx, | ||
265 | pcie->device_id.segment, pcie->device_id.bus, | ||
266 | pcie->device_id.device, pcie->device_id.function); | ||
267 | printk("%s""slot: %d\n", pfx, | ||
268 | pcie->device_id.slot >> CPER_PCIE_SLOT_SHIFT); | ||
269 | printk("%s""secondary_bus: 0x%02x\n", pfx, | ||
270 | pcie->device_id.secondary_bus); | ||
271 | printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx, | ||
272 | pcie->device_id.vendor_id, pcie->device_id.device_id); | ||
273 | p = pcie->device_id.class_code; | ||
274 | printk("%s""class_code: %02x%02x%02x\n", pfx, p[0], p[1], p[2]); | ||
275 | } | ||
276 | if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER) | ||
277 | printk("%s""serial number: 0x%04x, 0x%04x\n", pfx, | ||
278 | pcie->serial_number.lower, pcie->serial_number.upper); | ||
279 | if (pcie->validation_bits & CPER_PCIE_VALID_BRIDGE_CONTROL_STATUS) | ||
280 | printk( | ||
281 | "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", | ||
282 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); | ||
283 | #ifdef CONFIG_ACPI_APEI_PCIEAER | ||
284 | if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) { | ||
285 | struct aer_capability_regs *aer_regs = (void *)pcie->aer_info; | ||
286 | cper_print_aer(pfx, gdata->error_severity, aer_regs); | ||
287 | } | ||
288 | #endif | ||
289 | } | ||
290 | |||
291 | static const char *apei_estatus_section_flag_strs[] = { | ||
292 | "primary", | ||
293 | "containment warning", | ||
294 | "reset", | ||
295 | "threshold exceeded", | ||
296 | "resource not accessible", | ||
297 | "latent error", | ||
298 | }; | ||
299 | |||
300 | static void apei_estatus_print_section( | ||
301 | const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no) | ||
302 | { | ||
303 | uuid_le *sec_type = (uuid_le *)gdata->section_type; | ||
304 | __u16 severity; | ||
305 | |||
306 | severity = gdata->error_severity; | ||
307 | printk("%s""section: %d, severity: %d, %s\n", pfx, sec_no, severity, | ||
308 | cper_severity_str(severity)); | ||
309 | printk("%s""flags: 0x%02x\n", pfx, gdata->flags); | ||
310 | cper_print_bits(pfx, gdata->flags, apei_estatus_section_flag_strs, | ||
311 | ARRAY_SIZE(apei_estatus_section_flag_strs)); | ||
312 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) | ||
313 | printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id); | ||
314 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) | ||
315 | printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); | ||
316 | |||
317 | if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) { | ||
318 | struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1); | ||
319 | printk("%s""section_type: general processor error\n", pfx); | ||
320 | if (gdata->error_data_length >= sizeof(*proc_err)) | ||
321 | cper_print_proc_generic(pfx, proc_err); | ||
322 | else | ||
323 | goto err_section_too_small; | ||
324 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { | ||
325 | struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); | ||
326 | printk("%s""section_type: memory error\n", pfx); | ||
327 | if (gdata->error_data_length >= sizeof(*mem_err)) | ||
328 | cper_print_mem(pfx, mem_err); | ||
329 | else | ||
330 | goto err_section_too_small; | ||
331 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { | ||
332 | struct cper_sec_pcie *pcie = (void *)(gdata + 1); | ||
333 | printk("%s""section_type: PCIe error\n", pfx); | ||
334 | if (gdata->error_data_length >= sizeof(*pcie)) | ||
335 | cper_print_pcie(pfx, pcie, gdata); | ||
336 | else | ||
337 | goto err_section_too_small; | ||
338 | } else | ||
339 | printk("%s""section type: unknown, %pUl\n", pfx, sec_type); | ||
340 | |||
341 | return; | ||
342 | |||
343 | err_section_too_small: | ||
344 | pr_err(FW_WARN "error section length is too small\n"); | ||
345 | } | ||
346 | |||
347 | void apei_estatus_print(const char *pfx, | ||
348 | const struct acpi_hest_generic_status *estatus) | ||
349 | { | ||
350 | struct acpi_hest_generic_data *gdata; | ||
351 | unsigned int data_len, gedata_len; | ||
352 | int sec_no = 0; | ||
353 | __u16 severity; | ||
354 | |||
355 | printk("%s""APEI generic hardware error status\n", pfx); | ||
356 | severity = estatus->error_severity; | ||
357 | printk("%s""severity: %d, %s\n", pfx, severity, | ||
358 | cper_severity_str(severity)); | ||
359 | data_len = estatus->data_length; | ||
360 | gdata = (struct acpi_hest_generic_data *)(estatus + 1); | ||
361 | while (data_len > sizeof(*gdata)) { | ||
362 | gedata_len = gdata->error_data_length; | ||
363 | apei_estatus_print_section(pfx, gdata, sec_no); | ||
364 | data_len -= gedata_len + sizeof(*gdata); | ||
365 | sec_no++; | ||
366 | } | ||
367 | } | ||
368 | EXPORT_SYMBOL_GPL(apei_estatus_print); | ||
369 | |||
49 | int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus) | 370 | int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus) |
50 | { | 371 | { |
51 | if (estatus->data_length && | 372 | if (estatus->data_length && |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index cf29df69380b..f74b2ea11f21 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #define EINJ_PFX "EINJ: " | 39 | #define EINJ_PFX "EINJ: " |
40 | 40 | ||
41 | #define SPIN_UNIT 100 /* 100ns */ | 41 | #define SPIN_UNIT 100 /* 100ns */ |
42 | /* Firmware should respond within 1 miliseconds */ | 42 | /* Firmware should respond within 1 milliseconds */ |
43 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) | 43 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) |
44 | 44 | ||
45 | /* | 45 | /* |
@@ -101,6 +101,14 @@ static DEFINE_MUTEX(einj_mutex); | |||
101 | 101 | ||
102 | static struct einj_parameter *einj_param; | 102 | static struct einj_parameter *einj_param; |
103 | 103 | ||
104 | #ifndef writeq | ||
105 | static inline void writeq(__u64 val, volatile void __iomem *addr) | ||
106 | { | ||
107 | writel(val, addr); | ||
108 | writel(val >> 32, addr+4); | ||
109 | } | ||
110 | #endif | ||
111 | |||
104 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) | 112 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) |
105 | { | 113 | { |
106 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), | 114 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), |
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c index da1228a9a544..a4cfb64c86a1 100644 --- a/drivers/acpi/apei/erst-dbg.c +++ b/drivers/acpi/apei/erst-dbg.c | |||
@@ -43,12 +43,27 @@ static DEFINE_MUTEX(erst_dbg_mutex); | |||
43 | 43 | ||
44 | static int erst_dbg_open(struct inode *inode, struct file *file) | 44 | static int erst_dbg_open(struct inode *inode, struct file *file) |
45 | { | 45 | { |
46 | int rc, *pos; | ||
47 | |||
46 | if (erst_disable) | 48 | if (erst_disable) |
47 | return -ENODEV; | 49 | return -ENODEV; |
48 | 50 | ||
51 | pos = (int *)&file->private_data; | ||
52 | |||
53 | rc = erst_get_record_id_begin(pos); | ||
54 | if (rc) | ||
55 | return rc; | ||
56 | |||
49 | return nonseekable_open(inode, file); | 57 | return nonseekable_open(inode, file); |
50 | } | 58 | } |
51 | 59 | ||
60 | static int erst_dbg_release(struct inode *inode, struct file *file) | ||
61 | { | ||
62 | erst_get_record_id_end(); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
52 | static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | 67 | static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) |
53 | { | 68 | { |
54 | int rc; | 69 | int rc; |
@@ -79,18 +94,20 @@ static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
79 | static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf, | 94 | static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf, |
80 | size_t usize, loff_t *off) | 95 | size_t usize, loff_t *off) |
81 | { | 96 | { |
82 | int rc; | 97 | int rc, *pos; |
83 | ssize_t len = 0; | 98 | ssize_t len = 0; |
84 | u64 id; | 99 | u64 id; |
85 | 100 | ||
86 | if (*off != 0) | 101 | if (*off) |
87 | return -EINVAL; | 102 | return -EINVAL; |
88 | 103 | ||
89 | if (mutex_lock_interruptible(&erst_dbg_mutex) != 0) | 104 | if (mutex_lock_interruptible(&erst_dbg_mutex) != 0) |
90 | return -EINTR; | 105 | return -EINTR; |
91 | 106 | ||
107 | pos = (int *)&filp->private_data; | ||
108 | |||
92 | retry_next: | 109 | retry_next: |
93 | rc = erst_get_next_record_id(&id); | 110 | rc = erst_get_record_id_next(pos, &id); |
94 | if (rc) | 111 | if (rc) |
95 | goto out; | 112 | goto out; |
96 | /* no more record */ | 113 | /* no more record */ |
@@ -181,9 +198,11 @@ out: | |||
181 | static const struct file_operations erst_dbg_ops = { | 198 | static const struct file_operations erst_dbg_ops = { |
182 | .owner = THIS_MODULE, | 199 | .owner = THIS_MODULE, |
183 | .open = erst_dbg_open, | 200 | .open = erst_dbg_open, |
201 | .release = erst_dbg_release, | ||
184 | .read = erst_dbg_read, | 202 | .read = erst_dbg_read, |
185 | .write = erst_dbg_write, | 203 | .write = erst_dbg_write, |
186 | .unlocked_ioctl = erst_dbg_ioctl, | 204 | .unlocked_ioctl = erst_dbg_ioctl, |
205 | .llseek = no_llseek, | ||
187 | }; | 206 | }; |
188 | 207 | ||
189 | static struct miscdevice erst_dbg_dev = { | 208 | static struct miscdevice erst_dbg_dev = { |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 1211c03149e8..e6cef8e1b534 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/cper.h> | 34 | #include <linux/cper.h> |
35 | #include <linux/nmi.h> | 35 | #include <linux/nmi.h> |
36 | #include <linux/hardirq.h> | 36 | #include <linux/hardirq.h> |
37 | #include <linux/pstore.h> | ||
37 | #include <acpi/apei.h> | 38 | #include <acpi/apei.h> |
38 | 39 | ||
39 | #include "apei-internal.h" | 40 | #include "apei-internal.h" |
@@ -53,7 +54,7 @@ | |||
53 | sizeof(struct acpi_table_erst))) | 54 | sizeof(struct acpi_table_erst))) |
54 | 55 | ||
55 | #define SPIN_UNIT 100 /* 100ns */ | 56 | #define SPIN_UNIT 100 /* 100ns */ |
56 | /* Firmware should respond within 1 miliseconds */ | 57 | /* Firmware should respond within 1 milliseconds */ |
57 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) | 58 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) |
58 | #define FIRMWARE_MAX_STALL 50 /* 50us */ | 59 | #define FIRMWARE_MAX_STALL 50 /* 50us */ |
59 | 60 | ||
@@ -86,7 +87,7 @@ static struct erst_erange { | |||
86 | * It is used to provide exclusive accessing for ERST Error Log | 87 | * It is used to provide exclusive accessing for ERST Error Log |
87 | * Address Range too. | 88 | * Address Range too. |
88 | */ | 89 | */ |
89 | static DEFINE_SPINLOCK(erst_lock); | 90 | static DEFINE_RAW_SPINLOCK(erst_lock); |
90 | 91 | ||
91 | static inline int erst_errno(int command_status) | 92 | static inline int erst_errno(int command_status) |
92 | { | 93 | { |
@@ -421,14 +422,30 @@ ssize_t erst_get_record_count(void) | |||
421 | if (erst_disable) | 422 | if (erst_disable) |
422 | return -ENODEV; | 423 | return -ENODEV; |
423 | 424 | ||
424 | spin_lock_irqsave(&erst_lock, flags); | 425 | raw_spin_lock_irqsave(&erst_lock, flags); |
425 | count = __erst_get_record_count(); | 426 | count = __erst_get_record_count(); |
426 | spin_unlock_irqrestore(&erst_lock, flags); | 427 | raw_spin_unlock_irqrestore(&erst_lock, flags); |
427 | 428 | ||
428 | return count; | 429 | return count; |
429 | } | 430 | } |
430 | EXPORT_SYMBOL_GPL(erst_get_record_count); | 431 | EXPORT_SYMBOL_GPL(erst_get_record_count); |
431 | 432 | ||
433 | #define ERST_RECORD_ID_CACHE_SIZE_MIN 16 | ||
434 | #define ERST_RECORD_ID_CACHE_SIZE_MAX 1024 | ||
435 | |||
436 | struct erst_record_id_cache { | ||
437 | struct mutex lock; | ||
438 | u64 *entries; | ||
439 | int len; | ||
440 | int size; | ||
441 | int refcount; | ||
442 | }; | ||
443 | |||
444 | static struct erst_record_id_cache erst_record_id_cache = { | ||
445 | .lock = __MUTEX_INITIALIZER(erst_record_id_cache.lock), | ||
446 | .refcount = 0, | ||
447 | }; | ||
448 | |||
432 | static int __erst_get_next_record_id(u64 *record_id) | 449 | static int __erst_get_next_record_id(u64 *record_id) |
433 | { | 450 | { |
434 | struct apei_exec_context ctx; | 451 | struct apei_exec_context ctx; |
@@ -443,26 +460,179 @@ static int __erst_get_next_record_id(u64 *record_id) | |||
443 | return 0; | 460 | return 0; |
444 | } | 461 | } |
445 | 462 | ||
463 | int erst_get_record_id_begin(int *pos) | ||
464 | { | ||
465 | int rc; | ||
466 | |||
467 | if (erst_disable) | ||
468 | return -ENODEV; | ||
469 | |||
470 | rc = mutex_lock_interruptible(&erst_record_id_cache.lock); | ||
471 | if (rc) | ||
472 | return rc; | ||
473 | erst_record_id_cache.refcount++; | ||
474 | mutex_unlock(&erst_record_id_cache.lock); | ||
475 | |||
476 | *pos = 0; | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | EXPORT_SYMBOL_GPL(erst_get_record_id_begin); | ||
481 | |||
482 | /* erst_record_id_cache.lock must be held by caller */ | ||
483 | static int __erst_record_id_cache_add_one(void) | ||
484 | { | ||
485 | u64 id, prev_id, first_id; | ||
486 | int i, rc; | ||
487 | u64 *entries; | ||
488 | unsigned long flags; | ||
489 | |||
490 | id = prev_id = first_id = APEI_ERST_INVALID_RECORD_ID; | ||
491 | retry: | ||
492 | raw_spin_lock_irqsave(&erst_lock, flags); | ||
493 | rc = __erst_get_next_record_id(&id); | ||
494 | raw_spin_unlock_irqrestore(&erst_lock, flags); | ||
495 | if (rc == -ENOENT) | ||
496 | return 0; | ||
497 | if (rc) | ||
498 | return rc; | ||
499 | if (id == APEI_ERST_INVALID_RECORD_ID) | ||
500 | return 0; | ||
501 | /* can not skip current ID, or loop back to first ID */ | ||
502 | if (id == prev_id || id == first_id) | ||
503 | return 0; | ||
504 | if (first_id == APEI_ERST_INVALID_RECORD_ID) | ||
505 | first_id = id; | ||
506 | prev_id = id; | ||
507 | |||
508 | entries = erst_record_id_cache.entries; | ||
509 | for (i = 0; i < erst_record_id_cache.len; i++) { | ||
510 | if (entries[i] == id) | ||
511 | break; | ||
512 | } | ||
513 | /* record id already in cache, try next */ | ||
514 | if (i < erst_record_id_cache.len) | ||
515 | goto retry; | ||
516 | if (erst_record_id_cache.len >= erst_record_id_cache.size) { | ||
517 | int new_size, alloc_size; | ||
518 | u64 *new_entries; | ||
519 | |||
520 | new_size = erst_record_id_cache.size * 2; | ||
521 | new_size = clamp_val(new_size, ERST_RECORD_ID_CACHE_SIZE_MIN, | ||
522 | ERST_RECORD_ID_CACHE_SIZE_MAX); | ||
523 | if (new_size <= erst_record_id_cache.size) { | ||
524 | if (printk_ratelimit()) | ||
525 | pr_warning(FW_WARN ERST_PFX | ||
526 | "too many record ID!\n"); | ||
527 | return 0; | ||
528 | } | ||
529 | alloc_size = new_size * sizeof(entries[0]); | ||
530 | if (alloc_size < PAGE_SIZE) | ||
531 | new_entries = kmalloc(alloc_size, GFP_KERNEL); | ||
532 | else | ||
533 | new_entries = vmalloc(alloc_size); | ||
534 | if (!new_entries) | ||
535 | return -ENOMEM; | ||
536 | memcpy(new_entries, entries, | ||
537 | erst_record_id_cache.len * sizeof(entries[0])); | ||
538 | if (erst_record_id_cache.size < PAGE_SIZE) | ||
539 | kfree(entries); | ||
540 | else | ||
541 | vfree(entries); | ||
542 | erst_record_id_cache.entries = entries = new_entries; | ||
543 | erst_record_id_cache.size = new_size; | ||
544 | } | ||
545 | entries[i] = id; | ||
546 | erst_record_id_cache.len++; | ||
547 | |||
548 | return 1; | ||
549 | } | ||
550 | |||
446 | /* | 551 | /* |
447 | * Get the record ID of an existing error record on the persistent | 552 | * Get the record ID of an existing error record on the persistent |
448 | * storage. If there is no error record on the persistent storage, the | 553 | * storage. If there is no error record on the persistent storage, the |
449 | * returned record_id is APEI_ERST_INVALID_RECORD_ID. | 554 | * returned record_id is APEI_ERST_INVALID_RECORD_ID. |
450 | */ | 555 | */ |
451 | int erst_get_next_record_id(u64 *record_id) | 556 | int erst_get_record_id_next(int *pos, u64 *record_id) |
452 | { | 557 | { |
453 | int rc; | 558 | int rc = 0; |
454 | unsigned long flags; | 559 | u64 *entries; |
455 | 560 | ||
456 | if (erst_disable) | 561 | if (erst_disable) |
457 | return -ENODEV; | 562 | return -ENODEV; |
458 | 563 | ||
459 | spin_lock_irqsave(&erst_lock, flags); | 564 | /* must be enclosed by erst_get_record_id_begin/end */ |
460 | rc = __erst_get_next_record_id(record_id); | 565 | BUG_ON(!erst_record_id_cache.refcount); |
461 | spin_unlock_irqrestore(&erst_lock, flags); | 566 | BUG_ON(*pos < 0 || *pos > erst_record_id_cache.len); |
567 | |||
568 | mutex_lock(&erst_record_id_cache.lock); | ||
569 | entries = erst_record_id_cache.entries; | ||
570 | for (; *pos < erst_record_id_cache.len; (*pos)++) | ||
571 | if (entries[*pos] != APEI_ERST_INVALID_RECORD_ID) | ||
572 | break; | ||
573 | /* found next record id in cache */ | ||
574 | if (*pos < erst_record_id_cache.len) { | ||
575 | *record_id = entries[*pos]; | ||
576 | (*pos)++; | ||
577 | goto out_unlock; | ||
578 | } | ||
579 | |||
580 | /* Try to add one more record ID to cache */ | ||
581 | rc = __erst_record_id_cache_add_one(); | ||
582 | if (rc < 0) | ||
583 | goto out_unlock; | ||
584 | /* successfully add one new ID */ | ||
585 | if (rc == 1) { | ||
586 | *record_id = erst_record_id_cache.entries[*pos]; | ||
587 | (*pos)++; | ||
588 | rc = 0; | ||
589 | } else { | ||
590 | *pos = -1; | ||
591 | *record_id = APEI_ERST_INVALID_RECORD_ID; | ||
592 | } | ||
593 | out_unlock: | ||
594 | mutex_unlock(&erst_record_id_cache.lock); | ||
462 | 595 | ||
463 | return rc; | 596 | return rc; |
464 | } | 597 | } |
465 | EXPORT_SYMBOL_GPL(erst_get_next_record_id); | 598 | EXPORT_SYMBOL_GPL(erst_get_record_id_next); |
599 | |||
600 | /* erst_record_id_cache.lock must be held by caller */ | ||
601 | static void __erst_record_id_cache_compact(void) | ||
602 | { | ||
603 | int i, wpos = 0; | ||
604 | u64 *entries; | ||
605 | |||
606 | if (erst_record_id_cache.refcount) | ||
607 | return; | ||
608 | |||
609 | entries = erst_record_id_cache.entries; | ||
610 | for (i = 0; i < erst_record_id_cache.len; i++) { | ||
611 | if (entries[i] == APEI_ERST_INVALID_RECORD_ID) | ||
612 | continue; | ||
613 | if (wpos != i) | ||
614 | memcpy(&entries[wpos], &entries[i], sizeof(entries[i])); | ||
615 | wpos++; | ||
616 | } | ||
617 | erst_record_id_cache.len = wpos; | ||
618 | } | ||
619 | |||
620 | void erst_get_record_id_end(void) | ||
621 | { | ||
622 | /* | ||
623 | * erst_disable != 0 should be detected by invoker via the | ||
624 | * return value of erst_get_record_id_begin/next, so this | ||
625 | * function should not be called for erst_disable != 0. | ||
626 | */ | ||
627 | BUG_ON(erst_disable); | ||
628 | |||
629 | mutex_lock(&erst_record_id_cache.lock); | ||
630 | erst_record_id_cache.refcount--; | ||
631 | BUG_ON(erst_record_id_cache.refcount < 0); | ||
632 | __erst_record_id_cache_compact(); | ||
633 | mutex_unlock(&erst_record_id_cache.lock); | ||
634 | } | ||
635 | EXPORT_SYMBOL_GPL(erst_get_record_id_end); | ||
466 | 636 | ||
467 | static int __erst_write_to_storage(u64 offset) | 637 | static int __erst_write_to_storage(u64 offset) |
468 | { | 638 | { |
@@ -624,17 +794,17 @@ int erst_write(const struct cper_record_header *record) | |||
624 | return -EINVAL; | 794 | return -EINVAL; |
625 | 795 | ||
626 | if (erst_erange.attr & ERST_RANGE_NVRAM) { | 796 | if (erst_erange.attr & ERST_RANGE_NVRAM) { |
627 | if (!spin_trylock_irqsave(&erst_lock, flags)) | 797 | if (!raw_spin_trylock_irqsave(&erst_lock, flags)) |
628 | return -EBUSY; | 798 | return -EBUSY; |
629 | rc = __erst_write_to_nvram(record); | 799 | rc = __erst_write_to_nvram(record); |
630 | spin_unlock_irqrestore(&erst_lock, flags); | 800 | raw_spin_unlock_irqrestore(&erst_lock, flags); |
631 | return rc; | 801 | return rc; |
632 | } | 802 | } |
633 | 803 | ||
634 | if (record->record_length > erst_erange.size) | 804 | if (record->record_length > erst_erange.size) |
635 | return -EINVAL; | 805 | return -EINVAL; |
636 | 806 | ||
637 | if (!spin_trylock_irqsave(&erst_lock, flags)) | 807 | if (!raw_spin_trylock_irqsave(&erst_lock, flags)) |
638 | return -EBUSY; | 808 | return -EBUSY; |
639 | memcpy(erst_erange.vaddr, record, record->record_length); | 809 | memcpy(erst_erange.vaddr, record, record->record_length); |
640 | rcd_erange = erst_erange.vaddr; | 810 | rcd_erange = erst_erange.vaddr; |
@@ -642,7 +812,7 @@ int erst_write(const struct cper_record_header *record) | |||
642 | memcpy(&rcd_erange->persistence_information, "ER", 2); | 812 | memcpy(&rcd_erange->persistence_information, "ER", 2); |
643 | 813 | ||
644 | rc = __erst_write_to_storage(0); | 814 | rc = __erst_write_to_storage(0); |
645 | spin_unlock_irqrestore(&erst_lock, flags); | 815 | raw_spin_unlock_irqrestore(&erst_lock, flags); |
646 | 816 | ||
647 | return rc; | 817 | return rc; |
648 | } | 818 | } |
@@ -696,63 +866,41 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record, | |||
696 | if (erst_disable) | 866 | if (erst_disable) |
697 | return -ENODEV; | 867 | return -ENODEV; |
698 | 868 | ||
699 | spin_lock_irqsave(&erst_lock, flags); | 869 | raw_spin_lock_irqsave(&erst_lock, flags); |
700 | len = __erst_read(record_id, record, buflen); | 870 | len = __erst_read(record_id, record, buflen); |
701 | spin_unlock_irqrestore(&erst_lock, flags); | 871 | raw_spin_unlock_irqrestore(&erst_lock, flags); |
702 | return len; | 872 | return len; |
703 | } | 873 | } |
704 | EXPORT_SYMBOL_GPL(erst_read); | 874 | EXPORT_SYMBOL_GPL(erst_read); |
705 | 875 | ||
706 | /* | ||
707 | * If return value > buflen, the buffer size is not big enough, | ||
708 | * else if return value = 0, there is no more record to read, | ||
709 | * else if return value < 0, something goes wrong, | ||
710 | * else everything is OK, and return value is record length | ||
711 | */ | ||
712 | ssize_t erst_read_next(struct cper_record_header *record, size_t buflen) | ||
713 | { | ||
714 | int rc; | ||
715 | ssize_t len; | ||
716 | unsigned long flags; | ||
717 | u64 record_id; | ||
718 | |||
719 | if (erst_disable) | ||
720 | return -ENODEV; | ||
721 | |||
722 | spin_lock_irqsave(&erst_lock, flags); | ||
723 | rc = __erst_get_next_record_id(&record_id); | ||
724 | if (rc) { | ||
725 | spin_unlock_irqrestore(&erst_lock, flags); | ||
726 | return rc; | ||
727 | } | ||
728 | /* no more record */ | ||
729 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { | ||
730 | spin_unlock_irqrestore(&erst_lock, flags); | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | len = __erst_read(record_id, record, buflen); | ||
735 | spin_unlock_irqrestore(&erst_lock, flags); | ||
736 | |||
737 | return len; | ||
738 | } | ||
739 | EXPORT_SYMBOL_GPL(erst_read_next); | ||
740 | |||
741 | int erst_clear(u64 record_id) | 876 | int erst_clear(u64 record_id) |
742 | { | 877 | { |
743 | int rc; | 878 | int rc, i; |
744 | unsigned long flags; | 879 | unsigned long flags; |
880 | u64 *entries; | ||
745 | 881 | ||
746 | if (erst_disable) | 882 | if (erst_disable) |
747 | return -ENODEV; | 883 | return -ENODEV; |
748 | 884 | ||
749 | spin_lock_irqsave(&erst_lock, flags); | 885 | rc = mutex_lock_interruptible(&erst_record_id_cache.lock); |
886 | if (rc) | ||
887 | return rc; | ||
888 | raw_spin_lock_irqsave(&erst_lock, flags); | ||
750 | if (erst_erange.attr & ERST_RANGE_NVRAM) | 889 | if (erst_erange.attr & ERST_RANGE_NVRAM) |
751 | rc = __erst_clear_from_nvram(record_id); | 890 | rc = __erst_clear_from_nvram(record_id); |
752 | else | 891 | else |
753 | rc = __erst_clear_from_storage(record_id); | 892 | rc = __erst_clear_from_storage(record_id); |
754 | spin_unlock_irqrestore(&erst_lock, flags); | 893 | raw_spin_unlock_irqrestore(&erst_lock, flags); |
755 | 894 | if (rc) | |
895 | goto out; | ||
896 | entries = erst_record_id_cache.entries; | ||
897 | for (i = 0; i < erst_record_id_cache.len; i++) { | ||
898 | if (entries[i] == record_id) | ||
899 | entries[i] = APEI_ERST_INVALID_RECORD_ID; | ||
900 | } | ||
901 | __erst_record_id_cache_compact(); | ||
902 | out: | ||
903 | mutex_unlock(&erst_record_id_cache.lock); | ||
756 | return rc; | 904 | return rc; |
757 | } | 905 | } |
758 | EXPORT_SYMBOL_GPL(erst_clear); | 906 | EXPORT_SYMBOL_GPL(erst_clear); |
@@ -781,6 +929,157 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) | |||
781 | return 0; | 929 | return 0; |
782 | } | 930 | } |
783 | 931 | ||
932 | static int erst_open_pstore(struct pstore_info *psi); | ||
933 | static int erst_close_pstore(struct pstore_info *psi); | ||
934 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | ||
935 | struct timespec *time); | ||
936 | static u64 erst_writer(enum pstore_type_id type, size_t size); | ||
937 | |||
938 | static struct pstore_info erst_info = { | ||
939 | .owner = THIS_MODULE, | ||
940 | .name = "erst", | ||
941 | .open = erst_open_pstore, | ||
942 | .close = erst_close_pstore, | ||
943 | .read = erst_reader, | ||
944 | .write = erst_writer, | ||
945 | .erase = erst_clear | ||
946 | }; | ||
947 | |||
948 | #define CPER_CREATOR_PSTORE \ | ||
949 | UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \ | ||
950 | 0x64, 0x90, 0xb8, 0x9d) | ||
951 | #define CPER_SECTION_TYPE_DMESG \ | ||
952 | UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \ | ||
953 | 0x94, 0x19, 0xeb, 0x12) | ||
954 | #define CPER_SECTION_TYPE_MCE \ | ||
955 | UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \ | ||
956 | 0x04, 0x4a, 0x38, 0xfc) | ||
957 | |||
958 | struct cper_pstore_record { | ||
959 | struct cper_record_header hdr; | ||
960 | struct cper_section_descriptor sec_hdr; | ||
961 | char data[]; | ||
962 | } __packed; | ||
963 | |||
964 | static int reader_pos; | ||
965 | |||
966 | static int erst_open_pstore(struct pstore_info *psi) | ||
967 | { | ||
968 | int rc; | ||
969 | |||
970 | if (erst_disable) | ||
971 | return -ENODEV; | ||
972 | |||
973 | rc = erst_get_record_id_begin(&reader_pos); | ||
974 | |||
975 | return rc; | ||
976 | } | ||
977 | |||
978 | static int erst_close_pstore(struct pstore_info *psi) | ||
979 | { | ||
980 | erst_get_record_id_end(); | ||
981 | |||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | ||
986 | struct timespec *time) | ||
987 | { | ||
988 | int rc; | ||
989 | ssize_t len = 0; | ||
990 | u64 record_id; | ||
991 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) | ||
992 | (erst_info.buf - sizeof(*rcd)); | ||
993 | |||
994 | if (erst_disable) | ||
995 | return -ENODEV; | ||
996 | |||
997 | skip: | ||
998 | rc = erst_get_record_id_next(&reader_pos, &record_id); | ||
999 | if (rc) | ||
1000 | goto out; | ||
1001 | |||
1002 | /* no more record */ | ||
1003 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { | ||
1004 | rc = -1; | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) + | ||
1009 | erst_info.bufsize); | ||
1010 | /* The record may be cleared by others, try read next record */ | ||
1011 | if (len == -ENOENT) | ||
1012 | goto skip; | ||
1013 | else if (len < 0) { | ||
1014 | rc = -1; | ||
1015 | goto out; | ||
1016 | } | ||
1017 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) | ||
1018 | goto skip; | ||
1019 | |||
1020 | *id = record_id; | ||
1021 | if (uuid_le_cmp(rcd->sec_hdr.section_type, | ||
1022 | CPER_SECTION_TYPE_DMESG) == 0) | ||
1023 | *type = PSTORE_TYPE_DMESG; | ||
1024 | else if (uuid_le_cmp(rcd->sec_hdr.section_type, | ||
1025 | CPER_SECTION_TYPE_MCE) == 0) | ||
1026 | *type = PSTORE_TYPE_MCE; | ||
1027 | else | ||
1028 | *type = PSTORE_TYPE_UNKNOWN; | ||
1029 | |||
1030 | if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP) | ||
1031 | time->tv_sec = rcd->hdr.timestamp; | ||
1032 | else | ||
1033 | time->tv_sec = 0; | ||
1034 | time->tv_nsec = 0; | ||
1035 | |||
1036 | out: | ||
1037 | return (rc < 0) ? rc : (len - sizeof(*rcd)); | ||
1038 | } | ||
1039 | |||
1040 | static u64 erst_writer(enum pstore_type_id type, size_t size) | ||
1041 | { | ||
1042 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) | ||
1043 | (erst_info.buf - sizeof(*rcd)); | ||
1044 | |||
1045 | memset(rcd, 0, sizeof(*rcd)); | ||
1046 | memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE); | ||
1047 | rcd->hdr.revision = CPER_RECORD_REV; | ||
1048 | rcd->hdr.signature_end = CPER_SIG_END; | ||
1049 | rcd->hdr.section_count = 1; | ||
1050 | rcd->hdr.error_severity = CPER_SEV_FATAL; | ||
1051 | /* timestamp valid. platform_id, partition_id are invalid */ | ||
1052 | rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP; | ||
1053 | rcd->hdr.timestamp = get_seconds(); | ||
1054 | rcd->hdr.record_length = sizeof(*rcd) + size; | ||
1055 | rcd->hdr.creator_id = CPER_CREATOR_PSTORE; | ||
1056 | rcd->hdr.notification_type = CPER_NOTIFY_MCE; | ||
1057 | rcd->hdr.record_id = cper_next_record_id(); | ||
1058 | rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; | ||
1059 | |||
1060 | rcd->sec_hdr.section_offset = sizeof(*rcd); | ||
1061 | rcd->sec_hdr.section_length = size; | ||
1062 | rcd->sec_hdr.revision = CPER_SEC_REV; | ||
1063 | /* fru_id and fru_text is invalid */ | ||
1064 | rcd->sec_hdr.validation_bits = 0; | ||
1065 | rcd->sec_hdr.flags = CPER_SEC_PRIMARY; | ||
1066 | switch (type) { | ||
1067 | case PSTORE_TYPE_DMESG: | ||
1068 | rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; | ||
1069 | break; | ||
1070 | case PSTORE_TYPE_MCE: | ||
1071 | rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE; | ||
1072 | break; | ||
1073 | default: | ||
1074 | return -EINVAL; | ||
1075 | } | ||
1076 | rcd->sec_hdr.section_severity = CPER_SEV_FATAL; | ||
1077 | |||
1078 | erst_write(&rcd->hdr); | ||
1079 | |||
1080 | return rcd->hdr.record_id; | ||
1081 | } | ||
1082 | |||
784 | static int __init erst_init(void) | 1083 | static int __init erst_init(void) |
785 | { | 1084 | { |
786 | int rc = 0; | 1085 | int rc = 0; |
@@ -788,6 +1087,7 @@ static int __init erst_init(void) | |||
788 | struct apei_exec_context ctx; | 1087 | struct apei_exec_context ctx; |
789 | struct apei_resources erst_resources; | 1088 | struct apei_resources erst_resources; |
790 | struct resource *r; | 1089 | struct resource *r; |
1090 | char *buf; | ||
791 | 1091 | ||
792 | if (acpi_disabled) | 1092 | if (acpi_disabled) |
793 | goto err; | 1093 | goto err; |
@@ -854,6 +1154,18 @@ static int __init erst_init(void) | |||
854 | if (!erst_erange.vaddr) | 1154 | if (!erst_erange.vaddr) |
855 | goto err_release_erange; | 1155 | goto err_release_erange; |
856 | 1156 | ||
1157 | buf = kmalloc(erst_erange.size, GFP_KERNEL); | ||
1158 | mutex_init(&erst_info.buf_mutex); | ||
1159 | if (buf) { | ||
1160 | erst_info.buf = buf + sizeof(struct cper_pstore_record); | ||
1161 | erst_info.bufsize = erst_erange.size - | ||
1162 | sizeof(struct cper_pstore_record); | ||
1163 | if (pstore_register(&erst_info)) { | ||
1164 | pr_info(ERST_PFX "Could not register with persistent store\n"); | ||
1165 | kfree(buf); | ||
1166 | } | ||
1167 | } | ||
1168 | |||
857 | pr_info(ERST_PFX | 1169 | pr_info(ERST_PFX |
858 | "Error Record Serialization Table (ERST) support is initialized.\n"); | 1170 | "Error Record Serialization Table (ERST) support is initialized.\n"); |
859 | 1171 | ||
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 0d505e59214d..f703b2881153 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -12,10 +12,6 @@ | |||
12 | * For more information about Generic Hardware Error Source, please | 12 | * For more information about Generic Hardware Error Source, please |
13 | * refer to ACPI Specification version 4.0, section 17.3.2.6 | 13 | * refer to ACPI Specification version 4.0, section 17.3.2.6 |
14 | * | 14 | * |
15 | * Now, only SCI notification type and memory errors are | ||
16 | * supported. More notification type and hardware error type will be | ||
17 | * added later. | ||
18 | * | ||
19 | * Copyright 2010 Intel Corp. | 15 | * Copyright 2010 Intel Corp. |
20 | * Author: Huang Ying <ying.huang@intel.com> | 16 | * Author: Huang Ying <ying.huang@intel.com> |
21 | * | 17 | * |
@@ -39,14 +35,18 @@ | |||
39 | #include <linux/acpi.h> | 35 | #include <linux/acpi.h> |
40 | #include <linux/io.h> | 36 | #include <linux/io.h> |
41 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/timer.h> | ||
42 | #include <linux/cper.h> | 39 | #include <linux/cper.h> |
43 | #include <linux/kdebug.h> | 40 | #include <linux/kdebug.h> |
44 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
45 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/ratelimit.h> | ||
44 | #include <linux/vmalloc.h> | ||
46 | #include <acpi/apei.h> | 45 | #include <acpi/apei.h> |
47 | #include <acpi/atomicio.h> | 46 | #include <acpi/atomicio.h> |
48 | #include <acpi/hed.h> | 47 | #include <acpi/hed.h> |
49 | #include <asm/mce.h> | 48 | #include <asm/mce.h> |
49 | #include <asm/tlbflush.h> | ||
50 | 50 | ||
51 | #include "apei-internal.h" | 51 | #include "apei-internal.h" |
52 | 52 | ||
@@ -55,42 +55,131 @@ | |||
55 | #define GHES_ESTATUS_MAX_SIZE 65536 | 55 | #define GHES_ESTATUS_MAX_SIZE 65536 |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * One struct ghes is created for each generic hardware error | 58 | * One struct ghes is created for each generic hardware error source. |
59 | * source. | ||
60 | * | ||
61 | * It provides the context for APEI hardware error timer/IRQ/SCI/NMI | 59 | * It provides the context for APEI hardware error timer/IRQ/SCI/NMI |
62 | * handler. Handler for one generic hardware error source is only | 60 | * handler. |
63 | * triggered after the previous one is done. So handler can uses | ||
64 | * struct ghes without locking. | ||
65 | * | 61 | * |
66 | * estatus: memory buffer for error status block, allocated during | 62 | * estatus: memory buffer for error status block, allocated during |
67 | * HEST parsing. | 63 | * HEST parsing. |
68 | */ | 64 | */ |
69 | #define GHES_TO_CLEAR 0x0001 | 65 | #define GHES_TO_CLEAR 0x0001 |
66 | #define GHES_EXITING 0x0002 | ||
70 | 67 | ||
71 | struct ghes { | 68 | struct ghes { |
72 | struct acpi_hest_generic *generic; | 69 | struct acpi_hest_generic *generic; |
73 | struct acpi_hest_generic_status *estatus; | 70 | struct acpi_hest_generic_status *estatus; |
74 | struct list_head list; | ||
75 | u64 buffer_paddr; | 71 | u64 buffer_paddr; |
76 | unsigned long flags; | 72 | unsigned long flags; |
73 | union { | ||
74 | struct list_head list; | ||
75 | struct timer_list timer; | ||
76 | unsigned int irq; | ||
77 | }; | ||
77 | }; | 78 | }; |
78 | 79 | ||
80 | static int ghes_panic_timeout __read_mostly = 30; | ||
81 | |||
79 | /* | 82 | /* |
80 | * Error source lists, one list for each notification method. The | 83 | * All error sources notified with SCI shares one notifier function, |
81 | * members in lists are struct ghes. | 84 | * so they need to be linked and checked one by one. This is applied |
85 | * to NMI too. | ||
82 | * | 86 | * |
83 | * The list members are only added in HEST parsing and deleted during | 87 | * RCU is used for these lists, so ghes_list_mutex is only used for |
84 | * module_exit, that is, single-threaded. So no lock is needed for | 88 | * list changing, not for traversing. |
85 | * that. | ||
86 | * | ||
87 | * But the mutual exclusion is needed between members adding/deleting | ||
88 | * and timer/IRQ/SCI/NMI handler, which may traverse the list. RCU is | ||
89 | * used for that. | ||
90 | */ | 89 | */ |
91 | static LIST_HEAD(ghes_sci); | 90 | static LIST_HEAD(ghes_sci); |
91 | static LIST_HEAD(ghes_nmi); | ||
92 | static DEFINE_MUTEX(ghes_list_mutex); | 92 | static DEFINE_MUTEX(ghes_list_mutex); |
93 | 93 | ||
94 | /* | ||
95 | * NMI may be triggered on any CPU, so ghes_nmi_lock is used for | ||
96 | * mutual exclusion. | ||
97 | */ | ||
98 | static DEFINE_RAW_SPINLOCK(ghes_nmi_lock); | ||
99 | |||
100 | /* | ||
101 | * Because the memory area used to transfer hardware error information | ||
102 | * from BIOS to Linux can be determined only in NMI, IRQ or timer | ||
103 | * handler, but general ioremap can not be used in atomic context, so | ||
104 | * a special version of atomic ioremap is implemented for that. | ||
105 | */ | ||
106 | |||
107 | /* | ||
108 | * Two virtual pages are used, one for NMI context, the other for | ||
109 | * IRQ/PROCESS context | ||
110 | */ | ||
111 | #define GHES_IOREMAP_PAGES 2 | ||
112 | #define GHES_IOREMAP_NMI_PAGE(base) (base) | ||
113 | #define GHES_IOREMAP_IRQ_PAGE(base) ((base) + PAGE_SIZE) | ||
114 | |||
115 | /* virtual memory area for atomic ioremap */ | ||
116 | static struct vm_struct *ghes_ioremap_area; | ||
117 | /* | ||
118 | * These 2 spinlock is used to prevent atomic ioremap virtual memory | ||
119 | * area from being mapped simultaneously. | ||
120 | */ | ||
121 | static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi); | ||
122 | static DEFINE_SPINLOCK(ghes_ioremap_lock_irq); | ||
123 | |||
124 | static int ghes_ioremap_init(void) | ||
125 | { | ||
126 | ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES, | ||
127 | VM_IOREMAP, VMALLOC_START, VMALLOC_END); | ||
128 | if (!ghes_ioremap_area) { | ||
129 | pr_err(GHES_PFX "Failed to allocate virtual memory area for atomic ioremap.\n"); | ||
130 | return -ENOMEM; | ||
131 | } | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void ghes_ioremap_exit(void) | ||
137 | { | ||
138 | free_vm_area(ghes_ioremap_area); | ||
139 | } | ||
140 | |||
141 | static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn) | ||
142 | { | ||
143 | unsigned long vaddr; | ||
144 | |||
145 | vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr); | ||
146 | ioremap_page_range(vaddr, vaddr + PAGE_SIZE, | ||
147 | pfn << PAGE_SHIFT, PAGE_KERNEL); | ||
148 | |||
149 | return (void __iomem *)vaddr; | ||
150 | } | ||
151 | |||
152 | static void __iomem *ghes_ioremap_pfn_irq(u64 pfn) | ||
153 | { | ||
154 | unsigned long vaddr; | ||
155 | |||
156 | vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr); | ||
157 | ioremap_page_range(vaddr, vaddr + PAGE_SIZE, | ||
158 | pfn << PAGE_SHIFT, PAGE_KERNEL); | ||
159 | |||
160 | return (void __iomem *)vaddr; | ||
161 | } | ||
162 | |||
163 | static void ghes_iounmap_nmi(void __iomem *vaddr_ptr) | ||
164 | { | ||
165 | unsigned long vaddr = (unsigned long __force)vaddr_ptr; | ||
166 | void *base = ghes_ioremap_area->addr; | ||
167 | |||
168 | BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base)); | ||
169 | unmap_kernel_range_noflush(vaddr, PAGE_SIZE); | ||
170 | __flush_tlb_one(vaddr); | ||
171 | } | ||
172 | |||
173 | static void ghes_iounmap_irq(void __iomem *vaddr_ptr) | ||
174 | { | ||
175 | unsigned long vaddr = (unsigned long __force)vaddr_ptr; | ||
176 | void *base = ghes_ioremap_area->addr; | ||
177 | |||
178 | BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base)); | ||
179 | unmap_kernel_range_noflush(vaddr, PAGE_SIZE); | ||
180 | __flush_tlb_one(vaddr); | ||
181 | } | ||
182 | |||
94 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) | 183 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) |
95 | { | 184 | { |
96 | struct ghes *ghes; | 185 | struct ghes *ghes; |
@@ -101,7 +190,6 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) | |||
101 | if (!ghes) | 190 | if (!ghes) |
102 | return ERR_PTR(-ENOMEM); | 191 | return ERR_PTR(-ENOMEM); |
103 | ghes->generic = generic; | 192 | ghes->generic = generic; |
104 | INIT_LIST_HEAD(&ghes->list); | ||
105 | rc = acpi_pre_map_gar(&generic->error_status_address); | 193 | rc = acpi_pre_map_gar(&generic->error_status_address); |
106 | if (rc) | 194 | if (rc) |
107 | goto err_free; | 195 | goto err_free; |
@@ -153,27 +241,46 @@ static inline int ghes_severity(int severity) | |||
153 | case CPER_SEV_FATAL: | 241 | case CPER_SEV_FATAL: |
154 | return GHES_SEV_PANIC; | 242 | return GHES_SEV_PANIC; |
155 | default: | 243 | default: |
156 | /* Unkown, go panic */ | 244 | /* Unknown, go panic */ |
157 | return GHES_SEV_PANIC; | 245 | return GHES_SEV_PANIC; |
158 | } | 246 | } |
159 | } | 247 | } |
160 | 248 | ||
161 | /* SCI handler run in work queue, so ioremap can be used here */ | 249 | static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, |
162 | static int ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, | 250 | int from_phys) |
163 | int from_phys) | ||
164 | { | 251 | { |
165 | void *vaddr; | 252 | void __iomem *vaddr; |
166 | 253 | unsigned long flags = 0; | |
167 | vaddr = ioremap_cache(paddr, len); | 254 | int in_nmi = in_nmi(); |
168 | if (!vaddr) | 255 | u64 offset; |
169 | return -ENOMEM; | 256 | u32 trunk; |
170 | if (from_phys) | 257 | |
171 | memcpy(buffer, vaddr, len); | 258 | while (len > 0) { |
172 | else | 259 | offset = paddr - (paddr & PAGE_MASK); |
173 | memcpy(vaddr, buffer, len); | 260 | if (in_nmi) { |
174 | iounmap(vaddr); | 261 | raw_spin_lock(&ghes_ioremap_lock_nmi); |
175 | 262 | vaddr = ghes_ioremap_pfn_nmi(paddr >> PAGE_SHIFT); | |
176 | return 0; | 263 | } else { |
264 | spin_lock_irqsave(&ghes_ioremap_lock_irq, flags); | ||
265 | vaddr = ghes_ioremap_pfn_irq(paddr >> PAGE_SHIFT); | ||
266 | } | ||
267 | trunk = PAGE_SIZE - offset; | ||
268 | trunk = min(trunk, len); | ||
269 | if (from_phys) | ||
270 | memcpy_fromio(buffer, vaddr + offset, trunk); | ||
271 | else | ||
272 | memcpy_toio(vaddr + offset, buffer, trunk); | ||
273 | len -= trunk; | ||
274 | paddr += trunk; | ||
275 | buffer += trunk; | ||
276 | if (in_nmi) { | ||
277 | ghes_iounmap_nmi(vaddr); | ||
278 | raw_spin_unlock(&ghes_ioremap_lock_nmi); | ||
279 | } else { | ||
280 | ghes_iounmap_irq(vaddr); | ||
281 | spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags); | ||
282 | } | ||
283 | } | ||
177 | } | 284 | } |
178 | 285 | ||
179 | static int ghes_read_estatus(struct ghes *ghes, int silent) | 286 | static int ghes_read_estatus(struct ghes *ghes, int silent) |
@@ -194,10 +301,8 @@ static int ghes_read_estatus(struct ghes *ghes, int silent) | |||
194 | if (!buf_paddr) | 301 | if (!buf_paddr) |
195 | return -ENOENT; | 302 | return -ENOENT; |
196 | 303 | ||
197 | rc = ghes_copy_tofrom_phys(ghes->estatus, buf_paddr, | 304 | ghes_copy_tofrom_phys(ghes->estatus, buf_paddr, |
198 | sizeof(*ghes->estatus), 1); | 305 | sizeof(*ghes->estatus), 1); |
199 | if (rc) | ||
200 | return rc; | ||
201 | if (!ghes->estatus->block_status) | 306 | if (!ghes->estatus->block_status) |
202 | return -ENOENT; | 307 | return -ENOENT; |
203 | 308 | ||
@@ -212,17 +317,15 @@ static int ghes_read_estatus(struct ghes *ghes, int silent) | |||
212 | goto err_read_block; | 317 | goto err_read_block; |
213 | if (apei_estatus_check_header(ghes->estatus)) | 318 | if (apei_estatus_check_header(ghes->estatus)) |
214 | goto err_read_block; | 319 | goto err_read_block; |
215 | rc = ghes_copy_tofrom_phys(ghes->estatus + 1, | 320 | ghes_copy_tofrom_phys(ghes->estatus + 1, |
216 | buf_paddr + sizeof(*ghes->estatus), | 321 | buf_paddr + sizeof(*ghes->estatus), |
217 | len - sizeof(*ghes->estatus), 1); | 322 | len - sizeof(*ghes->estatus), 1); |
218 | if (rc) | ||
219 | return rc; | ||
220 | if (apei_estatus_check(ghes->estatus)) | 323 | if (apei_estatus_check(ghes->estatus)) |
221 | goto err_read_block; | 324 | goto err_read_block; |
222 | rc = 0; | 325 | rc = 0; |
223 | 326 | ||
224 | err_read_block: | 327 | err_read_block: |
225 | if (rc && !silent) | 328 | if (rc && !silent && printk_ratelimit()) |
226 | pr_warning(FW_WARN GHES_PFX | 329 | pr_warning(FW_WARN GHES_PFX |
227 | "Failed to read error status block!\n"); | 330 | "Failed to read error status block!\n"); |
228 | return rc; | 331 | return rc; |
@@ -255,11 +358,26 @@ static void ghes_do_proc(struct ghes *ghes) | |||
255 | } | 358 | } |
256 | #endif | 359 | #endif |
257 | } | 360 | } |
361 | } | ||
258 | 362 | ||
259 | if (!processed && printk_ratelimit()) | 363 | static void ghes_print_estatus(const char *pfx, struct ghes *ghes) |
260 | pr_warning(GHES_PFX | 364 | { |
261 | "Unknown error record from generic hardware error source: %d\n", | 365 | /* Not more than 2 messages every 5 seconds */ |
262 | ghes->generic->header.source_id); | 366 | static DEFINE_RATELIMIT_STATE(ratelimit, 5*HZ, 2); |
367 | |||
368 | if (pfx == NULL) { | ||
369 | if (ghes_severity(ghes->estatus->error_severity) <= | ||
370 | GHES_SEV_CORRECTED) | ||
371 | pfx = KERN_WARNING HW_ERR; | ||
372 | else | ||
373 | pfx = KERN_ERR HW_ERR; | ||
374 | } | ||
375 | if (__ratelimit(&ratelimit)) { | ||
376 | printk( | ||
377 | "%s""Hardware error from APEI Generic Hardware Error Source: %d\n", | ||
378 | pfx, ghes->generic->header.source_id); | ||
379 | apei_estatus_print(pfx, ghes->estatus); | ||
380 | } | ||
263 | } | 381 | } |
264 | 382 | ||
265 | static int ghes_proc(struct ghes *ghes) | 383 | static int ghes_proc(struct ghes *ghes) |
@@ -269,6 +387,7 @@ static int ghes_proc(struct ghes *ghes) | |||
269 | rc = ghes_read_estatus(ghes, 0); | 387 | rc = ghes_read_estatus(ghes, 0); |
270 | if (rc) | 388 | if (rc) |
271 | goto out; | 389 | goto out; |
390 | ghes_print_estatus(NULL, ghes); | ||
272 | ghes_do_proc(ghes); | 391 | ghes_do_proc(ghes); |
273 | 392 | ||
274 | out: | 393 | out: |
@@ -276,6 +395,42 @@ out: | |||
276 | return 0; | 395 | return 0; |
277 | } | 396 | } |
278 | 397 | ||
398 | static void ghes_add_timer(struct ghes *ghes) | ||
399 | { | ||
400 | struct acpi_hest_generic *g = ghes->generic; | ||
401 | unsigned long expire; | ||
402 | |||
403 | if (!g->notify.poll_interval) { | ||
404 | pr_warning(FW_WARN GHES_PFX "Poll interval is 0 for generic hardware error source: %d, disabled.\n", | ||
405 | g->header.source_id); | ||
406 | return; | ||
407 | } | ||
408 | expire = jiffies + msecs_to_jiffies(g->notify.poll_interval); | ||
409 | ghes->timer.expires = round_jiffies_relative(expire); | ||
410 | add_timer(&ghes->timer); | ||
411 | } | ||
412 | |||
413 | static void ghes_poll_func(unsigned long data) | ||
414 | { | ||
415 | struct ghes *ghes = (void *)data; | ||
416 | |||
417 | ghes_proc(ghes); | ||
418 | if (!(ghes->flags & GHES_EXITING)) | ||
419 | ghes_add_timer(ghes); | ||
420 | } | ||
421 | |||
422 | static irqreturn_t ghes_irq_func(int irq, void *data) | ||
423 | { | ||
424 | struct ghes *ghes = data; | ||
425 | int rc; | ||
426 | |||
427 | rc = ghes_proc(ghes); | ||
428 | if (rc) | ||
429 | return IRQ_NONE; | ||
430 | |||
431 | return IRQ_HANDLED; | ||
432 | } | ||
433 | |||
279 | static int ghes_notify_sci(struct notifier_block *this, | 434 | static int ghes_notify_sci(struct notifier_block *this, |
280 | unsigned long event, void *data) | 435 | unsigned long event, void *data) |
281 | { | 436 | { |
@@ -292,10 +447,63 @@ static int ghes_notify_sci(struct notifier_block *this, | |||
292 | return ret; | 447 | return ret; |
293 | } | 448 | } |
294 | 449 | ||
450 | static int ghes_notify_nmi(struct notifier_block *this, | ||
451 | unsigned long cmd, void *data) | ||
452 | { | ||
453 | struct ghes *ghes, *ghes_global = NULL; | ||
454 | int sev, sev_global = -1; | ||
455 | int ret = NOTIFY_DONE; | ||
456 | |||
457 | if (cmd != DIE_NMI) | ||
458 | return ret; | ||
459 | |||
460 | raw_spin_lock(&ghes_nmi_lock); | ||
461 | list_for_each_entry_rcu(ghes, &ghes_nmi, list) { | ||
462 | if (ghes_read_estatus(ghes, 1)) { | ||
463 | ghes_clear_estatus(ghes); | ||
464 | continue; | ||
465 | } | ||
466 | sev = ghes_severity(ghes->estatus->error_severity); | ||
467 | if (sev > sev_global) { | ||
468 | sev_global = sev; | ||
469 | ghes_global = ghes; | ||
470 | } | ||
471 | ret = NOTIFY_STOP; | ||
472 | } | ||
473 | |||
474 | if (ret == NOTIFY_DONE) | ||
475 | goto out; | ||
476 | |||
477 | if (sev_global >= GHES_SEV_PANIC) { | ||
478 | oops_begin(); | ||
479 | ghes_print_estatus(KERN_EMERG HW_ERR, ghes_global); | ||
480 | /* reboot to log the error! */ | ||
481 | if (panic_timeout == 0) | ||
482 | panic_timeout = ghes_panic_timeout; | ||
483 | panic("Fatal hardware error!"); | ||
484 | } | ||
485 | |||
486 | list_for_each_entry_rcu(ghes, &ghes_nmi, list) { | ||
487 | if (!(ghes->flags & GHES_TO_CLEAR)) | ||
488 | continue; | ||
489 | /* Do not print estatus because printk is not NMI safe */ | ||
490 | ghes_do_proc(ghes); | ||
491 | ghes_clear_estatus(ghes); | ||
492 | } | ||
493 | |||
494 | out: | ||
495 | raw_spin_unlock(&ghes_nmi_lock); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
295 | static struct notifier_block ghes_notifier_sci = { | 499 | static struct notifier_block ghes_notifier_sci = { |
296 | .notifier_call = ghes_notify_sci, | 500 | .notifier_call = ghes_notify_sci, |
297 | }; | 501 | }; |
298 | 502 | ||
503 | static struct notifier_block ghes_notifier_nmi = { | ||
504 | .notifier_call = ghes_notify_nmi, | ||
505 | }; | ||
506 | |||
299 | static int __devinit ghes_probe(struct platform_device *ghes_dev) | 507 | static int __devinit ghes_probe(struct platform_device *ghes_dev) |
300 | { | 508 | { |
301 | struct acpi_hest_generic *generic; | 509 | struct acpi_hest_generic *generic; |
@@ -306,18 +514,27 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) | |||
306 | if (!generic->enabled) | 514 | if (!generic->enabled) |
307 | return -ENODEV; | 515 | return -ENODEV; |
308 | 516 | ||
309 | if (generic->error_block_length < | 517 | switch (generic->notify.type) { |
310 | sizeof(struct acpi_hest_generic_status)) { | 518 | case ACPI_HEST_NOTIFY_POLLED: |
311 | pr_warning(FW_BUG GHES_PFX | 519 | case ACPI_HEST_NOTIFY_EXTERNAL: |
312 | "Invalid error block length: %u for generic hardware error source: %d\n", | 520 | case ACPI_HEST_NOTIFY_SCI: |
313 | generic->error_block_length, | 521 | case ACPI_HEST_NOTIFY_NMI: |
522 | break; | ||
523 | case ACPI_HEST_NOTIFY_LOCAL: | ||
524 | pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n", | ||
314 | generic->header.source_id); | 525 | generic->header.source_id); |
315 | goto err; | 526 | goto err; |
527 | default: | ||
528 | pr_warning(FW_WARN GHES_PFX "Unknown notification type: %u for generic hardware error source: %d\n", | ||
529 | generic->notify.type, generic->header.source_id); | ||
530 | goto err; | ||
316 | } | 531 | } |
317 | if (generic->records_to_preallocate == 0) { | 532 | |
318 | pr_warning(FW_BUG GHES_PFX | 533 | rc = -EIO; |
319 | "Invalid records to preallocate: %u for generic hardware error source: %d\n", | 534 | if (generic->error_block_length < |
320 | generic->records_to_preallocate, | 535 | sizeof(struct acpi_hest_generic_status)) { |
536 | pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n", | ||
537 | generic->error_block_length, | ||
321 | generic->header.source_id); | 538 | generic->header.source_id); |
322 | goto err; | 539 | goto err; |
323 | } | 540 | } |
@@ -327,38 +544,43 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) | |||
327 | ghes = NULL; | 544 | ghes = NULL; |
328 | goto err; | 545 | goto err; |
329 | } | 546 | } |
330 | if (generic->notify.type == ACPI_HEST_NOTIFY_SCI) { | 547 | switch (generic->notify.type) { |
548 | case ACPI_HEST_NOTIFY_POLLED: | ||
549 | ghes->timer.function = ghes_poll_func; | ||
550 | ghes->timer.data = (unsigned long)ghes; | ||
551 | init_timer_deferrable(&ghes->timer); | ||
552 | ghes_add_timer(ghes); | ||
553 | break; | ||
554 | case ACPI_HEST_NOTIFY_EXTERNAL: | ||
555 | /* External interrupt vector is GSI */ | ||
556 | if (acpi_gsi_to_irq(generic->notify.vector, &ghes->irq)) { | ||
557 | pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n", | ||
558 | generic->header.source_id); | ||
559 | goto err; | ||
560 | } | ||
561 | if (request_irq(ghes->irq, ghes_irq_func, | ||
562 | 0, "GHES IRQ", ghes)) { | ||
563 | pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n", | ||
564 | generic->header.source_id); | ||
565 | goto err; | ||
566 | } | ||
567 | break; | ||
568 | case ACPI_HEST_NOTIFY_SCI: | ||
331 | mutex_lock(&ghes_list_mutex); | 569 | mutex_lock(&ghes_list_mutex); |
332 | if (list_empty(&ghes_sci)) | 570 | if (list_empty(&ghes_sci)) |
333 | register_acpi_hed_notifier(&ghes_notifier_sci); | 571 | register_acpi_hed_notifier(&ghes_notifier_sci); |
334 | list_add_rcu(&ghes->list, &ghes_sci); | 572 | list_add_rcu(&ghes->list, &ghes_sci); |
335 | mutex_unlock(&ghes_list_mutex); | 573 | mutex_unlock(&ghes_list_mutex); |
336 | } else { | 574 | break; |
337 | unsigned char *notify = NULL; | 575 | case ACPI_HEST_NOTIFY_NMI: |
338 | 576 | mutex_lock(&ghes_list_mutex); | |
339 | switch (generic->notify.type) { | 577 | if (list_empty(&ghes_nmi)) |
340 | case ACPI_HEST_NOTIFY_POLLED: | 578 | register_die_notifier(&ghes_notifier_nmi); |
341 | notify = "POLL"; | 579 | list_add_rcu(&ghes->list, &ghes_nmi); |
342 | break; | 580 | mutex_unlock(&ghes_list_mutex); |
343 | case ACPI_HEST_NOTIFY_EXTERNAL: | 581 | break; |
344 | case ACPI_HEST_NOTIFY_LOCAL: | 582 | default: |
345 | notify = "IRQ"; | 583 | BUG(); |
346 | break; | ||
347 | case ACPI_HEST_NOTIFY_NMI: | ||
348 | notify = "NMI"; | ||
349 | break; | ||
350 | } | ||
351 | if (notify) { | ||
352 | pr_warning(GHES_PFX | ||
353 | "Generic hardware error source: %d notified via %s is not supported!\n", | ||
354 | generic->header.source_id, notify); | ||
355 | } else { | ||
356 | pr_warning(FW_WARN GHES_PFX | ||
357 | "Unknown notification type: %u for generic hardware error source: %d\n", | ||
358 | generic->notify.type, generic->header.source_id); | ||
359 | } | ||
360 | rc = -ENODEV; | ||
361 | goto err; | ||
362 | } | 584 | } |
363 | platform_set_drvdata(ghes_dev, ghes); | 585 | platform_set_drvdata(ghes_dev, ghes); |
364 | 586 | ||
@@ -379,7 +601,14 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev) | |||
379 | ghes = platform_get_drvdata(ghes_dev); | 601 | ghes = platform_get_drvdata(ghes_dev); |
380 | generic = ghes->generic; | 602 | generic = ghes->generic; |
381 | 603 | ||
604 | ghes->flags |= GHES_EXITING; | ||
382 | switch (generic->notify.type) { | 605 | switch (generic->notify.type) { |
606 | case ACPI_HEST_NOTIFY_POLLED: | ||
607 | del_timer_sync(&ghes->timer); | ||
608 | break; | ||
609 | case ACPI_HEST_NOTIFY_EXTERNAL: | ||
610 | free_irq(ghes->irq, ghes); | ||
611 | break; | ||
383 | case ACPI_HEST_NOTIFY_SCI: | 612 | case ACPI_HEST_NOTIFY_SCI: |
384 | mutex_lock(&ghes_list_mutex); | 613 | mutex_lock(&ghes_list_mutex); |
385 | list_del_rcu(&ghes->list); | 614 | list_del_rcu(&ghes->list); |
@@ -387,12 +616,23 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev) | |||
387 | unregister_acpi_hed_notifier(&ghes_notifier_sci); | 616 | unregister_acpi_hed_notifier(&ghes_notifier_sci); |
388 | mutex_unlock(&ghes_list_mutex); | 617 | mutex_unlock(&ghes_list_mutex); |
389 | break; | 618 | break; |
619 | case ACPI_HEST_NOTIFY_NMI: | ||
620 | mutex_lock(&ghes_list_mutex); | ||
621 | list_del_rcu(&ghes->list); | ||
622 | if (list_empty(&ghes_nmi)) | ||
623 | unregister_die_notifier(&ghes_notifier_nmi); | ||
624 | mutex_unlock(&ghes_list_mutex); | ||
625 | /* | ||
626 | * To synchronize with NMI handler, ghes can only be | ||
627 | * freed after NMI handler finishes. | ||
628 | */ | ||
629 | synchronize_rcu(); | ||
630 | break; | ||
390 | default: | 631 | default: |
391 | BUG(); | 632 | BUG(); |
392 | break; | 633 | break; |
393 | } | 634 | } |
394 | 635 | ||
395 | synchronize_rcu(); | ||
396 | ghes_fini(ghes); | 636 | ghes_fini(ghes); |
397 | kfree(ghes); | 637 | kfree(ghes); |
398 | 638 | ||
@@ -412,6 +652,8 @@ static struct platform_driver ghes_platform_driver = { | |||
412 | 652 | ||
413 | static int __init ghes_init(void) | 653 | static int __init ghes_init(void) |
414 | { | 654 | { |
655 | int rc; | ||
656 | |||
415 | if (acpi_disabled) | 657 | if (acpi_disabled) |
416 | return -ENODEV; | 658 | return -ENODEV; |
417 | 659 | ||
@@ -420,12 +662,25 @@ static int __init ghes_init(void) | |||
420 | return -EINVAL; | 662 | return -EINVAL; |
421 | } | 663 | } |
422 | 664 | ||
423 | return platform_driver_register(&ghes_platform_driver); | 665 | rc = ghes_ioremap_init(); |
666 | if (rc) | ||
667 | goto err; | ||
668 | |||
669 | rc = platform_driver_register(&ghes_platform_driver); | ||
670 | if (rc) | ||
671 | goto err_ioremap_exit; | ||
672 | |||
673 | return 0; | ||
674 | err_ioremap_exit: | ||
675 | ghes_ioremap_exit(); | ||
676 | err: | ||
677 | return rc; | ||
424 | } | 678 | } |
425 | 679 | ||
426 | static void __exit ghes_exit(void) | 680 | static void __exit ghes_exit(void) |
427 | { | 681 | { |
428 | platform_driver_unregister(&ghes_platform_driver); | 682 | platform_driver_unregister(&ghes_platform_driver); |
683 | ghes_ioremap_exit(); | ||
429 | } | 684 | } |
430 | 685 | ||
431 | module_init(ghes_init); | 686 | module_init(ghes_init); |
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 1a3508a7fe03..181bc2f7bb74 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c | |||
@@ -46,9 +46,9 @@ EXPORT_SYMBOL_GPL(hest_disable); | |||
46 | 46 | ||
47 | /* HEST table parsing */ | 47 | /* HEST table parsing */ |
48 | 48 | ||
49 | static struct acpi_table_hest *hest_tab; | 49 | static struct acpi_table_hest *__read_mostly hest_tab; |
50 | 50 | ||
51 | static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { | 51 | static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { |
52 | [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ | 52 | [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ |
53 | [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, | 53 | [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, |
54 | [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi), | 54 | [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi), |
@@ -126,7 +126,7 @@ struct ghes_arr { | |||
126 | unsigned int count; | 126 | unsigned int count; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) | 129 | static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) |
130 | { | 130 | { |
131 | int *count = data; | 131 | int *count = data; |
132 | 132 | ||
@@ -135,17 +135,27 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) | |||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) | 138 | static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) |
139 | { | 139 | { |
140 | struct platform_device *ghes_dev; | 140 | struct platform_device *ghes_dev; |
141 | struct ghes_arr *ghes_arr = data; | 141 | struct ghes_arr *ghes_arr = data; |
142 | int rc; | 142 | int rc, i; |
143 | 143 | ||
144 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) | 144 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) |
145 | return 0; | 145 | return 0; |
146 | 146 | ||
147 | if (!((struct acpi_hest_generic *)hest_hdr)->enabled) | 147 | if (!((struct acpi_hest_generic *)hest_hdr)->enabled) |
148 | return 0; | 148 | return 0; |
149 | for (i = 0; i < ghes_arr->count; i++) { | ||
150 | struct acpi_hest_header *hdr; | ||
151 | ghes_dev = ghes_arr->ghes_devs[i]; | ||
152 | hdr = *(struct acpi_hest_header **)ghes_dev->dev.platform_data; | ||
153 | if (hdr->source_id == hest_hdr->source_id) { | ||
154 | pr_warning(FW_WARN HEST_PFX "Duplicated hardware error source ID: %d.\n", | ||
155 | hdr->source_id); | ||
156 | return -EIO; | ||
157 | } | ||
158 | } | ||
149 | ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); | 159 | ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); |
150 | if (!ghes_dev) | 160 | if (!ghes_dev) |
151 | return -ENOMEM; | 161 | return -ENOMEM; |
@@ -165,7 +175,7 @@ err: | |||
165 | return rc; | 175 | return rc; |
166 | } | 176 | } |
167 | 177 | ||
168 | static int hest_ghes_dev_register(unsigned int ghes_count) | 178 | static int __init hest_ghes_dev_register(unsigned int ghes_count) |
169 | { | 179 | { |
170 | int rc, i; | 180 | int rc, i; |
171 | struct ghes_arr ghes_arr; | 181 | struct ghes_arr ghes_arr; |
@@ -195,24 +205,24 @@ static int __init setup_hest_disable(char *str) | |||
195 | 205 | ||
196 | __setup("hest_disable", setup_hest_disable); | 206 | __setup("hest_disable", setup_hest_disable); |
197 | 207 | ||
198 | static int __init hest_init(void) | 208 | void __init acpi_hest_init(void) |
199 | { | 209 | { |
200 | acpi_status status; | 210 | acpi_status status; |
201 | int rc = -ENODEV; | 211 | int rc = -ENODEV; |
202 | unsigned int ghes_count = 0; | 212 | unsigned int ghes_count = 0; |
203 | 213 | ||
204 | if (acpi_disabled) | ||
205 | goto err; | ||
206 | |||
207 | if (hest_disable) { | 214 | if (hest_disable) { |
208 | pr_info(HEST_PFX "HEST tabling parsing is disabled.\n"); | 215 | pr_info(HEST_PFX "Table parsing disabled.\n"); |
209 | goto err; | 216 | return; |
210 | } | 217 | } |
211 | 218 | ||
219 | if (acpi_disabled) | ||
220 | goto err; | ||
221 | |||
212 | status = acpi_get_table(ACPI_SIG_HEST, 0, | 222 | status = acpi_get_table(ACPI_SIG_HEST, 0, |
213 | (struct acpi_table_header **)&hest_tab); | 223 | (struct acpi_table_header **)&hest_tab); |
214 | if (status == AE_NOT_FOUND) { | 224 | if (status == AE_NOT_FOUND) { |
215 | pr_info(HEST_PFX "Table is not found!\n"); | 225 | pr_info(HEST_PFX "Table not found.\n"); |
216 | goto err; | 226 | goto err; |
217 | } else if (ACPI_FAILURE(status)) { | 227 | } else if (ACPI_FAILURE(status)) { |
218 | const char *msg = acpi_format_exception(status); | 228 | const char *msg = acpi_format_exception(status); |
@@ -226,15 +236,11 @@ static int __init hest_init(void) | |||
226 | goto err; | 236 | goto err; |
227 | 237 | ||
228 | rc = hest_ghes_dev_register(ghes_count); | 238 | rc = hest_ghes_dev_register(ghes_count); |
229 | if (rc) | 239 | if (!rc) { |
230 | goto err; | 240 | pr_info(HEST_PFX "Table parsing has been initialized.\n"); |
231 | 241 | return; | |
232 | pr_info(HEST_PFX "HEST table parsing is initialized.\n"); | 242 | } |
233 | 243 | ||
234 | return 0; | ||
235 | err: | 244 | err: |
236 | hest_disable = 1; | 245 | hest_disable = 1; |
237 | return rc; | ||
238 | } | 246 | } |
239 | |||
240 | subsys_initcall(hest_init); | ||
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c index 542e53903891..7489b89c300f 100644 --- a/drivers/acpi/atomicio.c +++ b/drivers/acpi/atomicio.c | |||
@@ -280,9 +280,11 @@ static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width) | |||
280 | case 32: | 280 | case 32: |
281 | *val = readl(addr); | 281 | *val = readl(addr); |
282 | break; | 282 | break; |
283 | #ifdef readq | ||
283 | case 64: | 284 | case 64: |
284 | *val = readq(addr); | 285 | *val = readq(addr); |
285 | break; | 286 | break; |
287 | #endif | ||
286 | default: | 288 | default: |
287 | return -EINVAL; | 289 | return -EINVAL; |
288 | } | 290 | } |
@@ -307,9 +309,11 @@ static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width) | |||
307 | case 32: | 309 | case 32: |
308 | writel(val, addr); | 310 | writel(val, addr); |
309 | break; | 311 | break; |
312 | #ifdef writeq | ||
310 | case 64: | 313 | case 64: |
311 | writeq(val, addr); | 314 | writeq(val, addr); |
312 | break; | 315 | break; |
316 | #endif | ||
313 | default: | 317 | default: |
314 | return -EINVAL; | 318 | return -EINVAL; |
315 | } | 319 | } |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 98417201e9ce..fcc13ac0aa18 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/async.h> | 33 | #include <linux/async.h> |
34 | #include <linux/dmi.h> | 34 | #include <linux/dmi.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/suspend.h> | ||
36 | 37 | ||
37 | #ifdef CONFIG_ACPI_PROCFS_POWER | 38 | #ifdef CONFIG_ACPI_PROCFS_POWER |
38 | #include <linux/proc_fs.h> | 39 | #include <linux/proc_fs.h> |
@@ -42,10 +43,7 @@ | |||
42 | 43 | ||
43 | #include <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
44 | #include <acpi/acpi_drivers.h> | 45 | #include <acpi/acpi_drivers.h> |
45 | |||
46 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
47 | #include <linux/power_supply.h> | 46 | #include <linux/power_supply.h> |
48 | #endif | ||
49 | 47 | ||
50 | #define PREFIX "ACPI: " | 48 | #define PREFIX "ACPI: " |
51 | 49 | ||
@@ -98,14 +96,14 @@ enum { | |||
98 | * due to bad math. | 96 | * due to bad math. |
99 | */ | 97 | */ |
100 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, | 98 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, |
99 | ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, | ||
101 | }; | 100 | }; |
102 | 101 | ||
103 | struct acpi_battery { | 102 | struct acpi_battery { |
104 | struct mutex lock; | 103 | struct mutex lock; |
105 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
106 | struct power_supply bat; | 104 | struct power_supply bat; |
107 | #endif | ||
108 | struct acpi_device *device; | 105 | struct acpi_device *device; |
106 | struct notifier_block pm_nb; | ||
109 | unsigned long update_time; | 107 | unsigned long update_time; |
110 | int rate_now; | 108 | int rate_now; |
111 | int capacity_now; | 109 | int capacity_now; |
@@ -141,7 +139,6 @@ inline int acpi_battery_present(struct acpi_battery *battery) | |||
141 | return battery->device->status.battery_present; | 139 | return battery->device->status.battery_present; |
142 | } | 140 | } |
143 | 141 | ||
144 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
145 | static int acpi_battery_technology(struct acpi_battery *battery) | 142 | static int acpi_battery_technology(struct acpi_battery *battery) |
146 | { | 143 | { |
147 | if (!strcasecmp("NiCd", battery->type)) | 144 | if (!strcasecmp("NiCd", battery->type)) |
@@ -186,6 +183,7 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
186 | enum power_supply_property psp, | 183 | enum power_supply_property psp, |
187 | union power_supply_propval *val) | 184 | union power_supply_propval *val) |
188 | { | 185 | { |
186 | int ret = 0; | ||
189 | struct acpi_battery *battery = to_acpi_battery(psy); | 187 | struct acpi_battery *battery = to_acpi_battery(psy); |
190 | 188 | ||
191 | if (acpi_battery_present(battery)) { | 189 | if (acpi_battery_present(battery)) { |
@@ -214,26 +212,44 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
214 | val->intval = battery->cycle_count; | 212 | val->intval = battery->cycle_count; |
215 | break; | 213 | break; |
216 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 214 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
217 | val->intval = battery->design_voltage * 1000; | 215 | if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) |
216 | ret = -ENODEV; | ||
217 | else | ||
218 | val->intval = battery->design_voltage * 1000; | ||
218 | break; | 219 | break; |
219 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 220 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
220 | val->intval = battery->voltage_now * 1000; | 221 | if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) |
222 | ret = -ENODEV; | ||
223 | else | ||
224 | val->intval = battery->voltage_now * 1000; | ||
221 | break; | 225 | break; |
222 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 226 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
223 | case POWER_SUPPLY_PROP_POWER_NOW: | 227 | case POWER_SUPPLY_PROP_POWER_NOW: |
224 | val->intval = battery->rate_now * 1000; | 228 | if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) |
229 | ret = -ENODEV; | ||
230 | else | ||
231 | val->intval = battery->rate_now * 1000; | ||
225 | break; | 232 | break; |
226 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | 233 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: |
227 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | 234 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: |
228 | val->intval = battery->design_capacity * 1000; | 235 | if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
236 | ret = -ENODEV; | ||
237 | else | ||
238 | val->intval = battery->design_capacity * 1000; | ||
229 | break; | 239 | break; |
230 | case POWER_SUPPLY_PROP_CHARGE_FULL: | 240 | case POWER_SUPPLY_PROP_CHARGE_FULL: |
231 | case POWER_SUPPLY_PROP_ENERGY_FULL: | 241 | case POWER_SUPPLY_PROP_ENERGY_FULL: |
232 | val->intval = battery->full_charge_capacity * 1000; | 242 | if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
243 | ret = -ENODEV; | ||
244 | else | ||
245 | val->intval = battery->full_charge_capacity * 1000; | ||
233 | break; | 246 | break; |
234 | case POWER_SUPPLY_PROP_CHARGE_NOW: | 247 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
235 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 248 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
236 | val->intval = battery->capacity_now * 1000; | 249 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) |
250 | ret = -ENODEV; | ||
251 | else | ||
252 | val->intval = battery->capacity_now * 1000; | ||
237 | break; | 253 | break; |
238 | case POWER_SUPPLY_PROP_MODEL_NAME: | 254 | case POWER_SUPPLY_PROP_MODEL_NAME: |
239 | val->strval = battery->model_number; | 255 | val->strval = battery->model_number; |
@@ -245,9 +261,9 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
245 | val->strval = battery->serial_number; | 261 | val->strval = battery->serial_number; |
246 | break; | 262 | break; |
247 | default: | 263 | default: |
248 | return -EINVAL; | 264 | ret = -EINVAL; |
249 | } | 265 | } |
250 | return 0; | 266 | return ret; |
251 | } | 267 | } |
252 | 268 | ||
253 | static enum power_supply_property charge_battery_props[] = { | 269 | static enum power_supply_property charge_battery_props[] = { |
@@ -281,7 +297,6 @@ static enum power_supply_property energy_battery_props[] = { | |||
281 | POWER_SUPPLY_PROP_MANUFACTURER, | 297 | POWER_SUPPLY_PROP_MANUFACTURER, |
282 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 298 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
283 | }; | 299 | }; |
284 | #endif | ||
285 | 300 | ||
286 | #ifdef CONFIG_ACPI_PROCFS_POWER | 301 | #ifdef CONFIG_ACPI_PROCFS_POWER |
287 | inline char *acpi_battery_units(struct acpi_battery *battery) | 302 | inline char *acpi_battery_units(struct acpi_battery *battery) |
@@ -412,6 +427,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
412 | result = extract_package(battery, buffer.pointer, | 427 | result = extract_package(battery, buffer.pointer, |
413 | info_offsets, ARRAY_SIZE(info_offsets)); | 428 | info_offsets, ARRAY_SIZE(info_offsets)); |
414 | kfree(buffer.pointer); | 429 | kfree(buffer.pointer); |
430 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | ||
431 | battery->full_charge_capacity = battery->design_capacity; | ||
415 | return result; | 432 | return result; |
416 | } | 433 | } |
417 | 434 | ||
@@ -448,6 +465,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
448 | battery->rate_now != -1) | 465 | battery->rate_now != -1) |
449 | battery->rate_now = abs((s16)battery->rate_now); | 466 | battery->rate_now = abs((s16)battery->rate_now); |
450 | 467 | ||
468 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | ||
469 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) | ||
470 | battery->capacity_now = (battery->capacity_now * | ||
471 | battery->full_charge_capacity) / 100; | ||
451 | return result; | 472 | return result; |
452 | } | 473 | } |
453 | 474 | ||
@@ -492,7 +513,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) | |||
492 | return acpi_battery_set_alarm(battery); | 513 | return acpi_battery_set_alarm(battery); |
493 | } | 514 | } |
494 | 515 | ||
495 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
496 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 516 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
497 | struct device_attribute *attr, | 517 | struct device_attribute *attr, |
498 | char *buf) | 518 | char *buf) |
@@ -552,7 +572,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery) | |||
552 | power_supply_unregister(&battery->bat); | 572 | power_supply_unregister(&battery->bat); |
553 | battery->bat.dev = NULL; | 573 | battery->bat.dev = NULL; |
554 | } | 574 | } |
555 | #endif | ||
556 | 575 | ||
557 | static void acpi_battery_quirks(struct acpi_battery *battery) | 576 | static void acpi_battery_quirks(struct acpi_battery *battery) |
558 | { | 577 | { |
@@ -561,6 +580,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery) | |||
561 | } | 580 | } |
562 | } | 581 | } |
563 | 582 | ||
583 | /* | ||
584 | * According to the ACPI spec, some kinds of primary batteries can | ||
585 | * report percentage battery remaining capacity directly to OS. | ||
586 | * In this case, it reports the Last Full Charged Capacity == 100 | ||
587 | * and BatteryPresentRate == 0xFFFFFFFF. | ||
588 | * | ||
589 | * Now we found some battery reports percentage remaining capacity | ||
590 | * even if it's rechargeable. | ||
591 | * https://bugzilla.kernel.org/show_bug.cgi?id=15979 | ||
592 | * | ||
593 | * Handle this correctly so that they won't break userspace. | ||
594 | */ | ||
595 | static void acpi_battery_quirks2(struct acpi_battery *battery) | ||
596 | { | ||
597 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | ||
598 | return ; | ||
599 | |||
600 | if (battery->full_charge_capacity == 100 && | ||
601 | battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && | ||
602 | battery->capacity_now >=0 && battery->capacity_now <= 100) { | ||
603 | set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags); | ||
604 | battery->full_charge_capacity = battery->design_capacity; | ||
605 | battery->capacity_now = (battery->capacity_now * | ||
606 | battery->full_charge_capacity) / 100; | ||
607 | } | ||
608 | } | ||
609 | |||
564 | static int acpi_battery_update(struct acpi_battery *battery) | 610 | static int acpi_battery_update(struct acpi_battery *battery) |
565 | { | 611 | { |
566 | int result, old_present = acpi_battery_present(battery); | 612 | int result, old_present = acpi_battery_present(battery); |
@@ -568,9 +614,7 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
568 | if (result) | 614 | if (result) |
569 | return result; | 615 | return result; |
570 | if (!acpi_battery_present(battery)) { | 616 | if (!acpi_battery_present(battery)) { |
571 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
572 | sysfs_remove_battery(battery); | 617 | sysfs_remove_battery(battery); |
573 | #endif | ||
574 | battery->update_time = 0; | 618 | battery->update_time = 0; |
575 | return 0; | 619 | return 0; |
576 | } | 620 | } |
@@ -582,11 +626,22 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
582 | acpi_battery_quirks(battery); | 626 | acpi_battery_quirks(battery); |
583 | acpi_battery_init_alarm(battery); | 627 | acpi_battery_init_alarm(battery); |
584 | } | 628 | } |
585 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
586 | if (!battery->bat.dev) | 629 | if (!battery->bat.dev) |
587 | sysfs_add_battery(battery); | 630 | sysfs_add_battery(battery); |
588 | #endif | 631 | result = acpi_battery_get_state(battery); |
589 | return acpi_battery_get_state(battery); | 632 | acpi_battery_quirks2(battery); |
633 | return result; | ||
634 | } | ||
635 | |||
636 | static void acpi_battery_refresh(struct acpi_battery *battery) | ||
637 | { | ||
638 | if (!battery->bat.dev) | ||
639 | return; | ||
640 | |||
641 | acpi_battery_get_info(battery); | ||
642 | /* The battery may have changed its reporting units. */ | ||
643 | sysfs_remove_battery(battery); | ||
644 | sysfs_add_battery(battery); | ||
590 | } | 645 | } |
591 | 646 | ||
592 | /* -------------------------------------------------------------------------- | 647 | /* -------------------------------------------------------------------------- |
@@ -826,6 +881,8 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
826 | struct proc_dir_entry *entry = NULL; | 881 | struct proc_dir_entry *entry = NULL; |
827 | int i; | 882 | int i; |
828 | 883 | ||
884 | printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded," | ||
885 | " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); | ||
829 | if (!acpi_device_dir(device)) { | 886 | if (!acpi_device_dir(device)) { |
830 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 887 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), |
831 | acpi_battery_dir); | 888 | acpi_battery_dir); |
@@ -867,26 +924,37 @@ static void acpi_battery_remove_fs(struct acpi_device *device) | |||
867 | static void acpi_battery_notify(struct acpi_device *device, u32 event) | 924 | static void acpi_battery_notify(struct acpi_device *device, u32 event) |
868 | { | 925 | { |
869 | struct acpi_battery *battery = acpi_driver_data(device); | 926 | struct acpi_battery *battery = acpi_driver_data(device); |
870 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
871 | struct device *old; | 927 | struct device *old; |
872 | #endif | ||
873 | 928 | ||
874 | if (!battery) | 929 | if (!battery) |
875 | return; | 930 | return; |
876 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
877 | old = battery->bat.dev; | 931 | old = battery->bat.dev; |
878 | #endif | 932 | if (event == ACPI_BATTERY_NOTIFY_INFO) |
933 | acpi_battery_refresh(battery); | ||
879 | acpi_battery_update(battery); | 934 | acpi_battery_update(battery); |
880 | acpi_bus_generate_proc_event(device, event, | 935 | acpi_bus_generate_proc_event(device, event, |
881 | acpi_battery_present(battery)); | 936 | acpi_battery_present(battery)); |
882 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 937 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
883 | dev_name(&device->dev), event, | 938 | dev_name(&device->dev), event, |
884 | acpi_battery_present(battery)); | 939 | acpi_battery_present(battery)); |
885 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
886 | /* acpi_battery_update could remove power_supply object */ | 940 | /* acpi_battery_update could remove power_supply object */ |
887 | if (old && battery->bat.dev) | 941 | if (old && battery->bat.dev) |
888 | power_supply_changed(&battery->bat); | 942 | power_supply_changed(&battery->bat); |
889 | #endif | 943 | } |
944 | |||
945 | static int battery_notify(struct notifier_block *nb, | ||
946 | unsigned long mode, void *_unused) | ||
947 | { | ||
948 | struct acpi_battery *battery = container_of(nb, struct acpi_battery, | ||
949 | pm_nb); | ||
950 | switch (mode) { | ||
951 | case PM_POST_SUSPEND: | ||
952 | sysfs_remove_battery(battery); | ||
953 | sysfs_add_battery(battery); | ||
954 | break; | ||
955 | } | ||
956 | |||
957 | return 0; | ||
890 | } | 958 | } |
891 | 959 | ||
892 | static int acpi_battery_add(struct acpi_device *device) | 960 | static int acpi_battery_add(struct acpi_device *device) |
@@ -921,6 +989,10 @@ static int acpi_battery_add(struct acpi_device *device) | |||
921 | #endif | 989 | #endif |
922 | kfree(battery); | 990 | kfree(battery); |
923 | } | 991 | } |
992 | |||
993 | battery->pm_nb.notifier_call = battery_notify; | ||
994 | register_pm_notifier(&battery->pm_nb); | ||
995 | |||
924 | return result; | 996 | return result; |
925 | } | 997 | } |
926 | 998 | ||
@@ -931,12 +1003,11 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
931 | if (!device || !acpi_driver_data(device)) | 1003 | if (!device || !acpi_driver_data(device)) |
932 | return -EINVAL; | 1004 | return -EINVAL; |
933 | battery = acpi_driver_data(device); | 1005 | battery = acpi_driver_data(device); |
1006 | unregister_pm_notifier(&battery->pm_nb); | ||
934 | #ifdef CONFIG_ACPI_PROCFS_POWER | 1007 | #ifdef CONFIG_ACPI_PROCFS_POWER |
935 | acpi_battery_remove_fs(device); | 1008 | acpi_battery_remove_fs(device); |
936 | #endif | 1009 | #endif |
937 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
938 | sysfs_remove_battery(battery); | 1010 | sysfs_remove_battery(battery); |
939 | #endif | ||
940 | mutex_destroy(&battery->lock); | 1011 | mutex_destroy(&battery->lock); |
941 | kfree(battery); | 1012 | kfree(battery); |
942 | return 0; | 1013 | return 0; |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 310e3b9749cb..d1e06c182cdb 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <acpi/acpi_bus.h> | 40 | #include <acpi/acpi_bus.h> |
41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
42 | #include <linux/dmi.h> | 42 | #include <linux/dmi.h> |
43 | #include <linux/suspend.h> | ||
43 | 44 | ||
44 | #include "internal.h" | 45 | #include "internal.h" |
45 | 46 | ||
@@ -52,22 +53,6 @@ EXPORT_SYMBOL(acpi_root_dir); | |||
52 | 53 | ||
53 | #define STRUCT_TO_INT(s) (*((int*)&s)) | 54 | #define STRUCT_TO_INT(s) (*((int*)&s)) |
54 | 55 | ||
55 | static int set_power_nocheck(const struct dmi_system_id *id) | ||
56 | { | ||
57 | printk(KERN_NOTICE PREFIX "%s detected - " | ||
58 | "disable power check in power transition\n", id->ident); | ||
59 | acpi_power_nocheck = 1; | ||
60 | return 0; | ||
61 | } | ||
62 | static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { | ||
63 | { | ||
64 | set_power_nocheck, "HP Pavilion 05", { | ||
65 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), | ||
66 | DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"), | ||
67 | DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL}, | ||
68 | {}, | ||
69 | }; | ||
70 | |||
71 | 56 | ||
72 | #ifdef CONFIG_X86 | 57 | #ifdef CONFIG_X86 |
73 | static int set_copy_dsdt(const struct dmi_system_id *id) | 58 | static int set_copy_dsdt(const struct dmi_system_id *id) |
@@ -196,33 +181,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data); | |||
196 | Power Management | 181 | Power Management |
197 | -------------------------------------------------------------------------- */ | 182 | -------------------------------------------------------------------------- */ |
198 | 183 | ||
199 | int acpi_bus_get_power(acpi_handle handle, int *state) | 184 | static int __acpi_bus_get_power(struct acpi_device *device, int *state) |
200 | { | 185 | { |
201 | int result = 0; | 186 | int result = 0; |
202 | acpi_status status = 0; | 187 | acpi_status status = 0; |
203 | struct acpi_device *device = NULL; | ||
204 | unsigned long long psc = 0; | 188 | unsigned long long psc = 0; |
205 | 189 | ||
206 | 190 | if (!device || !state) | |
207 | result = acpi_bus_get_device(handle, &device); | 191 | return -EINVAL; |
208 | if (result) | ||
209 | return result; | ||
210 | 192 | ||
211 | *state = ACPI_STATE_UNKNOWN; | 193 | *state = ACPI_STATE_UNKNOWN; |
212 | 194 | ||
213 | if (!device->flags.power_manageable) { | 195 | if (device->flags.power_manageable) { |
214 | /* TBD: Non-recursive algorithm for walking up hierarchy */ | ||
215 | if (device->parent) | ||
216 | *state = device->parent->power.state; | ||
217 | else | ||
218 | *state = ACPI_STATE_D0; | ||
219 | } else { | ||
220 | /* | 196 | /* |
221 | * Get the device's power state either directly (via _PSC) or | 197 | * Get the device's power state either directly (via _PSC) or |
222 | * indirectly (via power resources). | 198 | * indirectly (via power resources). |
223 | */ | 199 | */ |
224 | if (device->power.flags.power_resources) { | 200 | if (device->power.flags.power_resources) { |
225 | result = acpi_power_get_inferred_state(device); | 201 | result = acpi_power_get_inferred_state(device, state); |
226 | if (result) | 202 | if (result) |
227 | return result; | 203 | return result; |
228 | } else if (device->power.flags.explicit_get) { | 204 | } else if (device->power.flags.explicit_get) { |
@@ -230,59 +206,33 @@ int acpi_bus_get_power(acpi_handle handle, int *state) | |||
230 | NULL, &psc); | 206 | NULL, &psc); |
231 | if (ACPI_FAILURE(status)) | 207 | if (ACPI_FAILURE(status)) |
232 | return -ENODEV; | 208 | return -ENODEV; |
233 | device->power.state = (int)psc; | 209 | *state = (int)psc; |
234 | } | 210 | } |
235 | 211 | } else { | |
236 | *state = device->power.state; | 212 | /* TBD: Non-recursive algorithm for walking up hierarchy. */ |
213 | *state = device->parent ? | ||
214 | device->parent->power.state : ACPI_STATE_D0; | ||
237 | } | 215 | } |
238 | 216 | ||
239 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", | 217 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", |
240 | device->pnp.bus_id, device->power.state)); | 218 | device->pnp.bus_id, *state)); |
241 | 219 | ||
242 | return 0; | 220 | return 0; |
243 | } | 221 | } |
244 | 222 | ||
245 | EXPORT_SYMBOL(acpi_bus_get_power); | ||
246 | 223 | ||
247 | int acpi_bus_set_power(acpi_handle handle, int state) | 224 | static int __acpi_bus_set_power(struct acpi_device *device, int state) |
248 | { | 225 | { |
249 | int result = 0; | 226 | int result = 0; |
250 | acpi_status status = AE_OK; | 227 | acpi_status status = AE_OK; |
251 | struct acpi_device *device = NULL; | ||
252 | char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; | 228 | char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; |
253 | 229 | ||
254 | 230 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) | |
255 | result = acpi_bus_get_device(handle, &device); | ||
256 | if (result) | ||
257 | return result; | ||
258 | |||
259 | if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) | ||
260 | return -EINVAL; | 231 | return -EINVAL; |
261 | 232 | ||
262 | /* Make sure this is a valid target state */ | 233 | /* Make sure this is a valid target state */ |
263 | 234 | ||
264 | if (!device->flags.power_manageable) { | 235 | if (state == device->power.state) { |
265 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", | ||
266 | kobject_name(&device->dev.kobj))); | ||
267 | return -ENODEV; | ||
268 | } | ||
269 | /* | ||
270 | * Get device's current power state | ||
271 | */ | ||
272 | if (!acpi_power_nocheck) { | ||
273 | /* | ||
274 | * Maybe the incorrect power state is returned on the bogus | ||
275 | * bios, which is different with the real power state. | ||
276 | * For example: the bios returns D0 state and the real power | ||
277 | * state is D3. OS expects to set the device to D0 state. In | ||
278 | * such case if OS uses the power state returned by the BIOS, | ||
279 | * the device can't be transisted to the correct power state. | ||
280 | * So if the acpi_power_nocheck is set, it is unnecessary to | ||
281 | * get the power state by calling acpi_bus_get_power. | ||
282 | */ | ||
283 | acpi_bus_get_power(device->handle, &device->power.state); | ||
284 | } | ||
285 | if ((state == device->power.state) && !device->flags.force_power_state) { | ||
286 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", | 236 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", |
287 | state)); | 237 | state)); |
288 | return 0; | 238 | return 0; |
@@ -351,8 +301,75 @@ int acpi_bus_set_power(acpi_handle handle, int state) | |||
351 | return result; | 301 | return result; |
352 | } | 302 | } |
353 | 303 | ||
304 | |||
305 | int acpi_bus_set_power(acpi_handle handle, int state) | ||
306 | { | ||
307 | struct acpi_device *device; | ||
308 | int result; | ||
309 | |||
310 | result = acpi_bus_get_device(handle, &device); | ||
311 | if (result) | ||
312 | return result; | ||
313 | |||
314 | if (!device->flags.power_manageable) { | ||
315 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
316 | "Device [%s] is not power manageable\n", | ||
317 | dev_name(&device->dev))); | ||
318 | return -ENODEV; | ||
319 | } | ||
320 | |||
321 | return __acpi_bus_set_power(device, state); | ||
322 | } | ||
354 | EXPORT_SYMBOL(acpi_bus_set_power); | 323 | EXPORT_SYMBOL(acpi_bus_set_power); |
355 | 324 | ||
325 | |||
326 | int acpi_bus_init_power(struct acpi_device *device) | ||
327 | { | ||
328 | int state; | ||
329 | int result; | ||
330 | |||
331 | if (!device) | ||
332 | return -EINVAL; | ||
333 | |||
334 | device->power.state = ACPI_STATE_UNKNOWN; | ||
335 | |||
336 | result = __acpi_bus_get_power(device, &state); | ||
337 | if (result) | ||
338 | return result; | ||
339 | |||
340 | if (device->power.flags.power_resources) | ||
341 | result = acpi_power_on_resources(device, state); | ||
342 | |||
343 | if (!result) | ||
344 | device->power.state = state; | ||
345 | |||
346 | return result; | ||
347 | } | ||
348 | |||
349 | |||
350 | int acpi_bus_update_power(acpi_handle handle, int *state_p) | ||
351 | { | ||
352 | struct acpi_device *device; | ||
353 | int state; | ||
354 | int result; | ||
355 | |||
356 | result = acpi_bus_get_device(handle, &device); | ||
357 | if (result) | ||
358 | return result; | ||
359 | |||
360 | result = __acpi_bus_get_power(device, &state); | ||
361 | if (result) | ||
362 | return result; | ||
363 | |||
364 | result = __acpi_bus_set_power(device, state); | ||
365 | if (!result && state_p) | ||
366 | *state_p = state; | ||
367 | |||
368 | return result; | ||
369 | } | ||
370 | EXPORT_SYMBOL_GPL(acpi_bus_update_power); | ||
371 | |||
372 | |||
356 | bool acpi_bus_power_manageable(acpi_handle handle) | 373 | bool acpi_bus_power_manageable(acpi_handle handle) |
357 | { | 374 | { |
358 | struct acpi_device *device; | 375 | struct acpi_device *device; |
@@ -935,6 +952,12 @@ static int __init acpi_bus_init(void) | |||
935 | goto error1; | 952 | goto error1; |
936 | } | 953 | } |
937 | 954 | ||
955 | /* | ||
956 | * _PDC control method may load dynamic SSDT tables, | ||
957 | * and we need to install the table handler before that. | ||
958 | */ | ||
959 | acpi_sysfs_init(); | ||
960 | |||
938 | acpi_early_processor_set_pdc(); | 961 | acpi_early_processor_set_pdc(); |
939 | 962 | ||
940 | /* | 963 | /* |
@@ -984,8 +1007,7 @@ struct kobject *acpi_kobj; | |||
984 | 1007 | ||
985 | static int __init acpi_init(void) | 1008 | static int __init acpi_init(void) |
986 | { | 1009 | { |
987 | int result = 0; | 1010 | int result; |
988 | |||
989 | 1011 | ||
990 | if (acpi_disabled) { | 1012 | if (acpi_disabled) { |
991 | printk(KERN_INFO PREFIX "Interpreter disabled.\n"); | 1013 | printk(KERN_INFO PREFIX "Interpreter disabled.\n"); |
@@ -1000,37 +1022,18 @@ static int __init acpi_init(void) | |||
1000 | 1022 | ||
1001 | init_acpi_device_notify(); | 1023 | init_acpi_device_notify(); |
1002 | result = acpi_bus_init(); | 1024 | result = acpi_bus_init(); |
1003 | 1025 | if (result) { | |
1004 | if (!result) { | ||
1005 | pci_mmcfg_late_init(); | ||
1006 | if (!(pm_flags & PM_APM)) | ||
1007 | pm_flags |= PM_ACPI; | ||
1008 | else { | ||
1009 | printk(KERN_INFO PREFIX | ||
1010 | "APM is already active, exiting\n"); | ||
1011 | disable_acpi(); | ||
1012 | result = -ENODEV; | ||
1013 | } | ||
1014 | } else | ||
1015 | disable_acpi(); | 1026 | disable_acpi(); |
1016 | |||
1017 | if (acpi_disabled) | ||
1018 | return result; | 1027 | return result; |
1028 | } | ||
1019 | 1029 | ||
1020 | /* | 1030 | pci_mmcfg_late_init(); |
1021 | * If the laptop falls into the DMI check table, the power state check | ||
1022 | * will be disabled in the course of device power transition. | ||
1023 | */ | ||
1024 | dmi_check_system(power_nocheck_dmi_table); | ||
1025 | |||
1026 | acpi_scan_init(); | 1031 | acpi_scan_init(); |
1027 | acpi_ec_init(); | 1032 | acpi_ec_init(); |
1028 | acpi_power_init(); | ||
1029 | acpi_sysfs_init(); | ||
1030 | acpi_debugfs_init(); | 1033 | acpi_debugfs_init(); |
1031 | acpi_sleep_proc_init(); | 1034 | acpi_sleep_proc_init(); |
1032 | acpi_wakeup_device_init(); | 1035 | acpi_wakeup_device_init(); |
1033 | return result; | 1036 | return 0; |
1034 | } | 1037 | } |
1035 | 1038 | ||
1036 | subsys_initcall(acpi_init); | 1039 | subsys_initcall(acpi_init); |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1575a9b51f1d..d27d072472f9 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -78,8 +78,6 @@ static int acpi_button_add(struct acpi_device *device); | |||
78 | static int acpi_button_remove(struct acpi_device *device, int type); | 78 | static int acpi_button_remove(struct acpi_device *device, int type); |
79 | static int acpi_button_resume(struct acpi_device *device); | 79 | static int acpi_button_resume(struct acpi_device *device); |
80 | static void acpi_button_notify(struct acpi_device *device, u32 event); | 80 | static void acpi_button_notify(struct acpi_device *device, u32 event); |
81 | static int acpi_button_info_open_fs(struct inode *inode, struct file *file); | ||
82 | static int acpi_button_state_open_fs(struct inode *inode, struct file *file); | ||
83 | 81 | ||
84 | static struct acpi_driver acpi_button_driver = { | 82 | static struct acpi_driver acpi_button_driver = { |
85 | .name = "button", | 83 | .name = "button", |
@@ -98,22 +96,7 @@ struct acpi_button { | |||
98 | struct input_dev *input; | 96 | struct input_dev *input; |
99 | char phys[32]; /* for input device */ | 97 | char phys[32]; /* for input device */ |
100 | unsigned long pushed; | 98 | unsigned long pushed; |
101 | }; | 99 | bool wakeup_enabled; |
102 | |||
103 | static const struct file_operations acpi_button_info_fops = { | ||
104 | .owner = THIS_MODULE, | ||
105 | .open = acpi_button_info_open_fs, | ||
106 | .read = seq_read, | ||
107 | .llseek = seq_lseek, | ||
108 | .release = single_release, | ||
109 | }; | ||
110 | |||
111 | static const struct file_operations acpi_button_state_fops = { | ||
112 | .owner = THIS_MODULE, | ||
113 | .open = acpi_button_state_open_fs, | ||
114 | .read = seq_read, | ||
115 | .llseek = seq_lseek, | ||
116 | .release = single_release, | ||
117 | }; | 100 | }; |
118 | 101 | ||
119 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); | 102 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); |
@@ -124,20 +107,7 @@ static struct acpi_device *lid_device; | |||
124 | -------------------------------------------------------------------------- */ | 107 | -------------------------------------------------------------------------- */ |
125 | 108 | ||
126 | static struct proc_dir_entry *acpi_button_dir; | 109 | static struct proc_dir_entry *acpi_button_dir; |
127 | 110 | static struct proc_dir_entry *acpi_lid_dir; | |
128 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) | ||
129 | { | ||
130 | struct acpi_device *device = seq->private; | ||
131 | |||
132 | seq_printf(seq, "type: %s\n", | ||
133 | acpi_device_name(device)); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int acpi_button_info_open_fs(struct inode *inode, struct file *file) | ||
138 | { | ||
139 | return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); | ||
140 | } | ||
141 | 111 | ||
142 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) | 112 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) |
143 | { | 113 | { |
@@ -157,77 +127,85 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file) | |||
157 | return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); | 127 | return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); |
158 | } | 128 | } |
159 | 129 | ||
160 | static struct proc_dir_entry *acpi_power_dir; | 130 | static const struct file_operations acpi_button_state_fops = { |
161 | static struct proc_dir_entry *acpi_sleep_dir; | 131 | .owner = THIS_MODULE, |
162 | static struct proc_dir_entry *acpi_lid_dir; | 132 | .open = acpi_button_state_open_fs, |
133 | .read = seq_read, | ||
134 | .llseek = seq_lseek, | ||
135 | .release = single_release, | ||
136 | }; | ||
163 | 137 | ||
164 | static int acpi_button_add_fs(struct acpi_device *device) | 138 | static int acpi_button_add_fs(struct acpi_device *device) |
165 | { | 139 | { |
166 | struct acpi_button *button = acpi_driver_data(device); | 140 | struct acpi_button *button = acpi_driver_data(device); |
167 | struct proc_dir_entry *entry = NULL; | 141 | struct proc_dir_entry *entry = NULL; |
142 | int ret = 0; | ||
168 | 143 | ||
169 | switch (button->type) { | 144 | /* procfs I/F for ACPI lid device only */ |
170 | case ACPI_BUTTON_TYPE_POWER: | 145 | if (button->type != ACPI_BUTTON_TYPE_LID) |
171 | if (!acpi_power_dir) | 146 | return 0; |
172 | acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, | 147 | |
173 | acpi_button_dir); | 148 | if (acpi_button_dir || acpi_lid_dir) { |
174 | entry = acpi_power_dir; | 149 | printk(KERN_ERR PREFIX "More than one Lid device found!\n"); |
175 | break; | 150 | return -EEXIST; |
176 | case ACPI_BUTTON_TYPE_SLEEP: | ||
177 | if (!acpi_sleep_dir) | ||
178 | acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, | ||
179 | acpi_button_dir); | ||
180 | entry = acpi_sleep_dir; | ||
181 | break; | ||
182 | case ACPI_BUTTON_TYPE_LID: | ||
183 | if (!acpi_lid_dir) | ||
184 | acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, | ||
185 | acpi_button_dir); | ||
186 | entry = acpi_lid_dir; | ||
187 | break; | ||
188 | } | 151 | } |
189 | 152 | ||
190 | if (!entry) | 153 | /* create /proc/acpi/button */ |
154 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
155 | if (!acpi_button_dir) | ||
191 | return -ENODEV; | 156 | return -ENODEV; |
192 | 157 | ||
193 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); | 158 | /* create /proc/acpi/button/lid */ |
194 | if (!acpi_device_dir(device)) | 159 | acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); |
195 | return -ENODEV; | 160 | if (!acpi_lid_dir) { |
161 | ret = -ENODEV; | ||
162 | goto remove_button_dir; | ||
163 | } | ||
196 | 164 | ||
197 | /* 'info' [R] */ | 165 | /* create /proc/acpi/button/lid/LID/ */ |
198 | entry = proc_create_data(ACPI_BUTTON_FILE_INFO, | 166 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir); |
199 | S_IRUGO, acpi_device_dir(device), | 167 | if (!acpi_device_dir(device)) { |
200 | &acpi_button_info_fops, device); | 168 | ret = -ENODEV; |
201 | if (!entry) | 169 | goto remove_lid_dir; |
202 | return -ENODEV; | 170 | } |
203 | 171 | ||
204 | /* show lid state [R] */ | 172 | /* create /proc/acpi/button/lid/LID/state */ |
205 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 173 | entry = proc_create_data(ACPI_BUTTON_FILE_STATE, |
206 | entry = proc_create_data(ACPI_BUTTON_FILE_STATE, | 174 | S_IRUGO, acpi_device_dir(device), |
207 | S_IRUGO, acpi_device_dir(device), | 175 | &acpi_button_state_fops, device); |
208 | &acpi_button_state_fops, device); | 176 | if (!entry) { |
209 | if (!entry) | 177 | ret = -ENODEV; |
210 | return -ENODEV; | 178 | goto remove_dev_dir; |
211 | } | 179 | } |
212 | 180 | ||
213 | return 0; | 181 | done: |
182 | return ret; | ||
183 | |||
184 | remove_dev_dir: | ||
185 | remove_proc_entry(acpi_device_bid(device), | ||
186 | acpi_lid_dir); | ||
187 | acpi_device_dir(device) = NULL; | ||
188 | remove_lid_dir: | ||
189 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
190 | remove_button_dir: | ||
191 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
192 | goto done; | ||
214 | } | 193 | } |
215 | 194 | ||
216 | static int acpi_button_remove_fs(struct acpi_device *device) | 195 | static int acpi_button_remove_fs(struct acpi_device *device) |
217 | { | 196 | { |
218 | struct acpi_button *button = acpi_driver_data(device); | 197 | struct acpi_button *button = acpi_driver_data(device); |
219 | 198 | ||
220 | if (acpi_device_dir(device)) { | 199 | if (button->type != ACPI_BUTTON_TYPE_LID) |
221 | if (button->type == ACPI_BUTTON_TYPE_LID) | 200 | return 0; |
222 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, | ||
223 | acpi_device_dir(device)); | ||
224 | remove_proc_entry(ACPI_BUTTON_FILE_INFO, | ||
225 | acpi_device_dir(device)); | ||
226 | 201 | ||
227 | remove_proc_entry(acpi_device_bid(device), | 202 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, |
228 | acpi_device_dir(device)->parent); | 203 | acpi_device_dir(device)); |
229 | acpi_device_dir(device) = NULL; | 204 | remove_proc_entry(acpi_device_bid(device), |
230 | } | 205 | acpi_lid_dir); |
206 | acpi_device_dir(device) = NULL; | ||
207 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
208 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
231 | 209 | ||
232 | return 0; | 210 | return 0; |
233 | } | 211 | } |
@@ -279,6 +257,9 @@ static int acpi_lid_send_state(struct acpi_device *device) | |||
279 | input_report_switch(button->input, SW_LID, !state); | 257 | input_report_switch(button->input, SW_LID, !state); |
280 | input_sync(button->input); | 258 | input_sync(button->input); |
281 | 259 | ||
260 | if (state) | ||
261 | pm_wakeup_event(&device->dev, 0); | ||
262 | |||
282 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | 263 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); |
283 | if (ret == NOTIFY_DONE) | 264 | if (ret == NOTIFY_DONE) |
284 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, | 265 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, |
@@ -314,6 +295,8 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
314 | input_sync(input); | 295 | input_sync(input); |
315 | input_report_key(input, keycode, 0); | 296 | input_report_key(input, keycode, 0); |
316 | input_sync(input); | 297 | input_sync(input); |
298 | |||
299 | pm_wakeup_event(&device->dev, 0); | ||
317 | } | 300 | } |
318 | 301 | ||
319 | acpi_bus_generate_proc_event(device, event, ++button->pushed); | 302 | acpi_bus_generate_proc_event(device, event, ++button->pushed); |
@@ -338,7 +321,8 @@ static int acpi_button_add(struct acpi_device *device) | |||
338 | { | 321 | { |
339 | struct acpi_button *button; | 322 | struct acpi_button *button; |
340 | struct input_dev *input; | 323 | struct input_dev *input; |
341 | char *hid, *name, *class; | 324 | const char *hid = acpi_device_hid(device); |
325 | char *name, *class; | ||
342 | int error; | 326 | int error; |
343 | 327 | ||
344 | button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); | 328 | button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); |
@@ -353,7 +337,6 @@ static int acpi_button_add(struct acpi_device *device) | |||
353 | goto err_free_button; | 337 | goto err_free_button; |
354 | } | 338 | } |
355 | 339 | ||
356 | hid = acpi_device_hid(device); | ||
357 | name = acpi_device_name(device); | 340 | name = acpi_device_name(device); |
358 | class = acpi_device_class(device); | 341 | class = acpi_device_class(device); |
359 | 342 | ||
@@ -425,8 +408,10 @@ static int acpi_button_add(struct acpi_device *device) | |||
425 | /* Button's GPE is run-wake GPE */ | 408 | /* Button's GPE is run-wake GPE */ |
426 | acpi_enable_gpe(device->wakeup.gpe_device, | 409 | acpi_enable_gpe(device->wakeup.gpe_device, |
427 | device->wakeup.gpe_number); | 410 | device->wakeup.gpe_number); |
428 | device->wakeup.run_wake_count++; | 411 | if (!device_may_wakeup(&device->dev)) { |
429 | device->wakeup.state.enabled = 1; | 412 | device_set_wakeup_enable(&device->dev, true); |
413 | button->wakeup_enabled = true; | ||
414 | } | ||
430 | } | 415 | } |
431 | 416 | ||
432 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); | 417 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); |
@@ -448,8 +433,8 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
448 | if (device->wakeup.flags.valid) { | 433 | if (device->wakeup.flags.valid) { |
449 | acpi_disable_gpe(device->wakeup.gpe_device, | 434 | acpi_disable_gpe(device->wakeup.gpe_device, |
450 | device->wakeup.gpe_number); | 435 | device->wakeup.gpe_number); |
451 | device->wakeup.run_wake_count--; | 436 | if (button->wakeup_enabled) |
452 | device->wakeup.state.enabled = 0; | 437 | device_set_wakeup_enable(&device->dev, false); |
453 | } | 438 | } |
454 | 439 | ||
455 | acpi_button_remove_fs(device); | 440 | acpi_button_remove_fs(device); |
@@ -460,32 +445,12 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
460 | 445 | ||
461 | static int __init acpi_button_init(void) | 446 | static int __init acpi_button_init(void) |
462 | { | 447 | { |
463 | int result; | 448 | return acpi_bus_register_driver(&acpi_button_driver); |
464 | |||
465 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
466 | if (!acpi_button_dir) | ||
467 | return -ENODEV; | ||
468 | |||
469 | result = acpi_bus_register_driver(&acpi_button_driver); | ||
470 | if (result < 0) { | ||
471 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
472 | return -ENODEV; | ||
473 | } | ||
474 | |||
475 | return 0; | ||
476 | } | 449 | } |
477 | 450 | ||
478 | static void __exit acpi_button_exit(void) | 451 | static void __exit acpi_button_exit(void) |
479 | { | 452 | { |
480 | acpi_bus_unregister_driver(&acpi_button_driver); | 453 | acpi_bus_unregister_driver(&acpi_button_driver); |
481 | |||
482 | if (acpi_power_dir) | ||
483 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); | ||
484 | if (acpi_sleep_dir) | ||
485 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); | ||
486 | if (acpi_lid_dir) | ||
487 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
488 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
489 | } | 454 | } |
490 | 455 | ||
491 | module_init(acpi_button_init); | 456 | module_init(acpi_button_init); |
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c new file mode 100644 index 000000000000..5d42c2414ae5 --- /dev/null +++ b/drivers/acpi/custom_method.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * debugfs.c - ACPI debugfs interface to userspace. | ||
3 | */ | ||
4 | |||
5 | #include <linux/init.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/uaccess.h> | ||
9 | #include <linux/debugfs.h> | ||
10 | #include <acpi/acpi_drivers.h> | ||
11 | |||
12 | #include "internal.h" | ||
13 | |||
14 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | ||
15 | ACPI_MODULE_NAME("custom_method"); | ||
16 | MODULE_LICENSE("GPL"); | ||
17 | |||
18 | static struct dentry *cm_dentry; | ||
19 | |||
20 | /* /sys/kernel/debug/acpi/custom_method */ | ||
21 | |||
22 | static ssize_t cm_write(struct file *file, const char __user * user_buf, | ||
23 | size_t count, loff_t *ppos) | ||
24 | { | ||
25 | static char *buf; | ||
26 | static u32 max_size; | ||
27 | static u32 uncopied_bytes; | ||
28 | |||
29 | struct acpi_table_header table; | ||
30 | acpi_status status; | ||
31 | |||
32 | if (!(*ppos)) { | ||
33 | /* parse the table header to get the table length */ | ||
34 | if (count <= sizeof(struct acpi_table_header)) | ||
35 | return -EINVAL; | ||
36 | if (copy_from_user(&table, user_buf, | ||
37 | sizeof(struct acpi_table_header))) | ||
38 | return -EFAULT; | ||
39 | uncopied_bytes = max_size = table.length; | ||
40 | buf = kzalloc(max_size, GFP_KERNEL); | ||
41 | if (!buf) | ||
42 | return -ENOMEM; | ||
43 | } | ||
44 | |||
45 | if (buf == NULL) | ||
46 | return -EINVAL; | ||
47 | |||
48 | if ((*ppos > max_size) || | ||
49 | (*ppos + count > max_size) || | ||
50 | (*ppos + count < count) || | ||
51 | (count > uncopied_bytes)) | ||
52 | return -EINVAL; | ||
53 | |||
54 | if (copy_from_user(buf + (*ppos), user_buf, count)) { | ||
55 | kfree(buf); | ||
56 | buf = NULL; | ||
57 | return -EFAULT; | ||
58 | } | ||
59 | |||
60 | uncopied_bytes -= count; | ||
61 | *ppos += count; | ||
62 | |||
63 | if (!uncopied_bytes) { | ||
64 | status = acpi_install_method(buf); | ||
65 | kfree(buf); | ||
66 | buf = NULL; | ||
67 | if (ACPI_FAILURE(status)) | ||
68 | return -EINVAL; | ||
69 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); | ||
70 | } | ||
71 | |||
72 | return count; | ||
73 | } | ||
74 | |||
75 | static const struct file_operations cm_fops = { | ||
76 | .write = cm_write, | ||
77 | .llseek = default_llseek, | ||
78 | }; | ||
79 | |||
80 | static int __init acpi_custom_method_init(void) | ||
81 | { | ||
82 | if (acpi_debugfs_dir == NULL) | ||
83 | return -ENOENT; | ||
84 | |||
85 | cm_dentry = debugfs_create_file("custom_method", S_IWUSR, | ||
86 | acpi_debugfs_dir, NULL, &cm_fops); | ||
87 | if (cm_dentry == NULL) | ||
88 | return -ENODEV; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void __exit acpi_custom_method_exit(void) | ||
94 | { | ||
95 | if (cm_dentry) | ||
96 | debugfs_remove(cm_dentry); | ||
97 | } | ||
98 | |||
99 | module_init(acpi_custom_method_init); | ||
100 | module_exit(acpi_custom_method_exit); | ||
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c index 7de27d49c4b9..182a9fc36355 100644 --- a/drivers/acpi/debugfs.c +++ b/drivers/acpi/debugfs.c | |||
@@ -3,91 +3,16 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
6 | #include <linux/module.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/uaccess.h> | ||
9 | #include <linux/debugfs.h> | 6 | #include <linux/debugfs.h> |
10 | #include <acpi/acpi_drivers.h> | 7 | #include <acpi/acpi_drivers.h> |
11 | 8 | ||
12 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 9 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
13 | ACPI_MODULE_NAME("debugfs"); | 10 | ACPI_MODULE_NAME("debugfs"); |
14 | 11 | ||
12 | struct dentry *acpi_debugfs_dir; | ||
13 | EXPORT_SYMBOL_GPL(acpi_debugfs_dir); | ||
15 | 14 | ||
16 | /* /sys/modules/acpi/parameters/aml_debug_output */ | 15 | void __init acpi_debugfs_init(void) |
17 | |||
18 | module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, | ||
19 | bool, 0644); | ||
20 | MODULE_PARM_DESC(aml_debug_output, | ||
21 | "To enable/disable the ACPI Debug Object output."); | ||
22 | |||
23 | /* /sys/kernel/debug/acpi/custom_method */ | ||
24 | |||
25 | static ssize_t cm_write(struct file *file, const char __user * user_buf, | ||
26 | size_t count, loff_t *ppos) | ||
27 | { | 16 | { |
28 | static char *buf; | 17 | acpi_debugfs_dir = debugfs_create_dir("acpi", NULL); |
29 | static int uncopied_bytes; | ||
30 | struct acpi_table_header table; | ||
31 | acpi_status status; | ||
32 | |||
33 | if (!(*ppos)) { | ||
34 | /* parse the table header to get the table length */ | ||
35 | if (count <= sizeof(struct acpi_table_header)) | ||
36 | return -EINVAL; | ||
37 | if (copy_from_user(&table, user_buf, | ||
38 | sizeof(struct acpi_table_header))) | ||
39 | return -EFAULT; | ||
40 | uncopied_bytes = table.length; | ||
41 | buf = kzalloc(uncopied_bytes, GFP_KERNEL); | ||
42 | if (!buf) | ||
43 | return -ENOMEM; | ||
44 | } | ||
45 | |||
46 | if (uncopied_bytes < count) { | ||
47 | kfree(buf); | ||
48 | return -EINVAL; | ||
49 | } | ||
50 | |||
51 | if (copy_from_user(buf + (*ppos), user_buf, count)) { | ||
52 | kfree(buf); | ||
53 | return -EFAULT; | ||
54 | } | ||
55 | |||
56 | uncopied_bytes -= count; | ||
57 | *ppos += count; | ||
58 | |||
59 | if (!uncopied_bytes) { | ||
60 | status = acpi_install_method(buf); | ||
61 | kfree(buf); | ||
62 | if (ACPI_FAILURE(status)) | ||
63 | return -EINVAL; | ||
64 | add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); | ||
65 | } | ||
66 | |||
67 | return count; | ||
68 | } | ||
69 | |||
70 | static const struct file_operations cm_fops = { | ||
71 | .write = cm_write, | ||
72 | }; | ||
73 | |||
74 | int __init acpi_debugfs_init(void) | ||
75 | { | ||
76 | struct dentry *acpi_dir, *cm_dentry; | ||
77 | |||
78 | acpi_dir = debugfs_create_dir("acpi", NULL); | ||
79 | if (!acpi_dir) | ||
80 | goto err; | ||
81 | |||
82 | cm_dentry = debugfs_create_file("custom_method", S_IWUGO, | ||
83 | acpi_dir, NULL, &cm_fops); | ||
84 | if (!cm_dentry) | ||
85 | goto err; | ||
86 | |||
87 | return 0; | ||
88 | |||
89 | err: | ||
90 | if (acpi_dir) | ||
91 | debugfs_remove(acpi_dir); | ||
92 | return -EINVAL; | ||
93 | } | 18 | } |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 3fe29e992be8..1864ad3cf895 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -725,6 +725,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
725 | complete_dock(ds); | 725 | complete_dock(ds); |
726 | dock_event(ds, event, DOCK_EVENT); | 726 | dock_event(ds, event, DOCK_EVENT); |
727 | dock_lock(ds, 1); | 727 | dock_lock(ds, 1); |
728 | acpi_update_all_gpes(); | ||
728 | break; | 729 | break; |
729 | } | 730 | } |
730 | if (dock_present(ds) || dock_in_progress(ds)) | 731 | if (dock_present(ds) || dock_in_progress(ds)) |
@@ -929,7 +930,7 @@ static struct attribute_group dock_attribute_group = { | |||
929 | * allocated and initialize a new dock station device. Find all devices | 930 | * allocated and initialize a new dock station device. Find all devices |
930 | * that are on the dock station, and register for dock event notifications. | 931 | * that are on the dock station, and register for dock event notifications. |
931 | */ | 932 | */ |
932 | static int dock_add(acpi_handle handle) | 933 | static int __init dock_add(acpi_handle handle) |
933 | { | 934 | { |
934 | int ret, id; | 935 | int ret, id; |
935 | struct dock_station ds, *dock_station; | 936 | struct dock_station ds, *dock_station; |
@@ -1023,7 +1024,7 @@ static int dock_remove(struct dock_station *ds) | |||
1023 | * | 1024 | * |
1024 | * This is called by acpi_walk_namespace to look for dock stations. | 1025 | * This is called by acpi_walk_namespace to look for dock stations. |
1025 | */ | 1026 | */ |
1026 | static acpi_status | 1027 | static __init acpi_status |
1027 | find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) | 1028 | find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) |
1028 | { | 1029 | { |
1029 | if (is_dock(handle)) | 1030 | if (is_dock(handle)) |
@@ -1032,7 +1033,7 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
1032 | return AE_OK; | 1033 | return AE_OK; |
1033 | } | 1034 | } |
1034 | 1035 | ||
1035 | static acpi_status | 1036 | static __init acpi_status |
1036 | find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) | 1037 | find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) |
1037 | { | 1038 | { |
1038 | /* If bay is a dock, it's already handled */ | 1039 | /* If bay is a dock, it's already handled */ |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index f31291ba94d0..b19a18dd994f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -69,7 +69,6 @@ enum ec_command { | |||
69 | 69 | ||
70 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ | 70 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ |
71 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 71 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
72 | #define ACPI_EC_CDELAY 10 /* Wait 10us before polling EC */ | ||
73 | #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ | 72 | #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ |
74 | 73 | ||
75 | #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts | 74 | #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts |
@@ -83,6 +82,11 @@ enum { | |||
83 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ | 82 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ |
84 | }; | 83 | }; |
85 | 84 | ||
85 | /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ | ||
86 | static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; | ||
87 | module_param(ec_delay, uint, 0644); | ||
88 | MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); | ||
89 | |||
86 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 90 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
87 | /* External interfaces use first EC only, so remember */ | 91 | /* External interfaces use first EC only, so remember */ |
88 | typedef int (*acpi_ec_query_func) (void *data); | 92 | typedef int (*acpi_ec_query_func) (void *data); |
@@ -210,7 +214,7 @@ static int ec_poll(struct acpi_ec *ec) | |||
210 | int repeat = 2; /* number of command restarts */ | 214 | int repeat = 2; /* number of command restarts */ |
211 | while (repeat--) { | 215 | while (repeat--) { |
212 | unsigned long delay = jiffies + | 216 | unsigned long delay = jiffies + |
213 | msecs_to_jiffies(ACPI_EC_DELAY); | 217 | msecs_to_jiffies(ec_delay); |
214 | do { | 218 | do { |
215 | /* don't sleep with disabled interrupts */ | 219 | /* don't sleep with disabled interrupts */ |
216 | if (EC_FLAGS_MSI || irqs_disabled()) { | 220 | if (EC_FLAGS_MSI || irqs_disabled()) { |
@@ -265,7 +269,7 @@ static int ec_check_ibf0(struct acpi_ec *ec) | |||
265 | 269 | ||
266 | static int ec_wait_ibf0(struct acpi_ec *ec) | 270 | static int ec_wait_ibf0(struct acpi_ec *ec) |
267 | { | 271 | { |
268 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 272 | unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); |
269 | /* interrupt wait manually if GPE mode is not active */ | 273 | /* interrupt wait manually if GPE mode is not active */ |
270 | while (time_before(jiffies, delay)) | 274 | while (time_before(jiffies, delay)) |
271 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), | 275 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), |
@@ -428,8 +432,7 @@ EXPORT_SYMBOL(ec_write); | |||
428 | 432 | ||
429 | int ec_transaction(u8 command, | 433 | int ec_transaction(u8 command, |
430 | const u8 * wdata, unsigned wdata_len, | 434 | const u8 * wdata, unsigned wdata_len, |
431 | u8 * rdata, unsigned rdata_len, | 435 | u8 * rdata, unsigned rdata_len) |
432 | int force_poll) | ||
433 | { | 436 | { |
434 | struct transaction t = {.command = command, | 437 | struct transaction t = {.command = command, |
435 | .wdata = wdata, .rdata = rdata, | 438 | .wdata = wdata, .rdata = rdata, |
@@ -587,8 +590,6 @@ static void acpi_ec_gpe_query(void *ec_cxt) | |||
587 | mutex_unlock(&ec->lock); | 590 | mutex_unlock(&ec->lock); |
588 | } | 591 | } |
589 | 592 | ||
590 | static void acpi_ec_gpe_query(void *ec_cxt); | ||
591 | |||
592 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | 593 | static int ec_check_sci(struct acpi_ec *ec, u8 state) |
593 | { | 594 | { |
594 | if (state & ACPI_EC_FLAG_SCI) { | 595 | if (state & ACPI_EC_FLAG_SCI) { |
@@ -601,7 +602,8 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) | |||
601 | return 0; | 602 | return 0; |
602 | } | 603 | } |
603 | 604 | ||
604 | static u32 acpi_ec_gpe_handler(void *data) | 605 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, |
606 | u32 gpe_number, void *data) | ||
605 | { | 607 | { |
606 | struct acpi_ec *ec = data; | 608 | struct acpi_ec *ec = data; |
607 | 609 | ||
@@ -613,7 +615,7 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
613 | wake_up(&ec->wait); | 615 | wake_up(&ec->wait); |
614 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 616 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
615 | } | 617 | } |
616 | return ACPI_INTERRUPT_HANDLED; | 618 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; |
617 | } | 619 | } |
618 | 620 | ||
619 | /* -------------------------------------------------------------------------- | 621 | /* -------------------------------------------------------------------------- |
@@ -802,8 +804,6 @@ static int acpi_ec_add(struct acpi_device *device) | |||
802 | return -EINVAL; | 804 | return -EINVAL; |
803 | } | 805 | } |
804 | 806 | ||
805 | ec->handle = device->handle; | ||
806 | |||
807 | /* Find and register all query methods */ | 807 | /* Find and register all query methods */ |
808 | acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, | 808 | acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, |
809 | acpi_ec_register_query_methods, NULL, ec, NULL); | 809 | acpi_ec_register_query_methods, NULL, ec, NULL); |
@@ -929,8 +929,22 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { | |||
929 | ec_flag_msi, "MSI hardware", { | 929 | ec_flag_msi, "MSI hardware", { |
930 | DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, | 930 | DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, |
931 | { | 931 | { |
932 | ec_flag_msi, "MSI hardware", { | ||
933 | DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL}, | ||
934 | { | ||
935 | ec_flag_msi, "Quanta hardware", { | ||
936 | DMI_MATCH(DMI_SYS_VENDOR, "Quanta"), | ||
937 | DMI_MATCH(DMI_PRODUCT_NAME, "TW8/SW8/DW8"),}, NULL}, | ||
938 | { | ||
939 | ec_flag_msi, "Quanta hardware", { | ||
940 | DMI_MATCH(DMI_SYS_VENDOR, "Quanta"), | ||
941 | DMI_MATCH(DMI_PRODUCT_NAME, "TW9/SW9"),}, NULL}, | ||
942 | { | ||
932 | ec_validate_ecdt, "ASUS hardware", { | 943 | ec_validate_ecdt, "ASUS hardware", { |
933 | DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, | 944 | DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, |
945 | { | ||
946 | ec_validate_ecdt, "ASUS hardware", { | ||
947 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, | ||
934 | {}, | 948 | {}, |
935 | }; | 949 | }; |
936 | 950 | ||
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c index 0e869b3f81ca..05b44201a614 100644 --- a/drivers/acpi/ec_sys.c +++ b/drivers/acpi/ec_sys.c | |||
@@ -24,10 +24,6 @@ MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may " | |||
24 | 24 | ||
25 | #define EC_SPACE_SIZE 256 | 25 | #define EC_SPACE_SIZE 256 |
26 | 26 | ||
27 | struct sysdev_class acpi_ec_sysdev_class = { | ||
28 | .name = "ec", | ||
29 | }; | ||
30 | |||
31 | static struct dentry *acpi_ec_debugfs_dir; | 27 | static struct dentry *acpi_ec_debugfs_dir; |
32 | 28 | ||
33 | static int acpi_ec_open_io(struct inode *i, struct file *f) | 29 | static int acpi_ec_open_io(struct inode *i, struct file *f) |
@@ -101,6 +97,7 @@ static struct file_operations acpi_ec_io_ops = { | |||
101 | .open = acpi_ec_open_io, | 97 | .open = acpi_ec_open_io, |
102 | .read = acpi_ec_read_io, | 98 | .read = acpi_ec_read_io, |
103 | .write = acpi_ec_write_io, | 99 | .write = acpi_ec_write_io, |
100 | .llseek = default_llseek, | ||
104 | }; | 101 | }; |
105 | 102 | ||
106 | int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count) | 103 | int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count) |
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index d439314a75d8..85d908993809 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c | |||
@@ -110,6 +110,7 @@ static const struct file_operations acpi_system_event_ops = { | |||
110 | .read = acpi_system_read_event, | 110 | .read = acpi_system_read_event, |
111 | .release = acpi_system_close_event, | 111 | .release = acpi_system_close_event, |
112 | .poll = acpi_system_poll_event, | 112 | .poll = acpi_system_poll_event, |
113 | .llseek = default_llseek, | ||
113 | }; | 114 | }; |
114 | #endif /* CONFIG_ACPI_PROC_EVENT */ | 115 | #endif /* CONFIG_ACPI_PROC_EVENT */ |
115 | 116 | ||
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index d94d2953c974..467479f07c1f 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
@@ -27,8 +27,6 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
33 | #include <linux/thermal.h> | 31 | #include <linux/thermal.h> |
34 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
@@ -88,7 +86,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long | |||
88 | if (!device) | 86 | if (!device) |
89 | return -EINVAL; | 87 | return -EINVAL; |
90 | 88 | ||
91 | result = acpi_bus_get_power(device->handle, &acpi_state); | 89 | result = acpi_bus_update_power(device->handle, &acpi_state); |
92 | if (result) | 90 | if (result) |
93 | return result; | 91 | return result; |
94 | 92 | ||
@@ -119,129 +117,12 @@ static struct thermal_cooling_device_ops fan_cooling_ops = { | |||
119 | }; | 117 | }; |
120 | 118 | ||
121 | /* -------------------------------------------------------------------------- | 119 | /* -------------------------------------------------------------------------- |
122 | FS Interface (/proc) | ||
123 | -------------------------------------------------------------------------- */ | ||
124 | #ifdef CONFIG_ACPI_PROCFS | ||
125 | |||
126 | static struct proc_dir_entry *acpi_fan_dir; | ||
127 | |||
128 | static int acpi_fan_read_state(struct seq_file *seq, void *offset) | ||
129 | { | ||
130 | struct acpi_device *device = seq->private; | ||
131 | int state = 0; | ||
132 | |||
133 | |||
134 | if (device) { | ||
135 | if (acpi_bus_get_power(device->handle, &state)) | ||
136 | seq_printf(seq, "status: ERROR\n"); | ||
137 | else | ||
138 | seq_printf(seq, "status: %s\n", | ||
139 | !state ? "on" : "off"); | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int acpi_fan_state_open_fs(struct inode *inode, struct file *file) | ||
145 | { | ||
146 | return single_open(file, acpi_fan_read_state, PDE(inode)->data); | ||
147 | } | ||
148 | |||
149 | static ssize_t | ||
150 | acpi_fan_write_state(struct file *file, const char __user * buffer, | ||
151 | size_t count, loff_t * ppos) | ||
152 | { | ||
153 | int result = 0; | ||
154 | struct seq_file *m = file->private_data; | ||
155 | struct acpi_device *device = m->private; | ||
156 | char state_string[3] = { '\0' }; | ||
157 | |||
158 | if (count > sizeof(state_string) - 1) | ||
159 | return -EINVAL; | ||
160 | |||
161 | if (copy_from_user(state_string, buffer, count)) | ||
162 | return -EFAULT; | ||
163 | |||
164 | state_string[count] = '\0'; | ||
165 | if ((state_string[0] < '0') || (state_string[0] > '3')) | ||
166 | return -EINVAL; | ||
167 | if (state_string[1] == '\n') | ||
168 | state_string[1] = '\0'; | ||
169 | if (state_string[1] != '\0') | ||
170 | return -EINVAL; | ||
171 | |||
172 | result = acpi_bus_set_power(device->handle, | ||
173 | simple_strtoul(state_string, NULL, 0)); | ||
174 | if (result) | ||
175 | return result; | ||
176 | |||
177 | return count; | ||
178 | } | ||
179 | |||
180 | static const struct file_operations acpi_fan_state_ops = { | ||
181 | .open = acpi_fan_state_open_fs, | ||
182 | .read = seq_read, | ||
183 | .write = acpi_fan_write_state, | ||
184 | .llseek = seq_lseek, | ||
185 | .release = single_release, | ||
186 | .owner = THIS_MODULE, | ||
187 | }; | ||
188 | |||
189 | static int acpi_fan_add_fs(struct acpi_device *device) | ||
190 | { | ||
191 | struct proc_dir_entry *entry = NULL; | ||
192 | |||
193 | |||
194 | if (!device) | ||
195 | return -EINVAL; | ||
196 | |||
197 | if (!acpi_device_dir(device)) { | ||
198 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | ||
199 | acpi_fan_dir); | ||
200 | if (!acpi_device_dir(device)) | ||
201 | return -ENODEV; | ||
202 | } | ||
203 | |||
204 | /* 'status' [R/W] */ | ||
205 | entry = proc_create_data(ACPI_FAN_FILE_STATE, | ||
206 | S_IFREG | S_IRUGO | S_IWUSR, | ||
207 | acpi_device_dir(device), | ||
208 | &acpi_fan_state_ops, | ||
209 | device); | ||
210 | if (!entry) | ||
211 | return -ENODEV; | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int acpi_fan_remove_fs(struct acpi_device *device) | ||
216 | { | ||
217 | |||
218 | if (acpi_device_dir(device)) { | ||
219 | remove_proc_entry(ACPI_FAN_FILE_STATE, acpi_device_dir(device)); | ||
220 | remove_proc_entry(acpi_device_bid(device), acpi_fan_dir); | ||
221 | acpi_device_dir(device) = NULL; | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | #else | ||
227 | static int acpi_fan_add_fs(struct acpi_device *device) | ||
228 | { | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int acpi_fan_remove_fs(struct acpi_device *device) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
236 | #endif | ||
237 | /* -------------------------------------------------------------------------- | ||
238 | Driver Interface | 120 | Driver Interface |
239 | -------------------------------------------------------------------------- */ | 121 | -------------------------------------------------------------------------- */ |
240 | 122 | ||
241 | static int acpi_fan_add(struct acpi_device *device) | 123 | static int acpi_fan_add(struct acpi_device *device) |
242 | { | 124 | { |
243 | int result = 0; | 125 | int result = 0; |
244 | int state = 0; | ||
245 | struct thermal_cooling_device *cdev; | 126 | struct thermal_cooling_device *cdev; |
246 | 127 | ||
247 | if (!device) | 128 | if (!device) |
@@ -250,16 +131,12 @@ static int acpi_fan_add(struct acpi_device *device) | |||
250 | strcpy(acpi_device_name(device), "Fan"); | 131 | strcpy(acpi_device_name(device), "Fan"); |
251 | strcpy(acpi_device_class(device), ACPI_FAN_CLASS); | 132 | strcpy(acpi_device_class(device), ACPI_FAN_CLASS); |
252 | 133 | ||
253 | result = acpi_bus_get_power(device->handle, &state); | 134 | result = acpi_bus_update_power(device->handle, NULL); |
254 | if (result) { | 135 | if (result) { |
255 | printk(KERN_ERR PREFIX "Reading power state\n"); | 136 | printk(KERN_ERR PREFIX "Setting initial power state\n"); |
256 | goto end; | 137 | goto end; |
257 | } | 138 | } |
258 | 139 | ||
259 | device->flags.force_power_state = 1; | ||
260 | acpi_bus_set_power(device->handle, state); | ||
261 | device->flags.force_power_state = 0; | ||
262 | |||
263 | cdev = thermal_cooling_device_register("Fan", device, | 140 | cdev = thermal_cooling_device_register("Fan", device, |
264 | &fan_cooling_ops); | 141 | &fan_cooling_ops); |
265 | if (IS_ERR(cdev)) { | 142 | if (IS_ERR(cdev)) { |
@@ -284,10 +161,6 @@ static int acpi_fan_add(struct acpi_device *device) | |||
284 | dev_err(&device->dev, "Failed to create sysfs link " | 161 | dev_err(&device->dev, "Failed to create sysfs link " |
285 | "'device'\n"); | 162 | "'device'\n"); |
286 | 163 | ||
287 | result = acpi_fan_add_fs(device); | ||
288 | if (result) | ||
289 | goto end; | ||
290 | |||
291 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | 164 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", |
292 | acpi_device_name(device), acpi_device_bid(device), | 165 | acpi_device_name(device), acpi_device_bid(device), |
293 | !device->power.state ? "on" : "off"); | 166 | !device->power.state ? "on" : "off"); |
@@ -303,7 +176,6 @@ static int acpi_fan_remove(struct acpi_device *device, int type) | |||
303 | if (!device || !cdev) | 176 | if (!device || !cdev) |
304 | return -EINVAL; | 177 | return -EINVAL; |
305 | 178 | ||
306 | acpi_fan_remove_fs(device); | ||
307 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); | 179 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); |
308 | sysfs_remove_link(&cdev->device.kobj, "device"); | 180 | sysfs_remove_link(&cdev->device.kobj, "device"); |
309 | thermal_cooling_device_unregister(cdev); | 181 | thermal_cooling_device_unregister(cdev); |
@@ -323,22 +195,14 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) | |||
323 | 195 | ||
324 | static int acpi_fan_resume(struct acpi_device *device) | 196 | static int acpi_fan_resume(struct acpi_device *device) |
325 | { | 197 | { |
326 | int result = 0; | 198 | int result; |
327 | int power_state = 0; | ||
328 | 199 | ||
329 | if (!device) | 200 | if (!device) |
330 | return -EINVAL; | 201 | return -EINVAL; |
331 | 202 | ||
332 | result = acpi_bus_get_power(device->handle, &power_state); | 203 | result = acpi_bus_update_power(device->handle, NULL); |
333 | if (result) { | 204 | if (result) |
334 | printk(KERN_ERR PREFIX | 205 | printk(KERN_ERR PREFIX "Error updating fan power state\n"); |
335 | "Error reading fan power state\n"); | ||
336 | return result; | ||
337 | } | ||
338 | |||
339 | device->flags.force_power_state = 1; | ||
340 | acpi_bus_set_power(device->handle, power_state); | ||
341 | device->flags.force_power_state = 0; | ||
342 | 206 | ||
343 | return result; | 207 | return result; |
344 | } | 208 | } |
@@ -347,19 +211,9 @@ static int __init acpi_fan_init(void) | |||
347 | { | 211 | { |
348 | int result = 0; | 212 | int result = 0; |
349 | 213 | ||
350 | #ifdef CONFIG_ACPI_PROCFS | ||
351 | acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); | ||
352 | if (!acpi_fan_dir) | ||
353 | return -ENODEV; | ||
354 | #endif | ||
355 | |||
356 | result = acpi_bus_register_driver(&acpi_fan_driver); | 214 | result = acpi_bus_register_driver(&acpi_fan_driver); |
357 | if (result < 0) { | 215 | if (result < 0) |
358 | #ifdef CONFIG_ACPI_PROCFS | ||
359 | remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); | ||
360 | #endif | ||
361 | return -ENODEV; | 216 | return -ENODEV; |
362 | } | ||
363 | 217 | ||
364 | return 0; | 218 | return 0; |
365 | } | 219 | } |
@@ -369,10 +223,6 @@ static void __exit acpi_fan_exit(void) | |||
369 | 223 | ||
370 | acpi_bus_unregister_driver(&acpi_fan_driver); | 224 | acpi_bus_unregister_driver(&acpi_fan_driver); |
371 | 225 | ||
372 | #ifdef CONFIG_ACPI_PROCFS | ||
373 | remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); | ||
374 | #endif | ||
375 | |||
376 | return; | 226 | return; |
377 | } | 227 | } |
378 | 228 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 78b0164c35b2..7c47ed55e528 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -167,11 +167,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
167 | "firmware_node"); | 167 | "firmware_node"); |
168 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | 168 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, |
169 | "physical_node"); | 169 | "physical_node"); |
170 | if (acpi_dev->wakeup.flags.valid) { | 170 | if (acpi_dev->wakeup.flags.valid) |
171 | device_set_wakeup_capable(dev, true); | 171 | device_set_wakeup_capable(dev, true); |
172 | device_set_wakeup_enable(dev, | ||
173 | acpi_dev->wakeup.state.enabled); | ||
174 | } | ||
175 | } | 172 | } |
176 | 173 | ||
177 | return 0; | 174 | return 0; |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a212bfeddf8c..ca75b9ce0489 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #ifndef _ACPI_INTERNAL_H_ | 21 | #ifndef _ACPI_INTERNAL_H_ |
22 | #define _ACPI_INTERNAL_H_ | 22 | #define _ACPI_INTERNAL_H_ |
23 | 23 | ||
24 | #include <linux/sysdev.h> | ||
25 | |||
26 | #define PREFIX "ACPI: " | 24 | #define PREFIX "ACPI: " |
27 | 25 | ||
28 | int init_acpi_device_notify(void); | 26 | int init_acpi_device_notify(void); |
@@ -30,9 +28,10 @@ int acpi_scan_init(void); | |||
30 | int acpi_sysfs_init(void); | 28 | int acpi_sysfs_init(void); |
31 | 29 | ||
32 | #ifdef CONFIG_DEBUG_FS | 30 | #ifdef CONFIG_DEBUG_FS |
31 | extern struct dentry *acpi_debugfs_dir; | ||
33 | int acpi_debugfs_init(void); | 32 | int acpi_debugfs_init(void); |
34 | #else | 33 | #else |
35 | static inline int acpi_debugfs_init(void) { return 0; } | 34 | static inline void acpi_debugfs_init(void) { return; } |
36 | #endif | 35 | #endif |
37 | 36 | ||
38 | /* -------------------------------------------------------------------------- | 37 | /* -------------------------------------------------------------------------- |
@@ -41,9 +40,10 @@ static inline int acpi_debugfs_init(void) { return 0; } | |||
41 | int acpi_power_init(void); | 40 | int acpi_power_init(void); |
42 | int acpi_device_sleep_wake(struct acpi_device *dev, | 41 | int acpi_device_sleep_wake(struct acpi_device *dev, |
43 | int enable, int sleep_state, int dev_state); | 42 | int enable, int sleep_state, int dev_state); |
44 | int acpi_power_get_inferred_state(struct acpi_device *device); | 43 | int acpi_power_get_inferred_state(struct acpi_device *device, int *state); |
44 | int acpi_power_on_resources(struct acpi_device *device, int state); | ||
45 | int acpi_power_transition(struct acpi_device *device, int state); | 45 | int acpi_power_transition(struct acpi_device *device, int state); |
46 | extern int acpi_power_nocheck; | 46 | int acpi_bus_init_power(struct acpi_device *device); |
47 | 47 | ||
48 | int acpi_wakeup_device_init(void); | 48 | int acpi_wakeup_device_init(void); |
49 | void acpi_early_processor_set_pdc(void); | 49 | void acpi_early_processor_set_pdc(void); |
@@ -63,7 +63,6 @@ struct acpi_ec { | |||
63 | struct list_head list; | 63 | struct list_head list; |
64 | struct transaction *curr; | 64 | struct transaction *curr; |
65 | spinlock_t curr_lock; | 65 | spinlock_t curr_lock; |
66 | struct sys_device sysdev; | ||
67 | }; | 66 | }; |
68 | 67 | ||
69 | extern struct acpi_ec *first_ec; | 68 | extern struct acpi_ec *first_ec; |
@@ -82,8 +81,16 @@ extern int acpi_sleep_init(void); | |||
82 | 81 | ||
83 | #ifdef CONFIG_ACPI_SLEEP | 82 | #ifdef CONFIG_ACPI_SLEEP |
84 | int acpi_sleep_proc_init(void); | 83 | int acpi_sleep_proc_init(void); |
84 | int suspend_nvs_alloc(void); | ||
85 | void suspend_nvs_free(void); | ||
86 | int suspend_nvs_save(void); | ||
87 | void suspend_nvs_restore(void); | ||
85 | #else | 88 | #else |
86 | static inline int acpi_sleep_proc_init(void) { return 0; } | 89 | static inline int acpi_sleep_proc_init(void) { return 0; } |
90 | static inline int suspend_nvs_alloc(void) { return 0; } | ||
91 | static inline void suspend_nvs_free(void) {} | ||
92 | static inline int suspend_nvs_save(void) { return 0; } | ||
93 | static inline void suspend_nvs_restore(void) {} | ||
87 | #endif | 94 | #endif |
88 | 95 | ||
89 | #endif /* _ACPI_INTERNAL_H_ */ | 96 | #endif /* _ACPI_INTERNAL_H_ */ |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 5718566e00f9..3b5c3189fd99 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -274,15 +274,21 @@ acpi_table_parse_srat(enum acpi_srat_type id, | |||
274 | 274 | ||
275 | int __init acpi_numa_init(void) | 275 | int __init acpi_numa_init(void) |
276 | { | 276 | { |
277 | int ret = 0; | 277 | int cnt = 0; |
278 | |||
279 | /* | ||
280 | * Should not limit number with cpu num that is from NR_CPUS or nr_cpus= | ||
281 | * SRAT cpu entries could have different order with that in MADT. | ||
282 | * So go over all cpu entries in SRAT to get apicid to node mapping. | ||
283 | */ | ||
278 | 284 | ||
279 | /* SRAT: Static Resource Affinity Table */ | 285 | /* SRAT: Static Resource Affinity Table */ |
280 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { | 286 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { |
281 | acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, | 287 | acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, |
282 | acpi_parse_x2apic_affinity, nr_cpu_ids); | 288 | acpi_parse_x2apic_affinity, 0); |
283 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, | 289 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, |
284 | acpi_parse_processor_affinity, nr_cpu_ids); | 290 | acpi_parse_processor_affinity, 0); |
285 | ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, | 291 | cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, |
286 | acpi_parse_memory_affinity, | 292 | acpi_parse_memory_affinity, |
287 | NR_NODE_MEMBLKS); | 293 | NR_NODE_MEMBLKS); |
288 | } | 294 | } |
@@ -291,7 +297,10 @@ int __init acpi_numa_init(void) | |||
291 | acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); | 297 | acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); |
292 | 298 | ||
293 | acpi_numa_arch_fixup(); | 299 | acpi_numa_arch_fixup(); |
294 | return ret; | 300 | |
301 | if (cnt <= 0) | ||
302 | return cnt ?: -ENOENT; | ||
303 | return 0; | ||
295 | } | 304 | } |
296 | 305 | ||
297 | int acpi_get_pxm(acpi_handle h) | 306 | int acpi_get_pxm(acpi_handle h) |
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c new file mode 100644 index 000000000000..096787b43c96 --- /dev/null +++ b/drivers/acpi/nvs.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * nvs.c - Routines for saving and restoring ACPI NVS memory region | ||
3 | * | ||
4 | * Copyright (C) 2008-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
5 | * | ||
6 | * This file is released under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/io.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/list.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/acpi_io.h> | ||
16 | #include <acpi/acpiosxf.h> | ||
17 | |||
18 | /* | ||
19 | * Platforms, like ACPI, may want us to save some memory used by them during | ||
20 | * suspend and to restore the contents of this memory during the subsequent | ||
21 | * resume. The code below implements a mechanism allowing us to do that. | ||
22 | */ | ||
23 | |||
24 | struct nvs_page { | ||
25 | unsigned long phys_start; | ||
26 | unsigned int size; | ||
27 | void *kaddr; | ||
28 | void *data; | ||
29 | bool unmap; | ||
30 | struct list_head node; | ||
31 | }; | ||
32 | |||
33 | static LIST_HEAD(nvs_list); | ||
34 | |||
35 | /** | ||
36 | * suspend_nvs_register - register platform NVS memory region to save | ||
37 | * @start - physical address of the region | ||
38 | * @size - size of the region | ||
39 | * | ||
40 | * The NVS region need not be page-aligned (both ends) and we arrange | ||
41 | * things so that the data from page-aligned addresses in this region will | ||
42 | * be copied into separate RAM pages. | ||
43 | */ | ||
44 | int suspend_nvs_register(unsigned long start, unsigned long size) | ||
45 | { | ||
46 | struct nvs_page *entry, *next; | ||
47 | |||
48 | pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n", | ||
49 | start, size); | ||
50 | |||
51 | while (size > 0) { | ||
52 | unsigned int nr_bytes; | ||
53 | |||
54 | entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL); | ||
55 | if (!entry) | ||
56 | goto Error; | ||
57 | |||
58 | list_add_tail(&entry->node, &nvs_list); | ||
59 | entry->phys_start = start; | ||
60 | nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK); | ||
61 | entry->size = (size < nr_bytes) ? size : nr_bytes; | ||
62 | |||
63 | start += entry->size; | ||
64 | size -= entry->size; | ||
65 | } | ||
66 | return 0; | ||
67 | |||
68 | Error: | ||
69 | list_for_each_entry_safe(entry, next, &nvs_list, node) { | ||
70 | list_del(&entry->node); | ||
71 | kfree(entry); | ||
72 | } | ||
73 | return -ENOMEM; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * suspend_nvs_free - free data pages allocated for saving NVS regions | ||
78 | */ | ||
79 | void suspend_nvs_free(void) | ||
80 | { | ||
81 | struct nvs_page *entry; | ||
82 | |||
83 | list_for_each_entry(entry, &nvs_list, node) | ||
84 | if (entry->data) { | ||
85 | free_page((unsigned long)entry->data); | ||
86 | entry->data = NULL; | ||
87 | if (entry->kaddr) { | ||
88 | if (entry->unmap) { | ||
89 | iounmap(entry->kaddr); | ||
90 | entry->unmap = false; | ||
91 | } else { | ||
92 | acpi_os_unmap_memory(entry->kaddr, | ||
93 | entry->size); | ||
94 | } | ||
95 | entry->kaddr = NULL; | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * suspend_nvs_alloc - allocate memory necessary for saving NVS regions | ||
102 | */ | ||
103 | int suspend_nvs_alloc(void) | ||
104 | { | ||
105 | struct nvs_page *entry; | ||
106 | |||
107 | list_for_each_entry(entry, &nvs_list, node) { | ||
108 | entry->data = (void *)__get_free_page(GFP_KERNEL); | ||
109 | if (!entry->data) { | ||
110 | suspend_nvs_free(); | ||
111 | return -ENOMEM; | ||
112 | } | ||
113 | } | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * suspend_nvs_save - save NVS memory regions | ||
119 | */ | ||
120 | int suspend_nvs_save(void) | ||
121 | { | ||
122 | struct nvs_page *entry; | ||
123 | |||
124 | printk(KERN_INFO "PM: Saving platform NVS memory\n"); | ||
125 | |||
126 | list_for_each_entry(entry, &nvs_list, node) | ||
127 | if (entry->data) { | ||
128 | unsigned long phys = entry->phys_start; | ||
129 | unsigned int size = entry->size; | ||
130 | |||
131 | entry->kaddr = acpi_os_get_iomem(phys, size); | ||
132 | if (!entry->kaddr) { | ||
133 | entry->kaddr = acpi_os_ioremap(phys, size); | ||
134 | entry->unmap = !!entry->kaddr; | ||
135 | } | ||
136 | if (!entry->kaddr) { | ||
137 | suspend_nvs_free(); | ||
138 | return -ENOMEM; | ||
139 | } | ||
140 | memcpy(entry->data, entry->kaddr, entry->size); | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * suspend_nvs_restore - restore NVS memory regions | ||
148 | * | ||
149 | * This function is going to be called with interrupts disabled, so it | ||
150 | * cannot iounmap the virtual addresses used to access the NVS region. | ||
151 | */ | ||
152 | void suspend_nvs_restore(void) | ||
153 | { | ||
154 | struct nvs_page *entry; | ||
155 | |||
156 | printk(KERN_INFO "PM: Restoring platform NVS memory\n"); | ||
157 | |||
158 | list_for_each_entry(entry, &nvs_list, node) | ||
159 | if (entry->data) | ||
160 | memcpy(entry->kaddr, entry->data, entry->size); | ||
161 | } | ||
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 65b25a303b86..372f9b70f7f4 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | #include <linux/nmi.h> | 39 | #include <linux/nmi.h> |
40 | #include <linux/acpi.h> | 40 | #include <linux/acpi.h> |
41 | #include <linux/acpi_io.h> | ||
41 | #include <linux/efi.h> | 42 | #include <linux/efi.h> |
42 | #include <linux/ioport.h> | 43 | #include <linux/ioport.h> |
43 | #include <linux/list.h> | 44 | #include <linux/list.h> |
@@ -75,7 +76,6 @@ EXPORT_SYMBOL(acpi_in_debugger); | |||
75 | extern char line_buf[80]; | 76 | extern char line_buf[80]; |
76 | #endif /*ENABLE_DEBUGGER */ | 77 | #endif /*ENABLE_DEBUGGER */ |
77 | 78 | ||
78 | static unsigned int acpi_irq_irq; | ||
79 | static acpi_osd_handler acpi_irq_handler; | 79 | static acpi_osd_handler acpi_irq_handler; |
80 | static void *acpi_irq_context; | 80 | static void *acpi_irq_context; |
81 | static struct workqueue_struct *kacpid_wq; | 81 | static struct workqueue_struct *kacpid_wq; |
@@ -95,8 +95,22 @@ struct acpi_res_list { | |||
95 | static LIST_HEAD(resource_list_head); | 95 | static LIST_HEAD(resource_list_head); |
96 | static DEFINE_SPINLOCK(acpi_res_lock); | 96 | static DEFINE_SPINLOCK(acpi_res_lock); |
97 | 97 | ||
98 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | 98 | /* |
99 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; | 99 | * This list of permanent mappings is for memory that may be accessed from |
100 | * interrupt context, where we can't do the ioremap(). | ||
101 | */ | ||
102 | struct acpi_ioremap { | ||
103 | struct list_head list; | ||
104 | void __iomem *virt; | ||
105 | acpi_physical_address phys; | ||
106 | acpi_size size; | ||
107 | unsigned long refcount; | ||
108 | }; | ||
109 | |||
110 | static LIST_HEAD(acpi_ioremaps); | ||
111 | static DEFINE_MUTEX(acpi_ioremap_lock); | ||
112 | |||
113 | static void __init acpi_osi_setup_late(void); | ||
100 | 114 | ||
101 | /* | 115 | /* |
102 | * The story of _OSI(Linux) | 116 | * The story of _OSI(Linux) |
@@ -135,8 +149,21 @@ static struct osi_linux { | |||
135 | unsigned int enable:1; | 149 | unsigned int enable:1; |
136 | unsigned int dmi:1; | 150 | unsigned int dmi:1; |
137 | unsigned int cmdline:1; | 151 | unsigned int cmdline:1; |
138 | unsigned int known:1; | 152 | } osi_linux = {0, 0, 0}; |
139 | } osi_linux = { 0, 0, 0, 0}; | 153 | |
154 | static u32 acpi_osi_handler(acpi_string interface, u32 supported) | ||
155 | { | ||
156 | if (!strcmp("Linux", interface)) { | ||
157 | |||
158 | printk(KERN_NOTICE FW_BUG PREFIX | ||
159 | "BIOS _OSI(Linux) query %s%s\n", | ||
160 | osi_linux.enable ? "honored" : "ignored", | ||
161 | osi_linux.cmdline ? " via cmdline" : | ||
162 | osi_linux.dmi ? " via DMI" : ""); | ||
163 | } | ||
164 | |||
165 | return supported; | ||
166 | } | ||
140 | 167 | ||
141 | static void __init acpi_request_region (struct acpi_generic_address *addr, | 168 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
142 | unsigned int length, char *desc) | 169 | unsigned int length, char *desc) |
@@ -185,36 +212,6 @@ static int __init acpi_reserve_resources(void) | |||
185 | } | 212 | } |
186 | device_initcall(acpi_reserve_resources); | 213 | device_initcall(acpi_reserve_resources); |
187 | 214 | ||
188 | acpi_status __init acpi_os_initialize(void) | ||
189 | { | ||
190 | return AE_OK; | ||
191 | } | ||
192 | |||
193 | acpi_status acpi_os_initialize1(void) | ||
194 | { | ||
195 | kacpid_wq = create_workqueue("kacpid"); | ||
196 | kacpi_notify_wq = create_workqueue("kacpi_notify"); | ||
197 | kacpi_hotplug_wq = create_workqueue("kacpi_hotplug"); | ||
198 | BUG_ON(!kacpid_wq); | ||
199 | BUG_ON(!kacpi_notify_wq); | ||
200 | BUG_ON(!kacpi_hotplug_wq); | ||
201 | return AE_OK; | ||
202 | } | ||
203 | |||
204 | acpi_status acpi_os_terminate(void) | ||
205 | { | ||
206 | if (acpi_irq_handler) { | ||
207 | acpi_os_remove_interrupt_handler(acpi_irq_irq, | ||
208 | acpi_irq_handler); | ||
209 | } | ||
210 | |||
211 | destroy_workqueue(kacpid_wq); | ||
212 | destroy_workqueue(kacpi_notify_wq); | ||
213 | destroy_workqueue(kacpi_hotplug_wq); | ||
214 | |||
215 | return AE_OK; | ||
216 | } | ||
217 | |||
218 | void acpi_os_printf(const char *fmt, ...) | 215 | void acpi_os_printf(const char *fmt, ...) |
219 | { | 216 | { |
220 | va_list args; | 217 | va_list args; |
@@ -260,29 +257,151 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) | |||
260 | } | 257 | } |
261 | } | 258 | } |
262 | 259 | ||
260 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ | ||
261 | static struct acpi_ioremap * | ||
262 | acpi_map_lookup(acpi_physical_address phys, acpi_size size) | ||
263 | { | ||
264 | struct acpi_ioremap *map; | ||
265 | |||
266 | list_for_each_entry_rcu(map, &acpi_ioremaps, list) | ||
267 | if (map->phys <= phys && | ||
268 | phys + size <= map->phys + map->size) | ||
269 | return map; | ||
270 | |||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ | ||
275 | static void __iomem * | ||
276 | acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size) | ||
277 | { | ||
278 | struct acpi_ioremap *map; | ||
279 | |||
280 | map = acpi_map_lookup(phys, size); | ||
281 | if (map) | ||
282 | return map->virt + (phys - map->phys); | ||
283 | |||
284 | return NULL; | ||
285 | } | ||
286 | |||
287 | void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size) | ||
288 | { | ||
289 | struct acpi_ioremap *map; | ||
290 | void __iomem *virt = NULL; | ||
291 | |||
292 | mutex_lock(&acpi_ioremap_lock); | ||
293 | map = acpi_map_lookup(phys, size); | ||
294 | if (map) { | ||
295 | virt = map->virt + (phys - map->phys); | ||
296 | map->refcount++; | ||
297 | } | ||
298 | mutex_unlock(&acpi_ioremap_lock); | ||
299 | return virt; | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(acpi_os_get_iomem); | ||
302 | |||
303 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ | ||
304 | static struct acpi_ioremap * | ||
305 | acpi_map_lookup_virt(void __iomem *virt, acpi_size size) | ||
306 | { | ||
307 | struct acpi_ioremap *map; | ||
308 | |||
309 | list_for_each_entry_rcu(map, &acpi_ioremaps, list) | ||
310 | if (map->virt <= virt && | ||
311 | virt + size <= map->virt + map->size) | ||
312 | return map; | ||
313 | |||
314 | return NULL; | ||
315 | } | ||
316 | |||
263 | void __iomem *__init_refok | 317 | void __iomem *__init_refok |
264 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 318 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
265 | { | 319 | { |
320 | struct acpi_ioremap *map; | ||
321 | void __iomem *virt; | ||
322 | acpi_physical_address pg_off; | ||
323 | acpi_size pg_sz; | ||
324 | |||
266 | if (phys > ULONG_MAX) { | 325 | if (phys > ULONG_MAX) { |
267 | printk(KERN_ERR PREFIX "Cannot map memory that high\n"); | 326 | printk(KERN_ERR PREFIX "Cannot map memory that high\n"); |
268 | return NULL; | 327 | return NULL; |
269 | } | 328 | } |
270 | if (acpi_gbl_permanent_mmap) | 329 | |
271 | /* | 330 | if (!acpi_gbl_permanent_mmap) |
272 | * ioremap checks to ensure this is in reserved space | ||
273 | */ | ||
274 | return ioremap((unsigned long)phys, size); | ||
275 | else | ||
276 | return __acpi_map_table((unsigned long)phys, size); | 331 | return __acpi_map_table((unsigned long)phys, size); |
332 | |||
333 | mutex_lock(&acpi_ioremap_lock); | ||
334 | /* Check if there's a suitable mapping already. */ | ||
335 | map = acpi_map_lookup(phys, size); | ||
336 | if (map) { | ||
337 | map->refcount++; | ||
338 | goto out; | ||
339 | } | ||
340 | |||
341 | map = kzalloc(sizeof(*map), GFP_KERNEL); | ||
342 | if (!map) { | ||
343 | mutex_unlock(&acpi_ioremap_lock); | ||
344 | return NULL; | ||
345 | } | ||
346 | |||
347 | pg_off = round_down(phys, PAGE_SIZE); | ||
348 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; | ||
349 | virt = acpi_os_ioremap(pg_off, pg_sz); | ||
350 | if (!virt) { | ||
351 | mutex_unlock(&acpi_ioremap_lock); | ||
352 | kfree(map); | ||
353 | return NULL; | ||
354 | } | ||
355 | |||
356 | INIT_LIST_HEAD(&map->list); | ||
357 | map->virt = virt; | ||
358 | map->phys = pg_off; | ||
359 | map->size = pg_sz; | ||
360 | map->refcount = 1; | ||
361 | |||
362 | list_add_tail_rcu(&map->list, &acpi_ioremaps); | ||
363 | |||
364 | out: | ||
365 | mutex_unlock(&acpi_ioremap_lock); | ||
366 | return map->virt + (phys - map->phys); | ||
277 | } | 367 | } |
278 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); | 368 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); |
279 | 369 | ||
370 | static void acpi_os_drop_map_ref(struct acpi_ioremap *map) | ||
371 | { | ||
372 | if (!--map->refcount) | ||
373 | list_del_rcu(&map->list); | ||
374 | } | ||
375 | |||
376 | static void acpi_os_map_cleanup(struct acpi_ioremap *map) | ||
377 | { | ||
378 | if (!map->refcount) { | ||
379 | synchronize_rcu(); | ||
380 | iounmap(map->virt); | ||
381 | kfree(map); | ||
382 | } | ||
383 | } | ||
384 | |||
280 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | 385 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) |
281 | { | 386 | { |
282 | if (acpi_gbl_permanent_mmap) | 387 | struct acpi_ioremap *map; |
283 | iounmap(virt); | 388 | |
284 | else | 389 | if (!acpi_gbl_permanent_mmap) { |
285 | __acpi_unmap_table(virt, size); | 390 | __acpi_unmap_table(virt, size); |
391 | return; | ||
392 | } | ||
393 | |||
394 | mutex_lock(&acpi_ioremap_lock); | ||
395 | map = acpi_map_lookup_virt(virt, size); | ||
396 | if (!map) { | ||
397 | mutex_unlock(&acpi_ioremap_lock); | ||
398 | WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); | ||
399 | return; | ||
400 | } | ||
401 | acpi_os_drop_map_ref(map); | ||
402 | mutex_unlock(&acpi_ioremap_lock); | ||
403 | |||
404 | acpi_os_map_cleanup(map); | ||
286 | } | 405 | } |
287 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); | 406 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); |
288 | 407 | ||
@@ -292,6 +411,45 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | |||
292 | __acpi_unmap_table(virt, size); | 411 | __acpi_unmap_table(virt, size); |
293 | } | 412 | } |
294 | 413 | ||
414 | static int acpi_os_map_generic_address(struct acpi_generic_address *addr) | ||
415 | { | ||
416 | void __iomem *virt; | ||
417 | |||
418 | if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
419 | return 0; | ||
420 | |||
421 | if (!addr->address || !addr->bit_width) | ||
422 | return -EINVAL; | ||
423 | |||
424 | virt = acpi_os_map_memory(addr->address, addr->bit_width / 8); | ||
425 | if (!virt) | ||
426 | return -EIO; | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) | ||
432 | { | ||
433 | struct acpi_ioremap *map; | ||
434 | |||
435 | if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
436 | return; | ||
437 | |||
438 | if (!addr->address || !addr->bit_width) | ||
439 | return; | ||
440 | |||
441 | mutex_lock(&acpi_ioremap_lock); | ||
442 | map = acpi_map_lookup(addr->address, addr->bit_width / 8); | ||
443 | if (!map) { | ||
444 | mutex_unlock(&acpi_ioremap_lock); | ||
445 | return; | ||
446 | } | ||
447 | acpi_os_drop_map_ref(map); | ||
448 | mutex_unlock(&acpi_ioremap_lock); | ||
449 | |||
450 | acpi_os_map_cleanup(map); | ||
451 | } | ||
452 | |||
295 | #ifdef ACPI_FUTURE_USAGE | 453 | #ifdef ACPI_FUTURE_USAGE |
296 | acpi_status | 454 | acpi_status |
297 | acpi_os_get_physical_address(void *virt, acpi_physical_address * phys) | 455 | acpi_os_get_physical_address(void *virt, acpi_physical_address * phys) |
@@ -373,11 +531,15 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
373 | acpi_irq_stats_init(); | 531 | acpi_irq_stats_init(); |
374 | 532 | ||
375 | /* | 533 | /* |
376 | * Ignore the GSI from the core, and use the value in our copy of the | 534 | * ACPI interrupts different from the SCI in our copy of the FADT are |
377 | * FADT. It may not be the same if an interrupt source override exists | 535 | * not supported. |
378 | * for the SCI. | ||
379 | */ | 536 | */ |
380 | gsi = acpi_gbl_FADT.sci_interrupt; | 537 | if (gsi != acpi_gbl_FADT.sci_interrupt) |
538 | return AE_BAD_PARAMETER; | ||
539 | |||
540 | if (acpi_irq_handler) | ||
541 | return AE_ALREADY_ACQUIRED; | ||
542 | |||
381 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { | 543 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { |
382 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", | 544 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", |
383 | gsi); | 545 | gsi); |
@@ -388,20 +550,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
388 | acpi_irq_context = context; | 550 | acpi_irq_context = context; |
389 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { | 551 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { |
390 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); | 552 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); |
553 | acpi_irq_handler = NULL; | ||
391 | return AE_NOT_ACQUIRED; | 554 | return AE_NOT_ACQUIRED; |
392 | } | 555 | } |
393 | acpi_irq_irq = irq; | ||
394 | 556 | ||
395 | return AE_OK; | 557 | return AE_OK; |
396 | } | 558 | } |
397 | 559 | ||
398 | acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) | 560 | acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) |
399 | { | 561 | { |
400 | if (irq) { | 562 | if (irq != acpi_gbl_FADT.sci_interrupt) |
401 | free_irq(irq, acpi_irq); | 563 | return AE_BAD_PARAMETER; |
402 | acpi_irq_handler = NULL; | 564 | |
403 | acpi_irq_irq = 0; | 565 | free_irq(irq, acpi_irq); |
404 | } | 566 | acpi_irq_handler = NULL; |
405 | 567 | ||
406 | return AE_OK; | 568 | return AE_OK; |
407 | } | 569 | } |
@@ -493,10 +655,21 @@ EXPORT_SYMBOL(acpi_os_write_port); | |||
493 | acpi_status | 655 | acpi_status |
494 | acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) | 656 | acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) |
495 | { | 657 | { |
496 | u32 dummy; | ||
497 | void __iomem *virt_addr; | 658 | void __iomem *virt_addr; |
659 | unsigned int size = width / 8; | ||
660 | bool unmap = false; | ||
661 | u32 dummy; | ||
662 | |||
663 | rcu_read_lock(); | ||
664 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); | ||
665 | if (!virt_addr) { | ||
666 | rcu_read_unlock(); | ||
667 | virt_addr = acpi_os_ioremap(phys_addr, size); | ||
668 | if (!virt_addr) | ||
669 | return AE_BAD_ADDRESS; | ||
670 | unmap = true; | ||
671 | } | ||
498 | 672 | ||
499 | virt_addr = ioremap(phys_addr, width); | ||
500 | if (!value) | 673 | if (!value) |
501 | value = &dummy; | 674 | value = &dummy; |
502 | 675 | ||
@@ -514,7 +687,10 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) | |||
514 | BUG(); | 687 | BUG(); |
515 | } | 688 | } |
516 | 689 | ||
517 | iounmap(virt_addr); | 690 | if (unmap) |
691 | iounmap(virt_addr); | ||
692 | else | ||
693 | rcu_read_unlock(); | ||
518 | 694 | ||
519 | return AE_OK; | 695 | return AE_OK; |
520 | } | 696 | } |
@@ -523,8 +699,18 @@ acpi_status | |||
523 | acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) | 699 | acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) |
524 | { | 700 | { |
525 | void __iomem *virt_addr; | 701 | void __iomem *virt_addr; |
526 | 702 | unsigned int size = width / 8; | |
527 | virt_addr = ioremap(phys_addr, width); | 703 | bool unmap = false; |
704 | |||
705 | rcu_read_lock(); | ||
706 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); | ||
707 | if (!virt_addr) { | ||
708 | rcu_read_unlock(); | ||
709 | virt_addr = acpi_os_ioremap(phys_addr, size); | ||
710 | if (!virt_addr) | ||
711 | return AE_BAD_ADDRESS; | ||
712 | unmap = true; | ||
713 | } | ||
528 | 714 | ||
529 | switch (width) { | 715 | switch (width) { |
530 | case 8: | 716 | case 8: |
@@ -540,16 +726,20 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) | |||
540 | BUG(); | 726 | BUG(); |
541 | } | 727 | } |
542 | 728 | ||
543 | iounmap(virt_addr); | 729 | if (unmap) |
730 | iounmap(virt_addr); | ||
731 | else | ||
732 | rcu_read_unlock(); | ||
544 | 733 | ||
545 | return AE_OK; | 734 | return AE_OK; |
546 | } | 735 | } |
547 | 736 | ||
548 | acpi_status | 737 | acpi_status |
549 | acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, | 738 | acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, |
550 | u32 *value, u32 width) | 739 | u64 *value, u32 width) |
551 | { | 740 | { |
552 | int result, size; | 741 | int result, size; |
742 | u32 value32; | ||
553 | 743 | ||
554 | if (!value) | 744 | if (!value) |
555 | return AE_BAD_PARAMETER; | 745 | return AE_BAD_PARAMETER; |
@@ -570,7 +760,8 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, | |||
570 | 760 | ||
571 | result = raw_pci_read(pci_id->segment, pci_id->bus, | 761 | result = raw_pci_read(pci_id->segment, pci_id->bus, |
572 | PCI_DEVFN(pci_id->device, pci_id->function), | 762 | PCI_DEVFN(pci_id->device, pci_id->function), |
573 | reg, size, value); | 763 | reg, size, &value32); |
764 | *value = value32; | ||
574 | 765 | ||
575 | return (result ? AE_ERROR : AE_OK); | 766 | return (result ? AE_ERROR : AE_OK); |
576 | } | 767 | } |
@@ -602,74 +793,6 @@ acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, | |||
602 | return (result ? AE_ERROR : AE_OK); | 793 | return (result ? AE_ERROR : AE_OK); |
603 | } | 794 | } |
604 | 795 | ||
605 | /* TODO: Change code to take advantage of driver model more */ | ||
606 | static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ | ||
607 | acpi_handle chandle, /* current node */ | ||
608 | struct acpi_pci_id **id, | ||
609 | int *is_bridge, u8 * bus_number) | ||
610 | { | ||
611 | acpi_handle handle; | ||
612 | struct acpi_pci_id *pci_id = *id; | ||
613 | acpi_status status; | ||
614 | unsigned long long temp; | ||
615 | acpi_object_type type; | ||
616 | |||
617 | acpi_get_parent(chandle, &handle); | ||
618 | if (handle != rhandle) { | ||
619 | acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, | ||
620 | bus_number); | ||
621 | |||
622 | status = acpi_get_type(handle, &type); | ||
623 | if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) | ||
624 | return; | ||
625 | |||
626 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, | ||
627 | &temp); | ||
628 | if (ACPI_SUCCESS(status)) { | ||
629 | u32 val; | ||
630 | pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp)); | ||
631 | pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp)); | ||
632 | |||
633 | if (*is_bridge) | ||
634 | pci_id->bus = *bus_number; | ||
635 | |||
636 | /* any nicer way to get bus number of bridge ? */ | ||
637 | status = | ||
638 | acpi_os_read_pci_configuration(pci_id, 0x0e, &val, | ||
639 | 8); | ||
640 | if (ACPI_SUCCESS(status) | ||
641 | && ((val & 0x7f) == 1 || (val & 0x7f) == 2)) { | ||
642 | status = | ||
643 | acpi_os_read_pci_configuration(pci_id, 0x18, | ||
644 | &val, 8); | ||
645 | if (!ACPI_SUCCESS(status)) { | ||
646 | /* Certainly broken... FIX ME */ | ||
647 | return; | ||
648 | } | ||
649 | *is_bridge = 1; | ||
650 | pci_id->bus = val; | ||
651 | status = | ||
652 | acpi_os_read_pci_configuration(pci_id, 0x19, | ||
653 | &val, 8); | ||
654 | if (ACPI_SUCCESS(status)) { | ||
655 | *bus_number = val; | ||
656 | } | ||
657 | } else | ||
658 | *is_bridge = 0; | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | |||
663 | void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ | ||
664 | acpi_handle chandle, /* current node */ | ||
665 | struct acpi_pci_id **id) | ||
666 | { | ||
667 | int is_bridge = 1; | ||
668 | u8 bus_number = (*id)->bus; | ||
669 | |||
670 | acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); | ||
671 | } | ||
672 | |||
673 | static void acpi_os_execute_deferred(struct work_struct *work) | 796 | static void acpi_os_execute_deferred(struct work_struct *work) |
674 | { | 797 | { |
675 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | 798 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); |
@@ -779,24 +902,6 @@ void acpi_os_wait_events_complete(void *context) | |||
779 | 902 | ||
780 | EXPORT_SYMBOL(acpi_os_wait_events_complete); | 903 | EXPORT_SYMBOL(acpi_os_wait_events_complete); |
781 | 904 | ||
782 | /* | ||
783 | * Allocate the memory for a spinlock and initialize it. | ||
784 | */ | ||
785 | acpi_status acpi_os_create_lock(acpi_spinlock * handle) | ||
786 | { | ||
787 | spin_lock_init(*handle); | ||
788 | |||
789 | return AE_OK; | ||
790 | } | ||
791 | |||
792 | /* | ||
793 | * Deallocate the memory for a spinlock. | ||
794 | */ | ||
795 | void acpi_os_delete_lock(acpi_spinlock handle) | ||
796 | { | ||
797 | return; | ||
798 | } | ||
799 | |||
800 | acpi_status | 905 | acpi_status |
801 | acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) | 906 | acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) |
802 | { | 907 | { |
@@ -970,19 +1075,66 @@ static int __init acpi_os_name_setup(char *str) | |||
970 | 1075 | ||
971 | __setup("acpi_os_name=", acpi_os_name_setup); | 1076 | __setup("acpi_os_name=", acpi_os_name_setup); |
972 | 1077 | ||
1078 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | ||
1079 | #define OSI_STRING_ENTRIES_MAX 16 /* arbitrary */ | ||
1080 | |||
1081 | struct osi_setup_entry { | ||
1082 | char string[OSI_STRING_LENGTH_MAX]; | ||
1083 | bool enable; | ||
1084 | }; | ||
1085 | |||
1086 | static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX]; | ||
1087 | |||
1088 | void __init acpi_osi_setup(char *str) | ||
1089 | { | ||
1090 | struct osi_setup_entry *osi; | ||
1091 | bool enable = true; | ||
1092 | int i; | ||
1093 | |||
1094 | if (!acpi_gbl_create_osi_method) | ||
1095 | return; | ||
1096 | |||
1097 | if (str == NULL || *str == '\0') { | ||
1098 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | ||
1099 | acpi_gbl_create_osi_method = FALSE; | ||
1100 | return; | ||
1101 | } | ||
1102 | |||
1103 | if (*str == '!') { | ||
1104 | str++; | ||
1105 | enable = false; | ||
1106 | } | ||
1107 | |||
1108 | for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { | ||
1109 | osi = &osi_setup_entries[i]; | ||
1110 | if (!strcmp(osi->string, str)) { | ||
1111 | osi->enable = enable; | ||
1112 | break; | ||
1113 | } else if (osi->string[0] == '\0') { | ||
1114 | osi->enable = enable; | ||
1115 | strncpy(osi->string, str, OSI_STRING_LENGTH_MAX); | ||
1116 | break; | ||
1117 | } | ||
1118 | } | ||
1119 | } | ||
1120 | |||
973 | static void __init set_osi_linux(unsigned int enable) | 1121 | static void __init set_osi_linux(unsigned int enable) |
974 | { | 1122 | { |
975 | if (osi_linux.enable != enable) { | 1123 | if (osi_linux.enable != enable) |
976 | osi_linux.enable = enable; | 1124 | osi_linux.enable = enable; |
977 | printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", | 1125 | |
978 | enable ? "Add": "Delet"); | 1126 | if (osi_linux.enable) |
979 | } | 1127 | acpi_osi_setup("Linux"); |
1128 | else | ||
1129 | acpi_osi_setup("!Linux"); | ||
1130 | |||
980 | return; | 1131 | return; |
981 | } | 1132 | } |
982 | 1133 | ||
983 | static void __init acpi_cmdline_osi_linux(unsigned int enable) | 1134 | static void __init acpi_cmdline_osi_linux(unsigned int enable) |
984 | { | 1135 | { |
985 | osi_linux.cmdline = 1; /* cmdline set the default */ | 1136 | osi_linux.cmdline = 1; /* cmdline set the default and override DMI */ |
1137 | osi_linux.dmi = 0; | ||
986 | set_osi_linux(enable); | 1138 | set_osi_linux(enable); |
987 | 1139 | ||
988 | return; | 1140 | return; |
@@ -990,15 +1142,12 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable) | |||
990 | 1142 | ||
991 | void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) | 1143 | void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) |
992 | { | 1144 | { |
993 | osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */ | ||
994 | |||
995 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); | 1145 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
996 | 1146 | ||
997 | if (enable == -1) | 1147 | if (enable == -1) |
998 | return; | 1148 | return; |
999 | 1149 | ||
1000 | osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */ | 1150 | osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */ |
1001 | |||
1002 | set_osi_linux(enable); | 1151 | set_osi_linux(enable); |
1003 | 1152 | ||
1004 | return; | 1153 | return; |
@@ -1011,27 +1160,46 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) | |||
1011 | * string starting with '!' disables that string | 1160 | * string starting with '!' disables that string |
1012 | * otherwise string is added to list, augmenting built-in strings | 1161 | * otherwise string is added to list, augmenting built-in strings |
1013 | */ | 1162 | */ |
1014 | int __init acpi_osi_setup(char *str) | 1163 | static void __init acpi_osi_setup_late(void) |
1015 | { | 1164 | { |
1016 | if (str == NULL || *str == '\0') { | 1165 | struct osi_setup_entry *osi; |
1017 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | 1166 | char *str; |
1018 | acpi_gbl_create_osi_method = FALSE; | 1167 | int i; |
1019 | } else if (!strcmp("!Linux", str)) { | 1168 | acpi_status status; |
1020 | acpi_cmdline_osi_linux(0); /* !enable */ | 1169 | |
1021 | } else if (*str == '!') { | 1170 | for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { |
1022 | if (acpi_osi_invalidate(++str) == AE_OK) | 1171 | osi = &osi_setup_entries[i]; |
1023 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | 1172 | str = osi->string; |
1024 | } else if (!strcmp("Linux", str)) { | 1173 | |
1025 | acpi_cmdline_osi_linux(1); /* enable */ | 1174 | if (*str == '\0') |
1026 | } else if (*osi_additional_string == '\0') { | 1175 | break; |
1027 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); | 1176 | if (osi->enable) { |
1028 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | 1177 | status = acpi_install_interface(str); |
1178 | |||
1179 | if (ACPI_SUCCESS(status)) | ||
1180 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | ||
1181 | } else { | ||
1182 | status = acpi_remove_interface(str); | ||
1183 | |||
1184 | if (ACPI_SUCCESS(status)) | ||
1185 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | ||
1186 | } | ||
1029 | } | 1187 | } |
1188 | } | ||
1189 | |||
1190 | static int __init osi_setup(char *str) | ||
1191 | { | ||
1192 | if (str && !strcmp("Linux", str)) | ||
1193 | acpi_cmdline_osi_linux(1); | ||
1194 | else if (str && !strcmp("!Linux", str)) | ||
1195 | acpi_cmdline_osi_linux(0); | ||
1196 | else | ||
1197 | acpi_osi_setup(str); | ||
1030 | 1198 | ||
1031 | return 1; | 1199 | return 1; |
1032 | } | 1200 | } |
1033 | 1201 | ||
1034 | __setup("acpi_osi=", acpi_osi_setup); | 1202 | __setup("acpi_osi=", osi_setup); |
1035 | 1203 | ||
1036 | /* enable serialization to combat AE_ALREADY_EXISTS errors */ | 1204 | /* enable serialization to combat AE_ALREADY_EXISTS errors */ |
1037 | static int __init acpi_serialize_setup(char *str) | 1205 | static int __init acpi_serialize_setup(char *str) |
@@ -1089,8 +1257,7 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup); | |||
1089 | int acpi_check_resource_conflict(const struct resource *res) | 1257 | int acpi_check_resource_conflict(const struct resource *res) |
1090 | { | 1258 | { |
1091 | struct acpi_res_list *res_list_elem; | 1259 | struct acpi_res_list *res_list_elem; |
1092 | int ioport; | 1260 | int ioport = 0, clash = 0; |
1093 | int clash = 0; | ||
1094 | 1261 | ||
1095 | if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) | 1262 | if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) |
1096 | return 0; | 1263 | return 0; |
@@ -1120,9 +1287,13 @@ int acpi_check_resource_conflict(const struct resource *res) | |||
1120 | if (clash) { | 1287 | if (clash) { |
1121 | if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { | 1288 | if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { |
1122 | printk(KERN_WARNING "ACPI: resource %s %pR" | 1289 | printk(KERN_WARNING "ACPI: resource %s %pR" |
1123 | " conflicts with ACPI region %s %pR\n", | 1290 | " conflicts with ACPI region %s " |
1291 | "[%s 0x%zx-0x%zx]\n", | ||
1124 | res->name, res, res_list_elem->name, | 1292 | res->name, res, res_list_elem->name, |
1125 | res_list_elem); | 1293 | (res_list_elem->resource_type == |
1294 | ACPI_ADR_SPACE_SYSTEM_IO) ? "io" : "mem", | ||
1295 | (size_t) res_list_elem->start, | ||
1296 | (size_t) res_list_elem->end); | ||
1126 | if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX) | 1297 | if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX) |
1127 | printk(KERN_NOTICE "ACPI: This conflict may" | 1298 | printk(KERN_NOTICE "ACPI: This conflict may" |
1128 | " cause random problems and system" | 1299 | " cause random problems and system" |
@@ -1152,21 +1323,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n, | |||
1152 | } | 1323 | } |
1153 | EXPORT_SYMBOL(acpi_check_region); | 1324 | EXPORT_SYMBOL(acpi_check_region); |
1154 | 1325 | ||
1155 | int acpi_check_mem_region(resource_size_t start, resource_size_t n, | ||
1156 | const char *name) | ||
1157 | { | ||
1158 | struct resource res = { | ||
1159 | .start = start, | ||
1160 | .end = start + n - 1, | ||
1161 | .name = name, | ||
1162 | .flags = IORESOURCE_MEM, | ||
1163 | }; | ||
1164 | |||
1165 | return acpi_check_resource_conflict(&res); | ||
1166 | |||
1167 | } | ||
1168 | EXPORT_SYMBOL(acpi_check_mem_region); | ||
1169 | |||
1170 | /* | 1326 | /* |
1171 | * Let drivers know whether the resource checks are effective | 1327 | * Let drivers know whether the resource checks are effective |
1172 | */ | 1328 | */ |
@@ -1177,6 +1333,14 @@ int acpi_resources_are_enforced(void) | |||
1177 | EXPORT_SYMBOL(acpi_resources_are_enforced); | 1333 | EXPORT_SYMBOL(acpi_resources_are_enforced); |
1178 | 1334 | ||
1179 | /* | 1335 | /* |
1336 | * Deallocate the memory for a spinlock. | ||
1337 | */ | ||
1338 | void acpi_os_delete_lock(acpi_spinlock handle) | ||
1339 | { | ||
1340 | ACPI_FREE(handle); | ||
1341 | } | ||
1342 | |||
1343 | /* | ||
1180 | * Acquire a spinlock. | 1344 | * Acquire a spinlock. |
1181 | * | 1345 | * |
1182 | * handle is a pointer to the spinlock_t. | 1346 | * handle is a pointer to the spinlock_t. |
@@ -1282,38 +1446,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) | |||
1282 | return (AE_OK); | 1446 | return (AE_OK); |
1283 | } | 1447 | } |
1284 | 1448 | ||
1285 | /****************************************************************************** | ||
1286 | * | ||
1287 | * FUNCTION: acpi_os_validate_interface | ||
1288 | * | ||
1289 | * PARAMETERS: interface - Requested interface to be validated | ||
1290 | * | ||
1291 | * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise | ||
1292 | * | ||
1293 | * DESCRIPTION: Match an interface string to the interfaces supported by the | ||
1294 | * host. Strings originate from an AML call to the _OSI method. | ||
1295 | * | ||
1296 | *****************************************************************************/ | ||
1297 | |||
1298 | acpi_status | ||
1299 | acpi_os_validate_interface (char *interface) | ||
1300 | { | ||
1301 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) | ||
1302 | return AE_OK; | ||
1303 | if (!strcmp("Linux", interface)) { | ||
1304 | |||
1305 | printk(KERN_NOTICE PREFIX | ||
1306 | "BIOS _OSI(Linux) query %s%s\n", | ||
1307 | osi_linux.enable ? "honored" : "ignored", | ||
1308 | osi_linux.cmdline ? " via cmdline" : | ||
1309 | osi_linux.dmi ? " via DMI" : ""); | ||
1310 | |||
1311 | if (osi_linux.enable) | ||
1312 | return AE_OK; | ||
1313 | } | ||
1314 | return AE_SUPPORT; | ||
1315 | } | ||
1316 | |||
1317 | static inline int acpi_res_list_add(struct acpi_res_list *res) | 1449 | static inline int acpi_res_list_add(struct acpi_res_list *res) |
1318 | { | 1450 | { |
1319 | struct acpi_res_list *res_list_elem; | 1451 | struct acpi_res_list *res_list_elem; |
@@ -1462,5 +1594,46 @@ acpi_os_validate_address ( | |||
1462 | } | 1594 | } |
1463 | return AE_OK; | 1595 | return AE_OK; |
1464 | } | 1596 | } |
1465 | |||
1466 | #endif | 1597 | #endif |
1598 | |||
1599 | acpi_status __init acpi_os_initialize(void) | ||
1600 | { | ||
1601 | acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block); | ||
1602 | acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block); | ||
1603 | acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block); | ||
1604 | acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block); | ||
1605 | |||
1606 | return AE_OK; | ||
1607 | } | ||
1608 | |||
1609 | acpi_status __init acpi_os_initialize1(void) | ||
1610 | { | ||
1611 | kacpid_wq = alloc_workqueue("kacpid", 0, 1); | ||
1612 | kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); | ||
1613 | kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1); | ||
1614 | BUG_ON(!kacpid_wq); | ||
1615 | BUG_ON(!kacpi_notify_wq); | ||
1616 | BUG_ON(!kacpi_hotplug_wq); | ||
1617 | acpi_install_interface_handler(acpi_osi_handler); | ||
1618 | acpi_osi_setup_late(); | ||
1619 | return AE_OK; | ||
1620 | } | ||
1621 | |||
1622 | acpi_status acpi_os_terminate(void) | ||
1623 | { | ||
1624 | if (acpi_irq_handler) { | ||
1625 | acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt, | ||
1626 | acpi_irq_handler); | ||
1627 | } | ||
1628 | |||
1629 | acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe1_block); | ||
1630 | acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe0_block); | ||
1631 | acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1b_event_block); | ||
1632 | acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1a_event_block); | ||
1633 | |||
1634 | destroy_workqueue(kacpid_wq); | ||
1635 | destroy_workqueue(kacpi_notify_wq); | ||
1636 | destroy_workqueue(kacpi_hotplug_wq); | ||
1637 | |||
1638 | return AE_OK; | ||
1639 | } | ||
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index e4804fb05e23..f907cfbfa13c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
37 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
38 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 8d47a5846aeb..4a29763b8eb4 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -29,12 +29,11 @@ | |||
29 | * for IRQ management (e.g. start()->_SRS). | 29 | * for IRQ management (e.g. start()->_SRS). |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/sysdev.h> | 32 | #include <linux/syscore_ops.h> |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/proc_fs.h> | ||
38 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
39 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
40 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
@@ -758,14 +757,13 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link) | |||
758 | return 0; | 757 | return 0; |
759 | } | 758 | } |
760 | 759 | ||
761 | static int irqrouter_resume(struct sys_device *dev) | 760 | static void irqrouter_resume(void) |
762 | { | 761 | { |
763 | struct acpi_pci_link *link; | 762 | struct acpi_pci_link *link; |
764 | 763 | ||
765 | list_for_each_entry(link, &acpi_link_list, list) { | 764 | list_for_each_entry(link, &acpi_link_list, list) { |
766 | acpi_pci_link_resume(link); | 765 | acpi_pci_link_resume(link); |
767 | } | 766 | } |
768 | return 0; | ||
769 | } | 767 | } |
770 | 768 | ||
771 | static int acpi_pci_link_remove(struct acpi_device *device, int type) | 769 | static int acpi_pci_link_remove(struct acpi_device *device, int type) |
@@ -872,32 +870,19 @@ static int __init acpi_irq_balance_set(char *str) | |||
872 | 870 | ||
873 | __setup("acpi_irq_balance", acpi_irq_balance_set); | 871 | __setup("acpi_irq_balance", acpi_irq_balance_set); |
874 | 872 | ||
875 | /* FIXME: we will remove this interface after all drivers call pci_disable_device */ | 873 | static struct syscore_ops irqrouter_syscore_ops = { |
876 | static struct sysdev_class irqrouter_sysdev_class = { | ||
877 | .name = "irqrouter", | ||
878 | .resume = irqrouter_resume, | 874 | .resume = irqrouter_resume, |
879 | }; | 875 | }; |
880 | 876 | ||
881 | static struct sys_device device_irqrouter = { | 877 | static int __init irqrouter_init_ops(void) |
882 | .id = 0, | ||
883 | .cls = &irqrouter_sysdev_class, | ||
884 | }; | ||
885 | |||
886 | static int __init irqrouter_init_sysfs(void) | ||
887 | { | 878 | { |
888 | int error; | 879 | if (!acpi_disabled && !acpi_noirq) |
880 | register_syscore_ops(&irqrouter_syscore_ops); | ||
889 | 881 | ||
890 | if (acpi_disabled || acpi_noirq) | 882 | return 0; |
891 | return 0; | ||
892 | |||
893 | error = sysdev_class_register(&irqrouter_sysdev_class); | ||
894 | if (!error) | ||
895 | error = sysdev_register(&device_irqrouter); | ||
896 | |||
897 | return error; | ||
898 | } | 883 | } |
899 | 884 | ||
900 | device_initcall(irqrouter_init_sysfs); | 885 | device_initcall(irqrouter_init_ops); |
901 | 886 | ||
902 | static int __init acpi_pci_link_init(void) | 887 | static int __init acpi_pci_link_init(void) |
903 | { | 888 | { |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 3ba8d1f44a73..d06078d660ad 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -27,16 +27,17 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
32 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
33 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
34 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
35 | #include <linux/pci-acpi.h> | 34 | #include <linux/pci-acpi.h> |
35 | #include <linux/pci-aspm.h> | ||
36 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/acpi_bus.h> |
39 | #include <acpi/acpi_drivers.h> | 39 | #include <acpi/acpi_drivers.h> |
40 | #include <acpi/apei.h> | ||
40 | 41 | ||
41 | #define PREFIX "ACPI: " | 42 | #define PREFIX "ACPI: " |
42 | 43 | ||
@@ -48,6 +49,11 @@ static int acpi_pci_root_add(struct acpi_device *device); | |||
48 | static int acpi_pci_root_remove(struct acpi_device *device, int type); | 49 | static int acpi_pci_root_remove(struct acpi_device *device, int type); |
49 | static int acpi_pci_root_start(struct acpi_device *device); | 50 | static int acpi_pci_root_start(struct acpi_device *device); |
50 | 51 | ||
52 | #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | ||
53 | | OSC_ACTIVE_STATE_PWR_SUPPORT \ | ||
54 | | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \ | ||
55 | | OSC_MSI_SUPPORT) | ||
56 | |||
51 | static const struct acpi_device_id root_device_ids[] = { | 57 | static const struct acpi_device_id root_device_ids[] = { |
52 | {"PNP0A03", 0}, | 58 | {"PNP0A03", 0}, |
53 | {"", 0}, | 59 | {"", 0}, |
@@ -559,7 +565,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
559 | /* Indicate support for various _OSC capabilities. */ | 565 | /* Indicate support for various _OSC capabilities. */ |
560 | if (pci_ext_cfg_avail(root->bus->self)) | 566 | if (pci_ext_cfg_avail(root->bus->self)) |
561 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; | 567 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; |
562 | if (pcie_aspm_enabled()) | 568 | if (pcie_aspm_support_enabled()) |
563 | flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | | 569 | flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | |
564 | OSC_CLOCK_PWR_CAPABILITY_SUPPORT; | 570 | OSC_CLOCK_PWR_CAPABILITY_SUPPORT; |
565 | if (pci_msi_enabled()) | 571 | if (pci_msi_enabled()) |
@@ -567,6 +573,43 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
567 | if (flags != base_flags) | 573 | if (flags != base_flags) |
568 | acpi_pci_osc_support(root, flags); | 574 | acpi_pci_osc_support(root, flags); |
569 | 575 | ||
576 | if (!pcie_ports_disabled | ||
577 | && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { | ||
578 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL | ||
579 | | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | ||
580 | | OSC_PCI_EXPRESS_PME_CONTROL; | ||
581 | |||
582 | if (pci_aer_available()) { | ||
583 | if (aer_acpi_firmware_first()) | ||
584 | dev_dbg(root->bus->bridge, | ||
585 | "PCIe errors handled by BIOS.\n"); | ||
586 | else | ||
587 | flags |= OSC_PCI_EXPRESS_AER_CONTROL; | ||
588 | } | ||
589 | |||
590 | dev_info(root->bus->bridge, | ||
591 | "Requesting ACPI _OSC control (0x%02x)\n", flags); | ||
592 | |||
593 | status = acpi_pci_osc_control_set(device->handle, &flags, | ||
594 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
595 | if (ACPI_SUCCESS(status)) { | ||
596 | dev_info(root->bus->bridge, | ||
597 | "ACPI _OSC control (0x%02x) granted\n", flags); | ||
598 | } else { | ||
599 | dev_info(root->bus->bridge, | ||
600 | "ACPI _OSC request failed (%s), " | ||
601 | "returned control mask: 0x%02x\n", | ||
602 | acpi_format_exception(status), flags); | ||
603 | pr_info("ACPI _OSC control for PCIe not granted, " | ||
604 | "disabling ASPM\n"); | ||
605 | pcie_no_aspm(); | ||
606 | } | ||
607 | } else { | ||
608 | dev_info(root->bus->bridge, | ||
609 | "Unable to request _OSC control " | ||
610 | "(_OSC support mask: 0x%02x)\n", flags); | ||
611 | } | ||
612 | |||
570 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 613 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
571 | if (device->wakeup.flags.run_wake) | 614 | if (device->wakeup.flags.run_wake) |
572 | device_set_run_wake(root->bus->bridge, true); | 615 | device_set_run_wake(root->bus->bridge, true); |
@@ -601,6 +644,8 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
601 | 644 | ||
602 | static int __init acpi_pci_root_init(void) | 645 | static int __init acpi_pci_root_init(void) |
603 | { | 646 | { |
647 | acpi_hest_init(); | ||
648 | |||
604 | if (acpi_pci_disabled) | 649 | if (acpi_pci_disabled) |
605 | return 0; | 650 | return 0; |
606 | 651 | ||
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 844c155aeb0f..9ac2a9fa90ff 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -56,9 +56,6 @@ ACPI_MODULE_NAME("power"); | |||
56 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 | 56 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 |
57 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF | 57 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF |
58 | 58 | ||
59 | int acpi_power_nocheck; | ||
60 | module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); | ||
61 | |||
62 | static int acpi_power_add(struct acpi_device *device); | 59 | static int acpi_power_add(struct acpi_device *device); |
63 | static int acpi_power_remove(struct acpi_device *device, int type); | 60 | static int acpi_power_remove(struct acpi_device *device, int type); |
64 | static int acpi_power_resume(struct acpi_device *device); | 61 | static int acpi_power_resume(struct acpi_device *device); |
@@ -80,18 +77,13 @@ static struct acpi_driver acpi_power_driver = { | |||
80 | }, | 77 | }, |
81 | }; | 78 | }; |
82 | 79 | ||
83 | struct acpi_power_reference { | ||
84 | struct list_head node; | ||
85 | struct acpi_device *device; | ||
86 | }; | ||
87 | |||
88 | struct acpi_power_resource { | 80 | struct acpi_power_resource { |
89 | struct acpi_device * device; | 81 | struct acpi_device * device; |
90 | acpi_bus_id name; | 82 | acpi_bus_id name; |
91 | u32 system_level; | 83 | u32 system_level; |
92 | u32 order; | 84 | u32 order; |
85 | unsigned int ref_count; | ||
93 | struct mutex resource_lock; | 86 | struct mutex resource_lock; |
94 | struct list_head reference; | ||
95 | }; | 87 | }; |
96 | 88 | ||
97 | static struct list_head acpi_power_resource_list; | 89 | static struct list_head acpi_power_resource_list; |
@@ -153,9 +145,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state) | |||
153 | 145 | ||
154 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | 146 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) |
155 | { | 147 | { |
156 | int result = 0, state1; | 148 | int cur_state; |
157 | u32 i = 0; | 149 | int i = 0; |
158 | |||
159 | 150 | ||
160 | if (!list || !state) | 151 | if (!list || !state) |
161 | return -EINVAL; | 152 | return -EINVAL; |
@@ -163,122 +154,149 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
163 | /* The state of the list is 'on' IFF all resources are 'on'. */ | 154 | /* The state of the list is 'on' IFF all resources are 'on'. */ |
164 | 155 | ||
165 | for (i = 0; i < list->count; i++) { | 156 | for (i = 0; i < list->count; i++) { |
166 | /* | 157 | struct acpi_power_resource *resource; |
167 | * The state of the power resource can be obtained by | 158 | acpi_handle handle = list->handles[i]; |
168 | * using the ACPI handle. In such case it is unnecessary to | 159 | int result; |
169 | * get the Power resource first and then get its state again. | 160 | |
170 | */ | 161 | result = acpi_power_get_context(handle, &resource); |
171 | result = acpi_power_get_state(list->handles[i], &state1); | ||
172 | if (result) | 162 | if (result) |
173 | return result; | 163 | return result; |
174 | 164 | ||
175 | *state = state1; | 165 | mutex_lock(&resource->resource_lock); |
166 | |||
167 | result = acpi_power_get_state(handle, &cur_state); | ||
168 | |||
169 | mutex_unlock(&resource->resource_lock); | ||
176 | 170 | ||
177 | if (*state != ACPI_POWER_RESOURCE_STATE_ON) | 171 | if (result) |
172 | return result; | ||
173 | |||
174 | if (cur_state != ACPI_POWER_RESOURCE_STATE_ON) | ||
178 | break; | 175 | break; |
179 | } | 176 | } |
180 | 177 | ||
181 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", | 178 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", |
182 | *state ? "on" : "off")); | 179 | cur_state ? "on" : "off")); |
183 | 180 | ||
184 | return result; | 181 | *state = cur_state; |
182 | |||
183 | return 0; | ||
185 | } | 184 | } |
186 | 185 | ||
187 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | 186 | static int __acpi_power_on(struct acpi_power_resource *resource) |
188 | { | 187 | { |
189 | int result = 0; | ||
190 | int found = 0; | ||
191 | acpi_status status = AE_OK; | 188 | acpi_status status = AE_OK; |
192 | struct acpi_power_resource *resource = NULL; | ||
193 | struct list_head *node, *next; | ||
194 | struct acpi_power_reference *ref; | ||
195 | 189 | ||
190 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); | ||
191 | if (ACPI_FAILURE(status)) | ||
192 | return -ENODEV; | ||
193 | |||
194 | /* Update the power resource's _device_ power state */ | ||
195 | resource->device->power.state = ACPI_STATE_D0; | ||
196 | |||
197 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", | ||
198 | resource->name)); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int acpi_power_on(acpi_handle handle) | ||
204 | { | ||
205 | int result = 0; | ||
206 | struct acpi_power_resource *resource = NULL; | ||
196 | 207 | ||
197 | result = acpi_power_get_context(handle, &resource); | 208 | result = acpi_power_get_context(handle, &resource); |
198 | if (result) | 209 | if (result) |
199 | return result; | 210 | return result; |
200 | 211 | ||
201 | mutex_lock(&resource->resource_lock); | 212 | mutex_lock(&resource->resource_lock); |
202 | list_for_each_safe(node, next, &resource->reference) { | ||
203 | ref = container_of(node, struct acpi_power_reference, node); | ||
204 | if (dev->handle == ref->device->handle) { | ||
205 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n", | ||
206 | dev->pnp.bus_id, resource->name)); | ||
207 | found = 1; | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | 213 | ||
212 | if (!found) { | 214 | if (resource->ref_count++) { |
213 | ref = kmalloc(sizeof (struct acpi_power_reference), | 215 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
214 | irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); | 216 | "Power resource [%s] already on", |
215 | if (!ref) { | 217 | resource->name)); |
216 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n")); | 218 | } else { |
217 | mutex_unlock(&resource->resource_lock); | 219 | result = __acpi_power_on(resource); |
218 | return -ENOMEM; | 220 | if (result) |
219 | } | 221 | resource->ref_count--; |
220 | list_add_tail(&ref->node, &resource->reference); | ||
221 | ref->device = dev; | ||
222 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n", | ||
223 | dev->pnp.bus_id, resource->name)); | ||
224 | } | 222 | } |
225 | mutex_unlock(&resource->resource_lock); | ||
226 | 223 | ||
227 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); | 224 | mutex_unlock(&resource->resource_lock); |
228 | if (ACPI_FAILURE(status)) | ||
229 | return -ENODEV; | ||
230 | |||
231 | /* Update the power resource's _device_ power state */ | ||
232 | resource->device->power.state = ACPI_STATE_D0; | ||
233 | 225 | ||
234 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n", | 226 | return result; |
235 | resource->name)); | ||
236 | return 0; | ||
237 | } | 227 | } |
238 | 228 | ||
239 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | 229 | static int acpi_power_off(acpi_handle handle) |
240 | { | 230 | { |
241 | int result = 0; | 231 | int result = 0; |
242 | acpi_status status = AE_OK; | 232 | acpi_status status = AE_OK; |
243 | struct acpi_power_resource *resource = NULL; | 233 | struct acpi_power_resource *resource = NULL; |
244 | struct list_head *node, *next; | ||
245 | struct acpi_power_reference *ref; | ||
246 | 234 | ||
247 | result = acpi_power_get_context(handle, &resource); | 235 | result = acpi_power_get_context(handle, &resource); |
248 | if (result) | 236 | if (result) |
249 | return result; | 237 | return result; |
250 | 238 | ||
251 | mutex_lock(&resource->resource_lock); | 239 | mutex_lock(&resource->resource_lock); |
252 | list_for_each_safe(node, next, &resource->reference) { | 240 | |
253 | ref = container_of(node, struct acpi_power_reference, node); | 241 | if (!resource->ref_count) { |
254 | if (dev->handle == ref->device->handle) { | 242 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
255 | list_del(&ref->node); | 243 | "Power resource [%s] already off", |
256 | kfree(ref); | 244 | resource->name)); |
257 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n", | 245 | goto unlock; |
258 | dev->pnp.bus_id, resource->name)); | ||
259 | break; | ||
260 | } | ||
261 | } | 246 | } |
262 | 247 | ||
263 | if (!list_empty(&resource->reference)) { | 248 | if (--resource->ref_count) { |
264 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n", | 249 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
265 | resource->name)); | 250 | "Power resource [%s] still in use\n", |
266 | mutex_unlock(&resource->resource_lock); | 251 | resource->name)); |
267 | return 0; | 252 | goto unlock; |
268 | } | 253 | } |
269 | mutex_unlock(&resource->resource_lock); | ||
270 | 254 | ||
271 | status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); | 255 | status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); |
272 | if (ACPI_FAILURE(status)) | 256 | if (ACPI_FAILURE(status)) { |
273 | return -ENODEV; | 257 | result = -ENODEV; |
258 | } else { | ||
259 | /* Update the power resource's _device_ power state */ | ||
260 | resource->device->power.state = ACPI_STATE_D3; | ||
274 | 261 | ||
275 | /* Update the power resource's _device_ power state */ | 262 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
276 | resource->device->power.state = ACPI_STATE_D3; | 263 | "Power resource [%s] turned off\n", |
264 | resource->name)); | ||
265 | } | ||
277 | 266 | ||
278 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n", | 267 | unlock: |
279 | resource->name)); | 268 | mutex_unlock(&resource->resource_lock); |
280 | 269 | ||
281 | return 0; | 270 | return result; |
271 | } | ||
272 | |||
273 | static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res) | ||
274 | { | ||
275 | int i; | ||
276 | |||
277 | for (i = num_res - 1; i >= 0 ; i--) | ||
278 | acpi_power_off(list->handles[i]); | ||
279 | } | ||
280 | |||
281 | static void acpi_power_off_list(struct acpi_handle_list *list) | ||
282 | { | ||
283 | __acpi_power_off_list(list, list->count); | ||
284 | } | ||
285 | |||
286 | static int acpi_power_on_list(struct acpi_handle_list *list) | ||
287 | { | ||
288 | int result = 0; | ||
289 | int i; | ||
290 | |||
291 | for (i = 0; i < list->count; i++) { | ||
292 | result = acpi_power_on(list->handles[i]); | ||
293 | if (result) { | ||
294 | __acpi_power_off_list(list, i); | ||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | return result; | ||
282 | } | 300 | } |
283 | 301 | ||
284 | /** | 302 | /** |
@@ -364,7 +382,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) | |||
364 | 382 | ||
365 | /* Open power resource */ | 383 | /* Open power resource */ |
366 | for (i = 0; i < dev->wakeup.resources.count; i++) { | 384 | for (i = 0; i < dev->wakeup.resources.count; i++) { |
367 | int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev); | 385 | int ret = acpi_power_on(dev->wakeup.resources.handles[i]); |
368 | if (ret) { | 386 | if (ret) { |
369 | printk(KERN_ERR PREFIX "Transition power state\n"); | 387 | printk(KERN_ERR PREFIX "Transition power state\n"); |
370 | dev->wakeup.flags.valid = 0; | 388 | dev->wakeup.flags.valid = 0; |
@@ -419,8 +437,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) | |||
419 | 437 | ||
420 | /* Close power resource */ | 438 | /* Close power resource */ |
421 | for (i = 0; i < dev->wakeup.resources.count; i++) { | 439 | for (i = 0; i < dev->wakeup.resources.count; i++) { |
422 | int ret = acpi_power_off_device( | 440 | int ret = acpi_power_off(dev->wakeup.resources.handles[i]); |
423 | dev->wakeup.resources.handles[i], dev); | ||
424 | if (ret) { | 441 | if (ret) { |
425 | printk(KERN_ERR PREFIX "Transition power state\n"); | 442 | printk(KERN_ERR PREFIX "Transition power state\n"); |
426 | dev->wakeup.flags.valid = 0; | 443 | dev->wakeup.flags.valid = 0; |
@@ -438,19 +455,16 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) | |||
438 | Device Power Management | 455 | Device Power Management |
439 | -------------------------------------------------------------------------- */ | 456 | -------------------------------------------------------------------------- */ |
440 | 457 | ||
441 | int acpi_power_get_inferred_state(struct acpi_device *device) | 458 | int acpi_power_get_inferred_state(struct acpi_device *device, int *state) |
442 | { | 459 | { |
443 | int result = 0; | 460 | int result = 0; |
444 | struct acpi_handle_list *list = NULL; | 461 | struct acpi_handle_list *list = NULL; |
445 | int list_state = 0; | 462 | int list_state = 0; |
446 | int i = 0; | 463 | int i = 0; |
447 | 464 | ||
448 | 465 | if (!device || !state) | |
449 | if (!device) | ||
450 | return -EINVAL; | 466 | return -EINVAL; |
451 | 467 | ||
452 | device->power.state = ACPI_STATE_UNKNOWN; | ||
453 | |||
454 | /* | 468 | /* |
455 | * We know a device's inferred power state when all the resources | 469 | * We know a device's inferred power state when all the resources |
456 | * required for a given D-state are 'on'. | 470 | * required for a given D-state are 'on'. |
@@ -465,66 +479,51 @@ int acpi_power_get_inferred_state(struct acpi_device *device) | |||
465 | return result; | 479 | return result; |
466 | 480 | ||
467 | if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { | 481 | if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { |
468 | device->power.state = i; | 482 | *state = i; |
469 | return 0; | 483 | return 0; |
470 | } | 484 | } |
471 | } | 485 | } |
472 | 486 | ||
473 | device->power.state = ACPI_STATE_D3; | 487 | *state = ACPI_STATE_D3; |
474 | |||
475 | return 0; | 488 | return 0; |
476 | } | 489 | } |
477 | 490 | ||
478 | int acpi_power_transition(struct acpi_device *device, int state) | 491 | int acpi_power_on_resources(struct acpi_device *device, int state) |
479 | { | 492 | { |
480 | int result = 0; | 493 | if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3) |
481 | struct acpi_handle_list *cl = NULL; /* Current Resources */ | 494 | return -EINVAL; |
482 | struct acpi_handle_list *tl = NULL; /* Target Resources */ | 495 | |
483 | int i = 0; | 496 | return acpi_power_on_list(&device->power.states[state].resources); |
497 | } | ||
484 | 498 | ||
499 | int acpi_power_transition(struct acpi_device *device, int state) | ||
500 | { | ||
501 | int result; | ||
485 | 502 | ||
486 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) | 503 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) |
487 | return -EINVAL; | 504 | return -EINVAL; |
488 | 505 | ||
506 | if (device->power.state == state) | ||
507 | return 0; | ||
508 | |||
489 | if ((device->power.state < ACPI_STATE_D0) | 509 | if ((device->power.state < ACPI_STATE_D0) |
490 | || (device->power.state > ACPI_STATE_D3)) | 510 | || (device->power.state > ACPI_STATE_D3)) |
491 | return -ENODEV; | 511 | return -ENODEV; |
492 | 512 | ||
493 | cl = &device->power.states[device->power.state].resources; | ||
494 | tl = &device->power.states[state].resources; | ||
495 | |||
496 | /* TBD: Resources must be ordered. */ | 513 | /* TBD: Resources must be ordered. */ |
497 | 514 | ||
498 | /* | 515 | /* |
499 | * First we reference all power resources required in the target list | 516 | * First we reference all power resources required in the target list |
500 | * (e.g. so the device doesn't lose power while transitioning). | 517 | * (e.g. so the device doesn't lose power while transitioning). Then, |
501 | */ | 518 | * we dereference all power resources used in the current list. |
502 | for (i = 0; i < tl->count; i++) { | ||
503 | result = acpi_power_on(tl->handles[i], device); | ||
504 | if (result) | ||
505 | goto end; | ||
506 | } | ||
507 | |||
508 | if (device->power.state == state) { | ||
509 | goto end; | ||
510 | } | ||
511 | |||
512 | /* | ||
513 | * Then we dereference all power resources used in the current list. | ||
514 | */ | 519 | */ |
515 | for (i = 0; i < cl->count; i++) { | 520 | result = acpi_power_on_list(&device->power.states[state].resources); |
516 | result = acpi_power_off_device(cl->handles[i], device); | 521 | if (!result) |
517 | if (result) | 522 | acpi_power_off_list( |
518 | goto end; | 523 | &device->power.states[device->power.state].resources); |
519 | } | ||
520 | 524 | ||
521 | end: | 525 | /* We shouldn't change the state unless the above operations succeed. */ |
522 | if (result) | 526 | device->power.state = result ? ACPI_STATE_UNKNOWN : state; |
523 | device->power.state = ACPI_STATE_UNKNOWN; | ||
524 | else { | ||
525 | /* We shouldn't change the state till all above operations succeed */ | ||
526 | device->power.state = state; | ||
527 | } | ||
528 | 527 | ||
529 | return result; | 528 | return result; |
530 | } | 529 | } |
@@ -551,7 +550,6 @@ static int acpi_power_add(struct acpi_device *device) | |||
551 | 550 | ||
552 | resource->device = device; | 551 | resource->device = device; |
553 | mutex_init(&resource->resource_lock); | 552 | mutex_init(&resource->resource_lock); |
554 | INIT_LIST_HEAD(&resource->reference); | ||
555 | strcpy(resource->name, device->pnp.bus_id); | 553 | strcpy(resource->name, device->pnp.bus_id); |
556 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 554 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
557 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 555 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
@@ -594,22 +592,14 @@ static int acpi_power_add(struct acpi_device *device) | |||
594 | 592 | ||
595 | static int acpi_power_remove(struct acpi_device *device, int type) | 593 | static int acpi_power_remove(struct acpi_device *device, int type) |
596 | { | 594 | { |
597 | struct acpi_power_resource *resource = NULL; | 595 | struct acpi_power_resource *resource; |
598 | struct list_head *node, *next; | ||
599 | 596 | ||
600 | 597 | if (!device) | |
601 | if (!device || !acpi_driver_data(device)) | ||
602 | return -EINVAL; | 598 | return -EINVAL; |
603 | 599 | ||
604 | resource = acpi_driver_data(device); | 600 | resource = acpi_driver_data(device); |
605 | 601 | if (!resource) | |
606 | mutex_lock(&resource->resource_lock); | 602 | return -EINVAL; |
607 | list_for_each_safe(node, next, &resource->reference) { | ||
608 | struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node); | ||
609 | list_del(&ref->node); | ||
610 | kfree(ref); | ||
611 | } | ||
612 | mutex_unlock(&resource->resource_lock); | ||
613 | 603 | ||
614 | kfree(resource); | 604 | kfree(resource); |
615 | 605 | ||
@@ -619,29 +609,28 @@ static int acpi_power_remove(struct acpi_device *device, int type) | |||
619 | static int acpi_power_resume(struct acpi_device *device) | 609 | static int acpi_power_resume(struct acpi_device *device) |
620 | { | 610 | { |
621 | int result = 0, state; | 611 | int result = 0, state; |
622 | struct acpi_power_resource *resource = NULL; | 612 | struct acpi_power_resource *resource; |
623 | struct acpi_power_reference *ref; | ||
624 | 613 | ||
625 | if (!device || !acpi_driver_data(device)) | 614 | if (!device) |
626 | return -EINVAL; | 615 | return -EINVAL; |
627 | 616 | ||
628 | resource = acpi_driver_data(device); | 617 | resource = acpi_driver_data(device); |
618 | if (!resource) | ||
619 | return -EINVAL; | ||
620 | |||
621 | mutex_lock(&resource->resource_lock); | ||
629 | 622 | ||
630 | result = acpi_power_get_state(device->handle, &state); | 623 | result = acpi_power_get_state(device->handle, &state); |
631 | if (result) | 624 | if (result) |
632 | return result; | 625 | goto unlock; |
633 | 626 | ||
634 | mutex_lock(&resource->resource_lock); | 627 | if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) |
635 | if (state == ACPI_POWER_RESOURCE_STATE_OFF && | 628 | result = __acpi_power_on(resource); |
636 | !list_empty(&resource->reference)) { | ||
637 | ref = container_of(resource->reference.next, struct acpi_power_reference, node); | ||
638 | mutex_unlock(&resource->resource_lock); | ||
639 | result = acpi_power_on(device->handle, ref->device); | ||
640 | return result; | ||
641 | } | ||
642 | 629 | ||
630 | unlock: | ||
643 | mutex_unlock(&resource->resource_lock); | 631 | mutex_unlock(&resource->resource_lock); |
644 | return 0; | 632 | |
633 | return result; | ||
645 | } | 634 | } |
646 | 635 | ||
647 | int __init acpi_power_init(void) | 636 | int __init acpi_power_init(void) |
diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c deleted file mode 100644 index 66f67293341e..000000000000 --- a/drivers/acpi/power_meter.c +++ /dev/null | |||
@@ -1,1023 +0,0 @@ | |||
1 | /* | ||
2 | * A hwmon driver for ACPI 4.0 power meters | ||
3 | * Copyright (C) 2009 IBM | ||
4 | * | ||
5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/hwmon.h> | ||
24 | #include <linux/hwmon-sysfs.h> | ||
25 | #include <linux/jiffies.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/dmi.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/kdev_t.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/time.h> | ||
32 | #include <acpi/acpi_drivers.h> | ||
33 | #include <acpi/acpi_bus.h> | ||
34 | |||
35 | #define ACPI_POWER_METER_NAME "power_meter" | ||
36 | ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); | ||
37 | #define ACPI_POWER_METER_DEVICE_NAME "Power Meter" | ||
38 | #define ACPI_POWER_METER_CLASS "pwr_meter_resource" | ||
39 | |||
40 | #define NUM_SENSORS 17 | ||
41 | |||
42 | #define POWER_METER_CAN_MEASURE (1 << 0) | ||
43 | #define POWER_METER_CAN_TRIP (1 << 1) | ||
44 | #define POWER_METER_CAN_CAP (1 << 2) | ||
45 | #define POWER_METER_CAN_NOTIFY (1 << 3) | ||
46 | #define POWER_METER_IS_BATTERY (1 << 8) | ||
47 | #define UNKNOWN_HYSTERESIS 0xFFFFFFFF | ||
48 | |||
49 | #define METER_NOTIFY_CONFIG 0x80 | ||
50 | #define METER_NOTIFY_TRIP 0x81 | ||
51 | #define METER_NOTIFY_CAP 0x82 | ||
52 | #define METER_NOTIFY_CAPPING 0x83 | ||
53 | #define METER_NOTIFY_INTERVAL 0x84 | ||
54 | |||
55 | #define POWER_AVERAGE_NAME "power1_average" | ||
56 | #define POWER_CAP_NAME "power1_cap" | ||
57 | #define POWER_AVG_INTERVAL_NAME "power1_average_interval" | ||
58 | #define POWER_ALARM_NAME "power1_alarm" | ||
59 | |||
60 | static int cap_in_hardware; | ||
61 | static int force_cap_on; | ||
62 | |||
63 | static int can_cap_in_hardware(void) | ||
64 | { | ||
65 | return force_cap_on || cap_in_hardware; | ||
66 | } | ||
67 | |||
68 | static const struct acpi_device_id power_meter_ids[] = { | ||
69 | {"ACPI000D", 0}, | ||
70 | {"", 0}, | ||
71 | }; | ||
72 | MODULE_DEVICE_TABLE(acpi, power_meter_ids); | ||
73 | |||
74 | struct acpi_power_meter_capabilities { | ||
75 | u64 flags; | ||
76 | u64 units; | ||
77 | u64 type; | ||
78 | u64 accuracy; | ||
79 | u64 sampling_time; | ||
80 | u64 min_avg_interval; | ||
81 | u64 max_avg_interval; | ||
82 | u64 hysteresis; | ||
83 | u64 configurable_cap; | ||
84 | u64 min_cap; | ||
85 | u64 max_cap; | ||
86 | }; | ||
87 | |||
88 | struct acpi_power_meter_resource { | ||
89 | struct acpi_device *acpi_dev; | ||
90 | acpi_bus_id name; | ||
91 | struct mutex lock; | ||
92 | struct device *hwmon_dev; | ||
93 | struct acpi_power_meter_capabilities caps; | ||
94 | acpi_string model_number; | ||
95 | acpi_string serial_number; | ||
96 | acpi_string oem_info; | ||
97 | u64 power; | ||
98 | u64 cap; | ||
99 | u64 avg_interval; | ||
100 | int sensors_valid; | ||
101 | unsigned long sensors_last_updated; | ||
102 | struct sensor_device_attribute sensors[NUM_SENSORS]; | ||
103 | int num_sensors; | ||
104 | int trip[2]; | ||
105 | int num_domain_devices; | ||
106 | struct acpi_device **domain_devices; | ||
107 | struct kobject *holders_dir; | ||
108 | }; | ||
109 | |||
110 | struct ro_sensor_template { | ||
111 | char *label; | ||
112 | ssize_t (*show)(struct device *dev, | ||
113 | struct device_attribute *devattr, | ||
114 | char *buf); | ||
115 | int index; | ||
116 | }; | ||
117 | |||
118 | struct rw_sensor_template { | ||
119 | char *label; | ||
120 | ssize_t (*show)(struct device *dev, | ||
121 | struct device_attribute *devattr, | ||
122 | char *buf); | ||
123 | ssize_t (*set)(struct device *dev, | ||
124 | struct device_attribute *devattr, | ||
125 | const char *buf, size_t count); | ||
126 | int index; | ||
127 | }; | ||
128 | |||
129 | /* Averaging interval */ | ||
130 | static int update_avg_interval(struct acpi_power_meter_resource *resource) | ||
131 | { | ||
132 | unsigned long long data; | ||
133 | acpi_status status; | ||
134 | |||
135 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GAI", | ||
136 | NULL, &data); | ||
137 | if (ACPI_FAILURE(status)) { | ||
138 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GAI")); | ||
139 | return -ENODEV; | ||
140 | } | ||
141 | |||
142 | resource->avg_interval = data; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static ssize_t show_avg_interval(struct device *dev, | ||
147 | struct device_attribute *devattr, | ||
148 | char *buf) | ||
149 | { | ||
150 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
151 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
152 | |||
153 | mutex_lock(&resource->lock); | ||
154 | update_avg_interval(resource); | ||
155 | mutex_unlock(&resource->lock); | ||
156 | |||
157 | return sprintf(buf, "%llu\n", resource->avg_interval); | ||
158 | } | ||
159 | |||
160 | static ssize_t set_avg_interval(struct device *dev, | ||
161 | struct device_attribute *devattr, | ||
162 | const char *buf, size_t count) | ||
163 | { | ||
164 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
165 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
166 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
167 | struct acpi_object_list args = { 1, &arg0 }; | ||
168 | int res; | ||
169 | unsigned long temp; | ||
170 | unsigned long long data; | ||
171 | acpi_status status; | ||
172 | |||
173 | res = strict_strtoul(buf, 10, &temp); | ||
174 | if (res) | ||
175 | return res; | ||
176 | |||
177 | if (temp > resource->caps.max_avg_interval || | ||
178 | temp < resource->caps.min_avg_interval) | ||
179 | return -EINVAL; | ||
180 | arg0.integer.value = temp; | ||
181 | |||
182 | mutex_lock(&resource->lock); | ||
183 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PAI", | ||
184 | &args, &data); | ||
185 | if (!ACPI_FAILURE(status)) | ||
186 | resource->avg_interval = temp; | ||
187 | mutex_unlock(&resource->lock); | ||
188 | |||
189 | if (ACPI_FAILURE(status)) { | ||
190 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PAI")); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | /* _PAI returns 0 on success, nonzero otherwise */ | ||
195 | if (data) | ||
196 | return -EINVAL; | ||
197 | |||
198 | return count; | ||
199 | } | ||
200 | |||
201 | /* Cap functions */ | ||
202 | static int update_cap(struct acpi_power_meter_resource *resource) | ||
203 | { | ||
204 | unsigned long long data; | ||
205 | acpi_status status; | ||
206 | |||
207 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GHL", | ||
208 | NULL, &data); | ||
209 | if (ACPI_FAILURE(status)) { | ||
210 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GHL")); | ||
211 | return -ENODEV; | ||
212 | } | ||
213 | |||
214 | resource->cap = data; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static ssize_t show_cap(struct device *dev, | ||
219 | struct device_attribute *devattr, | ||
220 | char *buf) | ||
221 | { | ||
222 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
223 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
224 | |||
225 | mutex_lock(&resource->lock); | ||
226 | update_cap(resource); | ||
227 | mutex_unlock(&resource->lock); | ||
228 | |||
229 | return sprintf(buf, "%llu\n", resource->cap * 1000); | ||
230 | } | ||
231 | |||
232 | static ssize_t set_cap(struct device *dev, struct device_attribute *devattr, | ||
233 | const char *buf, size_t count) | ||
234 | { | ||
235 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
236 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
237 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
238 | struct acpi_object_list args = { 1, &arg0 }; | ||
239 | int res; | ||
240 | unsigned long temp; | ||
241 | unsigned long long data; | ||
242 | acpi_status status; | ||
243 | |||
244 | res = strict_strtoul(buf, 10, &temp); | ||
245 | if (res) | ||
246 | return res; | ||
247 | |||
248 | temp /= 1000; | ||
249 | if (temp > resource->caps.max_cap || temp < resource->caps.min_cap) | ||
250 | return -EINVAL; | ||
251 | arg0.integer.value = temp; | ||
252 | |||
253 | mutex_lock(&resource->lock); | ||
254 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_SHL", | ||
255 | &args, &data); | ||
256 | if (!ACPI_FAILURE(status)) | ||
257 | resource->cap = temp; | ||
258 | mutex_unlock(&resource->lock); | ||
259 | |||
260 | if (ACPI_FAILURE(status)) { | ||
261 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SHL")); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | /* _SHL returns 0 on success, nonzero otherwise */ | ||
266 | if (data) | ||
267 | return -EINVAL; | ||
268 | |||
269 | return count; | ||
270 | } | ||
271 | |||
272 | /* Power meter trip points */ | ||
273 | static int set_acpi_trip(struct acpi_power_meter_resource *resource) | ||
274 | { | ||
275 | union acpi_object arg_objs[] = { | ||
276 | {ACPI_TYPE_INTEGER}, | ||
277 | {ACPI_TYPE_INTEGER} | ||
278 | }; | ||
279 | struct acpi_object_list args = { 2, arg_objs }; | ||
280 | unsigned long long data; | ||
281 | acpi_status status; | ||
282 | |||
283 | /* Both trip levels must be set */ | ||
284 | if (resource->trip[0] < 0 || resource->trip[1] < 0) | ||
285 | return 0; | ||
286 | |||
287 | /* This driver stores min, max; ACPI wants max, min. */ | ||
288 | arg_objs[0].integer.value = resource->trip[1]; | ||
289 | arg_objs[1].integer.value = resource->trip[0]; | ||
290 | |||
291 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PTP", | ||
292 | &args, &data); | ||
293 | if (ACPI_FAILURE(status)) { | ||
294 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTP")); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | /* _PTP returns 0 on success, nonzero otherwise */ | ||
299 | if (data) | ||
300 | return -EINVAL; | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static ssize_t set_trip(struct device *dev, struct device_attribute *devattr, | ||
306 | const char *buf, size_t count) | ||
307 | { | ||
308 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
309 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
310 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
311 | int res; | ||
312 | unsigned long temp; | ||
313 | |||
314 | res = strict_strtoul(buf, 10, &temp); | ||
315 | if (res) | ||
316 | return res; | ||
317 | |||
318 | temp /= 1000; | ||
319 | if (temp < 0) | ||
320 | return -EINVAL; | ||
321 | |||
322 | mutex_lock(&resource->lock); | ||
323 | resource->trip[attr->index - 7] = temp; | ||
324 | res = set_acpi_trip(resource); | ||
325 | mutex_unlock(&resource->lock); | ||
326 | |||
327 | if (res) | ||
328 | return res; | ||
329 | |||
330 | return count; | ||
331 | } | ||
332 | |||
333 | /* Power meter */ | ||
334 | static int update_meter(struct acpi_power_meter_resource *resource) | ||
335 | { | ||
336 | unsigned long long data; | ||
337 | acpi_status status; | ||
338 | unsigned long local_jiffies = jiffies; | ||
339 | |||
340 | if (time_before(local_jiffies, resource->sensors_last_updated + | ||
341 | msecs_to_jiffies(resource->caps.sampling_time)) && | ||
342 | resource->sensors_valid) | ||
343 | return 0; | ||
344 | |||
345 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PMM", | ||
346 | NULL, &data); | ||
347 | if (ACPI_FAILURE(status)) { | ||
348 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMM")); | ||
349 | return -ENODEV; | ||
350 | } | ||
351 | |||
352 | resource->power = data; | ||
353 | resource->sensors_valid = 1; | ||
354 | resource->sensors_last_updated = jiffies; | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static ssize_t show_power(struct device *dev, | ||
359 | struct device_attribute *devattr, | ||
360 | char *buf) | ||
361 | { | ||
362 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
363 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
364 | |||
365 | mutex_lock(&resource->lock); | ||
366 | update_meter(resource); | ||
367 | mutex_unlock(&resource->lock); | ||
368 | |||
369 | return sprintf(buf, "%llu\n", resource->power * 1000); | ||
370 | } | ||
371 | |||
372 | /* Miscellaneous */ | ||
373 | static ssize_t show_str(struct device *dev, | ||
374 | struct device_attribute *devattr, | ||
375 | char *buf) | ||
376 | { | ||
377 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
378 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
379 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
380 | acpi_string val; | ||
381 | |||
382 | switch (attr->index) { | ||
383 | case 0: | ||
384 | val = resource->model_number; | ||
385 | break; | ||
386 | case 1: | ||
387 | val = resource->serial_number; | ||
388 | break; | ||
389 | case 2: | ||
390 | val = resource->oem_info; | ||
391 | break; | ||
392 | default: | ||
393 | BUG(); | ||
394 | } | ||
395 | |||
396 | return sprintf(buf, "%s\n", val); | ||
397 | } | ||
398 | |||
399 | static ssize_t show_val(struct device *dev, | ||
400 | struct device_attribute *devattr, | ||
401 | char *buf) | ||
402 | { | ||
403 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
404 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
405 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
406 | u64 val = 0; | ||
407 | |||
408 | switch (attr->index) { | ||
409 | case 0: | ||
410 | val = resource->caps.min_avg_interval; | ||
411 | break; | ||
412 | case 1: | ||
413 | val = resource->caps.max_avg_interval; | ||
414 | break; | ||
415 | case 2: | ||
416 | val = resource->caps.min_cap * 1000; | ||
417 | break; | ||
418 | case 3: | ||
419 | val = resource->caps.max_cap * 1000; | ||
420 | break; | ||
421 | case 4: | ||
422 | if (resource->caps.hysteresis == UNKNOWN_HYSTERESIS) | ||
423 | return sprintf(buf, "unknown\n"); | ||
424 | |||
425 | val = resource->caps.hysteresis * 1000; | ||
426 | break; | ||
427 | case 5: | ||
428 | if (resource->caps.flags & POWER_METER_IS_BATTERY) | ||
429 | val = 1; | ||
430 | else | ||
431 | val = 0; | ||
432 | break; | ||
433 | case 6: | ||
434 | if (resource->power > resource->cap) | ||
435 | val = 1; | ||
436 | else | ||
437 | val = 0; | ||
438 | break; | ||
439 | case 7: | ||
440 | case 8: | ||
441 | if (resource->trip[attr->index - 7] < 0) | ||
442 | return sprintf(buf, "unknown\n"); | ||
443 | |||
444 | val = resource->trip[attr->index - 7] * 1000; | ||
445 | break; | ||
446 | default: | ||
447 | BUG(); | ||
448 | } | ||
449 | |||
450 | return sprintf(buf, "%llu\n", val); | ||
451 | } | ||
452 | |||
453 | static ssize_t show_accuracy(struct device *dev, | ||
454 | struct device_attribute *devattr, | ||
455 | char *buf) | ||
456 | { | ||
457 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
458 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
459 | unsigned int acc = resource->caps.accuracy; | ||
460 | |||
461 | return sprintf(buf, "%u.%u%%\n", acc / 1000, acc % 1000); | ||
462 | } | ||
463 | |||
464 | static ssize_t show_name(struct device *dev, | ||
465 | struct device_attribute *devattr, | ||
466 | char *buf) | ||
467 | { | ||
468 | return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME); | ||
469 | } | ||
470 | |||
471 | /* Sensor descriptions. If you add a sensor, update NUM_SENSORS above! */ | ||
472 | static struct ro_sensor_template meter_ro_attrs[] = { | ||
473 | {POWER_AVERAGE_NAME, show_power, 0}, | ||
474 | {"power1_accuracy", show_accuracy, 0}, | ||
475 | {"power1_average_interval_min", show_val, 0}, | ||
476 | {"power1_average_interval_max", show_val, 1}, | ||
477 | {"power1_is_battery", show_val, 5}, | ||
478 | {NULL, NULL, 0}, | ||
479 | }; | ||
480 | |||
481 | static struct rw_sensor_template meter_rw_attrs[] = { | ||
482 | {POWER_AVG_INTERVAL_NAME, show_avg_interval, set_avg_interval, 0}, | ||
483 | {NULL, NULL, NULL, 0}, | ||
484 | }; | ||
485 | |||
486 | static struct ro_sensor_template misc_cap_attrs[] = { | ||
487 | {"power1_cap_min", show_val, 2}, | ||
488 | {"power1_cap_max", show_val, 3}, | ||
489 | {"power1_cap_hyst", show_val, 4}, | ||
490 | {POWER_ALARM_NAME, show_val, 6}, | ||
491 | {NULL, NULL, 0}, | ||
492 | }; | ||
493 | |||
494 | static struct ro_sensor_template ro_cap_attrs[] = { | ||
495 | {POWER_CAP_NAME, show_cap, 0}, | ||
496 | {NULL, NULL, 0}, | ||
497 | }; | ||
498 | |||
499 | static struct rw_sensor_template rw_cap_attrs[] = { | ||
500 | {POWER_CAP_NAME, show_cap, set_cap, 0}, | ||
501 | {NULL, NULL, NULL, 0}, | ||
502 | }; | ||
503 | |||
504 | static struct rw_sensor_template trip_attrs[] = { | ||
505 | {"power1_average_min", show_val, set_trip, 7}, | ||
506 | {"power1_average_max", show_val, set_trip, 8}, | ||
507 | {NULL, NULL, NULL, 0}, | ||
508 | }; | ||
509 | |||
510 | static struct ro_sensor_template misc_attrs[] = { | ||
511 | {"name", show_name, 0}, | ||
512 | {"power1_model_number", show_str, 0}, | ||
513 | {"power1_oem_info", show_str, 2}, | ||
514 | {"power1_serial_number", show_str, 1}, | ||
515 | {NULL, NULL, 0}, | ||
516 | }; | ||
517 | |||
518 | /* Read power domain data */ | ||
519 | static void remove_domain_devices(struct acpi_power_meter_resource *resource) | ||
520 | { | ||
521 | int i; | ||
522 | |||
523 | if (!resource->num_domain_devices) | ||
524 | return; | ||
525 | |||
526 | for (i = 0; i < resource->num_domain_devices; i++) { | ||
527 | struct acpi_device *obj = resource->domain_devices[i]; | ||
528 | if (!obj) | ||
529 | continue; | ||
530 | |||
531 | sysfs_remove_link(resource->holders_dir, | ||
532 | kobject_name(&obj->dev.kobj)); | ||
533 | put_device(&obj->dev); | ||
534 | } | ||
535 | |||
536 | kfree(resource->domain_devices); | ||
537 | kobject_put(resource->holders_dir); | ||
538 | resource->num_domain_devices = 0; | ||
539 | } | ||
540 | |||
541 | static int read_domain_devices(struct acpi_power_meter_resource *resource) | ||
542 | { | ||
543 | int res = 0; | ||
544 | int i; | ||
545 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
546 | union acpi_object *pss; | ||
547 | acpi_status status; | ||
548 | |||
549 | status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMD", NULL, | ||
550 | &buffer); | ||
551 | if (ACPI_FAILURE(status)) { | ||
552 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMD")); | ||
553 | return -ENODEV; | ||
554 | } | ||
555 | |||
556 | pss = buffer.pointer; | ||
557 | if (!pss || | ||
558 | pss->type != ACPI_TYPE_PACKAGE) { | ||
559 | dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME | ||
560 | "Invalid _PMD data\n"); | ||
561 | res = -EFAULT; | ||
562 | goto end; | ||
563 | } | ||
564 | |||
565 | if (!pss->package.count) | ||
566 | goto end; | ||
567 | |||
568 | resource->domain_devices = kzalloc(sizeof(struct acpi_device *) * | ||
569 | pss->package.count, GFP_KERNEL); | ||
570 | if (!resource->domain_devices) { | ||
571 | res = -ENOMEM; | ||
572 | goto end; | ||
573 | } | ||
574 | |||
575 | resource->holders_dir = kobject_create_and_add("measures", | ||
576 | &resource->acpi_dev->dev.kobj); | ||
577 | if (!resource->holders_dir) { | ||
578 | res = -ENOMEM; | ||
579 | goto exit_free; | ||
580 | } | ||
581 | |||
582 | resource->num_domain_devices = pss->package.count; | ||
583 | |||
584 | for (i = 0; i < pss->package.count; i++) { | ||
585 | struct acpi_device *obj; | ||
586 | union acpi_object *element = &(pss->package.elements[i]); | ||
587 | |||
588 | /* Refuse non-references */ | ||
589 | if (element->type != ACPI_TYPE_LOCAL_REFERENCE) | ||
590 | continue; | ||
591 | |||
592 | /* Create a symlink to domain objects */ | ||
593 | resource->domain_devices[i] = NULL; | ||
594 | status = acpi_bus_get_device(element->reference.handle, | ||
595 | &resource->domain_devices[i]); | ||
596 | if (ACPI_FAILURE(status)) | ||
597 | continue; | ||
598 | |||
599 | obj = resource->domain_devices[i]; | ||
600 | get_device(&obj->dev); | ||
601 | |||
602 | res = sysfs_create_link(resource->holders_dir, &obj->dev.kobj, | ||
603 | kobject_name(&obj->dev.kobj)); | ||
604 | if (res) { | ||
605 | put_device(&obj->dev); | ||
606 | resource->domain_devices[i] = NULL; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | res = 0; | ||
611 | goto end; | ||
612 | |||
613 | exit_free: | ||
614 | kfree(resource->domain_devices); | ||
615 | end: | ||
616 | kfree(buffer.pointer); | ||
617 | return res; | ||
618 | } | ||
619 | |||
620 | /* Registration and deregistration */ | ||
621 | static int register_ro_attrs(struct acpi_power_meter_resource *resource, | ||
622 | struct ro_sensor_template *ro) | ||
623 | { | ||
624 | struct device *dev = &resource->acpi_dev->dev; | ||
625 | struct sensor_device_attribute *sensors = | ||
626 | &resource->sensors[resource->num_sensors]; | ||
627 | int res = 0; | ||
628 | |||
629 | while (ro->label) { | ||
630 | sensors->dev_attr.attr.name = ro->label; | ||
631 | sensors->dev_attr.attr.mode = S_IRUGO; | ||
632 | sensors->dev_attr.show = ro->show; | ||
633 | sensors->index = ro->index; | ||
634 | |||
635 | res = device_create_file(dev, &sensors->dev_attr); | ||
636 | if (res) { | ||
637 | sensors->dev_attr.attr.name = NULL; | ||
638 | goto error; | ||
639 | } | ||
640 | sensors++; | ||
641 | resource->num_sensors++; | ||
642 | ro++; | ||
643 | } | ||
644 | |||
645 | error: | ||
646 | return res; | ||
647 | } | ||
648 | |||
649 | static int register_rw_attrs(struct acpi_power_meter_resource *resource, | ||
650 | struct rw_sensor_template *rw) | ||
651 | { | ||
652 | struct device *dev = &resource->acpi_dev->dev; | ||
653 | struct sensor_device_attribute *sensors = | ||
654 | &resource->sensors[resource->num_sensors]; | ||
655 | int res = 0; | ||
656 | |||
657 | while (rw->label) { | ||
658 | sensors->dev_attr.attr.name = rw->label; | ||
659 | sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; | ||
660 | sensors->dev_attr.show = rw->show; | ||
661 | sensors->dev_attr.store = rw->set; | ||
662 | sensors->index = rw->index; | ||
663 | |||
664 | res = device_create_file(dev, &sensors->dev_attr); | ||
665 | if (res) { | ||
666 | sensors->dev_attr.attr.name = NULL; | ||
667 | goto error; | ||
668 | } | ||
669 | sensors++; | ||
670 | resource->num_sensors++; | ||
671 | rw++; | ||
672 | } | ||
673 | |||
674 | error: | ||
675 | return res; | ||
676 | } | ||
677 | |||
678 | static void remove_attrs(struct acpi_power_meter_resource *resource) | ||
679 | { | ||
680 | int i; | ||
681 | |||
682 | for (i = 0; i < resource->num_sensors; i++) { | ||
683 | if (!resource->sensors[i].dev_attr.attr.name) | ||
684 | continue; | ||
685 | device_remove_file(&resource->acpi_dev->dev, | ||
686 | &resource->sensors[i].dev_attr); | ||
687 | } | ||
688 | |||
689 | remove_domain_devices(resource); | ||
690 | |||
691 | resource->num_sensors = 0; | ||
692 | } | ||
693 | |||
694 | static int setup_attrs(struct acpi_power_meter_resource *resource) | ||
695 | { | ||
696 | int res = 0; | ||
697 | |||
698 | res = read_domain_devices(resource); | ||
699 | if (res) | ||
700 | return res; | ||
701 | |||
702 | if (resource->caps.flags & POWER_METER_CAN_MEASURE) { | ||
703 | res = register_ro_attrs(resource, meter_ro_attrs); | ||
704 | if (res) | ||
705 | goto error; | ||
706 | res = register_rw_attrs(resource, meter_rw_attrs); | ||
707 | if (res) | ||
708 | goto error; | ||
709 | } | ||
710 | |||
711 | if (resource->caps.flags & POWER_METER_CAN_CAP) { | ||
712 | if (!can_cap_in_hardware()) { | ||
713 | dev_err(&resource->acpi_dev->dev, | ||
714 | "Ignoring unsafe software power cap!\n"); | ||
715 | goto skip_unsafe_cap; | ||
716 | } | ||
717 | |||
718 | if (resource->caps.configurable_cap) { | ||
719 | res = register_rw_attrs(resource, rw_cap_attrs); | ||
720 | if (res) | ||
721 | goto error; | ||
722 | } else { | ||
723 | res = register_ro_attrs(resource, ro_cap_attrs); | ||
724 | if (res) | ||
725 | goto error; | ||
726 | } | ||
727 | res = register_ro_attrs(resource, misc_cap_attrs); | ||
728 | if (res) | ||
729 | goto error; | ||
730 | } | ||
731 | skip_unsafe_cap: | ||
732 | |||
733 | if (resource->caps.flags & POWER_METER_CAN_TRIP) { | ||
734 | res = register_rw_attrs(resource, trip_attrs); | ||
735 | if (res) | ||
736 | goto error; | ||
737 | } | ||
738 | |||
739 | res = register_ro_attrs(resource, misc_attrs); | ||
740 | if (res) | ||
741 | goto error; | ||
742 | |||
743 | return res; | ||
744 | error: | ||
745 | remove_attrs(resource); | ||
746 | return res; | ||
747 | } | ||
748 | |||
749 | static void free_capabilities(struct acpi_power_meter_resource *resource) | ||
750 | { | ||
751 | acpi_string *str; | ||
752 | int i; | ||
753 | |||
754 | str = &resource->model_number; | ||
755 | for (i = 0; i < 3; i++, str++) | ||
756 | kfree(*str); | ||
757 | } | ||
758 | |||
759 | static int read_capabilities(struct acpi_power_meter_resource *resource) | ||
760 | { | ||
761 | int res = 0; | ||
762 | int i; | ||
763 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
764 | struct acpi_buffer state = { 0, NULL }; | ||
765 | struct acpi_buffer format = { sizeof("NNNNNNNNNNN"), "NNNNNNNNNNN" }; | ||
766 | union acpi_object *pss; | ||
767 | acpi_string *str; | ||
768 | acpi_status status; | ||
769 | |||
770 | status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMC", NULL, | ||
771 | &buffer); | ||
772 | if (ACPI_FAILURE(status)) { | ||
773 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMC")); | ||
774 | return -ENODEV; | ||
775 | } | ||
776 | |||
777 | pss = buffer.pointer; | ||
778 | if (!pss || | ||
779 | pss->type != ACPI_TYPE_PACKAGE || | ||
780 | pss->package.count != 14) { | ||
781 | dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME | ||
782 | "Invalid _PMC data\n"); | ||
783 | res = -EFAULT; | ||
784 | goto end; | ||
785 | } | ||
786 | |||
787 | /* Grab all the integer data at once */ | ||
788 | state.length = sizeof(struct acpi_power_meter_capabilities); | ||
789 | state.pointer = &resource->caps; | ||
790 | |||
791 | status = acpi_extract_package(pss, &format, &state); | ||
792 | if (ACPI_FAILURE(status)) { | ||
793 | ACPI_EXCEPTION((AE_INFO, status, "Invalid data")); | ||
794 | res = -EFAULT; | ||
795 | goto end; | ||
796 | } | ||
797 | |||
798 | if (resource->caps.units) { | ||
799 | dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME | ||
800 | "Unknown units %llu.\n", | ||
801 | resource->caps.units); | ||
802 | res = -EINVAL; | ||
803 | goto end; | ||
804 | } | ||
805 | |||
806 | /* Grab the string data */ | ||
807 | str = &resource->model_number; | ||
808 | |||
809 | for (i = 11; i < 14; i++) { | ||
810 | union acpi_object *element = &(pss->package.elements[i]); | ||
811 | |||
812 | if (element->type != ACPI_TYPE_STRING) { | ||
813 | res = -EINVAL; | ||
814 | goto error; | ||
815 | } | ||
816 | |||
817 | *str = kzalloc(sizeof(u8) * (element->string.length + 1), | ||
818 | GFP_KERNEL); | ||
819 | if (!*str) { | ||
820 | res = -ENOMEM; | ||
821 | goto error; | ||
822 | } | ||
823 | |||
824 | strncpy(*str, element->string.pointer, element->string.length); | ||
825 | str++; | ||
826 | } | ||
827 | |||
828 | dev_info(&resource->acpi_dev->dev, "Found ACPI power meter.\n"); | ||
829 | goto end; | ||
830 | error: | ||
831 | str = &resource->model_number; | ||
832 | for (i = 0; i < 3; i++, str++) | ||
833 | kfree(*str); | ||
834 | end: | ||
835 | kfree(buffer.pointer); | ||
836 | return res; | ||
837 | } | ||
838 | |||
839 | /* Handle ACPI event notifications */ | ||
840 | static void acpi_power_meter_notify(struct acpi_device *device, u32 event) | ||
841 | { | ||
842 | struct acpi_power_meter_resource *resource; | ||
843 | int res; | ||
844 | |||
845 | if (!device || !acpi_driver_data(device)) | ||
846 | return; | ||
847 | |||
848 | resource = acpi_driver_data(device); | ||
849 | |||
850 | mutex_lock(&resource->lock); | ||
851 | switch (event) { | ||
852 | case METER_NOTIFY_CONFIG: | ||
853 | free_capabilities(resource); | ||
854 | res = read_capabilities(resource); | ||
855 | if (res) | ||
856 | break; | ||
857 | |||
858 | remove_attrs(resource); | ||
859 | setup_attrs(resource); | ||
860 | break; | ||
861 | case METER_NOTIFY_TRIP: | ||
862 | sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME); | ||
863 | update_meter(resource); | ||
864 | break; | ||
865 | case METER_NOTIFY_CAP: | ||
866 | sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME); | ||
867 | update_cap(resource); | ||
868 | break; | ||
869 | case METER_NOTIFY_INTERVAL: | ||
870 | sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME); | ||
871 | update_avg_interval(resource); | ||
872 | break; | ||
873 | case METER_NOTIFY_CAPPING: | ||
874 | sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME); | ||
875 | dev_info(&device->dev, "Capping in progress.\n"); | ||
876 | break; | ||
877 | default: | ||
878 | BUG(); | ||
879 | } | ||
880 | mutex_unlock(&resource->lock); | ||
881 | |||
882 | acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS, | ||
883 | dev_name(&device->dev), event, 0); | ||
884 | } | ||
885 | |||
886 | static int acpi_power_meter_add(struct acpi_device *device) | ||
887 | { | ||
888 | int res; | ||
889 | struct acpi_power_meter_resource *resource; | ||
890 | |||
891 | if (!device) | ||
892 | return -EINVAL; | ||
893 | |||
894 | resource = kzalloc(sizeof(struct acpi_power_meter_resource), | ||
895 | GFP_KERNEL); | ||
896 | if (!resource) | ||
897 | return -ENOMEM; | ||
898 | |||
899 | resource->sensors_valid = 0; | ||
900 | resource->acpi_dev = device; | ||
901 | mutex_init(&resource->lock); | ||
902 | strcpy(acpi_device_name(device), ACPI_POWER_METER_DEVICE_NAME); | ||
903 | strcpy(acpi_device_class(device), ACPI_POWER_METER_CLASS); | ||
904 | device->driver_data = resource; | ||
905 | |||
906 | free_capabilities(resource); | ||
907 | res = read_capabilities(resource); | ||
908 | if (res) | ||
909 | goto exit_free; | ||
910 | |||
911 | resource->trip[0] = resource->trip[1] = -1; | ||
912 | |||
913 | res = setup_attrs(resource); | ||
914 | if (res) | ||
915 | goto exit_free; | ||
916 | |||
917 | resource->hwmon_dev = hwmon_device_register(&device->dev); | ||
918 | if (IS_ERR(resource->hwmon_dev)) { | ||
919 | res = PTR_ERR(resource->hwmon_dev); | ||
920 | goto exit_remove; | ||
921 | } | ||
922 | |||
923 | res = 0; | ||
924 | goto exit; | ||
925 | |||
926 | exit_remove: | ||
927 | remove_attrs(resource); | ||
928 | exit_free: | ||
929 | kfree(resource); | ||
930 | exit: | ||
931 | return res; | ||
932 | } | ||
933 | |||
934 | static int acpi_power_meter_remove(struct acpi_device *device, int type) | ||
935 | { | ||
936 | struct acpi_power_meter_resource *resource; | ||
937 | |||
938 | if (!device || !acpi_driver_data(device)) | ||
939 | return -EINVAL; | ||
940 | |||
941 | resource = acpi_driver_data(device); | ||
942 | hwmon_device_unregister(resource->hwmon_dev); | ||
943 | |||
944 | free_capabilities(resource); | ||
945 | remove_attrs(resource); | ||
946 | |||
947 | kfree(resource); | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | static int acpi_power_meter_resume(struct acpi_device *device) | ||
952 | { | ||
953 | struct acpi_power_meter_resource *resource; | ||
954 | |||
955 | if (!device || !acpi_driver_data(device)) | ||
956 | return -EINVAL; | ||
957 | |||
958 | resource = acpi_driver_data(device); | ||
959 | free_capabilities(resource); | ||
960 | read_capabilities(resource); | ||
961 | |||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | static struct acpi_driver acpi_power_meter_driver = { | ||
966 | .name = "power_meter", | ||
967 | .class = ACPI_POWER_METER_CLASS, | ||
968 | .ids = power_meter_ids, | ||
969 | .ops = { | ||
970 | .add = acpi_power_meter_add, | ||
971 | .remove = acpi_power_meter_remove, | ||
972 | .resume = acpi_power_meter_resume, | ||
973 | .notify = acpi_power_meter_notify, | ||
974 | }, | ||
975 | }; | ||
976 | |||
977 | /* Module init/exit routines */ | ||
978 | static int __init enable_cap_knobs(const struct dmi_system_id *d) | ||
979 | { | ||
980 | cap_in_hardware = 1; | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static struct dmi_system_id __initdata pm_dmi_table[] = { | ||
985 | { | ||
986 | enable_cap_knobs, "IBM Active Energy Manager", | ||
987 | { | ||
988 | DMI_MATCH(DMI_SYS_VENDOR, "IBM") | ||
989 | }, | ||
990 | }, | ||
991 | {} | ||
992 | }; | ||
993 | |||
994 | static int __init acpi_power_meter_init(void) | ||
995 | { | ||
996 | int result; | ||
997 | |||
998 | if (acpi_disabled) | ||
999 | return -ENODEV; | ||
1000 | |||
1001 | dmi_check_system(pm_dmi_table); | ||
1002 | |||
1003 | result = acpi_bus_register_driver(&acpi_power_meter_driver); | ||
1004 | if (result < 0) | ||
1005 | return -ENODEV; | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | static void __exit acpi_power_meter_exit(void) | ||
1011 | { | ||
1012 | acpi_bus_unregister_driver(&acpi_power_meter_driver); | ||
1013 | } | ||
1014 | |||
1015 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
1016 | MODULE_DESCRIPTION("ACPI 4.0 power meter driver"); | ||
1017 | MODULE_LICENSE("GPL"); | ||
1018 | |||
1019 | module_param(force_cap_on, bool, 0644); | ||
1020 | MODULE_PARM_DESC(force_cap_on, "Enable power cap even it is unsafe to do so."); | ||
1021 | |||
1022 | module_init(acpi_power_meter_init); | ||
1023 | module_exit(acpi_power_meter_exit); | ||
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index afad67769db6..f5f986991b52 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
@@ -311,7 +311,9 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
311 | dev->pnp.bus_id, | 311 | dev->pnp.bus_id, |
312 | (u32) dev->wakeup.sleep_state, | 312 | (u32) dev->wakeup.sleep_state, |
313 | dev->wakeup.flags.run_wake ? '*' : ' ', | 313 | dev->wakeup.flags.run_wake ? '*' : ' ', |
314 | dev->wakeup.state.enabled ? "enabled" : "disabled"); | 314 | (device_may_wakeup(&dev->dev) |
315 | || (ldev && device_may_wakeup(ldev))) ? | ||
316 | "enabled" : "disabled"); | ||
315 | if (ldev) | 317 | if (ldev) |
316 | seq_printf(seq, "%s:%s", | 318 | seq_printf(seq, "%s:%s", |
317 | ldev->bus ? ldev->bus->name : "no-bus", | 319 | ldev->bus ? ldev->bus->name : "no-bus", |
@@ -328,8 +330,10 @@ static void physical_device_enable_wakeup(struct acpi_device *adev) | |||
328 | { | 330 | { |
329 | struct device *dev = acpi_get_physical_device(adev->handle); | 331 | struct device *dev = acpi_get_physical_device(adev->handle); |
330 | 332 | ||
331 | if (dev && device_can_wakeup(dev)) | 333 | if (dev && device_can_wakeup(dev)) { |
332 | device_set_wakeup_enable(dev, adev->wakeup.state.enabled); | 334 | bool enable = !device_may_wakeup(dev); |
335 | device_set_wakeup_enable(dev, enable); | ||
336 | } | ||
333 | } | 337 | } |
334 | 338 | ||
335 | static ssize_t | 339 | static ssize_t |
@@ -341,7 +345,6 @@ acpi_system_write_wakeup_device(struct file *file, | |||
341 | char strbuf[5]; | 345 | char strbuf[5]; |
342 | char str[5] = ""; | 346 | char str[5] = ""; |
343 | unsigned int len = count; | 347 | unsigned int len = count; |
344 | struct acpi_device *found_dev = NULL; | ||
345 | 348 | ||
346 | if (len > 4) | 349 | if (len > 4) |
347 | len = 4; | 350 | len = 4; |
@@ -361,33 +364,13 @@ acpi_system_write_wakeup_device(struct file *file, | |||
361 | continue; | 364 | continue; |
362 | 365 | ||
363 | if (!strncmp(dev->pnp.bus_id, str, 4)) { | 366 | if (!strncmp(dev->pnp.bus_id, str, 4)) { |
364 | dev->wakeup.state.enabled = | 367 | if (device_can_wakeup(&dev->dev)) { |
365 | dev->wakeup.state.enabled ? 0 : 1; | 368 | bool enable = !device_may_wakeup(&dev->dev); |
366 | found_dev = dev; | 369 | device_set_wakeup_enable(&dev->dev, enable); |
367 | break; | 370 | } else { |
368 | } | ||
369 | } | ||
370 | if (found_dev) { | ||
371 | physical_device_enable_wakeup(found_dev); | ||
372 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | ||
373 | struct acpi_device *dev = container_of(node, | ||
374 | struct | ||
375 | acpi_device, | ||
376 | wakeup_list); | ||
377 | |||
378 | if ((dev != found_dev) && | ||
379 | (dev->wakeup.gpe_number == | ||
380 | found_dev->wakeup.gpe_number) | ||
381 | && (dev->wakeup.gpe_device == | ||
382 | found_dev->wakeup.gpe_device)) { | ||
383 | printk(KERN_WARNING | ||
384 | "ACPI: '%s' and '%s' have the same GPE, " | ||
385 | "can't disable/enable one separately\n", | ||
386 | dev->pnp.bus_id, found_dev->pnp.bus_id); | ||
387 | dev->wakeup.state.enabled = | ||
388 | found_dev->wakeup.state.enabled; | ||
389 | physical_device_enable_wakeup(dev); | 371 | physical_device_enable_wakeup(dev); |
390 | } | 372 | } |
373 | break; | ||
391 | } | 374 | } |
392 | } | 375 | } |
393 | mutex_unlock(&acpi_device_lock); | 376 | mutex_unlock(&acpi_device_lock); |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index bec561c14beb..02d2a4c9084d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -19,15 +19,15 @@ | |||
19 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 19 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
20 | ACPI_MODULE_NAME("processor_core"); | 20 | ACPI_MODULE_NAME("processor_core"); |
21 | 21 | ||
22 | static int set_no_mwait(const struct dmi_system_id *id) | 22 | static int __init set_no_mwait(const struct dmi_system_id *id) |
23 | { | 23 | { |
24 | printk(KERN_NOTICE PREFIX "%s detected - " | 24 | printk(KERN_NOTICE PREFIX "%s detected - " |
25 | "disabling mwait for CPU C-states\n", id->ident); | 25 | "disabling mwait for CPU C-states\n", id->ident); |
26 | idle_nomwait = 1; | 26 | boot_option_idle_override = IDLE_NOMWAIT; |
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | 29 | ||
30 | static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { | 30 | static struct dmi_system_id __initdata processor_idle_dmi_table[] = { |
31 | { | 31 | { |
32 | set_no_mwait, "Extensa 5220", { | 32 | set_no_mwait, "Extensa 5220", { |
33 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), | 33 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), |
@@ -37,7 +37,6 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { | |||
37 | {}, | 37 | {}, |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #ifdef CONFIG_SMP | ||
41 | static int map_lapic_id(struct acpi_subtable_header *entry, | 40 | static int map_lapic_id(struct acpi_subtable_header *entry, |
42 | u32 acpi_id, int *apic_id) | 41 | u32 acpi_id, int *apic_id) |
43 | { | 42 | { |
@@ -165,7 +164,9 @@ exit: | |||
165 | 164 | ||
166 | int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) | 165 | int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) |
167 | { | 166 | { |
167 | #ifdef CONFIG_SMP | ||
168 | int i; | 168 | int i; |
169 | #endif | ||
169 | int apic_id = -1; | 170 | int apic_id = -1; |
170 | 171 | ||
171 | apic_id = map_mat_entry(handle, type, acpi_id); | 172 | apic_id = map_mat_entry(handle, type, acpi_id); |
@@ -174,16 +175,21 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) | |||
174 | if (apic_id == -1) | 175 | if (apic_id == -1) |
175 | return apic_id; | 176 | return apic_id; |
176 | 177 | ||
178 | #ifdef CONFIG_SMP | ||
177 | for_each_possible_cpu(i) { | 179 | for_each_possible_cpu(i) { |
178 | if (cpu_physical_id(i) == apic_id) | 180 | if (cpu_physical_id(i) == apic_id) |
179 | return i; | 181 | return i; |
180 | } | 182 | } |
183 | #else | ||
184 | /* In UP kernel, only processor 0 is valid */ | ||
185 | if (apic_id == 0) | ||
186 | return apic_id; | ||
187 | #endif | ||
181 | return -1; | 188 | return -1; |
182 | } | 189 | } |
183 | EXPORT_SYMBOL_GPL(acpi_get_cpuid); | 190 | EXPORT_SYMBOL_GPL(acpi_get_cpuid); |
184 | #endif | ||
185 | 191 | ||
186 | static bool processor_physically_present(acpi_handle handle) | 192 | static bool __init processor_physically_present(acpi_handle handle) |
187 | { | 193 | { |
188 | int cpuid, type; | 194 | int cpuid, type; |
189 | u32 acpi_id; | 195 | u32 acpi_id; |
@@ -217,13 +223,13 @@ static bool processor_physically_present(acpi_handle handle) | |||
217 | type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; | 223 | type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; |
218 | cpuid = acpi_get_cpuid(handle, type, acpi_id); | 224 | cpuid = acpi_get_cpuid(handle, type, acpi_id); |
219 | 225 | ||
220 | if ((cpuid == -1) && (num_possible_cpus() > 1)) | 226 | if (cpuid == -1) |
221 | return false; | 227 | return false; |
222 | 228 | ||
223 | return true; | 229 | return true; |
224 | } | 230 | } |
225 | 231 | ||
226 | static void acpi_set_pdc_bits(u32 *buf) | 232 | static void __cpuinit acpi_set_pdc_bits(u32 *buf) |
227 | { | 233 | { |
228 | buf[0] = ACPI_PDC_REVISION_ID; | 234 | buf[0] = ACPI_PDC_REVISION_ID; |
229 | buf[1] = 1; | 235 | buf[1] = 1; |
@@ -235,7 +241,7 @@ static void acpi_set_pdc_bits(u32 *buf) | |||
235 | arch_acpi_set_pdc_bits(buf); | 241 | arch_acpi_set_pdc_bits(buf); |
236 | } | 242 | } |
237 | 243 | ||
238 | static struct acpi_object_list *acpi_processor_alloc_pdc(void) | 244 | static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void) |
239 | { | 245 | { |
240 | struct acpi_object_list *obj_list; | 246 | struct acpi_object_list *obj_list; |
241 | union acpi_object *obj; | 247 | union acpi_object *obj; |
@@ -278,12 +284,12 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) | |||
278 | * _PDC is required for a BIOS-OS handshake for most of the newer | 284 | * _PDC is required for a BIOS-OS handshake for most of the newer |
279 | * ACPI processor features. | 285 | * ACPI processor features. |
280 | */ | 286 | */ |
281 | static int | 287 | static int __cpuinit |
282 | acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) | 288 | acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) |
283 | { | 289 | { |
284 | acpi_status status = AE_OK; | 290 | acpi_status status = AE_OK; |
285 | 291 | ||
286 | if (idle_nomwait) { | 292 | if (boot_option_idle_override == IDLE_NOMWAIT) { |
287 | /* | 293 | /* |
288 | * If mwait is disabled for CPU C-states, the C2C3_FFH access | 294 | * If mwait is disabled for CPU C-states, the C2C3_FFH access |
289 | * mode will be disabled in the parameter of _PDC object. | 295 | * mode will be disabled in the parameter of _PDC object. |
@@ -306,7 +312,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) | |||
306 | return status; | 312 | return status; |
307 | } | 313 | } |
308 | 314 | ||
309 | void acpi_processor_set_pdc(acpi_handle handle) | 315 | void __cpuinit acpi_processor_set_pdc(acpi_handle handle) |
310 | { | 316 | { |
311 | struct acpi_object_list *obj_list; | 317 | struct acpi_object_list *obj_list; |
312 | 318 | ||
@@ -323,9 +329,8 @@ void acpi_processor_set_pdc(acpi_handle handle) | |||
323 | kfree(obj_list->pointer); | 329 | kfree(obj_list->pointer); |
324 | kfree(obj_list); | 330 | kfree(obj_list); |
325 | } | 331 | } |
326 | EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); | ||
327 | 332 | ||
328 | static acpi_status | 333 | static acpi_status __init |
329 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | 334 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) |
330 | { | 335 | { |
331 | if (processor_physically_present(handle) == false) | 336 | if (processor_physically_present(handle) == false) |
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 347eb21b2353..a4e0f1ba6040 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -40,8 +40,6 @@ | |||
40 | #include <linux/pm.h> | 40 | #include <linux/pm.h> |
41 | #include <linux/cpufreq.h> | 41 | #include <linux/cpufreq.h> |
42 | #include <linux/cpu.h> | 42 | #include <linux/cpu.h> |
43 | #include <linux/proc_fs.h> | ||
44 | #include <linux/seq_file.h> | ||
45 | #include <linux/dmi.h> | 43 | #include <linux/dmi.h> |
46 | #include <linux/moduleparam.h> | 44 | #include <linux/moduleparam.h> |
47 | #include <linux/cpuidle.h> | 45 | #include <linux/cpuidle.h> |
@@ -244,43 +242,6 @@ static int acpi_processor_errata(struct acpi_processor *pr) | |||
244 | return result; | 242 | return result; |
245 | } | 243 | } |
246 | 244 | ||
247 | static struct proc_dir_entry *acpi_processor_dir = NULL; | ||
248 | |||
249 | static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) | ||
250 | { | ||
251 | struct proc_dir_entry *entry = NULL; | ||
252 | |||
253 | |||
254 | if (!acpi_device_dir(device)) { | ||
255 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | ||
256 | acpi_processor_dir); | ||
257 | if (!acpi_device_dir(device)) | ||
258 | return -ENODEV; | ||
259 | } | ||
260 | |||
261 | /* 'throttling' [R/W] */ | ||
262 | entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING, | ||
263 | S_IFREG | S_IRUGO | S_IWUSR, | ||
264 | acpi_device_dir(device), | ||
265 | &acpi_processor_throttling_fops, | ||
266 | acpi_driver_data(device)); | ||
267 | if (!entry) | ||
268 | return -EIO; | ||
269 | return 0; | ||
270 | } | ||
271 | static int acpi_processor_remove_fs(struct acpi_device *device) | ||
272 | { | ||
273 | |||
274 | if (acpi_device_dir(device)) { | ||
275 | remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, | ||
276 | acpi_device_dir(device)); | ||
277 | remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); | ||
278 | acpi_device_dir(device) = NULL; | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* -------------------------------------------------------------------------- | 245 | /* -------------------------------------------------------------------------- |
285 | Driver Interface | 246 | Driver Interface |
286 | -------------------------------------------------------------------------- */ | 247 | -------------------------------------------------------------------------- */ |
@@ -466,8 +427,13 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, | |||
466 | if (action == CPU_ONLINE && pr) { | 427 | if (action == CPU_ONLINE && pr) { |
467 | acpi_processor_ppc_has_changed(pr, 0); | 428 | acpi_processor_ppc_has_changed(pr, 0); |
468 | acpi_processor_cst_has_changed(pr); | 429 | acpi_processor_cst_has_changed(pr); |
430 | acpi_processor_reevaluate_tstate(pr, action); | ||
469 | acpi_processor_tstate_has_changed(pr); | 431 | acpi_processor_tstate_has_changed(pr); |
470 | } | 432 | } |
433 | if (action == CPU_DEAD && pr) { | ||
434 | /* invalidate the flag.throttling after one CPU is offline */ | ||
435 | acpi_processor_reevaluate_tstate(pr, action); | ||
436 | } | ||
471 | return NOTIFY_OK; | 437 | return NOTIFY_OK; |
472 | } | 438 | } |
473 | 439 | ||
@@ -525,14 +491,10 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
525 | 491 | ||
526 | per_cpu(processors, pr->id) = pr; | 492 | per_cpu(processors, pr->id) = pr; |
527 | 493 | ||
528 | result = acpi_processor_add_fs(device); | ||
529 | if (result) | ||
530 | goto err_free_cpumask; | ||
531 | |||
532 | sysdev = get_cpu_sysdev(pr->id); | 494 | sysdev = get_cpu_sysdev(pr->id); |
533 | if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { | 495 | if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { |
534 | result = -EFAULT; | 496 | result = -EFAULT; |
535 | goto err_remove_fs; | 497 | goto err_free_cpumask; |
536 | } | 498 | } |
537 | 499 | ||
538 | #ifdef CONFIG_CPU_FREQ | 500 | #ifdef CONFIG_CPU_FREQ |
@@ -578,8 +540,6 @@ err_thermal_unregister: | |||
578 | thermal_cooling_device_unregister(pr->cdev); | 540 | thermal_cooling_device_unregister(pr->cdev); |
579 | err_power_exit: | 541 | err_power_exit: |
580 | acpi_processor_power_exit(pr, device); | 542 | acpi_processor_power_exit(pr, device); |
581 | err_remove_fs: | ||
582 | acpi_processor_remove_fs(device); | ||
583 | err_free_cpumask: | 543 | err_free_cpumask: |
584 | free_cpumask_var(pr->throttling.shared_cpu_map); | 544 | free_cpumask_var(pr->throttling.shared_cpu_map); |
585 | 545 | ||
@@ -608,8 +568,6 @@ static int acpi_processor_remove(struct acpi_device *device, int type) | |||
608 | 568 | ||
609 | sysfs_remove_link(&device->dev.kobj, "sysdev"); | 569 | sysfs_remove_link(&device->dev.kobj, "sysdev"); |
610 | 570 | ||
611 | acpi_processor_remove_fs(device); | ||
612 | |||
613 | if (pr->cdev) { | 571 | if (pr->cdev) { |
614 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); | 572 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); |
615 | sysfs_remove_link(&pr->cdev->device.kobj, "device"); | 573 | sysfs_remove_link(&pr->cdev->device.kobj, "device"); |
@@ -677,8 +635,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) | |||
677 | return 0; | 635 | return 0; |
678 | } | 636 | } |
679 | 637 | ||
680 | static void __ref acpi_processor_hotplug_notify(acpi_handle handle, | 638 | static void acpi_processor_hotplug_notify(acpi_handle handle, |
681 | u32 event, void *data) | 639 | u32 event, void *data) |
682 | { | 640 | { |
683 | struct acpi_processor *pr; | 641 | struct acpi_processor *pr; |
684 | struct acpi_device *device = NULL; | 642 | struct acpi_device *device = NULL; |
@@ -842,10 +800,6 @@ static int __init acpi_processor_init(void) | |||
842 | 800 | ||
843 | memset(&errata, 0, sizeof(errata)); | 801 | memset(&errata, 0, sizeof(errata)); |
844 | 802 | ||
845 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); | ||
846 | if (!acpi_processor_dir) | ||
847 | return -ENOMEM; | ||
848 | |||
849 | if (!cpuidle_register_driver(&acpi_idle_driver)) { | 803 | if (!cpuidle_register_driver(&acpi_idle_driver)) { |
850 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", | 804 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", |
851 | acpi_idle_driver.name); | 805 | acpi_idle_driver.name); |
@@ -871,8 +825,6 @@ static int __init acpi_processor_init(void) | |||
871 | out_cpuidle: | 825 | out_cpuidle: |
872 | cpuidle_unregister_driver(&acpi_idle_driver); | 826 | cpuidle_unregister_driver(&acpi_idle_driver); |
873 | 827 | ||
874 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | ||
875 | |||
876 | return result; | 828 | return result; |
877 | } | 829 | } |
878 | 830 | ||
@@ -891,14 +843,10 @@ static void __exit acpi_processor_exit(void) | |||
891 | 843 | ||
892 | cpuidle_unregister_driver(&acpi_idle_driver); | 844 | cpuidle_unregister_driver(&acpi_idle_driver); |
893 | 845 | ||
894 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | ||
895 | |||
896 | return; | 846 | return; |
897 | } | 847 | } |
898 | 848 | ||
899 | module_init(acpi_processor_init); | 849 | module_init(acpi_processor_init); |
900 | module_exit(acpi_processor_exit); | 850 | module_exit(acpi_processor_exit); |
901 | 851 | ||
902 | EXPORT_SYMBOL(acpi_processor_set_thermal_limit); | ||
903 | |||
904 | MODULE_ALIAS("processor"); | 852 | MODULE_ALIAS("processor"); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f4428e82b352..431ab11c8c1b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -64,7 +64,6 @@ | |||
64 | #define ACPI_PROCESSOR_CLASS "processor" | 64 | #define ACPI_PROCESSOR_CLASS "processor" |
65 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 65 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
66 | ACPI_MODULE_NAME("processor_idle"); | 66 | ACPI_MODULE_NAME("processor_idle"); |
67 | #define ACPI_PROCESSOR_FILE_POWER "power" | ||
68 | #define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) | 67 | #define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) |
69 | #define C2_OVERHEAD 1 /* 1us */ | 68 | #define C2_OVERHEAD 1 /* 1us */ |
70 | #define C3_OVERHEAD 1 /* 1us */ | 69 | #define C3_OVERHEAD 1 /* 1us */ |
@@ -80,6 +79,13 @@ module_param(bm_check_disable, uint, 0000); | |||
80 | static unsigned int latency_factor __read_mostly = 2; | 79 | static unsigned int latency_factor __read_mostly = 2; |
81 | module_param(latency_factor, uint, 0644); | 80 | module_param(latency_factor, uint, 0644); |
82 | 81 | ||
82 | static int disabled_by_idle_boot_param(void) | ||
83 | { | ||
84 | return boot_option_idle_override == IDLE_POLL || | ||
85 | boot_option_idle_override == IDLE_FORCE_MWAIT || | ||
86 | boot_option_idle_override == IDLE_HALT; | ||
87 | } | ||
88 | |||
83 | /* | 89 | /* |
84 | * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. | 90 | * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. |
85 | * For now disable this. Probably a bug somewhere else. | 91 | * For now disable this. Probably a bug somewhere else. |
@@ -155,7 +161,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr, | |||
155 | if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) | 161 | if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) |
156 | return; | 162 | return; |
157 | 163 | ||
158 | if (c1e_detected) | 164 | if (amd_e400_c1e_detected) |
159 | type = ACPI_STATE_C1; | 165 | type = ACPI_STATE_C1; |
160 | 166 | ||
161 | /* | 167 | /* |
@@ -456,7 +462,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
456 | continue; | 462 | continue; |
457 | } | 463 | } |
458 | if (cx.type == ACPI_STATE_C1 && | 464 | if (cx.type == ACPI_STATE_C1 && |
459 | (idle_halt || idle_nomwait)) { | 465 | (boot_option_idle_override == IDLE_NOMWAIT)) { |
460 | /* | 466 | /* |
461 | * In most cases the C1 space_id obtained from | 467 | * In most cases the C1 space_id obtained from |
462 | * _CST object is FIXED_HARDWARE access mode. | 468 | * _CST object is FIXED_HARDWARE access mode. |
@@ -747,7 +753,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
747 | struct acpi_processor *pr; | 753 | struct acpi_processor *pr; |
748 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 754 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
749 | 755 | ||
750 | pr = __get_cpu_var(processors); | 756 | pr = __this_cpu_read(processors); |
751 | 757 | ||
752 | if (unlikely(!pr)) | 758 | if (unlikely(!pr)) |
753 | return 0; | 759 | return 0; |
@@ -788,7 +794,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
788 | s64 idle_time_ns; | 794 | s64 idle_time_ns; |
789 | s64 idle_time; | 795 | s64 idle_time; |
790 | 796 | ||
791 | pr = __get_cpu_var(processors); | 797 | pr = __this_cpu_read(processors); |
792 | 798 | ||
793 | if (unlikely(!pr)) | 799 | if (unlikely(!pr)) |
794 | return 0; | 800 | return 0; |
@@ -865,7 +871,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
865 | s64 idle_time; | 871 | s64 idle_time; |
866 | 872 | ||
867 | 873 | ||
868 | pr = __get_cpu_var(processors); | 874 | pr = __this_cpu_read(processors); |
869 | 875 | ||
870 | if (unlikely(!pr)) | 876 | if (unlikely(!pr)) |
871 | return 0; | 877 | return 0; |
@@ -1013,12 +1019,10 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) | |||
1013 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); | 1019 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); |
1014 | state->exit_latency = cx->latency; | 1020 | state->exit_latency = cx->latency; |
1015 | state->target_residency = cx->latency * latency_factor; | 1021 | state->target_residency = cx->latency * latency_factor; |
1016 | state->power_usage = cx->power; | ||
1017 | 1022 | ||
1018 | state->flags = 0; | 1023 | state->flags = 0; |
1019 | switch (cx->type) { | 1024 | switch (cx->type) { |
1020 | case ACPI_STATE_C1: | 1025 | case ACPI_STATE_C1: |
1021 | state->flags |= CPUIDLE_FLAG_SHALLOW; | ||
1022 | if (cx->entry_method == ACPI_CSTATE_FFH) | 1026 | if (cx->entry_method == ACPI_CSTATE_FFH) |
1023 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 1027 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
1024 | 1028 | ||
@@ -1027,16 +1031,13 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) | |||
1027 | break; | 1031 | break; |
1028 | 1032 | ||
1029 | case ACPI_STATE_C2: | 1033 | case ACPI_STATE_C2: |
1030 | state->flags |= CPUIDLE_FLAG_BALANCED; | ||
1031 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 1034 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
1032 | state->enter = acpi_idle_enter_simple; | 1035 | state->enter = acpi_idle_enter_simple; |
1033 | dev->safe_state = state; | 1036 | dev->safe_state = state; |
1034 | break; | 1037 | break; |
1035 | 1038 | ||
1036 | case ACPI_STATE_C3: | 1039 | case ACPI_STATE_C3: |
1037 | state->flags |= CPUIDLE_FLAG_DEEP; | ||
1038 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 1040 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
1039 | state->flags |= CPUIDLE_FLAG_CHECK_BM; | ||
1040 | state->enter = pr->flags.bm_check ? | 1041 | state->enter = pr->flags.bm_check ? |
1041 | acpi_idle_enter_bm : | 1042 | acpi_idle_enter_bm : |
1042 | acpi_idle_enter_simple; | 1043 | acpi_idle_enter_simple; |
@@ -1060,7 +1061,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1060 | { | 1061 | { |
1061 | int ret = 0; | 1062 | int ret = 0; |
1062 | 1063 | ||
1063 | if (boot_option_idle_override) | 1064 | if (disabled_by_idle_boot_param()) |
1064 | return 0; | 1065 | return 0; |
1065 | 1066 | ||
1066 | if (!pr) | 1067 | if (!pr) |
@@ -1091,19 +1092,10 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1091 | acpi_status status = 0; | 1092 | acpi_status status = 0; |
1092 | static int first_run; | 1093 | static int first_run; |
1093 | 1094 | ||
1094 | if (boot_option_idle_override) | 1095 | if (disabled_by_idle_boot_param()) |
1095 | return 0; | 1096 | return 0; |
1096 | 1097 | ||
1097 | if (!first_run) { | 1098 | if (!first_run) { |
1098 | if (idle_halt) { | ||
1099 | /* | ||
1100 | * When the boot option of "idle=halt" is added, halt | ||
1101 | * is used for CPU IDLE. | ||
1102 | * In such case C2/C3 is meaningless. So the max_cstate | ||
1103 | * is set to one. | ||
1104 | */ | ||
1105 | max_cstate = 1; | ||
1106 | } | ||
1107 | dmi_check_system(processor_power_dmi_table); | 1099 | dmi_check_system(processor_power_dmi_table); |
1108 | max_cstate = acpi_processor_cstate_check(max_cstate); | 1100 | max_cstate = acpi_processor_cstate_check(max_cstate); |
1109 | if (max_cstate < ACPI_C_STATES_MAX) | 1101 | if (max_cstate < ACPI_C_STATES_MAX) |
@@ -1144,7 +1136,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1144 | int acpi_processor_power_exit(struct acpi_processor *pr, | 1136 | int acpi_processor_power_exit(struct acpi_processor *pr, |
1145 | struct acpi_device *device) | 1137 | struct acpi_device *device) |
1146 | { | 1138 | { |
1147 | if (boot_option_idle_override) | 1139 | if (disabled_by_idle_boot_param()) |
1148 | return 0; | 1140 | return 0; |
1149 | 1141 | ||
1150 | cpuidle_unregister_device(&pr->power.dev); | 1142 | cpuidle_unregister_device(&pr->power.dev); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 3a73a93596e8..85b32376dad7 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -49,10 +49,6 @@ ACPI_MODULE_NAME("processor_perflib"); | |||
49 | 49 | ||
50 | static DEFINE_MUTEX(performance_mutex); | 50 | static DEFINE_MUTEX(performance_mutex); |
51 | 51 | ||
52 | /* Use cpufreq debug layer for _PPC changes. */ | ||
53 | #define cpufreq_printk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \ | ||
54 | "cpufreq-core", msg) | ||
55 | |||
56 | /* | 52 | /* |
57 | * _PPC support is implemented as a CPUfreq policy notifier: | 53 | * _PPC support is implemented as a CPUfreq policy notifier: |
58 | * This means each time a CPUfreq driver registered also with | 54 | * This means each time a CPUfreq driver registered also with |
@@ -145,7 +141,7 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) | |||
145 | return -ENODEV; | 141 | return -ENODEV; |
146 | } | 142 | } |
147 | 143 | ||
148 | cpufreq_printk("CPU %d: _PPC is %d - frequency %s limited\n", pr->id, | 144 | pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id, |
149 | (int)ppc, ppc ? "" : "not"); | 145 | (int)ppc, ppc ? "" : "not"); |
150 | 146 | ||
151 | pr->performance_platform_limit = (int)ppc; | 147 | pr->performance_platform_limit = (int)ppc; |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 953b25fb9869..79cb65332894 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -44,47 +44,6 @@ | |||
44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
45 | ACPI_MODULE_NAME("processor_thermal"); | 45 | ACPI_MODULE_NAME("processor_thermal"); |
46 | 46 | ||
47 | /* -------------------------------------------------------------------------- | ||
48 | Limit Interface | ||
49 | -------------------------------------------------------------------------- */ | ||
50 | static int acpi_processor_apply_limit(struct acpi_processor *pr) | ||
51 | { | ||
52 | int result = 0; | ||
53 | u16 px = 0; | ||
54 | u16 tx = 0; | ||
55 | |||
56 | |||
57 | if (!pr) | ||
58 | return -EINVAL; | ||
59 | |||
60 | if (!pr->flags.limit) | ||
61 | return -ENODEV; | ||
62 | |||
63 | if (pr->flags.throttling) { | ||
64 | if (pr->limit.user.tx > tx) | ||
65 | tx = pr->limit.user.tx; | ||
66 | if (pr->limit.thermal.tx > tx) | ||
67 | tx = pr->limit.thermal.tx; | ||
68 | |||
69 | result = acpi_processor_set_throttling(pr, tx, false); | ||
70 | if (result) | ||
71 | goto end; | ||
72 | } | ||
73 | |||
74 | pr->limit.state.px = px; | ||
75 | pr->limit.state.tx = tx; | ||
76 | |||
77 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
78 | "Processor [%d] limit set to (P%d:T%d)\n", pr->id, | ||
79 | pr->limit.state.px, pr->limit.state.tx)); | ||
80 | |||
81 | end: | ||
82 | if (result) | ||
83 | printk(KERN_ERR PREFIX "Unable to set limit\n"); | ||
84 | |||
85 | return result; | ||
86 | } | ||
87 | |||
88 | #ifdef CONFIG_CPU_FREQ | 47 | #ifdef CONFIG_CPU_FREQ |
89 | 48 | ||
90 | /* If a passive cooling situation is detected, primarily CPUfreq is used, as it | 49 | /* If a passive cooling situation is detected, primarily CPUfreq is used, as it |
@@ -107,36 +66,6 @@ static int cpu_has_cpufreq(unsigned int cpu) | |||
107 | return 1; | 66 | return 1; |
108 | } | 67 | } |
109 | 68 | ||
110 | static int acpi_thermal_cpufreq_increase(unsigned int cpu) | ||
111 | { | ||
112 | if (!cpu_has_cpufreq(cpu)) | ||
113 | return -ENODEV; | ||
114 | |||
115 | if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) < | ||
116 | CPUFREQ_THERMAL_MAX_STEP) { | ||
117 | per_cpu(cpufreq_thermal_reduction_pctg, cpu)++; | ||
118 | cpufreq_update_policy(cpu); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | return -ERANGE; | ||
123 | } | ||
124 | |||
125 | static int acpi_thermal_cpufreq_decrease(unsigned int cpu) | ||
126 | { | ||
127 | if (!cpu_has_cpufreq(cpu)) | ||
128 | return -ENODEV; | ||
129 | |||
130 | if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) > | ||
131 | (CPUFREQ_THERMAL_MIN_STEP + 1)) | ||
132 | per_cpu(cpufreq_thermal_reduction_pctg, cpu)--; | ||
133 | else | ||
134 | per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0; | ||
135 | cpufreq_update_policy(cpu); | ||
136 | /* We reached max freq again and can leave passive mode */ | ||
137 | return !per_cpu(cpufreq_thermal_reduction_pctg, cpu); | ||
138 | } | ||
139 | |||
140 | static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, | 69 | static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, |
141 | unsigned long event, void *data) | 70 | unsigned long event, void *data) |
142 | { | 71 | { |
@@ -227,124 +156,8 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) | |||
227 | return 0; | 156 | return 0; |
228 | } | 157 | } |
229 | 158 | ||
230 | static int acpi_thermal_cpufreq_increase(unsigned int cpu) | ||
231 | { | ||
232 | return -ENODEV; | ||
233 | } | ||
234 | static int acpi_thermal_cpufreq_decrease(unsigned int cpu) | ||
235 | { | ||
236 | return -ENODEV; | ||
237 | } | ||
238 | |||
239 | #endif | 159 | #endif |
240 | 160 | ||
241 | int acpi_processor_set_thermal_limit(acpi_handle handle, int type) | ||
242 | { | ||
243 | int result = 0; | ||
244 | struct acpi_processor *pr = NULL; | ||
245 | struct acpi_device *device = NULL; | ||
246 | int tx = 0, max_tx_px = 0; | ||
247 | |||
248 | |||
249 | if ((type < ACPI_PROCESSOR_LIMIT_NONE) | ||
250 | || (type > ACPI_PROCESSOR_LIMIT_DECREMENT)) | ||
251 | return -EINVAL; | ||
252 | |||
253 | result = acpi_bus_get_device(handle, &device); | ||
254 | if (result) | ||
255 | return result; | ||
256 | |||
257 | pr = acpi_driver_data(device); | ||
258 | if (!pr) | ||
259 | return -ENODEV; | ||
260 | |||
261 | /* Thermal limits are always relative to the current Px/Tx state. */ | ||
262 | if (pr->flags.throttling) | ||
263 | pr->limit.thermal.tx = pr->throttling.state; | ||
264 | |||
265 | /* | ||
266 | * Our default policy is to only use throttling at the lowest | ||
267 | * performance state. | ||
268 | */ | ||
269 | |||
270 | tx = pr->limit.thermal.tx; | ||
271 | |||
272 | switch (type) { | ||
273 | |||
274 | case ACPI_PROCESSOR_LIMIT_NONE: | ||
275 | do { | ||
276 | result = acpi_thermal_cpufreq_decrease(pr->id); | ||
277 | } while (!result); | ||
278 | tx = 0; | ||
279 | break; | ||
280 | |||
281 | case ACPI_PROCESSOR_LIMIT_INCREMENT: | ||
282 | /* if going up: P-states first, T-states later */ | ||
283 | |||
284 | result = acpi_thermal_cpufreq_increase(pr->id); | ||
285 | if (!result) | ||
286 | goto end; | ||
287 | else if (result == -ERANGE) | ||
288 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
289 | "At maximum performance state\n")); | ||
290 | |||
291 | if (pr->flags.throttling) { | ||
292 | if (tx == (pr->throttling.state_count - 1)) | ||
293 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
294 | "At maximum throttling state\n")); | ||
295 | else | ||
296 | tx++; | ||
297 | } | ||
298 | break; | ||
299 | |||
300 | case ACPI_PROCESSOR_LIMIT_DECREMENT: | ||
301 | /* if going down: T-states first, P-states later */ | ||
302 | |||
303 | if (pr->flags.throttling) { | ||
304 | if (tx == 0) { | ||
305 | max_tx_px = 1; | ||
306 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
307 | "At minimum throttling state\n")); | ||
308 | } else { | ||
309 | tx--; | ||
310 | goto end; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | result = acpi_thermal_cpufreq_decrease(pr->id); | ||
315 | if (result) { | ||
316 | /* | ||
317 | * We only could get -ERANGE, 1 or 0. | ||
318 | * In the first two cases we reached max freq again. | ||
319 | */ | ||
320 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
321 | "At minimum performance state\n")); | ||
322 | max_tx_px = 1; | ||
323 | } else | ||
324 | max_tx_px = 0; | ||
325 | |||
326 | break; | ||
327 | } | ||
328 | |||
329 | end: | ||
330 | if (pr->flags.throttling) { | ||
331 | pr->limit.thermal.px = 0; | ||
332 | pr->limit.thermal.tx = tx; | ||
333 | |||
334 | result = acpi_processor_apply_limit(pr); | ||
335 | if (result) | ||
336 | printk(KERN_ERR PREFIX "Unable to set thermal limit\n"); | ||
337 | |||
338 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n", | ||
339 | pr->limit.thermal.px, pr->limit.thermal.tx)); | ||
340 | } else | ||
341 | result = 0; | ||
342 | if (max_tx_px) | ||
343 | return 1; | ||
344 | else | ||
345 | return result; | ||
346 | } | ||
347 | |||
348 | int acpi_processor_get_limit_info(struct acpi_processor *pr) | 161 | int acpi_processor_get_limit_info(struct acpi_processor *pr) |
349 | { | 162 | { |
350 | 163 | ||
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 730863855ed5..605a2954ef17 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/cpufreq.h> | 34 | #include <linux/cpufreq.h> |
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/seq_file.h> | ||
37 | 35 | ||
38 | #include <asm/io.h> | 36 | #include <asm/io.h> |
39 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -368,6 +366,58 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr) | |||
368 | } | 366 | } |
369 | 367 | ||
370 | /* | 368 | /* |
369 | * This function is used to reevaluate whether the T-state is valid | ||
370 | * after one CPU is onlined/offlined. | ||
371 | * It is noted that it won't reevaluate the following properties for | ||
372 | * the T-state. | ||
373 | * 1. Control method. | ||
374 | * 2. the number of supported T-state | ||
375 | * 3. TSD domain | ||
376 | */ | ||
377 | void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, | ||
378 | unsigned long action) | ||
379 | { | ||
380 | int result = 0; | ||
381 | |||
382 | if (action == CPU_DEAD) { | ||
383 | /* When one CPU is offline, the T-state throttling | ||
384 | * will be invalidated. | ||
385 | */ | ||
386 | pr->flags.throttling = 0; | ||
387 | return; | ||
388 | } | ||
389 | /* the following is to recheck whether the T-state is valid for | ||
390 | * the online CPU | ||
391 | */ | ||
392 | if (!pr->throttling.state_count) { | ||
393 | /* If the number of T-state is invalid, it is | ||
394 | * invalidated. | ||
395 | */ | ||
396 | pr->flags.throttling = 0; | ||
397 | return; | ||
398 | } | ||
399 | pr->flags.throttling = 1; | ||
400 | |||
401 | /* Disable throttling (if enabled). We'll let subsequent | ||
402 | * policy (e.g.thermal) decide to lower performance if it | ||
403 | * so chooses, but for now we'll crank up the speed. | ||
404 | */ | ||
405 | |||
406 | result = acpi_processor_get_throttling(pr); | ||
407 | if (result) | ||
408 | goto end; | ||
409 | |||
410 | if (pr->throttling.state) { | ||
411 | result = acpi_processor_set_throttling(pr, 0, false); | ||
412 | if (result) | ||
413 | goto end; | ||
414 | } | ||
415 | |||
416 | end: | ||
417 | if (result) | ||
418 | pr->flags.throttling = 0; | ||
419 | } | ||
420 | /* | ||
371 | * _PTC - Processor Throttling Control (and status) register location | 421 | * _PTC - Processor Throttling Control (and status) register location |
372 | */ | 422 | */ |
373 | static int acpi_processor_get_throttling_control(struct acpi_processor *pr) | 423 | static int acpi_processor_get_throttling_control(struct acpi_processor *pr) |
@@ -660,20 +710,14 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) | |||
660 | } | 710 | } |
661 | 711 | ||
662 | #ifdef CONFIG_X86 | 712 | #ifdef CONFIG_X86 |
663 | static int acpi_throttling_rdmsr(struct acpi_processor *pr, | 713 | static int acpi_throttling_rdmsr(u64 *value) |
664 | u64 *value) | ||
665 | { | 714 | { |
666 | struct cpuinfo_x86 *c; | ||
667 | u64 msr_high, msr_low; | 715 | u64 msr_high, msr_low; |
668 | unsigned int cpu; | ||
669 | u64 msr = 0; | 716 | u64 msr = 0; |
670 | int ret = -1; | 717 | int ret = -1; |
671 | 718 | ||
672 | cpu = pr->id; | 719 | if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) || |
673 | c = &cpu_data(cpu); | 720 | !this_cpu_has(X86_FEATURE_ACPI)) { |
674 | |||
675 | if ((c->x86_vendor != X86_VENDOR_INTEL) || | ||
676 | !cpu_has(c, X86_FEATURE_ACPI)) { | ||
677 | printk(KERN_ERR PREFIX | 721 | printk(KERN_ERR PREFIX |
678 | "HARDWARE addr space,NOT supported yet\n"); | 722 | "HARDWARE addr space,NOT supported yet\n"); |
679 | } else { | 723 | } else { |
@@ -688,18 +732,13 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr, | |||
688 | return ret; | 732 | return ret; |
689 | } | 733 | } |
690 | 734 | ||
691 | static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) | 735 | static int acpi_throttling_wrmsr(u64 value) |
692 | { | 736 | { |
693 | struct cpuinfo_x86 *c; | ||
694 | unsigned int cpu; | ||
695 | int ret = -1; | 737 | int ret = -1; |
696 | u64 msr; | 738 | u64 msr; |
697 | 739 | ||
698 | cpu = pr->id; | 740 | if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) || |
699 | c = &cpu_data(cpu); | 741 | !this_cpu_has(X86_FEATURE_ACPI)) { |
700 | |||
701 | if ((c->x86_vendor != X86_VENDOR_INTEL) || | ||
702 | !cpu_has(c, X86_FEATURE_ACPI)) { | ||
703 | printk(KERN_ERR PREFIX | 742 | printk(KERN_ERR PREFIX |
704 | "HARDWARE addr space,NOT supported yet\n"); | 743 | "HARDWARE addr space,NOT supported yet\n"); |
705 | } else { | 744 | } else { |
@@ -711,15 +750,14 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) | |||
711 | return ret; | 750 | return ret; |
712 | } | 751 | } |
713 | #else | 752 | #else |
714 | static int acpi_throttling_rdmsr(struct acpi_processor *pr, | 753 | static int acpi_throttling_rdmsr(u64 *value) |
715 | u64 *value) | ||
716 | { | 754 | { |
717 | printk(KERN_ERR PREFIX | 755 | printk(KERN_ERR PREFIX |
718 | "HARDWARE addr space,NOT supported yet\n"); | 756 | "HARDWARE addr space,NOT supported yet\n"); |
719 | return -1; | 757 | return -1; |
720 | } | 758 | } |
721 | 759 | ||
722 | static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) | 760 | static int acpi_throttling_wrmsr(u64 value) |
723 | { | 761 | { |
724 | printk(KERN_ERR PREFIX | 762 | printk(KERN_ERR PREFIX |
725 | "HARDWARE addr space,NOT supported yet\n"); | 763 | "HARDWARE addr space,NOT supported yet\n"); |
@@ -751,7 +789,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, | |||
751 | ret = 0; | 789 | ret = 0; |
752 | break; | 790 | break; |
753 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 791 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |
754 | ret = acpi_throttling_rdmsr(pr, value); | 792 | ret = acpi_throttling_rdmsr(value); |
755 | break; | 793 | break; |
756 | default: | 794 | default: |
757 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | 795 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", |
@@ -784,7 +822,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr, | |||
784 | ret = 0; | 822 | ret = 0; |
785 | break; | 823 | break; |
786 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 824 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |
787 | ret = acpi_throttling_wrmsr(pr, value); | 825 | ret = acpi_throttling_wrmsr(value); |
788 | break; | 826 | break; |
789 | default: | 827 | default: |
790 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | 828 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", |
@@ -874,7 +912,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr) | |||
874 | */ | 912 | */ |
875 | cpumask_copy(saved_mask, ¤t->cpus_allowed); | 913 | cpumask_copy(saved_mask, ¤t->cpus_allowed); |
876 | /* FIXME: use work_on_cpu() */ | 914 | /* FIXME: use work_on_cpu() */ |
877 | set_cpus_allowed_ptr(current, cpumask_of(pr->id)); | 915 | if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { |
916 | /* Can't migrate to the target pr->id CPU. Exit */ | ||
917 | free_cpumask_var(saved_mask); | ||
918 | return -ENODEV; | ||
919 | } | ||
878 | ret = pr->throttling.acpi_processor_get_throttling(pr); | 920 | ret = pr->throttling.acpi_processor_get_throttling(pr); |
879 | /* restore the previous state */ | 921 | /* restore the previous state */ |
880 | set_cpus_allowed_ptr(current, saved_mask); | 922 | set_cpus_allowed_ptr(current, saved_mask); |
@@ -1049,6 +1091,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1049 | return -ENOMEM; | 1091 | return -ENOMEM; |
1050 | } | 1092 | } |
1051 | 1093 | ||
1094 | if (cpu_is_offline(pr->id)) { | ||
1095 | /* | ||
1096 | * the cpu pointed by pr->id is offline. Unnecessary to change | ||
1097 | * the throttling state any more. | ||
1098 | */ | ||
1099 | return -ENODEV; | ||
1100 | } | ||
1101 | |||
1052 | cpumask_copy(saved_mask, ¤t->cpus_allowed); | 1102 | cpumask_copy(saved_mask, ¤t->cpus_allowed); |
1053 | t_state.target_state = state; | 1103 | t_state.target_state = state; |
1054 | p_throttling = &(pr->throttling); | 1104 | p_throttling = &(pr->throttling); |
@@ -1072,7 +1122,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1072 | */ | 1122 | */ |
1073 | if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { | 1123 | if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { |
1074 | /* FIXME: use work_on_cpu() */ | 1124 | /* FIXME: use work_on_cpu() */ |
1075 | set_cpus_allowed_ptr(current, cpumask_of(pr->id)); | 1125 | if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { |
1126 | /* Can't migrate to the pr->id CPU. Exit */ | ||
1127 | ret = -ENODEV; | ||
1128 | goto exit; | ||
1129 | } | ||
1076 | ret = p_throttling->acpi_processor_set_throttling(pr, | 1130 | ret = p_throttling->acpi_processor_set_throttling(pr, |
1077 | t_state.target_state, force); | 1131 | t_state.target_state, force); |
1078 | } else { | 1132 | } else { |
@@ -1098,13 +1152,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1098 | */ | 1152 | */ |
1099 | if (!match_pr->flags.throttling) { | 1153 | if (!match_pr->flags.throttling) { |
1100 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1154 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1101 | "Throttling Controll is unsupported " | 1155 | "Throttling Control is unsupported " |
1102 | "on CPU %d\n", i)); | 1156 | "on CPU %d\n", i)); |
1103 | continue; | 1157 | continue; |
1104 | } | 1158 | } |
1105 | t_state.cpu = i; | 1159 | t_state.cpu = i; |
1106 | /* FIXME: use work_on_cpu() */ | 1160 | /* FIXME: use work_on_cpu() */ |
1107 | set_cpus_allowed_ptr(current, cpumask_of(i)); | 1161 | if (set_cpus_allowed_ptr(current, cpumask_of(i))) |
1162 | continue; | ||
1108 | ret = match_pr->throttling. | 1163 | ret = match_pr->throttling. |
1109 | acpi_processor_set_throttling( | 1164 | acpi_processor_set_throttling( |
1110 | match_pr, t_state.target_state, force); | 1165 | match_pr, t_state.target_state, force); |
@@ -1124,6 +1179,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1124 | /* restore the previous state */ | 1179 | /* restore the previous state */ |
1125 | /* FIXME: use work_on_cpu() */ | 1180 | /* FIXME: use work_on_cpu() */ |
1126 | set_cpus_allowed_ptr(current, saved_mask); | 1181 | set_cpus_allowed_ptr(current, saved_mask); |
1182 | exit: | ||
1127 | free_cpumask_var(online_throttling_cpus); | 1183 | free_cpumask_var(online_throttling_cpus); |
1128 | free_cpumask_var(saved_mask); | 1184 | free_cpumask_var(saved_mask); |
1129 | return ret; | 1185 | return ret; |
@@ -1214,111 +1270,3 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
1214 | return result; | 1270 | return result; |
1215 | } | 1271 | } |
1216 | 1272 | ||
1217 | /* proc interface */ | ||
1218 | static int acpi_processor_throttling_seq_show(struct seq_file *seq, | ||
1219 | void *offset) | ||
1220 | { | ||
1221 | struct acpi_processor *pr = seq->private; | ||
1222 | int i = 0; | ||
1223 | int result = 0; | ||
1224 | |||
1225 | if (!pr) | ||
1226 | goto end; | ||
1227 | |||
1228 | if (!(pr->throttling.state_count > 0)) { | ||
1229 | seq_puts(seq, "<not supported>\n"); | ||
1230 | goto end; | ||
1231 | } | ||
1232 | |||
1233 | result = acpi_processor_get_throttling(pr); | ||
1234 | |||
1235 | if (result) { | ||
1236 | seq_puts(seq, | ||
1237 | "Could not determine current throttling state.\n"); | ||
1238 | goto end; | ||
1239 | } | ||
1240 | |||
1241 | seq_printf(seq, "state count: %d\n" | ||
1242 | "active state: T%d\n" | ||
1243 | "state available: T%d to T%d\n", | ||
1244 | pr->throttling.state_count, pr->throttling.state, | ||
1245 | pr->throttling_platform_limit, | ||
1246 | pr->throttling.state_count - 1); | ||
1247 | |||
1248 | seq_puts(seq, "states:\n"); | ||
1249 | if (pr->throttling.acpi_processor_get_throttling == | ||
1250 | acpi_processor_get_throttling_fadt) { | ||
1251 | for (i = 0; i < pr->throttling.state_count; i++) | ||
1252 | seq_printf(seq, " %cT%d: %02d%%\n", | ||
1253 | (i == pr->throttling.state ? '*' : ' '), i, | ||
1254 | (pr->throttling.states[i].performance ? pr-> | ||
1255 | throttling.states[i].performance / 10 : 0)); | ||
1256 | } else { | ||
1257 | for (i = 0; i < pr->throttling.state_count; i++) | ||
1258 | seq_printf(seq, " %cT%d: %02d%%\n", | ||
1259 | (i == pr->throttling.state ? '*' : ' '), i, | ||
1260 | (int)pr->throttling.states_tss[i]. | ||
1261 | freqpercentage); | ||
1262 | } | ||
1263 | |||
1264 | end: | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | static int acpi_processor_throttling_open_fs(struct inode *inode, | ||
1269 | struct file *file) | ||
1270 | { | ||
1271 | return single_open(file, acpi_processor_throttling_seq_show, | ||
1272 | PDE(inode)->data); | ||
1273 | } | ||
1274 | |||
1275 | static ssize_t acpi_processor_write_throttling(struct file *file, | ||
1276 | const char __user * buffer, | ||
1277 | size_t count, loff_t * data) | ||
1278 | { | ||
1279 | int result = 0; | ||
1280 | struct seq_file *m = file->private_data; | ||
1281 | struct acpi_processor *pr = m->private; | ||
1282 | char state_string[5] = ""; | ||
1283 | char *charp = NULL; | ||
1284 | size_t state_val = 0; | ||
1285 | char tmpbuf[5] = ""; | ||
1286 | |||
1287 | if (!pr || (count > sizeof(state_string) - 1)) | ||
1288 | return -EINVAL; | ||
1289 | |||
1290 | if (copy_from_user(state_string, buffer, count)) | ||
1291 | return -EFAULT; | ||
1292 | |||
1293 | state_string[count] = '\0'; | ||
1294 | if ((count > 0) && (state_string[count-1] == '\n')) | ||
1295 | state_string[count-1] = '\0'; | ||
1296 | |||
1297 | charp = state_string; | ||
1298 | if ((state_string[0] == 't') || (state_string[0] == 'T')) | ||
1299 | charp++; | ||
1300 | |||
1301 | state_val = simple_strtoul(charp, NULL, 0); | ||
1302 | if (state_val >= pr->throttling.state_count) | ||
1303 | return -EINVAL; | ||
1304 | |||
1305 | snprintf(tmpbuf, 5, "%zu", state_val); | ||
1306 | |||
1307 | if (strcmp(tmpbuf, charp) != 0) | ||
1308 | return -EINVAL; | ||
1309 | |||
1310 | result = acpi_processor_set_throttling(pr, state_val, false); | ||
1311 | if (result) | ||
1312 | return result; | ||
1313 | |||
1314 | return count; | ||
1315 | } | ||
1316 | |||
1317 | const struct file_operations acpi_processor_throttling_fops = { | ||
1318 | .owner = THIS_MODULE, | ||
1319 | .open = acpi_processor_throttling_open_fs, | ||
1320 | .read = seq_read, | ||
1321 | .write = acpi_processor_write_throttling, | ||
1322 | .llseek = seq_lseek, | ||
1323 | .release = single_release, | ||
1324 | }; | ||
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index 93f91142d7ad..a6c77e8b37bd 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c | |||
@@ -15,9 +15,15 @@ void acpi_reboot(void) | |||
15 | 15 | ||
16 | rr = &acpi_gbl_FADT.reset_register; | 16 | rr = &acpi_gbl_FADT.reset_register; |
17 | 17 | ||
18 | /* Is the reset register supported? */ | 18 | /* ACPI reset register was only introduced with v2 of the FADT */ |
19 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || | 19 | |
20 | rr->bit_width != 8 || rr->bit_offset != 0) | 20 | if (acpi_gbl_FADT.header.revision < 2) |
21 | return; | ||
22 | |||
23 | /* Is the reset register supported? The spec says we should be | ||
24 | * checking the bit width and bit offset, but Windows ignores | ||
25 | * these fields */ | ||
26 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER)) | ||
21 | return; | 27 | return; |
22 | 28 | ||
23 | reset_value = acpi_gbl_FADT.reset_value; | 29 | reset_value = acpi_gbl_FADT.reset_value; |
@@ -45,6 +51,4 @@ void acpi_reboot(void) | |||
45 | acpi_reset(); | 51 | acpi_reset(); |
46 | break; | 52 | break; |
47 | } | 53 | } |
48 | /* Wait ten seconds */ | ||
49 | acpi_os_stall(10000000); | ||
50 | } | 54 | } |
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 4ff76e8174eb..51ae3794ec7f 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -40,10 +40,7 @@ | |||
40 | #include <linux/timer.h> | 40 | #include <linux/timer.h> |
41 | #include <linux/jiffies.h> | 41 | #include <linux/jiffies.h> |
42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
43 | |||
44 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
45 | #include <linux/power_supply.h> | 43 | #include <linux/power_supply.h> |
46 | #endif | ||
47 | 44 | ||
48 | #include "sbshc.h" | 45 | #include "sbshc.h" |
49 | 46 | ||
@@ -85,9 +82,7 @@ static const struct acpi_device_id sbs_device_ids[] = { | |||
85 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); | 82 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); |
86 | 83 | ||
87 | struct acpi_battery { | 84 | struct acpi_battery { |
88 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
89 | struct power_supply bat; | 85 | struct power_supply bat; |
90 | #endif | ||
91 | struct acpi_sbs *sbs; | 86 | struct acpi_sbs *sbs; |
92 | #ifdef CONFIG_ACPI_PROCFS_POWER | 87 | #ifdef CONFIG_ACPI_PROCFS_POWER |
93 | struct proc_dir_entry *proc_entry; | 88 | struct proc_dir_entry *proc_entry; |
@@ -120,9 +115,7 @@ struct acpi_battery { | |||
120 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); | 115 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); |
121 | 116 | ||
122 | struct acpi_sbs { | 117 | struct acpi_sbs { |
123 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
124 | struct power_supply charger; | 118 | struct power_supply charger; |
125 | #endif | ||
126 | struct acpi_device *device; | 119 | struct acpi_device *device; |
127 | struct acpi_smb_hc *hc; | 120 | struct acpi_smb_hc *hc; |
128 | struct mutex lock; | 121 | struct mutex lock; |
@@ -166,7 +159,6 @@ static inline int acpi_battery_scale(struct acpi_battery *battery) | |||
166 | acpi_battery_ipscale(battery); | 159 | acpi_battery_ipscale(battery); |
167 | } | 160 | } |
168 | 161 | ||
169 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
170 | static int sbs_get_ac_property(struct power_supply *psy, | 162 | static int sbs_get_ac_property(struct power_supply *psy, |
171 | enum power_supply_property psp, | 163 | enum power_supply_property psp, |
172 | union power_supply_propval *val) | 164 | union power_supply_propval *val) |
@@ -313,7 +305,6 @@ static enum power_supply_property sbs_energy_battery_props[] = { | |||
313 | POWER_SUPPLY_PROP_MANUFACTURER, | 305 | POWER_SUPPLY_PROP_MANUFACTURER, |
314 | }; | 306 | }; |
315 | 307 | ||
316 | #endif | ||
317 | 308 | ||
318 | /* -------------------------------------------------------------------------- | 309 | /* -------------------------------------------------------------------------- |
319 | Smart Battery System Management | 310 | Smart Battery System Management |
@@ -449,7 +440,6 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) | |||
449 | return result; | 440 | return result; |
450 | } | 441 | } |
451 | 442 | ||
452 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
453 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 443 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
454 | struct device_attribute *attr, | 444 | struct device_attribute *attr, |
455 | char *buf) | 445 | char *buf) |
@@ -479,7 +469,6 @@ static struct device_attribute alarm_attr = { | |||
479 | .show = acpi_battery_alarm_show, | 469 | .show = acpi_battery_alarm_show, |
480 | .store = acpi_battery_alarm_store, | 470 | .store = acpi_battery_alarm_store, |
481 | }; | 471 | }; |
482 | #endif | ||
483 | 472 | ||
484 | /* -------------------------------------------------------------------------- | 473 | /* -------------------------------------------------------------------------- |
485 | FS Interface (/proc/acpi) | 474 | FS Interface (/proc/acpi) |
@@ -495,6 +484,8 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir, | |||
495 | const struct file_operations *state_fops, | 484 | const struct file_operations *state_fops, |
496 | const struct file_operations *alarm_fops, void *data) | 485 | const struct file_operations *alarm_fops, void *data) |
497 | { | 486 | { |
487 | printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded," | ||
488 | " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); | ||
498 | if (!*dir) { | 489 | if (!*dir) { |
499 | *dir = proc_mkdir(dir_name, parent_dir); | 490 | *dir = proc_mkdir(dir_name, parent_dir); |
500 | if (!*dir) { | 491 | if (!*dir) { |
@@ -798,7 +789,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
798 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, | 789 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, |
799 | battery); | 790 | battery); |
800 | #endif | 791 | #endif |
801 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
802 | battery->bat.name = battery->name; | 792 | battery->bat.name = battery->name; |
803 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; | 793 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
804 | if (!acpi_battery_mode(battery)) { | 794 | if (!acpi_battery_mode(battery)) { |
@@ -819,7 +809,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
819 | goto end; | 809 | goto end; |
820 | battery->have_sysfs_alarm = 1; | 810 | battery->have_sysfs_alarm = 1; |
821 | end: | 811 | end: |
822 | #endif | ||
823 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", | 812 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", |
824 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 813 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
825 | battery->name, battery->present ? "present" : "absent"); | 814 | battery->name, battery->present ? "present" : "absent"); |
@@ -828,17 +817,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
828 | 817 | ||
829 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 818 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) |
830 | { | 819 | { |
831 | #if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) | ||
832 | struct acpi_battery *battery = &sbs->battery[id]; | 820 | struct acpi_battery *battery = &sbs->battery[id]; |
833 | #endif | ||
834 | 821 | ||
835 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
836 | if (battery->bat.dev) { | 822 | if (battery->bat.dev) { |
837 | if (battery->have_sysfs_alarm) | 823 | if (battery->have_sysfs_alarm) |
838 | device_remove_file(battery->bat.dev, &alarm_attr); | 824 | device_remove_file(battery->bat.dev, &alarm_attr); |
839 | power_supply_unregister(&battery->bat); | 825 | power_supply_unregister(&battery->bat); |
840 | } | 826 | } |
841 | #endif | ||
842 | #ifdef CONFIG_ACPI_PROCFS_POWER | 827 | #ifdef CONFIG_ACPI_PROCFS_POWER |
843 | if (battery->proc_entry) | 828 | if (battery->proc_entry) |
844 | acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); | 829 | acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); |
@@ -859,14 +844,12 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
859 | if (result) | 844 | if (result) |
860 | goto end; | 845 | goto end; |
861 | #endif | 846 | #endif |
862 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
863 | sbs->charger.name = "sbs-charger"; | 847 | sbs->charger.name = "sbs-charger"; |
864 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; | 848 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; |
865 | sbs->charger.properties = sbs_ac_props; | 849 | sbs->charger.properties = sbs_ac_props; |
866 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); | 850 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); |
867 | sbs->charger.get_property = sbs_get_ac_property; | 851 | sbs->charger.get_property = sbs_get_ac_property; |
868 | power_supply_register(&sbs->device->dev, &sbs->charger); | 852 | power_supply_register(&sbs->device->dev, &sbs->charger); |
869 | #endif | ||
870 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", | 853 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", |
871 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 854 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
872 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); | 855 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); |
@@ -876,10 +859,8 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
876 | 859 | ||
877 | static void acpi_charger_remove(struct acpi_sbs *sbs) | 860 | static void acpi_charger_remove(struct acpi_sbs *sbs) |
878 | { | 861 | { |
879 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
880 | if (sbs->charger.dev) | 862 | if (sbs->charger.dev) |
881 | power_supply_unregister(&sbs->charger); | 863 | power_supply_unregister(&sbs->charger); |
882 | #endif | ||
883 | #ifdef CONFIG_ACPI_PROCFS_POWER | 864 | #ifdef CONFIG_ACPI_PROCFS_POWER |
884 | if (sbs->charger_entry) | 865 | if (sbs->charger_entry) |
885 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); | 866 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); |
@@ -900,9 +881,7 @@ static void acpi_sbs_callback(void *context) | |||
900 | ACPI_SBS_NOTIFY_STATUS, | 881 | ACPI_SBS_NOTIFY_STATUS, |
901 | sbs->charger_present); | 882 | sbs->charger_present); |
902 | #endif | 883 | #endif |
903 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
904 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); | 884 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); |
905 | #endif | ||
906 | } | 885 | } |
907 | if (sbs->manager_present) { | 886 | if (sbs->manager_present) { |
908 | for (id = 0; id < MAX_SBS_BAT; ++id) { | 887 | for (id = 0; id < MAX_SBS_BAT; ++id) { |
@@ -919,9 +898,7 @@ static void acpi_sbs_callback(void *context) | |||
919 | ACPI_SBS_NOTIFY_STATUS, | 898 | ACPI_SBS_NOTIFY_STATUS, |
920 | bat->present); | 899 | bat->present); |
921 | #endif | 900 | #endif |
922 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
923 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); | 901 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); |
924 | #endif | ||
925 | } | 902 | } |
926 | } | 903 | } |
927 | } | 904 | } |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b23825ecfa37..449c556274c0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -26,6 +26,8 @@ extern struct acpi_device *acpi_root; | |||
26 | 26 | ||
27 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) | 27 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
28 | 28 | ||
29 | static const char *dummy_hid = "device"; | ||
30 | |||
29 | static LIST_HEAD(acpi_device_list); | 31 | static LIST_HEAD(acpi_device_list); |
30 | static LIST_HEAD(acpi_bus_id_list); | 32 | static LIST_HEAD(acpi_bus_id_list); |
31 | DEFINE_MUTEX(acpi_device_lock); | 33 | DEFINE_MUTEX(acpi_device_lock); |
@@ -49,6 +51,9 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
49 | int count; | 51 | int count; |
50 | struct acpi_hardware_id *id; | 52 | struct acpi_hardware_id *id; |
51 | 53 | ||
54 | if (list_empty(&acpi_dev->pnp.ids)) | ||
55 | return 0; | ||
56 | |||
52 | len = snprintf(modalias, size, "acpi:"); | 57 | len = snprintf(modalias, size, "acpi:"); |
53 | size -= len; | 58 | size -= len; |
54 | 59 | ||
@@ -202,13 +207,15 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
202 | goto end; | 207 | goto end; |
203 | } | 208 | } |
204 | 209 | ||
205 | result = device_create_file(&dev->dev, &dev_attr_hid); | 210 | if (!list_empty(&dev->pnp.ids)) { |
206 | if (result) | 211 | result = device_create_file(&dev->dev, &dev_attr_hid); |
207 | goto end; | 212 | if (result) |
213 | goto end; | ||
208 | 214 | ||
209 | result = device_create_file(&dev->dev, &dev_attr_modalias); | 215 | result = device_create_file(&dev->dev, &dev_attr_modalias); |
210 | if (result) | 216 | if (result) |
211 | goto end; | 217 | goto end; |
218 | } | ||
212 | 219 | ||
213 | /* | 220 | /* |
214 | * If device has _EJ0, 'eject' file is created that is used to trigger | 221 | * If device has _EJ0, 'eject' file is created that is used to trigger |
@@ -316,6 +323,9 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
316 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 323 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
317 | int len; | 324 | int len; |
318 | 325 | ||
326 | if (list_empty(&acpi_dev->pnp.ids)) | ||
327 | return 0; | ||
328 | |||
319 | if (add_uevent_var(env, "MODALIAS=")) | 329 | if (add_uevent_var(env, "MODALIAS=")) |
320 | return -ENOMEM; | 330 | return -ENOMEM; |
321 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 331 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], |
@@ -695,54 +705,85 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device) | |||
695 | } | 705 | } |
696 | 706 | ||
697 | static acpi_status | 707 | static acpi_status |
698 | acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, | 708 | acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, |
699 | union acpi_object *package) | 709 | struct acpi_device_wakeup *wakeup) |
700 | { | 710 | { |
701 | int i = 0; | 711 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
712 | union acpi_object *package = NULL; | ||
702 | union acpi_object *element = NULL; | 713 | union acpi_object *element = NULL; |
714 | acpi_status status; | ||
715 | int i = 0; | ||
703 | 716 | ||
704 | if (!device || !package || (package->package.count < 2)) | 717 | if (!wakeup) |
705 | return AE_BAD_PARAMETER; | 718 | return AE_BAD_PARAMETER; |
706 | 719 | ||
720 | /* _PRW */ | ||
721 | status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer); | ||
722 | if (ACPI_FAILURE(status)) { | ||
723 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); | ||
724 | return status; | ||
725 | } | ||
726 | |||
727 | package = (union acpi_object *)buffer.pointer; | ||
728 | |||
729 | if (!package || (package->package.count < 2)) { | ||
730 | status = AE_BAD_DATA; | ||
731 | goto out; | ||
732 | } | ||
733 | |||
707 | element = &(package->package.elements[0]); | 734 | element = &(package->package.elements[0]); |
708 | if (!element) | 735 | if (!element) { |
709 | return AE_BAD_PARAMETER; | 736 | status = AE_BAD_DATA; |
737 | goto out; | ||
738 | } | ||
710 | if (element->type == ACPI_TYPE_PACKAGE) { | 739 | if (element->type == ACPI_TYPE_PACKAGE) { |
711 | if ((element->package.count < 2) || | 740 | if ((element->package.count < 2) || |
712 | (element->package.elements[0].type != | 741 | (element->package.elements[0].type != |
713 | ACPI_TYPE_LOCAL_REFERENCE) | 742 | ACPI_TYPE_LOCAL_REFERENCE) |
714 | || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) | 743 | || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) { |
715 | return AE_BAD_DATA; | 744 | status = AE_BAD_DATA; |
716 | device->wakeup.gpe_device = | 745 | goto out; |
746 | } | ||
747 | wakeup->gpe_device = | ||
717 | element->package.elements[0].reference.handle; | 748 | element->package.elements[0].reference.handle; |
718 | device->wakeup.gpe_number = | 749 | wakeup->gpe_number = |
719 | (u32) element->package.elements[1].integer.value; | 750 | (u32) element->package.elements[1].integer.value; |
720 | } else if (element->type == ACPI_TYPE_INTEGER) { | 751 | } else if (element->type == ACPI_TYPE_INTEGER) { |
721 | device->wakeup.gpe_number = element->integer.value; | 752 | wakeup->gpe_device = NULL; |
722 | } else | 753 | wakeup->gpe_number = element->integer.value; |
723 | return AE_BAD_DATA; | 754 | } else { |
755 | status = AE_BAD_DATA; | ||
756 | goto out; | ||
757 | } | ||
724 | 758 | ||
725 | element = &(package->package.elements[1]); | 759 | element = &(package->package.elements[1]); |
726 | if (element->type != ACPI_TYPE_INTEGER) { | 760 | if (element->type != ACPI_TYPE_INTEGER) { |
727 | return AE_BAD_DATA; | 761 | status = AE_BAD_DATA; |
762 | goto out; | ||
728 | } | 763 | } |
729 | device->wakeup.sleep_state = element->integer.value; | 764 | wakeup->sleep_state = element->integer.value; |
730 | 765 | ||
731 | if ((package->package.count - 2) > ACPI_MAX_HANDLES) { | 766 | if ((package->package.count - 2) > ACPI_MAX_HANDLES) { |
732 | return AE_NO_MEMORY; | 767 | status = AE_NO_MEMORY; |
768 | goto out; | ||
733 | } | 769 | } |
734 | device->wakeup.resources.count = package->package.count - 2; | 770 | wakeup->resources.count = package->package.count - 2; |
735 | for (i = 0; i < device->wakeup.resources.count; i++) { | 771 | for (i = 0; i < wakeup->resources.count; i++) { |
736 | element = &(package->package.elements[i + 2]); | 772 | element = &(package->package.elements[i + 2]); |
737 | if (element->type != ACPI_TYPE_LOCAL_REFERENCE) | 773 | if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { |
738 | return AE_BAD_DATA; | 774 | status = AE_BAD_DATA; |
775 | goto out; | ||
776 | } | ||
739 | 777 | ||
740 | device->wakeup.resources.handles[i] = element->reference.handle; | 778 | wakeup->resources.handles[i] = element->reference.handle; |
741 | } | 779 | } |
742 | 780 | ||
743 | acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number); | 781 | acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); |
744 | 782 | ||
745 | return AE_OK; | 783 | out: |
784 | kfree(buffer.pointer); | ||
785 | |||
786 | return status; | ||
746 | } | 787 | } |
747 | 788 | ||
748 | static void acpi_bus_set_run_wake_flags(struct acpi_device *device) | 789 | static void acpi_bus_set_run_wake_flags(struct acpi_device *device) |
@@ -756,13 +797,12 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) | |||
756 | acpi_status status; | 797 | acpi_status status; |
757 | acpi_event_status event_status; | 798 | acpi_event_status event_status; |
758 | 799 | ||
759 | device->wakeup.run_wake_count = 0; | ||
760 | device->wakeup.flags.notifier_present = 0; | 800 | device->wakeup.flags.notifier_present = 0; |
761 | 801 | ||
762 | /* Power button, Lid switch always enable wakeup */ | 802 | /* Power button, Lid switch always enable wakeup */ |
763 | if (!acpi_match_device_ids(device, button_device_ids)) { | 803 | if (!acpi_match_device_ids(device, button_device_ids)) { |
764 | device->wakeup.flags.run_wake = 1; | 804 | device->wakeup.flags.run_wake = 1; |
765 | device->wakeup.flags.always_enabled = 1; | 805 | device_set_wakeup_capable(&device->dev, true); |
766 | return; | 806 | return; |
767 | } | 807 | } |
768 | 808 | ||
@@ -774,29 +814,24 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) | |||
774 | !!(event_status & ACPI_EVENT_FLAG_HANDLE); | 814 | !!(event_status & ACPI_EVENT_FLAG_HANDLE); |
775 | } | 815 | } |
776 | 816 | ||
777 | static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | 817 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) |
778 | { | 818 | { |
819 | acpi_handle temp; | ||
779 | acpi_status status = 0; | 820 | acpi_status status = 0; |
780 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
781 | union acpi_object *package = NULL; | ||
782 | int psw_error; | 821 | int psw_error; |
783 | 822 | ||
784 | /* _PRW */ | 823 | /* Presence of _PRW indicates wake capable */ |
785 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); | 824 | status = acpi_get_handle(device->handle, "_PRW", &temp); |
786 | if (ACPI_FAILURE(status)) { | 825 | if (ACPI_FAILURE(status)) |
787 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); | 826 | return; |
788 | goto end; | ||
789 | } | ||
790 | 827 | ||
791 | package = (union acpi_object *)buffer.pointer; | 828 | status = acpi_bus_extract_wakeup_device_power_package(device->handle, |
792 | status = acpi_bus_extract_wakeup_device_power_package(device, package); | 829 | &device->wakeup); |
793 | if (ACPI_FAILURE(status)) { | 830 | if (ACPI_FAILURE(status)) { |
794 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); | 831 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); |
795 | goto end; | 832 | return; |
796 | } | 833 | } |
797 | 834 | ||
798 | kfree(buffer.pointer); | ||
799 | |||
800 | device->wakeup.flags.valid = 1; | 835 | device->wakeup.flags.valid = 1; |
801 | device->wakeup.prepare_count = 0; | 836 | device->wakeup.prepare_count = 0; |
802 | acpi_bus_set_run_wake_flags(device); | 837 | acpi_bus_set_run_wake_flags(device); |
@@ -810,13 +845,10 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
810 | if (psw_error) | 845 | if (psw_error) |
811 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 846 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
812 | "error in _DSW or _PSW evaluation\n")); | 847 | "error in _DSW or _PSW evaluation\n")); |
813 | |||
814 | end: | ||
815 | if (ACPI_FAILURE(status)) | ||
816 | device->flags.wake_capable = 0; | ||
817 | return 0; | ||
818 | } | 848 | } |
819 | 849 | ||
850 | static void acpi_bus_add_power_resource(acpi_handle handle); | ||
851 | |||
820 | static int acpi_bus_get_power_flags(struct acpi_device *device) | 852 | static int acpi_bus_get_power_flags(struct acpi_device *device) |
821 | { | 853 | { |
822 | acpi_status status = 0; | 854 | acpi_status status = 0; |
@@ -845,8 +877,12 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
845 | acpi_evaluate_reference(device->handle, object_name, NULL, | 877 | acpi_evaluate_reference(device->handle, object_name, NULL, |
846 | &ps->resources); | 878 | &ps->resources); |
847 | if (ps->resources.count) { | 879 | if (ps->resources.count) { |
880 | int j; | ||
881 | |||
848 | device->power.flags.power_resources = 1; | 882 | device->power.flags.power_resources = 1; |
849 | ps->flags.valid = 1; | 883 | ps->flags.valid = 1; |
884 | for (j = 0; j < ps->resources.count; j++) | ||
885 | acpi_bus_add_power_resource(ps->resources.handles[j]); | ||
850 | } | 886 | } |
851 | 887 | ||
852 | /* Evaluate "_PSx" to see if we can do explicit sets */ | 888 | /* Evaluate "_PSx" to see if we can do explicit sets */ |
@@ -871,10 +907,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
871 | device->power.states[ACPI_STATE_D3].flags.valid = 1; | 907 | device->power.states[ACPI_STATE_D3].flags.valid = 1; |
872 | device->power.states[ACPI_STATE_D3].power = 0; | 908 | device->power.states[ACPI_STATE_D3].power = 0; |
873 | 909 | ||
874 | /* TBD: System wake support and resource requirements. */ | 910 | acpi_bus_init_power(device); |
875 | |||
876 | device->power.state = ACPI_STATE_UNKNOWN; | ||
877 | acpi_bus_get_power(device->handle, &(device->power.state)); | ||
878 | 911 | ||
879 | return 0; | 912 | return 0; |
880 | } | 913 | } |
@@ -910,6 +943,10 @@ static int acpi_bus_get_flags(struct acpi_device *device) | |||
910 | if (ACPI_SUCCESS(status)) | 943 | if (ACPI_SUCCESS(status)) |
911 | device->flags.lockable = 1; | 944 | device->flags.lockable = 1; |
912 | 945 | ||
946 | /* Power resources cannot be power manageable. */ | ||
947 | if (device->device_type == ACPI_BUS_TYPE_POWER) | ||
948 | return 0; | ||
949 | |||
913 | /* Presence of _PS0|_PR0 indicates 'power manageable' */ | 950 | /* Presence of _PS0|_PR0 indicates 'power manageable' */ |
914 | status = acpi_get_handle(device->handle, "_PS0", &temp); | 951 | status = acpi_get_handle(device->handle, "_PS0", &temp); |
915 | if (ACPI_FAILURE(status)) | 952 | if (ACPI_FAILURE(status)) |
@@ -917,11 +954,6 @@ static int acpi_bus_get_flags(struct acpi_device *device) | |||
917 | if (ACPI_SUCCESS(status)) | 954 | if (ACPI_SUCCESS(status)) |
918 | device->flags.power_manageable = 1; | 955 | device->flags.power_manageable = 1; |
919 | 956 | ||
920 | /* Presence of _PRW indicates wake capable */ | ||
921 | status = acpi_get_handle(device->handle, "_PRW", &temp); | ||
922 | if (ACPI_SUCCESS(status)) | ||
923 | device->flags.wake_capable = 1; | ||
924 | |||
925 | /* TBD: Performance management */ | 957 | /* TBD: Performance management */ |
926 | 958 | ||
927 | return 0; | 959 | return 0; |
@@ -1010,10 +1042,13 @@ static int acpi_dock_match(struct acpi_device *device) | |||
1010 | return acpi_get_handle(device->handle, "_DCK", &tmp); | 1042 | return acpi_get_handle(device->handle, "_DCK", &tmp); |
1011 | } | 1043 | } |
1012 | 1044 | ||
1013 | char *acpi_device_hid(struct acpi_device *device) | 1045 | const char *acpi_device_hid(struct acpi_device *device) |
1014 | { | 1046 | { |
1015 | struct acpi_hardware_id *hid; | 1047 | struct acpi_hardware_id *hid; |
1016 | 1048 | ||
1049 | if (list_empty(&device->pnp.ids)) | ||
1050 | return dummy_hid; | ||
1051 | |||
1017 | hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); | 1052 | hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); |
1018 | return hid->id; | 1053 | return hid->id; |
1019 | } | 1054 | } |
@@ -1142,16 +1177,6 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
1142 | acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); | 1177 | acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); |
1143 | break; | 1178 | break; |
1144 | } | 1179 | } |
1145 | |||
1146 | /* | ||
1147 | * We build acpi_devices for some objects that don't have _HID or _CID, | ||
1148 | * e.g., PCI bridges and slots. Drivers can't bind to these objects, | ||
1149 | * but we do use them indirectly by traversing the acpi_device tree. | ||
1150 | * This generic ID isn't useful for driver binding, but it provides | ||
1151 | * the useful property that "every acpi_device has an ID." | ||
1152 | */ | ||
1153 | if (list_empty(&device->pnp.ids)) | ||
1154 | acpi_add_id(device, "device"); | ||
1155 | } | 1180 | } |
1156 | 1181 | ||
1157 | static int acpi_device_set_context(struct acpi_device *device) | 1182 | static int acpi_device_set_context(struct acpi_device *device) |
@@ -1255,11 +1280,7 @@ static int acpi_add_single_object(struct acpi_device **child, | |||
1255 | * Wakeup device management | 1280 | * Wakeup device management |
1256 | *----------------------- | 1281 | *----------------------- |
1257 | */ | 1282 | */ |
1258 | if (device->flags.wake_capable) { | 1283 | acpi_bus_get_wakeup_device_flags(device); |
1259 | result = acpi_bus_get_wakeup_device_flags(device); | ||
1260 | if (result) | ||
1261 | goto end; | ||
1262 | } | ||
1263 | 1284 | ||
1264 | /* | 1285 | /* |
1265 | * Performance Management | 1286 | * Performance Management |
@@ -1303,6 +1324,20 @@ end: | |||
1303 | #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ | 1324 | #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ |
1304 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) | 1325 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) |
1305 | 1326 | ||
1327 | static void acpi_bus_add_power_resource(acpi_handle handle) | ||
1328 | { | ||
1329 | struct acpi_bus_ops ops = { | ||
1330 | .acpi_op_add = 1, | ||
1331 | .acpi_op_start = 1, | ||
1332 | }; | ||
1333 | struct acpi_device *device = NULL; | ||
1334 | |||
1335 | acpi_bus_get_device(handle, &device); | ||
1336 | if (!device) | ||
1337 | acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, | ||
1338 | ACPI_STA_DEFAULT, &ops); | ||
1339 | } | ||
1340 | |||
1306 | static int acpi_bus_type_and_status(acpi_handle handle, int *type, | 1341 | static int acpi_bus_type_and_status(acpi_handle handle, int *type, |
1307 | unsigned long long *sta) | 1342 | unsigned long long *sta) |
1308 | { | 1343 | { |
@@ -1357,8 +1392,16 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, | |||
1357 | return AE_OK; | 1392 | return AE_OK; |
1358 | 1393 | ||
1359 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && | 1394 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && |
1360 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) | 1395 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { |
1396 | struct acpi_device_wakeup wakeup; | ||
1397 | acpi_handle temp; | ||
1398 | |||
1399 | status = acpi_get_handle(handle, "_PRW", &temp); | ||
1400 | if (ACPI_SUCCESS(status)) | ||
1401 | acpi_bus_extract_wakeup_device_power_package(handle, | ||
1402 | &wakeup); | ||
1361 | return AE_CTRL_DEPTH; | 1403 | return AE_CTRL_DEPTH; |
1404 | } | ||
1362 | 1405 | ||
1363 | /* | 1406 | /* |
1364 | * We may already have an acpi_device from a previous enumeration. If | 1407 | * We may already have an acpi_device from a previous enumeration. If |
@@ -1431,6 +1474,7 @@ EXPORT_SYMBOL(acpi_bus_add); | |||
1431 | int acpi_bus_start(struct acpi_device *device) | 1474 | int acpi_bus_start(struct acpi_device *device) |
1432 | { | 1475 | { |
1433 | struct acpi_bus_ops ops; | 1476 | struct acpi_bus_ops ops; |
1477 | int result; | ||
1434 | 1478 | ||
1435 | if (!device) | 1479 | if (!device) |
1436 | return -EINVAL; | 1480 | return -EINVAL; |
@@ -1438,7 +1482,11 @@ int acpi_bus_start(struct acpi_device *device) | |||
1438 | memset(&ops, 0, sizeof(ops)); | 1482 | memset(&ops, 0, sizeof(ops)); |
1439 | ops.acpi_op_start = 1; | 1483 | ops.acpi_op_start = 1; |
1440 | 1484 | ||
1441 | return acpi_bus_scan(device->handle, &ops, NULL); | 1485 | result = acpi_bus_scan(device->handle, &ops, NULL); |
1486 | |||
1487 | acpi_update_all_gpes(); | ||
1488 | |||
1489 | return result; | ||
1442 | } | 1490 | } |
1443 | EXPORT_SYMBOL(acpi_bus_start); | 1491 | EXPORT_SYMBOL(acpi_bus_start); |
1444 | 1492 | ||
@@ -1542,6 +1590,8 @@ int __init acpi_scan_init(void) | |||
1542 | printk(KERN_ERR PREFIX "Could not register bus type\n"); | 1590 | printk(KERN_ERR PREFIX "Could not register bus type\n"); |
1543 | } | 1591 | } |
1544 | 1592 | ||
1593 | acpi_power_init(); | ||
1594 | |||
1545 | /* | 1595 | /* |
1546 | * Enumerate devices in the ACPI namespace. | 1596 | * Enumerate devices in the ACPI namespace. |
1547 | */ | 1597 | */ |
@@ -1552,6 +1602,8 @@ int __init acpi_scan_init(void) | |||
1552 | 1602 | ||
1553 | if (result) | 1603 | if (result) |
1554 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); | 1604 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); |
1605 | else | ||
1606 | acpi_update_all_gpes(); | ||
1555 | 1607 | ||
1556 | return result; | 1608 | return result; |
1557 | } | 1609 | } |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4754ff6e70e6..6c949602cbd1 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/suspend.h> | 17 | #include <linux/suspend.h> |
18 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
19 | #include <linux/acpi.h> | ||
19 | 20 | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | 22 | ||
@@ -25,7 +26,7 @@ | |||
25 | #include "internal.h" | 26 | #include "internal.h" |
26 | #include "sleep.h" | 27 | #include "sleep.h" |
27 | 28 | ||
28 | u8 sleep_states[ACPI_S_STATE_COUNT]; | 29 | static u8 sleep_states[ACPI_S_STATE_COUNT]; |
29 | 30 | ||
30 | static void acpi_sleep_tts_switch(u32 acpi_state) | 31 | static void acpi_sleep_tts_switch(u32 acpi_state) |
31 | { | 32 | { |
@@ -124,8 +125,7 @@ static int acpi_pm_freeze(void) | |||
124 | static int acpi_pm_pre_suspend(void) | 125 | static int acpi_pm_pre_suspend(void) |
125 | { | 126 | { |
126 | acpi_pm_freeze(); | 127 | acpi_pm_freeze(); |
127 | suspend_nvs_save(); | 128 | return suspend_nvs_save(); |
128 | return 0; | ||
129 | } | 129 | } |
130 | 130 | ||
131 | /** | 131 | /** |
@@ -151,7 +151,7 @@ static int acpi_pm_prepare(void) | |||
151 | { | 151 | { |
152 | int error = __acpi_pm_prepare(); | 152 | int error = __acpi_pm_prepare(); |
153 | if (!error) | 153 | if (!error) |
154 | acpi_pm_pre_suspend(); | 154 | error = acpi_pm_pre_suspend(); |
155 | 155 | ||
156 | return error; | 156 | return error; |
157 | } | 157 | } |
@@ -167,6 +167,7 @@ static void acpi_pm_finish(void) | |||
167 | u32 acpi_state = acpi_target_sleep_state; | 167 | u32 acpi_state = acpi_target_sleep_state; |
168 | 168 | ||
169 | acpi_ec_unblock_transactions(); | 169 | acpi_ec_unblock_transactions(); |
170 | suspend_nvs_free(); | ||
170 | 171 | ||
171 | if (acpi_state == ACPI_STATE_S0) | 172 | if (acpi_state == ACPI_STATE_S0) |
172 | return; | 173 | return; |
@@ -187,7 +188,6 @@ static void acpi_pm_finish(void) | |||
187 | */ | 188 | */ |
188 | static void acpi_pm_end(void) | 189 | static void acpi_pm_end(void) |
189 | { | 190 | { |
190 | suspend_nvs_free(); | ||
191 | /* | 191 | /* |
192 | * This is necessary in case acpi_pm_finish() is not called during a | 192 | * This is necessary in case acpi_pm_finish() is not called during a |
193 | * failing transition to a sleep state. | 193 | * failing transition to a sleep state. |
@@ -200,8 +200,6 @@ static void acpi_pm_end(void) | |||
200 | #endif /* CONFIG_ACPI_SLEEP */ | 200 | #endif /* CONFIG_ACPI_SLEEP */ |
201 | 201 | ||
202 | #ifdef CONFIG_SUSPEND | 202 | #ifdef CONFIG_SUSPEND |
203 | extern void do_suspend_lowlevel(void); | ||
204 | |||
205 | static u32 acpi_suspend_states[] = { | 203 | static u32 acpi_suspend_states[] = { |
206 | [PM_SUSPEND_ON] = ACPI_STATE_S0, | 204 | [PM_SUSPEND_ON] = ACPI_STATE_S0, |
207 | [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, | 205 | [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, |
@@ -244,20 +242,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
244 | static int acpi_suspend_enter(suspend_state_t pm_state) | 242 | static int acpi_suspend_enter(suspend_state_t pm_state) |
245 | { | 243 | { |
246 | acpi_status status = AE_OK; | 244 | acpi_status status = AE_OK; |
247 | unsigned long flags = 0; | ||
248 | u32 acpi_state = acpi_target_sleep_state; | 245 | u32 acpi_state = acpi_target_sleep_state; |
246 | int error; | ||
249 | 247 | ||
250 | ACPI_FLUSH_CPU_CACHE(); | 248 | ACPI_FLUSH_CPU_CACHE(); |
251 | 249 | ||
252 | /* Do arch specific saving of state. */ | ||
253 | if (acpi_state == ACPI_STATE_S3) { | ||
254 | int error = acpi_save_state_mem(); | ||
255 | |||
256 | if (error) | ||
257 | return error; | ||
258 | } | ||
259 | |||
260 | local_irq_save(flags); | ||
261 | switch (acpi_state) { | 250 | switch (acpi_state) { |
262 | case ACPI_STATE_S1: | 251 | case ACPI_STATE_S1: |
263 | barrier(); | 252 | barrier(); |
@@ -265,7 +254,10 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
265 | break; | 254 | break; |
266 | 255 | ||
267 | case ACPI_STATE_S3: | 256 | case ACPI_STATE_S3: |
268 | do_suspend_lowlevel(); | 257 | error = acpi_suspend_lowlevel(); |
258 | if (error) | ||
259 | return error; | ||
260 | pr_info(PREFIX "Low-level resume complete\n"); | ||
269 | break; | 261 | break; |
270 | } | 262 | } |
271 | 263 | ||
@@ -291,13 +283,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
291 | /* Allow EC transactions to happen. */ | 283 | /* Allow EC transactions to happen. */ |
292 | acpi_ec_unblock_transactions_early(); | 284 | acpi_ec_unblock_transactions_early(); |
293 | 285 | ||
294 | local_irq_restore(flags); | ||
295 | printk(KERN_DEBUG "Back to C!\n"); | ||
296 | |||
297 | /* restore processor state */ | ||
298 | if (acpi_state == ACPI_STATE_S3) | ||
299 | acpi_restore_state_mem(); | ||
300 | |||
301 | suspend_nvs_restore(); | 286 | suspend_nvs_restore(); |
302 | 287 | ||
303 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 288 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
@@ -319,7 +304,7 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state) | |||
319 | } | 304 | } |
320 | } | 305 | } |
321 | 306 | ||
322 | static struct platform_suspend_ops acpi_suspend_ops = { | 307 | static const struct platform_suspend_ops acpi_suspend_ops = { |
323 | .valid = acpi_suspend_state_valid, | 308 | .valid = acpi_suspend_state_valid, |
324 | .begin = acpi_suspend_begin, | 309 | .begin = acpi_suspend_begin, |
325 | .prepare_late = acpi_pm_prepare, | 310 | .prepare_late = acpi_pm_prepare, |
@@ -347,7 +332,7 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) | |||
347 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 332 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
348 | * been requested. | 333 | * been requested. |
349 | */ | 334 | */ |
350 | static struct platform_suspend_ops acpi_suspend_ops_old = { | 335 | static const struct platform_suspend_ops acpi_suspend_ops_old = { |
351 | .valid = acpi_suspend_state_valid, | 336 | .valid = acpi_suspend_state_valid, |
352 | .begin = acpi_suspend_begin_old, | 337 | .begin = acpi_suspend_begin_old, |
353 | .prepare_late = acpi_pm_pre_suspend, | 338 | .prepare_late = acpi_pm_pre_suspend, |
@@ -419,6 +404,30 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
419 | DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), | 404 | DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), |
420 | }, | 405 | }, |
421 | }, | 406 | }, |
407 | { | ||
408 | .callback = init_nvs_nosave, | ||
409 | .ident = "Sony Vaio VPCEB1Z1E", | ||
410 | .matches = { | ||
411 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
412 | DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), | ||
413 | }, | ||
414 | }, | ||
415 | { | ||
416 | .callback = init_nvs_nosave, | ||
417 | .ident = "Sony Vaio VGN-NW130D", | ||
418 | .matches = { | ||
419 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
420 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), | ||
421 | }, | ||
422 | }, | ||
423 | { | ||
424 | .callback = init_nvs_nosave, | ||
425 | .ident = "Averatec AV1020-ED2", | ||
426 | .matches = { | ||
427 | DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), | ||
428 | DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), | ||
429 | }, | ||
430 | }, | ||
422 | {}, | 431 | {}, |
423 | }; | 432 | }; |
424 | #endif /* CONFIG_SUSPEND */ | 433 | #endif /* CONFIG_SUSPEND */ |
@@ -449,16 +458,13 @@ static int acpi_hibernation_begin(void) | |||
449 | static int acpi_hibernation_enter(void) | 458 | static int acpi_hibernation_enter(void) |
450 | { | 459 | { |
451 | acpi_status status = AE_OK; | 460 | acpi_status status = AE_OK; |
452 | unsigned long flags = 0; | ||
453 | 461 | ||
454 | ACPI_FLUSH_CPU_CACHE(); | 462 | ACPI_FLUSH_CPU_CACHE(); |
455 | 463 | ||
456 | local_irq_save(flags); | ||
457 | /* This shouldn't return. If it returns, we have a problem */ | 464 | /* This shouldn't return. If it returns, we have a problem */ |
458 | status = acpi_enter_sleep_state(ACPI_STATE_S4); | 465 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
459 | /* Reprogram control registers and execute _BFS */ | 466 | /* Reprogram control registers and execute _BFS */ |
460 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | 467 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); |
461 | local_irq_restore(flags); | ||
462 | 468 | ||
463 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 469 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
464 | } | 470 | } |
@@ -490,7 +496,7 @@ static void acpi_pm_thaw(void) | |||
490 | acpi_enable_all_runtime_gpes(); | 496 | acpi_enable_all_runtime_gpes(); |
491 | } | 497 | } |
492 | 498 | ||
493 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 499 | static const struct platform_hibernation_ops acpi_hibernation_ops = { |
494 | .begin = acpi_hibernation_begin, | 500 | .begin = acpi_hibernation_begin, |
495 | .end = acpi_pm_end, | 501 | .end = acpi_pm_end, |
496 | .pre_snapshot = acpi_pm_prepare, | 502 | .pre_snapshot = acpi_pm_prepare, |
@@ -533,7 +539,7 @@ static int acpi_hibernation_begin_old(void) | |||
533 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 539 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
534 | * been requested. | 540 | * been requested. |
535 | */ | 541 | */ |
536 | static struct platform_hibernation_ops acpi_hibernation_ops_old = { | 542 | static const struct platform_hibernation_ops acpi_hibernation_ops_old = { |
537 | .begin = acpi_hibernation_begin_old, | 543 | .begin = acpi_hibernation_begin_old, |
538 | .end = acpi_pm_end, | 544 | .end = acpi_pm_end, |
539 | .pre_snapshot = acpi_pm_pre_suspend, | 545 | .pre_snapshot = acpi_pm_pre_suspend, |
@@ -562,7 +568,7 @@ int acpi_suspend(u32 acpi_state) | |||
562 | return -EINVAL; | 568 | return -EINVAL; |
563 | } | 569 | } |
564 | 570 | ||
565 | #ifdef CONFIG_PM_SLEEP | 571 | #ifdef CONFIG_PM |
566 | /** | 572 | /** |
567 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device | 573 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device |
568 | * in the system sleep state given by %acpi_target_sleep_state | 574 | * in the system sleep state given by %acpi_target_sleep_state |
@@ -624,7 +630,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
624 | * can wake the system. _S0W may be valid, too. | 630 | * can wake the system. _S0W may be valid, too. |
625 | */ | 631 | */ |
626 | if (acpi_target_sleep_state == ACPI_STATE_S0 || | 632 | if (acpi_target_sleep_state == ACPI_STATE_S0 || |
627 | (device_may_wakeup(dev) && adev->wakeup.state.enabled && | 633 | (device_may_wakeup(dev) && |
628 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { | 634 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { |
629 | acpi_status status; | 635 | acpi_status status; |
630 | 636 | ||
@@ -632,7 +638,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
632 | status = acpi_evaluate_integer(handle, acpi_method, NULL, | 638 | status = acpi_evaluate_integer(handle, acpi_method, NULL, |
633 | &d_max); | 639 | &d_max); |
634 | if (ACPI_FAILURE(status)) { | 640 | if (ACPI_FAILURE(status)) { |
635 | d_max = d_min; | 641 | if (acpi_target_sleep_state != ACPI_STATE_S0 || |
642 | status != AE_NOT_FOUND) | ||
643 | d_max = d_min; | ||
636 | } else if (d_max < d_min) { | 644 | } else if (d_max < d_min) { |
637 | /* Warn the user of the broken DSDT */ | 645 | /* Warn the user of the broken DSDT */ |
638 | printk(KERN_WARNING "ACPI: Wrong value from %s\n", | 646 | printk(KERN_WARNING "ACPI: Wrong value from %s\n", |
@@ -646,7 +654,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
646 | *d_min_p = d_min; | 654 | *d_min_p = d_min; |
647 | return d_max; | 655 | return d_max; |
648 | } | 656 | } |
657 | #endif /* CONFIG_PM */ | ||
649 | 658 | ||
659 | #ifdef CONFIG_PM_SLEEP | ||
650 | /** | 660 | /** |
651 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | 661 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up |
652 | * capability of given device | 662 | * capability of given device |
@@ -677,7 +687,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | |||
677 | 687 | ||
678 | return error; | 688 | return error; |
679 | } | 689 | } |
680 | #endif | 690 | #endif /* CONFIG_PM_SLEEP */ |
681 | 691 | ||
682 | static void acpi_power_off_prepare(void) | 692 | static void acpi_power_off_prepare(void) |
683 | { | 693 | { |
@@ -702,7 +712,7 @@ static void acpi_power_off(void) | |||
702 | * paths through the BIOS, so disable _GTS and _BFS by default, | 712 | * paths through the BIOS, so disable _GTS and _BFS by default, |
703 | * but do speak up and offer the option to enable them. | 713 | * but do speak up and offer the option to enable them. |
704 | */ | 714 | */ |
705 | void __init acpi_gts_bfs_check(void) | 715 | static void __init acpi_gts_bfs_check(void) |
706 | { | 716 | { |
707 | acpi_handle dummy; | 717 | acpi_handle dummy; |
708 | 718 | ||
diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index d8821805c3bc..74d59c8f4678 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h | |||
@@ -1,5 +1,4 @@ | |||
1 | 1 | ||
2 | extern u8 sleep_states[]; | ||
3 | extern int acpi_suspend(u32 state); | 2 | extern int acpi_suspend(u32 state); |
4 | 3 | ||
5 | extern void acpi_enable_wakeup_devices(u8 sleep_state); | 4 | extern void acpi_enable_wakeup_devices(u8 sleep_state); |
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index f8588f81048a..77255f250dbb 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c | |||
@@ -220,6 +220,14 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | |||
220 | NULL, 0644); | 220 | NULL, 0644); |
221 | #endif /* CONFIG_ACPI_DEBUG */ | 221 | #endif /* CONFIG_ACPI_DEBUG */ |
222 | 222 | ||
223 | |||
224 | /* /sys/modules/acpi/parameters/aml_debug_output */ | ||
225 | |||
226 | module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, | ||
227 | bool, 0644); | ||
228 | MODULE_PARM_DESC(aml_debug_output, | ||
229 | "To enable/disable the ACPI Debug Object output."); | ||
230 | |||
223 | /* /sys/module/acpi/parameters/acpica_version */ | 231 | /* /sys/module/acpi/parameters/acpica_version */ |
224 | static int param_get_acpica_version(char *buffer, struct kernel_param *kp) | 232 | static int param_get_acpica_version(char *buffer, struct kernel_param *kp) |
225 | { | 233 | { |
@@ -438,7 +446,7 @@ static void delete_gpe_attr_array(void) | |||
438 | return; | 446 | return; |
439 | } | 447 | } |
440 | 448 | ||
441 | void acpi_os_gpe_count(u32 gpe_number) | 449 | static void gpe_count(u32 gpe_number) |
442 | { | 450 | { |
443 | acpi_gpe_count++; | 451 | acpi_gpe_count++; |
444 | 452 | ||
@@ -454,7 +462,7 @@ void acpi_os_gpe_count(u32 gpe_number) | |||
454 | return; | 462 | return; |
455 | } | 463 | } |
456 | 464 | ||
457 | void acpi_os_fixed_event_count(u32 event_number) | 465 | static void fixed_event_count(u32 event_number) |
458 | { | 466 | { |
459 | if (!all_counters) | 467 | if (!all_counters) |
460 | return; | 468 | return; |
@@ -468,6 +476,16 @@ void acpi_os_fixed_event_count(u32 event_number) | |||
468 | return; | 476 | return; |
469 | } | 477 | } |
470 | 478 | ||
479 | static void acpi_gbl_event_handler(u32 event_type, acpi_handle device, | ||
480 | u32 event_number, void *context) | ||
481 | { | ||
482 | if (event_type == ACPI_EVENT_TYPE_GPE) | ||
483 | gpe_count(event_number); | ||
484 | |||
485 | if (event_type == ACPI_EVENT_TYPE_FIXED) | ||
486 | fixed_event_count(event_number); | ||
487 | } | ||
488 | |||
471 | static int get_status(u32 index, acpi_event_status *status, | 489 | static int get_status(u32 index, acpi_event_status *status, |
472 | acpi_handle *handle) | 490 | acpi_handle *handle) |
473 | { | 491 | { |
@@ -601,6 +619,7 @@ end: | |||
601 | 619 | ||
602 | void acpi_irq_stats_init(void) | 620 | void acpi_irq_stats_init(void) |
603 | { | 621 | { |
622 | acpi_status status; | ||
604 | int i; | 623 | int i; |
605 | 624 | ||
606 | if (all_counters) | 625 | if (all_counters) |
@@ -619,6 +638,10 @@ void acpi_irq_stats_init(void) | |||
619 | if (all_counters == NULL) | 638 | if (all_counters == NULL) |
620 | goto fail; | 639 | goto fail; |
621 | 640 | ||
641 | status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL); | ||
642 | if (ACPI_FAILURE(status)) | ||
643 | goto fail; | ||
644 | |||
622 | counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), | 645 | counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), |
623 | GFP_KERNEL); | 646 | GFP_KERNEL); |
624 | if (counter_attrs == NULL) | 647 | if (counter_attrs == NULL) |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 2f8f17131d9f..2607e17b520f 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -37,12 +37,6 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/types.h> | 39 | #include <linux/types.h> |
40 | |||
41 | #ifdef CONFIG_ACPI_PROCFS | ||
42 | #include <linux/proc_fs.h> | ||
43 | #include <linux/seq_file.h> | ||
44 | #endif | ||
45 | |||
46 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
47 | #include <linux/kmod.h> | 41 | #include <linux/kmod.h> |
48 | #include <linux/reboot.h> | 42 | #include <linux/reboot.h> |
@@ -195,61 +189,6 @@ struct acpi_thermal { | |||
195 | struct mutex lock; | 189 | struct mutex lock; |
196 | }; | 190 | }; |
197 | 191 | ||
198 | #ifdef CONFIG_ACPI_PROCFS | ||
199 | static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); | ||
200 | static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); | ||
201 | static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); | ||
202 | static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); | ||
203 | static ssize_t acpi_thermal_write_cooling_mode(struct file *, | ||
204 | const char __user *, size_t, | ||
205 | loff_t *); | ||
206 | static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); | ||
207 | static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, | ||
208 | size_t, loff_t *); | ||
209 | |||
210 | static const struct file_operations acpi_thermal_state_fops = { | ||
211 | .owner = THIS_MODULE, | ||
212 | .open = acpi_thermal_state_open_fs, | ||
213 | .read = seq_read, | ||
214 | .llseek = seq_lseek, | ||
215 | .release = single_release, | ||
216 | }; | ||
217 | |||
218 | static const struct file_operations acpi_thermal_temp_fops = { | ||
219 | .owner = THIS_MODULE, | ||
220 | .open = acpi_thermal_temp_open_fs, | ||
221 | .read = seq_read, | ||
222 | .llseek = seq_lseek, | ||
223 | .release = single_release, | ||
224 | }; | ||
225 | |||
226 | static const struct file_operations acpi_thermal_trip_fops = { | ||
227 | .owner = THIS_MODULE, | ||
228 | .open = acpi_thermal_trip_open_fs, | ||
229 | .read = seq_read, | ||
230 | .llseek = seq_lseek, | ||
231 | .release = single_release, | ||
232 | }; | ||
233 | |||
234 | static const struct file_operations acpi_thermal_cooling_fops = { | ||
235 | .owner = THIS_MODULE, | ||
236 | .open = acpi_thermal_cooling_open_fs, | ||
237 | .read = seq_read, | ||
238 | .write = acpi_thermal_write_cooling_mode, | ||
239 | .llseek = seq_lseek, | ||
240 | .release = single_release, | ||
241 | }; | ||
242 | |||
243 | static const struct file_operations acpi_thermal_polling_fops = { | ||
244 | .owner = THIS_MODULE, | ||
245 | .open = acpi_thermal_polling_open_fs, | ||
246 | .read = seq_read, | ||
247 | .write = acpi_thermal_write_polling, | ||
248 | .llseek = seq_lseek, | ||
249 | .release = single_release, | ||
250 | }; | ||
251 | #endif /* CONFIG_ACPI_PROCFS*/ | ||
252 | |||
253 | /* -------------------------------------------------------------------------- | 192 | /* -------------------------------------------------------------------------- |
254 | Thermal Zone Management | 193 | Thermal Zone Management |
255 | -------------------------------------------------------------------------- */ | 194 | -------------------------------------------------------------------------- */ |
@@ -958,358 +897,6 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) | |||
958 | 897 | ||
959 | 898 | ||
960 | /* -------------------------------------------------------------------------- | 899 | /* -------------------------------------------------------------------------- |
961 | FS Interface (/proc) | ||
962 | -------------------------------------------------------------------------- */ | ||
963 | #ifdef CONFIG_ACPI_PROCFS | ||
964 | static struct proc_dir_entry *acpi_thermal_dir; | ||
965 | |||
966 | static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) | ||
967 | { | ||
968 | struct acpi_thermal *tz = seq->private; | ||
969 | |||
970 | |||
971 | if (!tz) | ||
972 | goto end; | ||
973 | |||
974 | seq_puts(seq, "state: "); | ||
975 | |||
976 | if (!tz->state.critical && !tz->state.hot && !tz->state.passive | ||
977 | && !tz->state.active) | ||
978 | seq_puts(seq, "ok\n"); | ||
979 | else { | ||
980 | if (tz->state.critical) | ||
981 | seq_puts(seq, "critical "); | ||
982 | if (tz->state.hot) | ||
983 | seq_puts(seq, "hot "); | ||
984 | if (tz->state.passive) | ||
985 | seq_puts(seq, "passive "); | ||
986 | if (tz->state.active) | ||
987 | seq_printf(seq, "active[%d]", tz->state.active_index); | ||
988 | seq_puts(seq, "\n"); | ||
989 | } | ||
990 | |||
991 | end: | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file) | ||
996 | { | ||
997 | return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data); | ||
998 | } | ||
999 | |||
1000 | static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset) | ||
1001 | { | ||
1002 | int result = 0; | ||
1003 | struct acpi_thermal *tz = seq->private; | ||
1004 | |||
1005 | |||
1006 | if (!tz) | ||
1007 | goto end; | ||
1008 | |||
1009 | result = acpi_thermal_get_temperature(tz); | ||
1010 | if (result) | ||
1011 | goto end; | ||
1012 | |||
1013 | seq_printf(seq, "temperature: %ld C\n", | ||
1014 | KELVIN_TO_CELSIUS(tz->temperature)); | ||
1015 | |||
1016 | end: | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file) | ||
1021 | { | ||
1022 | return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data); | ||
1023 | } | ||
1024 | |||
1025 | static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) | ||
1026 | { | ||
1027 | struct acpi_thermal *tz = seq->private; | ||
1028 | struct acpi_device *device; | ||
1029 | acpi_status status; | ||
1030 | |||
1031 | int i = 0; | ||
1032 | int j = 0; | ||
1033 | |||
1034 | |||
1035 | if (!tz) | ||
1036 | goto end; | ||
1037 | |||
1038 | if (tz->trips.critical.flags.valid) | ||
1039 | seq_printf(seq, "critical (S5): %ld C%s", | ||
1040 | KELVIN_TO_CELSIUS(tz->trips.critical.temperature), | ||
1041 | nocrt ? " <disabled>\n" : "\n"); | ||
1042 | |||
1043 | if (tz->trips.hot.flags.valid) | ||
1044 | seq_printf(seq, "hot (S4): %ld C%s", | ||
1045 | KELVIN_TO_CELSIUS(tz->trips.hot.temperature), | ||
1046 | nocrt ? " <disabled>\n" : "\n"); | ||
1047 | |||
1048 | if (tz->trips.passive.flags.valid) { | ||
1049 | seq_printf(seq, | ||
1050 | "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", | ||
1051 | KELVIN_TO_CELSIUS(tz->trips.passive.temperature), | ||
1052 | tz->trips.passive.tc1, tz->trips.passive.tc2, | ||
1053 | tz->trips.passive.tsp); | ||
1054 | for (j = 0; j < tz->trips.passive.devices.count; j++) { | ||
1055 | status = acpi_bus_get_device(tz->trips.passive.devices. | ||
1056 | handles[j], &device); | ||
1057 | seq_printf(seq, "%4.4s ", status ? "" : | ||
1058 | acpi_device_bid(device)); | ||
1059 | } | ||
1060 | seq_puts(seq, "\n"); | ||
1061 | } else { | ||
1062 | seq_printf(seq, "passive (forced):"); | ||
1063 | if (tz->thermal_zone->forced_passive) | ||
1064 | seq_printf(seq, " %i C\n", | ||
1065 | tz->thermal_zone->forced_passive / 1000); | ||
1066 | else | ||
1067 | seq_printf(seq, "<not set>\n"); | ||
1068 | } | ||
1069 | |||
1070 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { | ||
1071 | if (!(tz->trips.active[i].flags.valid)) | ||
1072 | break; | ||
1073 | seq_printf(seq, "active[%d]: %ld C: devices=", | ||
1074 | i, | ||
1075 | KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); | ||
1076 | for (j = 0; j < tz->trips.active[i].devices.count; j++){ | ||
1077 | status = acpi_bus_get_device(tz->trips.active[i]. | ||
1078 | devices.handles[j], | ||
1079 | &device); | ||
1080 | seq_printf(seq, "%4.4s ", status ? "" : | ||
1081 | acpi_device_bid(device)); | ||
1082 | } | ||
1083 | seq_puts(seq, "\n"); | ||
1084 | } | ||
1085 | |||
1086 | end: | ||
1087 | return 0; | ||
1088 | } | ||
1089 | |||
1090 | static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) | ||
1091 | { | ||
1092 | return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); | ||
1093 | } | ||
1094 | |||
1095 | static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) | ||
1096 | { | ||
1097 | struct acpi_thermal *tz = seq->private; | ||
1098 | |||
1099 | |||
1100 | if (!tz) | ||
1101 | goto end; | ||
1102 | |||
1103 | if (!tz->flags.cooling_mode) | ||
1104 | seq_puts(seq, "<setting not supported>\n"); | ||
1105 | else | ||
1106 | seq_puts(seq, "0 - Active; 1 - Passive\n"); | ||
1107 | |||
1108 | end: | ||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1112 | static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file) | ||
1113 | { | ||
1114 | return single_open(file, acpi_thermal_cooling_seq_show, | ||
1115 | PDE(inode)->data); | ||
1116 | } | ||
1117 | |||
1118 | static ssize_t | ||
1119 | acpi_thermal_write_cooling_mode(struct file *file, | ||
1120 | const char __user * buffer, | ||
1121 | size_t count, loff_t * ppos) | ||
1122 | { | ||
1123 | struct seq_file *m = file->private_data; | ||
1124 | struct acpi_thermal *tz = m->private; | ||
1125 | int result = 0; | ||
1126 | char mode_string[12] = { '\0' }; | ||
1127 | |||
1128 | |||
1129 | if (!tz || (count > sizeof(mode_string) - 1)) | ||
1130 | return -EINVAL; | ||
1131 | |||
1132 | if (!tz->flags.cooling_mode) | ||
1133 | return -ENODEV; | ||
1134 | |||
1135 | if (copy_from_user(mode_string, buffer, count)) | ||
1136 | return -EFAULT; | ||
1137 | |||
1138 | mode_string[count] = '\0'; | ||
1139 | |||
1140 | result = acpi_thermal_set_cooling_mode(tz, | ||
1141 | simple_strtoul(mode_string, NULL, | ||
1142 | 0)); | ||
1143 | if (result) | ||
1144 | return result; | ||
1145 | |||
1146 | acpi_thermal_check(tz); | ||
1147 | |||
1148 | return count; | ||
1149 | } | ||
1150 | |||
1151 | static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) | ||
1152 | { | ||
1153 | struct acpi_thermal *tz = seq->private; | ||
1154 | |||
1155 | |||
1156 | if (!tz) | ||
1157 | goto end; | ||
1158 | |||
1159 | if (!tz->thermal_zone->polling_delay) { | ||
1160 | seq_puts(seq, "<polling disabled>\n"); | ||
1161 | goto end; | ||
1162 | } | ||
1163 | |||
1164 | seq_printf(seq, "polling frequency: %d seconds\n", | ||
1165 | (tz->thermal_zone->polling_delay / 1000)); | ||
1166 | |||
1167 | end: | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1171 | static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) | ||
1172 | { | ||
1173 | return single_open(file, acpi_thermal_polling_seq_show, | ||
1174 | PDE(inode)->data); | ||
1175 | } | ||
1176 | |||
1177 | static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) | ||
1178 | { | ||
1179 | if (!tz) | ||
1180 | return -EINVAL; | ||
1181 | |||
1182 | /* Convert value to deci-seconds */ | ||
1183 | tz->polling_frequency = seconds * 10; | ||
1184 | |||
1185 | tz->thermal_zone->polling_delay = seconds * 1000; | ||
1186 | |||
1187 | if (tz->tz_enabled) | ||
1188 | thermal_zone_device_update(tz->thermal_zone); | ||
1189 | |||
1190 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
1191 | "Polling frequency set to %lu seconds\n", | ||
1192 | tz->polling_frequency/10)); | ||
1193 | |||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | static ssize_t | ||
1198 | acpi_thermal_write_polling(struct file *file, | ||
1199 | const char __user * buffer, | ||
1200 | size_t count, loff_t * ppos) | ||
1201 | { | ||
1202 | struct seq_file *m = file->private_data; | ||
1203 | struct acpi_thermal *tz = m->private; | ||
1204 | int result = 0; | ||
1205 | char polling_string[12] = { '\0' }; | ||
1206 | int seconds = 0; | ||
1207 | |||
1208 | |||
1209 | if (!tz || (count > sizeof(polling_string) - 1)) | ||
1210 | return -EINVAL; | ||
1211 | |||
1212 | if (copy_from_user(polling_string, buffer, count)) | ||
1213 | return -EFAULT; | ||
1214 | |||
1215 | polling_string[count] = '\0'; | ||
1216 | |||
1217 | seconds = simple_strtoul(polling_string, NULL, 0); | ||
1218 | |||
1219 | result = acpi_thermal_set_polling(tz, seconds); | ||
1220 | if (result) | ||
1221 | return result; | ||
1222 | |||
1223 | acpi_thermal_check(tz); | ||
1224 | |||
1225 | return count; | ||
1226 | } | ||
1227 | |||
1228 | static int acpi_thermal_add_fs(struct acpi_device *device) | ||
1229 | { | ||
1230 | struct proc_dir_entry *entry = NULL; | ||
1231 | |||
1232 | |||
1233 | if (!acpi_device_dir(device)) { | ||
1234 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | ||
1235 | acpi_thermal_dir); | ||
1236 | if (!acpi_device_dir(device)) | ||
1237 | return -ENODEV; | ||
1238 | } | ||
1239 | |||
1240 | /* 'state' [R] */ | ||
1241 | entry = proc_create_data(ACPI_THERMAL_FILE_STATE, | ||
1242 | S_IRUGO, acpi_device_dir(device), | ||
1243 | &acpi_thermal_state_fops, | ||
1244 | acpi_driver_data(device)); | ||
1245 | if (!entry) | ||
1246 | return -ENODEV; | ||
1247 | |||
1248 | /* 'temperature' [R] */ | ||
1249 | entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE, | ||
1250 | S_IRUGO, acpi_device_dir(device), | ||
1251 | &acpi_thermal_temp_fops, | ||
1252 | acpi_driver_data(device)); | ||
1253 | if (!entry) | ||
1254 | return -ENODEV; | ||
1255 | |||
1256 | /* 'trip_points' [R] */ | ||
1257 | entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS, | ||
1258 | S_IRUGO, | ||
1259 | acpi_device_dir(device), | ||
1260 | &acpi_thermal_trip_fops, | ||
1261 | acpi_driver_data(device)); | ||
1262 | if (!entry) | ||
1263 | return -ENODEV; | ||
1264 | |||
1265 | /* 'cooling_mode' [R/W] */ | ||
1266 | entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE, | ||
1267 | S_IFREG | S_IRUGO | S_IWUSR, | ||
1268 | acpi_device_dir(device), | ||
1269 | &acpi_thermal_cooling_fops, | ||
1270 | acpi_driver_data(device)); | ||
1271 | if (!entry) | ||
1272 | return -ENODEV; | ||
1273 | |||
1274 | /* 'polling_frequency' [R/W] */ | ||
1275 | entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ, | ||
1276 | S_IFREG | S_IRUGO | S_IWUSR, | ||
1277 | acpi_device_dir(device), | ||
1278 | &acpi_thermal_polling_fops, | ||
1279 | acpi_driver_data(device)); | ||
1280 | if (!entry) | ||
1281 | return -ENODEV; | ||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1285 | static int acpi_thermal_remove_fs(struct acpi_device *device) | ||
1286 | { | ||
1287 | |||
1288 | if (acpi_device_dir(device)) { | ||
1289 | remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, | ||
1290 | acpi_device_dir(device)); | ||
1291 | remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, | ||
1292 | acpi_device_dir(device)); | ||
1293 | remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, | ||
1294 | acpi_device_dir(device)); | ||
1295 | remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, | ||
1296 | acpi_device_dir(device)); | ||
1297 | remove_proc_entry(ACPI_THERMAL_FILE_STATE, | ||
1298 | acpi_device_dir(device)); | ||
1299 | remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); | ||
1300 | acpi_device_dir(device) = NULL; | ||
1301 | } | ||
1302 | |||
1303 | return 0; | ||
1304 | } | ||
1305 | #else | ||
1306 | static inline int acpi_thermal_add_fs(struct acpi_device *device) { return 0; } | ||
1307 | static inline int acpi_thermal_remove_fs(struct acpi_device *device) | ||
1308 | { | ||
1309 | return 0; | ||
1310 | } | ||
1311 | #endif /* CONFIG_ACPI_PROCFS */ | ||
1312 | /* -------------------------------------------------------------------------- | ||
1313 | Driver Interface | 900 | Driver Interface |
1314 | -------------------------------------------------------------------------- */ | 901 | -------------------------------------------------------------------------- */ |
1315 | 902 | ||
@@ -1428,17 +1015,11 @@ static int acpi_thermal_add(struct acpi_device *device) | |||
1428 | if (result) | 1015 | if (result) |
1429 | goto free_memory; | 1016 | goto free_memory; |
1430 | 1017 | ||
1431 | result = acpi_thermal_add_fs(device); | ||
1432 | if (result) | ||
1433 | goto unregister_thermal_zone; | ||
1434 | |||
1435 | printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", | 1018 | printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", |
1436 | acpi_device_name(device), acpi_device_bid(device), | 1019 | acpi_device_name(device), acpi_device_bid(device), |
1437 | KELVIN_TO_CELSIUS(tz->temperature)); | 1020 | KELVIN_TO_CELSIUS(tz->temperature)); |
1438 | goto end; | 1021 | goto end; |
1439 | 1022 | ||
1440 | unregister_thermal_zone: | ||
1441 | thermal_zone_device_unregister(tz->thermal_zone); | ||
1442 | free_memory: | 1023 | free_memory: |
1443 | kfree(tz); | 1024 | kfree(tz); |
1444 | end: | 1025 | end: |
@@ -1454,7 +1035,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) | |||
1454 | 1035 | ||
1455 | tz = acpi_driver_data(device); | 1036 | tz = acpi_driver_data(device); |
1456 | 1037 | ||
1457 | acpi_thermal_remove_fs(device); | ||
1458 | acpi_thermal_unregister_thermal_zone(tz); | 1038 | acpi_thermal_unregister_thermal_zone(tz); |
1459 | mutex_destroy(&tz->lock); | 1039 | mutex_destroy(&tz->lock); |
1460 | kfree(tz); | 1040 | kfree(tz); |
@@ -1479,8 +1059,9 @@ static int acpi_thermal_resume(struct acpi_device *device) | |||
1479 | break; | 1059 | break; |
1480 | tz->trips.active[i].flags.enabled = 1; | 1060 | tz->trips.active[i].flags.enabled = 1; |
1481 | for (j = 0; j < tz->trips.active[i].devices.count; j++) { | 1061 | for (j = 0; j < tz->trips.active[i].devices.count; j++) { |
1482 | result = acpi_bus_get_power(tz->trips.active[i].devices. | 1062 | result = acpi_bus_update_power( |
1483 | handles[j], &power_state); | 1063 | tz->trips.active[i].devices.handles[j], |
1064 | &power_state); | ||
1484 | if (result || (power_state != ACPI_STATE_D0)) { | 1065 | if (result || (power_state != ACPI_STATE_D0)) { |
1485 | tz->trips.active[i].flags.enabled = 0; | 1066 | tz->trips.active[i].flags.enabled = 0; |
1486 | break; | 1067 | break; |
@@ -1580,19 +1161,9 @@ static int __init acpi_thermal_init(void) | |||
1580 | return -ENODEV; | 1161 | return -ENODEV; |
1581 | } | 1162 | } |
1582 | 1163 | ||
1583 | #ifdef CONFIG_ACPI_PROCFS | ||
1584 | acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); | ||
1585 | if (!acpi_thermal_dir) | ||
1586 | return -ENODEV; | ||
1587 | #endif | ||
1588 | |||
1589 | result = acpi_bus_register_driver(&acpi_thermal_driver); | 1164 | result = acpi_bus_register_driver(&acpi_thermal_driver); |
1590 | if (result < 0) { | 1165 | if (result < 0) |
1591 | #ifdef CONFIG_ACPI_PROCFS | ||
1592 | remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); | ||
1593 | #endif | ||
1594 | return -ENODEV; | 1166 | return -ENODEV; |
1595 | } | ||
1596 | 1167 | ||
1597 | return 0; | 1168 | return 0; |
1598 | } | 1169 | } |
@@ -1602,10 +1173,6 @@ static void __exit acpi_thermal_exit(void) | |||
1602 | 1173 | ||
1603 | acpi_bus_unregister_driver(&acpi_thermal_driver); | 1174 | acpi_bus_unregister_driver(&acpi_thermal_driver); |
1604 | 1175 | ||
1605 | #ifdef CONFIG_ACPI_PROCFS | ||
1606 | remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); | ||
1607 | #endif | ||
1608 | |||
1609 | return; | 1176 | return; |
1610 | } | 1177 | } |
1611 | 1178 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 67dec0c675aa..db39e9e607d8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -30,12 +30,9 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | #include <linux/input.h> | 33 | #include <linux/input.h> |
36 | #include <linux/backlight.h> | 34 | #include <linux/backlight.h> |
37 | #include <linux/thermal.h> | 35 | #include <linux/thermal.h> |
38 | #include <linux/video_output.h> | ||
39 | #include <linux/sort.h> | 36 | #include <linux/sort.h> |
40 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
41 | #include <linux/pci_ids.h> | 38 | #include <linux/pci_ids.h> |
@@ -83,6 +80,13 @@ module_param(brightness_switch_enabled, bool, 0644); | |||
83 | static int allow_duplicates; | 80 | static int allow_duplicates; |
84 | module_param(allow_duplicates, bool, 0644); | 81 | module_param(allow_duplicates, bool, 0644); |
85 | 82 | ||
83 | /* | ||
84 | * Some BIOSes claim they use minimum backlight at boot, | ||
85 | * and this may bring dimming screen after boot | ||
86 | */ | ||
87 | static int use_bios_initial_backlight = 1; | ||
88 | module_param(use_bios_initial_backlight, bool, 0644); | ||
89 | |||
86 | static int register_count = 0; | 90 | static int register_count = 0; |
87 | static int acpi_video_bus_add(struct acpi_device *device); | 91 | static int acpi_video_bus_add(struct acpi_device *device); |
88 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 92 | static int acpi_video_bus_remove(struct acpi_device *device, int type); |
@@ -152,9 +156,6 @@ struct acpi_video_bus { | |||
152 | struct acpi_video_bus_flags flags; | 156 | struct acpi_video_bus_flags flags; |
153 | struct list_head video_device_list; | 157 | struct list_head video_device_list; |
154 | struct mutex device_list_lock; /* protects video_device_list */ | 158 | struct mutex device_list_lock; /* protects video_device_list */ |
155 | #ifdef CONFIG_ACPI_PROCFS | ||
156 | struct proc_dir_entry *dir; | ||
157 | #endif | ||
158 | struct input_dev *input; | 159 | struct input_dev *input; |
159 | char phys[32]; /* for input device */ | 160 | char phys[32]; /* for input device */ |
160 | struct notifier_block pm_nb; | 161 | struct notifier_block pm_nb; |
@@ -177,9 +178,6 @@ struct acpi_video_device_cap { | |||
177 | u8 _BQC:1; /* Get current brightness level */ | 178 | u8 _BQC:1; /* Get current brightness level */ |
178 | u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */ | 179 | u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */ |
179 | u8 _DDC:1; /*Return the EDID for this device */ | 180 | u8 _DDC:1; /*Return the EDID for this device */ |
180 | u8 _DCS:1; /*Return status of output device */ | ||
181 | u8 _DGS:1; /*Query graphics state */ | ||
182 | u8 _DSS:1; /*Device state set */ | ||
183 | }; | 181 | }; |
184 | 182 | ||
185 | struct acpi_video_brightness_flags { | 183 | struct acpi_video_brightness_flags { |
@@ -207,110 +205,7 @@ struct acpi_video_device { | |||
207 | struct acpi_video_device_brightness *brightness; | 205 | struct acpi_video_device_brightness *brightness; |
208 | struct backlight_device *backlight; | 206 | struct backlight_device *backlight; |
209 | struct thermal_cooling_device *cooling_dev; | 207 | struct thermal_cooling_device *cooling_dev; |
210 | struct output_device *output_dev; | ||
211 | }; | ||
212 | |||
213 | #ifdef CONFIG_ACPI_PROCFS | ||
214 | /* bus */ | ||
215 | static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); | ||
216 | static const struct file_operations acpi_video_bus_info_fops = { | ||
217 | .owner = THIS_MODULE, | ||
218 | .open = acpi_video_bus_info_open_fs, | ||
219 | .read = seq_read, | ||
220 | .llseek = seq_lseek, | ||
221 | .release = single_release, | ||
222 | }; | ||
223 | |||
224 | static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file); | ||
225 | static const struct file_operations acpi_video_bus_ROM_fops = { | ||
226 | .owner = THIS_MODULE, | ||
227 | .open = acpi_video_bus_ROM_open_fs, | ||
228 | .read = seq_read, | ||
229 | .llseek = seq_lseek, | ||
230 | .release = single_release, | ||
231 | }; | ||
232 | |||
233 | static int acpi_video_bus_POST_info_open_fs(struct inode *inode, | ||
234 | struct file *file); | ||
235 | static const struct file_operations acpi_video_bus_POST_info_fops = { | ||
236 | .owner = THIS_MODULE, | ||
237 | .open = acpi_video_bus_POST_info_open_fs, | ||
238 | .read = seq_read, | ||
239 | .llseek = seq_lseek, | ||
240 | .release = single_release, | ||
241 | }; | ||
242 | |||
243 | static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); | ||
244 | static ssize_t acpi_video_bus_write_POST(struct file *file, | ||
245 | const char __user *buffer, size_t count, loff_t *data); | ||
246 | static const struct file_operations acpi_video_bus_POST_fops = { | ||
247 | .owner = THIS_MODULE, | ||
248 | .open = acpi_video_bus_POST_open_fs, | ||
249 | .read = seq_read, | ||
250 | .write = acpi_video_bus_write_POST, | ||
251 | .llseek = seq_lseek, | ||
252 | .release = single_release, | ||
253 | }; | ||
254 | |||
255 | static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); | ||
256 | static ssize_t acpi_video_bus_write_DOS(struct file *file, | ||
257 | const char __user *buffer, size_t count, loff_t *data); | ||
258 | static const struct file_operations acpi_video_bus_DOS_fops = { | ||
259 | .owner = THIS_MODULE, | ||
260 | .open = acpi_video_bus_DOS_open_fs, | ||
261 | .read = seq_read, | ||
262 | .write = acpi_video_bus_write_DOS, | ||
263 | .llseek = seq_lseek, | ||
264 | .release = single_release, | ||
265 | }; | ||
266 | |||
267 | /* device */ | ||
268 | static int acpi_video_device_info_open_fs(struct inode *inode, | ||
269 | struct file *file); | ||
270 | static const struct file_operations acpi_video_device_info_fops = { | ||
271 | .owner = THIS_MODULE, | ||
272 | .open = acpi_video_device_info_open_fs, | ||
273 | .read = seq_read, | ||
274 | .llseek = seq_lseek, | ||
275 | .release = single_release, | ||
276 | }; | ||
277 | |||
278 | static int acpi_video_device_state_open_fs(struct inode *inode, | ||
279 | struct file *file); | ||
280 | static ssize_t acpi_video_device_write_state(struct file *file, | ||
281 | const char __user *buffer, size_t count, loff_t *data); | ||
282 | static const struct file_operations acpi_video_device_state_fops = { | ||
283 | .owner = THIS_MODULE, | ||
284 | .open = acpi_video_device_state_open_fs, | ||
285 | .read = seq_read, | ||
286 | .write = acpi_video_device_write_state, | ||
287 | .llseek = seq_lseek, | ||
288 | .release = single_release, | ||
289 | }; | ||
290 | |||
291 | static int acpi_video_device_brightness_open_fs(struct inode *inode, | ||
292 | struct file *file); | ||
293 | static ssize_t acpi_video_device_write_brightness(struct file *file, | ||
294 | const char __user *buffer, size_t count, loff_t *data); | ||
295 | static const struct file_operations acpi_video_device_brightness_fops = { | ||
296 | .owner = THIS_MODULE, | ||
297 | .open = acpi_video_device_brightness_open_fs, | ||
298 | .read = seq_read, | ||
299 | .write = acpi_video_device_write_brightness, | ||
300 | .llseek = seq_lseek, | ||
301 | .release = single_release, | ||
302 | }; | ||
303 | |||
304 | static int acpi_video_device_EDID_open_fs(struct inode *inode, | ||
305 | struct file *file); | ||
306 | static const struct file_operations acpi_video_device_EDID_fops = { | ||
307 | .owner = THIS_MODULE, | ||
308 | .open = acpi_video_device_EDID_open_fs, | ||
309 | .read = seq_read, | ||
310 | .llseek = seq_lseek, | ||
311 | .release = single_release, | ||
312 | }; | 208 | }; |
313 | #endif /* CONFIG_ACPI_PROCFS */ | ||
314 | 209 | ||
315 | static const char device_decode[][30] = { | 210 | static const char device_decode[][30] = { |
316 | "motherboard VGA device", | 211 | "motherboard VGA device", |
@@ -333,10 +228,6 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, | |||
333 | u32 level_current, u32 event); | 228 | u32 level_current, u32 event); |
334 | static int acpi_video_switch_brightness(struct acpi_video_device *device, | 229 | static int acpi_video_switch_brightness(struct acpi_video_device *device, |
335 | int event); | 230 | int event); |
336 | static int acpi_video_device_get_state(struct acpi_video_device *device, | ||
337 | unsigned long long *state); | ||
338 | static int acpi_video_output_get(struct output_device *od); | ||
339 | static int acpi_video_device_set_state(struct acpi_video_device *device, int state); | ||
340 | 231 | ||
341 | /*backlight device sysfs support*/ | 232 | /*backlight device sysfs support*/ |
342 | static int acpi_video_get_brightness(struct backlight_device *bd) | 233 | static int acpi_video_get_brightness(struct backlight_device *bd) |
@@ -367,35 +258,11 @@ static int acpi_video_set_brightness(struct backlight_device *bd) | |||
367 | vd->brightness->levels[request_level]); | 258 | vd->brightness->levels[request_level]); |
368 | } | 259 | } |
369 | 260 | ||
370 | static struct backlight_ops acpi_backlight_ops = { | 261 | static const struct backlight_ops acpi_backlight_ops = { |
371 | .get_brightness = acpi_video_get_brightness, | 262 | .get_brightness = acpi_video_get_brightness, |
372 | .update_status = acpi_video_set_brightness, | 263 | .update_status = acpi_video_set_brightness, |
373 | }; | 264 | }; |
374 | 265 | ||
375 | /*video output device sysfs support*/ | ||
376 | static int acpi_video_output_get(struct output_device *od) | ||
377 | { | ||
378 | unsigned long long state; | ||
379 | struct acpi_video_device *vd = | ||
380 | (struct acpi_video_device *)dev_get_drvdata(&od->dev); | ||
381 | acpi_video_device_get_state(vd, &state); | ||
382 | return (int)state; | ||
383 | } | ||
384 | |||
385 | static int acpi_video_output_set(struct output_device *od) | ||
386 | { | ||
387 | unsigned long state = od->request_state; | ||
388 | struct acpi_video_device *vd= | ||
389 | (struct acpi_video_device *)dev_get_drvdata(&od->dev); | ||
390 | return acpi_video_device_set_state(vd, state); | ||
391 | } | ||
392 | |||
393 | static struct output_properties acpi_output_properties = { | ||
394 | .set_state = acpi_video_output_set, | ||
395 | .get_status = acpi_video_output_get, | ||
396 | }; | ||
397 | |||
398 | |||
399 | /* thermal cooling device callbacks */ | 266 | /* thermal cooling device callbacks */ |
400 | static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned | 267 | static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned |
401 | long *state) | 268 | long *state) |
@@ -451,34 +318,6 @@ static struct thermal_cooling_device_ops video_cooling_ops = { | |||
451 | Video Management | 318 | Video Management |
452 | -------------------------------------------------------------------------- */ | 319 | -------------------------------------------------------------------------- */ |
453 | 320 | ||
454 | /* device */ | ||
455 | |||
456 | static int | ||
457 | acpi_video_device_get_state(struct acpi_video_device *device, | ||
458 | unsigned long long *state) | ||
459 | { | ||
460 | int status; | ||
461 | |||
462 | status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state); | ||
463 | |||
464 | return status; | ||
465 | } | ||
466 | |||
467 | static int | ||
468 | acpi_video_device_set_state(struct acpi_video_device *device, int state) | ||
469 | { | ||
470 | int status; | ||
471 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
472 | struct acpi_object_list args = { 1, &arg0 }; | ||
473 | unsigned long long ret; | ||
474 | |||
475 | |||
476 | arg0.integer.value = state; | ||
477 | status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret); | ||
478 | |||
479 | return status; | ||
480 | } | ||
481 | |||
482 | static int | 321 | static int |
483 | acpi_video_device_lcd_query_levels(struct acpi_video_device *device, | 322 | acpi_video_device_lcd_query_levels(struct acpi_video_device *device, |
484 | union acpi_object **levels) | 323 | union acpi_object **levels) |
@@ -873,9 +712,11 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
873 | * when invoked for the first time, i.e. level_old is invalid. | 712 | * when invoked for the first time, i.e. level_old is invalid. |
874 | * set the backlight to max_level in this case | 713 | * set the backlight to max_level in this case |
875 | */ | 714 | */ |
876 | for (i = 2; i < br->count; i++) | 715 | if (use_bios_initial_backlight) { |
877 | if (level_old == br->levels[i]) | 716 | for (i = 2; i < br->count; i++) |
878 | level = level_old; | 717 | if (level_old == br->levels[i]) |
718 | level = level_old; | ||
719 | } | ||
879 | goto set_level; | 720 | goto set_level; |
880 | } | 721 | } |
881 | 722 | ||
@@ -938,18 +779,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
938 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { | 779 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { |
939 | device->cap._DDC = 1; | 780 | device->cap._DDC = 1; |
940 | } | 781 | } |
941 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) { | ||
942 | device->cap._DCS = 1; | ||
943 | } | ||
944 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) { | ||
945 | device->cap._DGS = 1; | ||
946 | } | ||
947 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) { | ||
948 | device->cap._DSS = 1; | ||
949 | } | ||
950 | 782 | ||
951 | if (acpi_video_backlight_support()) { | 783 | if (acpi_video_backlight_support()) { |
952 | struct backlight_properties props; | 784 | struct backlight_properties props; |
785 | struct pci_dev *pdev; | ||
786 | acpi_handle acpi_parent; | ||
787 | struct device *parent = NULL; | ||
953 | int result; | 788 | int result; |
954 | static int count = 0; | 789 | static int count = 0; |
955 | char *name; | 790 | char *name; |
@@ -962,9 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
962 | return; | 797 | return; |
963 | count++; | 798 | count++; |
964 | 799 | ||
800 | acpi_get_parent(device->dev->handle, &acpi_parent); | ||
801 | |||
802 | pdev = acpi_get_pci_dev(acpi_parent); | ||
803 | if (pdev) { | ||
804 | parent = &pdev->dev; | ||
805 | pci_dev_put(pdev); | ||
806 | } | ||
807 | |||
965 | memset(&props, 0, sizeof(struct backlight_properties)); | 808 | memset(&props, 0, sizeof(struct backlight_properties)); |
809 | props.type = BACKLIGHT_FIRMWARE; | ||
966 | props.max_brightness = device->brightness->count - 3; | 810 | props.max_brightness = device->brightness->count - 3; |
967 | device->backlight = backlight_device_register(name, NULL, device, | 811 | device->backlight = backlight_device_register(name, |
812 | parent, | ||
813 | device, | ||
968 | &acpi_backlight_ops, | 814 | &acpi_backlight_ops, |
969 | &props); | 815 | &props); |
970 | kfree(name); | 816 | kfree(name); |
@@ -978,11 +824,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
978 | device->backlight->props.brightness = | 824 | device->backlight->props.brightness = |
979 | acpi_video_get_brightness(device->backlight); | 825 | acpi_video_get_brightness(device->backlight); |
980 | 826 | ||
981 | result = sysfs_create_link(&device->backlight->dev.kobj, | ||
982 | &device->dev->dev.kobj, "device"); | ||
983 | if (result) | ||
984 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
985 | |||
986 | device->cooling_dev = thermal_cooling_device_register("LCD", | 827 | device->cooling_dev = thermal_cooling_device_register("LCD", |
987 | device->dev, &video_cooling_ops); | 828 | device->dev, &video_cooling_ops); |
988 | if (IS_ERR(device->cooling_dev)) { | 829 | if (IS_ERR(device->cooling_dev)) { |
@@ -1011,21 +852,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
1011 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 852 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
1012 | 853 | ||
1013 | } | 854 | } |
1014 | |||
1015 | if (acpi_video_display_switch_support()) { | ||
1016 | |||
1017 | if (device->cap._DCS && device->cap._DSS) { | ||
1018 | static int count; | ||
1019 | char *name; | ||
1020 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); | ||
1021 | if (!name) | ||
1022 | return; | ||
1023 | count++; | ||
1024 | device->output_dev = video_output_register(name, | ||
1025 | NULL, device, &acpi_output_properties); | ||
1026 | kfree(name); | ||
1027 | } | ||
1028 | } | ||
1029 | } | 855 | } |
1030 | 856 | ||
1031 | /* | 857 | /* |
@@ -1111,646 +937,6 @@ static int acpi_video_bus_check(struct acpi_video_bus *video) | |||
1111 | } | 937 | } |
1112 | 938 | ||
1113 | /* -------------------------------------------------------------------------- | 939 | /* -------------------------------------------------------------------------- |
1114 | FS Interface (/proc) | ||
1115 | -------------------------------------------------------------------------- */ | ||
1116 | #ifdef CONFIG_ACPI_PROCFS | ||
1117 | |||
1118 | static struct proc_dir_entry *acpi_video_dir; | ||
1119 | |||
1120 | /* video devices */ | ||
1121 | |||
1122 | static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) | ||
1123 | { | ||
1124 | struct acpi_video_device *dev = seq->private; | ||
1125 | |||
1126 | |||
1127 | if (!dev) | ||
1128 | goto end; | ||
1129 | |||
1130 | seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id); | ||
1131 | seq_printf(seq, "type: "); | ||
1132 | if (dev->flags.crt) | ||
1133 | seq_printf(seq, "CRT\n"); | ||
1134 | else if (dev->flags.lcd) | ||
1135 | seq_printf(seq, "LCD\n"); | ||
1136 | else if (dev->flags.tvout) | ||
1137 | seq_printf(seq, "TVOUT\n"); | ||
1138 | else if (dev->flags.dvi) | ||
1139 | seq_printf(seq, "DVI\n"); | ||
1140 | else | ||
1141 | seq_printf(seq, "UNKNOWN\n"); | ||
1142 | |||
1143 | seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no"); | ||
1144 | |||
1145 | end: | ||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | static int | ||
1150 | acpi_video_device_info_open_fs(struct inode *inode, struct file *file) | ||
1151 | { | ||
1152 | return single_open(file, acpi_video_device_info_seq_show, | ||
1153 | PDE(inode)->data); | ||
1154 | } | ||
1155 | |||
1156 | static int | ||
1157 | acpi_video_device_query(struct acpi_video_device *device, | ||
1158 | unsigned long long *state) | ||
1159 | { | ||
1160 | int status; | ||
1161 | |||
1162 | status = acpi_evaluate_integer(device->dev->handle, "_DGS", | ||
1163 | NULL, state); | ||
1164 | |||
1165 | return status; | ||
1166 | } | ||
1167 | |||
1168 | static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) | ||
1169 | { | ||
1170 | int status; | ||
1171 | struct acpi_video_device *dev = seq->private; | ||
1172 | unsigned long long state; | ||
1173 | |||
1174 | |||
1175 | if (!dev) | ||
1176 | goto end; | ||
1177 | |||
1178 | status = acpi_video_device_get_state(dev, &state); | ||
1179 | seq_printf(seq, "state: "); | ||
1180 | if (ACPI_SUCCESS(status)) | ||
1181 | seq_printf(seq, "0x%02llx\n", state); | ||
1182 | else | ||
1183 | seq_printf(seq, "<not supported>\n"); | ||
1184 | |||
1185 | status = acpi_video_device_query(dev, &state); | ||
1186 | seq_printf(seq, "query: "); | ||
1187 | if (ACPI_SUCCESS(status)) | ||
1188 | seq_printf(seq, "0x%02llx\n", state); | ||
1189 | else | ||
1190 | seq_printf(seq, "<not supported>\n"); | ||
1191 | |||
1192 | end: | ||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | static int | ||
1197 | acpi_video_device_state_open_fs(struct inode *inode, struct file *file) | ||
1198 | { | ||
1199 | return single_open(file, acpi_video_device_state_seq_show, | ||
1200 | PDE(inode)->data); | ||
1201 | } | ||
1202 | |||
1203 | static ssize_t | ||
1204 | acpi_video_device_write_state(struct file *file, | ||
1205 | const char __user * buffer, | ||
1206 | size_t count, loff_t * data) | ||
1207 | { | ||
1208 | int status; | ||
1209 | struct seq_file *m = file->private_data; | ||
1210 | struct acpi_video_device *dev = m->private; | ||
1211 | char str[12] = { 0 }; | ||
1212 | u32 state = 0; | ||
1213 | |||
1214 | |||
1215 | if (!dev || count >= sizeof(str)) | ||
1216 | return -EINVAL; | ||
1217 | |||
1218 | if (copy_from_user(str, buffer, count)) | ||
1219 | return -EFAULT; | ||
1220 | |||
1221 | str[count] = 0; | ||
1222 | state = simple_strtoul(str, NULL, 0); | ||
1223 | state &= ((1ul << 31) | (1ul << 30) | (1ul << 0)); | ||
1224 | |||
1225 | status = acpi_video_device_set_state(dev, state); | ||
1226 | |||
1227 | if (status) | ||
1228 | return -EFAULT; | ||
1229 | |||
1230 | return count; | ||
1231 | } | ||
1232 | |||
1233 | static int | ||
1234 | acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) | ||
1235 | { | ||
1236 | struct acpi_video_device *dev = seq->private; | ||
1237 | int i; | ||
1238 | |||
1239 | |||
1240 | if (!dev || !dev->brightness) { | ||
1241 | seq_printf(seq, "<not supported>\n"); | ||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | seq_printf(seq, "levels: "); | ||
1246 | for (i = 2; i < dev->brightness->count; i++) | ||
1247 | seq_printf(seq, " %d", dev->brightness->levels[i]); | ||
1248 | seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr); | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | static int | ||
1254 | acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file) | ||
1255 | { | ||
1256 | return single_open(file, acpi_video_device_brightness_seq_show, | ||
1257 | PDE(inode)->data); | ||
1258 | } | ||
1259 | |||
1260 | static ssize_t | ||
1261 | acpi_video_device_write_brightness(struct file *file, | ||
1262 | const char __user * buffer, | ||
1263 | size_t count, loff_t * data) | ||
1264 | { | ||
1265 | struct seq_file *m = file->private_data; | ||
1266 | struct acpi_video_device *dev = m->private; | ||
1267 | char str[5] = { 0 }; | ||
1268 | unsigned int level = 0; | ||
1269 | int i; | ||
1270 | |||
1271 | |||
1272 | if (!dev || !dev->brightness || count >= sizeof(str)) | ||
1273 | return -EINVAL; | ||
1274 | |||
1275 | if (copy_from_user(str, buffer, count)) | ||
1276 | return -EFAULT; | ||
1277 | |||
1278 | str[count] = 0; | ||
1279 | level = simple_strtoul(str, NULL, 0); | ||
1280 | |||
1281 | if (level > 100) | ||
1282 | return -EFAULT; | ||
1283 | |||
1284 | /* validate through the list of available levels */ | ||
1285 | for (i = 2; i < dev->brightness->count; i++) | ||
1286 | if (level == dev->brightness->levels[i]) { | ||
1287 | if (!acpi_video_device_lcd_set_level(dev, level)) | ||
1288 | return count; | ||
1289 | break; | ||
1290 | } | ||
1291 | |||
1292 | return -EINVAL; | ||
1293 | } | ||
1294 | |||
1295 | static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) | ||
1296 | { | ||
1297 | struct acpi_video_device *dev = seq->private; | ||
1298 | int status; | ||
1299 | int i; | ||
1300 | union acpi_object *edid = NULL; | ||
1301 | |||
1302 | |||
1303 | if (!dev) | ||
1304 | goto out; | ||
1305 | |||
1306 | status = acpi_video_device_EDID(dev, &edid, 128); | ||
1307 | if (ACPI_FAILURE(status)) { | ||
1308 | status = acpi_video_device_EDID(dev, &edid, 256); | ||
1309 | } | ||
1310 | |||
1311 | if (ACPI_FAILURE(status)) { | ||
1312 | goto out; | ||
1313 | } | ||
1314 | |||
1315 | if (edid && edid->type == ACPI_TYPE_BUFFER) { | ||
1316 | for (i = 0; i < edid->buffer.length; i++) | ||
1317 | seq_putc(seq, edid->buffer.pointer[i]); | ||
1318 | } | ||
1319 | |||
1320 | out: | ||
1321 | if (!edid) | ||
1322 | seq_printf(seq, "<not supported>\n"); | ||
1323 | else | ||
1324 | kfree(edid); | ||
1325 | |||
1326 | return 0; | ||
1327 | } | ||
1328 | |||
1329 | static int | ||
1330 | acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) | ||
1331 | { | ||
1332 | return single_open(file, acpi_video_device_EDID_seq_show, | ||
1333 | PDE(inode)->data); | ||
1334 | } | ||
1335 | |||
1336 | static int acpi_video_device_add_fs(struct acpi_device *device) | ||
1337 | { | ||
1338 | struct proc_dir_entry *entry, *device_dir; | ||
1339 | struct acpi_video_device *vid_dev; | ||
1340 | |||
1341 | vid_dev = acpi_driver_data(device); | ||
1342 | if (!vid_dev) | ||
1343 | return -ENODEV; | ||
1344 | |||
1345 | device_dir = proc_mkdir(acpi_device_bid(device), | ||
1346 | vid_dev->video->dir); | ||
1347 | if (!device_dir) | ||
1348 | return -ENOMEM; | ||
1349 | |||
1350 | /* 'info' [R] */ | ||
1351 | entry = proc_create_data("info", S_IRUGO, device_dir, | ||
1352 | &acpi_video_device_info_fops, acpi_driver_data(device)); | ||
1353 | if (!entry) | ||
1354 | goto err_remove_dir; | ||
1355 | |||
1356 | /* 'state' [R/W] */ | ||
1357 | entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR, | ||
1358 | device_dir, | ||
1359 | &acpi_video_device_state_fops, | ||
1360 | acpi_driver_data(device)); | ||
1361 | if (!entry) | ||
1362 | goto err_remove_info; | ||
1363 | |||
1364 | /* 'brightness' [R/W] */ | ||
1365 | entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR, | ||
1366 | device_dir, | ||
1367 | &acpi_video_device_brightness_fops, | ||
1368 | acpi_driver_data(device)); | ||
1369 | if (!entry) | ||
1370 | goto err_remove_state; | ||
1371 | |||
1372 | /* 'EDID' [R] */ | ||
1373 | entry = proc_create_data("EDID", S_IRUGO, device_dir, | ||
1374 | &acpi_video_device_EDID_fops, | ||
1375 | acpi_driver_data(device)); | ||
1376 | if (!entry) | ||
1377 | goto err_remove_brightness; | ||
1378 | |||
1379 | acpi_device_dir(device) = device_dir; | ||
1380 | |||
1381 | return 0; | ||
1382 | |||
1383 | err_remove_brightness: | ||
1384 | remove_proc_entry("brightness", device_dir); | ||
1385 | err_remove_state: | ||
1386 | remove_proc_entry("state", device_dir); | ||
1387 | err_remove_info: | ||
1388 | remove_proc_entry("info", device_dir); | ||
1389 | err_remove_dir: | ||
1390 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); | ||
1391 | return -ENOMEM; | ||
1392 | } | ||
1393 | |||
1394 | static int acpi_video_device_remove_fs(struct acpi_device *device) | ||
1395 | { | ||
1396 | struct acpi_video_device *vid_dev; | ||
1397 | struct proc_dir_entry *device_dir; | ||
1398 | |||
1399 | vid_dev = acpi_driver_data(device); | ||
1400 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) | ||
1401 | return -ENODEV; | ||
1402 | |||
1403 | device_dir = acpi_device_dir(device); | ||
1404 | if (device_dir) { | ||
1405 | remove_proc_entry("info", device_dir); | ||
1406 | remove_proc_entry("state", device_dir); | ||
1407 | remove_proc_entry("brightness", device_dir); | ||
1408 | remove_proc_entry("EDID", device_dir); | ||
1409 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); | ||
1410 | acpi_device_dir(device) = NULL; | ||
1411 | } | ||
1412 | |||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1416 | /* video bus */ | ||
1417 | static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset) | ||
1418 | { | ||
1419 | struct acpi_video_bus *video = seq->private; | ||
1420 | |||
1421 | |||
1422 | if (!video) | ||
1423 | goto end; | ||
1424 | |||
1425 | seq_printf(seq, "Switching heads: %s\n", | ||
1426 | video->flags.multihead ? "yes" : "no"); | ||
1427 | seq_printf(seq, "Video ROM: %s\n", | ||
1428 | video->flags.rom ? "yes" : "no"); | ||
1429 | seq_printf(seq, "Device to be POSTed on boot: %s\n", | ||
1430 | video->flags.post ? "yes" : "no"); | ||
1431 | |||
1432 | end: | ||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file) | ||
1437 | { | ||
1438 | return single_open(file, acpi_video_bus_info_seq_show, | ||
1439 | PDE(inode)->data); | ||
1440 | } | ||
1441 | |||
1442 | static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) | ||
1443 | { | ||
1444 | struct acpi_video_bus *video = seq->private; | ||
1445 | |||
1446 | |||
1447 | if (!video) | ||
1448 | goto end; | ||
1449 | |||
1450 | printk(KERN_INFO PREFIX "Please implement %s\n", __func__); | ||
1451 | seq_printf(seq, "<TODO>\n"); | ||
1452 | |||
1453 | end: | ||
1454 | return 0; | ||
1455 | } | ||
1456 | |||
1457 | static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) | ||
1458 | { | ||
1459 | return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data); | ||
1460 | } | ||
1461 | |||
1462 | static int | ||
1463 | acpi_video_bus_POST_options(struct acpi_video_bus *video, | ||
1464 | unsigned long long *options) | ||
1465 | { | ||
1466 | int status; | ||
1467 | |||
1468 | status = acpi_evaluate_integer(video->device->handle, "_VPO", | ||
1469 | NULL, options); | ||
1470 | *options &= 3; | ||
1471 | |||
1472 | return status; | ||
1473 | } | ||
1474 | |||
1475 | static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) | ||
1476 | { | ||
1477 | struct acpi_video_bus *video = seq->private; | ||
1478 | unsigned long long options; | ||
1479 | int status; | ||
1480 | |||
1481 | |||
1482 | if (!video) | ||
1483 | goto end; | ||
1484 | |||
1485 | status = acpi_video_bus_POST_options(video, &options); | ||
1486 | if (ACPI_SUCCESS(status)) { | ||
1487 | if (!(options & 1)) { | ||
1488 | printk(KERN_WARNING PREFIX | ||
1489 | "The motherboard VGA device is not listed as a possible POST device.\n"); | ||
1490 | printk(KERN_WARNING PREFIX | ||
1491 | "This indicates a BIOS bug. Please contact the manufacturer.\n"); | ||
1492 | } | ||
1493 | printk(KERN_WARNING "%llx\n", options); | ||
1494 | seq_printf(seq, "can POST: <integrated video>"); | ||
1495 | if (options & 2) | ||
1496 | seq_printf(seq, " <PCI video>"); | ||
1497 | if (options & 4) | ||
1498 | seq_printf(seq, " <AGP video>"); | ||
1499 | seq_putc(seq, '\n'); | ||
1500 | } else | ||
1501 | seq_printf(seq, "<not supported>\n"); | ||
1502 | end: | ||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1506 | static int | ||
1507 | acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file) | ||
1508 | { | ||
1509 | return single_open(file, acpi_video_bus_POST_info_seq_show, | ||
1510 | PDE(inode)->data); | ||
1511 | } | ||
1512 | |||
1513 | static int | ||
1514 | acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) | ||
1515 | { | ||
1516 | int status; | ||
1517 | |||
1518 | status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id); | ||
1519 | |||
1520 | return status; | ||
1521 | } | ||
1522 | |||
1523 | static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) | ||
1524 | { | ||
1525 | struct acpi_video_bus *video = seq->private; | ||
1526 | int status; | ||
1527 | unsigned long long id; | ||
1528 | |||
1529 | |||
1530 | if (!video) | ||
1531 | goto end; | ||
1532 | |||
1533 | status = acpi_video_bus_get_POST(video, &id); | ||
1534 | if (!ACPI_SUCCESS(status)) { | ||
1535 | seq_printf(seq, "<not supported>\n"); | ||
1536 | goto end; | ||
1537 | } | ||
1538 | seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]); | ||
1539 | |||
1540 | end: | ||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1544 | static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset) | ||
1545 | { | ||
1546 | struct acpi_video_bus *video = seq->private; | ||
1547 | |||
1548 | |||
1549 | seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting); | ||
1550 | |||
1551 | return 0; | ||
1552 | } | ||
1553 | |||
1554 | static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file) | ||
1555 | { | ||
1556 | return single_open(file, acpi_video_bus_POST_seq_show, | ||
1557 | PDE(inode)->data); | ||
1558 | } | ||
1559 | |||
1560 | static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file) | ||
1561 | { | ||
1562 | return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data); | ||
1563 | } | ||
1564 | |||
1565 | static int | ||
1566 | acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) | ||
1567 | { | ||
1568 | int status; | ||
1569 | unsigned long long tmp; | ||
1570 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
1571 | struct acpi_object_list args = { 1, &arg0 }; | ||
1572 | |||
1573 | |||
1574 | arg0.integer.value = option; | ||
1575 | |||
1576 | status = acpi_evaluate_integer(video->device->handle, "_SPD", | ||
1577 | &args, &tmp); | ||
1578 | if (ACPI_SUCCESS(status)) | ||
1579 | status = tmp ? (-EINVAL) : (AE_OK); | ||
1580 | |||
1581 | return status; | ||
1582 | } | ||
1583 | |||
1584 | static ssize_t | ||
1585 | acpi_video_bus_write_POST(struct file *file, | ||
1586 | const char __user * buffer, | ||
1587 | size_t count, loff_t * data) | ||
1588 | { | ||
1589 | int status; | ||
1590 | struct seq_file *m = file->private_data; | ||
1591 | struct acpi_video_bus *video = m->private; | ||
1592 | char str[12] = { 0 }; | ||
1593 | unsigned long long opt, options; | ||
1594 | |||
1595 | |||
1596 | if (!video || count >= sizeof(str)) | ||
1597 | return -EINVAL; | ||
1598 | |||
1599 | status = acpi_video_bus_POST_options(video, &options); | ||
1600 | if (!ACPI_SUCCESS(status)) | ||
1601 | return -EINVAL; | ||
1602 | |||
1603 | if (copy_from_user(str, buffer, count)) | ||
1604 | return -EFAULT; | ||
1605 | |||
1606 | str[count] = 0; | ||
1607 | opt = strtoul(str, NULL, 0); | ||
1608 | if (opt > 3) | ||
1609 | return -EFAULT; | ||
1610 | |||
1611 | /* just in case an OEM 'forgot' the motherboard... */ | ||
1612 | options |= 1; | ||
1613 | |||
1614 | if (options & (1ul << opt)) { | ||
1615 | status = acpi_video_bus_set_POST(video, opt); | ||
1616 | if (!ACPI_SUCCESS(status)) | ||
1617 | return -EFAULT; | ||
1618 | |||
1619 | } | ||
1620 | |||
1621 | return count; | ||
1622 | } | ||
1623 | |||
1624 | static ssize_t | ||
1625 | acpi_video_bus_write_DOS(struct file *file, | ||
1626 | const char __user * buffer, | ||
1627 | size_t count, loff_t * data) | ||
1628 | { | ||
1629 | int status; | ||
1630 | struct seq_file *m = file->private_data; | ||
1631 | struct acpi_video_bus *video = m->private; | ||
1632 | char str[12] = { 0 }; | ||
1633 | unsigned long opt; | ||
1634 | |||
1635 | |||
1636 | if (!video || count >= sizeof(str)) | ||
1637 | return -EINVAL; | ||
1638 | |||
1639 | if (copy_from_user(str, buffer, count)) | ||
1640 | return -EFAULT; | ||
1641 | |||
1642 | str[count] = 0; | ||
1643 | opt = strtoul(str, NULL, 0); | ||
1644 | if (opt > 7) | ||
1645 | return -EFAULT; | ||
1646 | |||
1647 | status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2); | ||
1648 | |||
1649 | if (!ACPI_SUCCESS(status)) | ||
1650 | return -EFAULT; | ||
1651 | |||
1652 | return count; | ||
1653 | } | ||
1654 | |||
1655 | static int acpi_video_bus_add_fs(struct acpi_device *device) | ||
1656 | { | ||
1657 | struct acpi_video_bus *video = acpi_driver_data(device); | ||
1658 | struct proc_dir_entry *device_dir; | ||
1659 | struct proc_dir_entry *entry; | ||
1660 | |||
1661 | device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); | ||
1662 | if (!device_dir) | ||
1663 | return -ENOMEM; | ||
1664 | |||
1665 | /* 'info' [R] */ | ||
1666 | entry = proc_create_data("info", S_IRUGO, device_dir, | ||
1667 | &acpi_video_bus_info_fops, | ||
1668 | acpi_driver_data(device)); | ||
1669 | if (!entry) | ||
1670 | goto err_remove_dir; | ||
1671 | |||
1672 | /* 'ROM' [R] */ | ||
1673 | entry = proc_create_data("ROM", S_IRUGO, device_dir, | ||
1674 | &acpi_video_bus_ROM_fops, | ||
1675 | acpi_driver_data(device)); | ||
1676 | if (!entry) | ||
1677 | goto err_remove_info; | ||
1678 | |||
1679 | /* 'POST_info' [R] */ | ||
1680 | entry = proc_create_data("POST_info", S_IRUGO, device_dir, | ||
1681 | &acpi_video_bus_POST_info_fops, | ||
1682 | acpi_driver_data(device)); | ||
1683 | if (!entry) | ||
1684 | goto err_remove_rom; | ||
1685 | |||
1686 | /* 'POST' [R/W] */ | ||
1687 | entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, | ||
1688 | device_dir, | ||
1689 | &acpi_video_bus_POST_fops, | ||
1690 | acpi_driver_data(device)); | ||
1691 | if (!entry) | ||
1692 | goto err_remove_post_info; | ||
1693 | |||
1694 | /* 'DOS' [R/W] */ | ||
1695 | entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, | ||
1696 | device_dir, | ||
1697 | &acpi_video_bus_DOS_fops, | ||
1698 | acpi_driver_data(device)); | ||
1699 | if (!entry) | ||
1700 | goto err_remove_post; | ||
1701 | |||
1702 | video->dir = acpi_device_dir(device) = device_dir; | ||
1703 | return 0; | ||
1704 | |||
1705 | err_remove_post: | ||
1706 | remove_proc_entry("POST", device_dir); | ||
1707 | err_remove_post_info: | ||
1708 | remove_proc_entry("POST_info", device_dir); | ||
1709 | err_remove_rom: | ||
1710 | remove_proc_entry("ROM", device_dir); | ||
1711 | err_remove_info: | ||
1712 | remove_proc_entry("info", device_dir); | ||
1713 | err_remove_dir: | ||
1714 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); | ||
1715 | return -ENOMEM; | ||
1716 | } | ||
1717 | |||
1718 | static int acpi_video_bus_remove_fs(struct acpi_device *device) | ||
1719 | { | ||
1720 | struct proc_dir_entry *device_dir = acpi_device_dir(device); | ||
1721 | |||
1722 | if (device_dir) { | ||
1723 | remove_proc_entry("info", device_dir); | ||
1724 | remove_proc_entry("ROM", device_dir); | ||
1725 | remove_proc_entry("POST_info", device_dir); | ||
1726 | remove_proc_entry("POST", device_dir); | ||
1727 | remove_proc_entry("DOS", device_dir); | ||
1728 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); | ||
1729 | acpi_device_dir(device) = NULL; | ||
1730 | } | ||
1731 | |||
1732 | return 0; | ||
1733 | } | ||
1734 | #else | ||
1735 | static inline int acpi_video_device_add_fs(struct acpi_device *device) | ||
1736 | { | ||
1737 | return 0; | ||
1738 | } | ||
1739 | static inline int acpi_video_device_remove_fs(struct acpi_device *device) | ||
1740 | { | ||
1741 | return 0; | ||
1742 | } | ||
1743 | static inline int acpi_video_bus_add_fs(struct acpi_device *device) | ||
1744 | { | ||
1745 | return 0; | ||
1746 | } | ||
1747 | static inline int acpi_video_bus_remove_fs(struct acpi_device *device) | ||
1748 | { | ||
1749 | return 0; | ||
1750 | } | ||
1751 | #endif /* CONFIG_ACPI_PROCFS */ | ||
1752 | |||
1753 | /* -------------------------------------------------------------------------- | ||
1754 | Driver Interface | 940 | Driver Interface |
1755 | -------------------------------------------------------------------------- */ | 941 | -------------------------------------------------------------------------- */ |
1756 | 942 | ||
@@ -1877,8 +1063,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1877 | list_add_tail(&data->entry, &video->video_device_list); | 1063 | list_add_tail(&data->entry, &video->video_device_list); |
1878 | mutex_unlock(&video->device_list_lock); | 1064 | mutex_unlock(&video->device_list_lock); |
1879 | 1065 | ||
1880 | acpi_video_device_add_fs(device); | ||
1881 | |||
1882 | return 0; | 1066 | return 0; |
1883 | } | 1067 | } |
1884 | 1068 | ||
@@ -2109,6 +1293,9 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, | |||
2109 | if (!video_device) | 1293 | if (!video_device) |
2110 | continue; | 1294 | continue; |
2111 | 1295 | ||
1296 | if (!video_device->cap._DDC) | ||
1297 | continue; | ||
1298 | |||
2112 | if (type) { | 1299 | if (type) { |
2113 | switch (type) { | 1300 | switch (type) { |
2114 | case ACPI_VIDEO_DISPLAY_CRT: | 1301 | case ACPI_VIDEO_DISPLAY_CRT: |
@@ -2167,7 +1354,7 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
2167 | status = acpi_video_bus_get_one_device(dev, video); | 1354 | status = acpi_video_bus_get_one_device(dev, video); |
2168 | if (ACPI_FAILURE(status)) { | 1355 | if (ACPI_FAILURE(status)) { |
2169 | printk(KERN_WARNING PREFIX | 1356 | printk(KERN_WARNING PREFIX |
2170 | "Cant attach device\n"); | 1357 | "Can't attach device\n"); |
2171 | continue; | 1358 | continue; |
2172 | } | 1359 | } |
2173 | } | 1360 | } |
@@ -2181,17 +1368,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
2181 | if (!device || !device->video) | 1368 | if (!device || !device->video) |
2182 | return -ENOENT; | 1369 | return -ENOENT; |
2183 | 1370 | ||
2184 | acpi_video_device_remove_fs(device->dev); | ||
2185 | |||
2186 | status = acpi_remove_notify_handler(device->dev->handle, | 1371 | status = acpi_remove_notify_handler(device->dev->handle, |
2187 | ACPI_DEVICE_NOTIFY, | 1372 | ACPI_DEVICE_NOTIFY, |
2188 | acpi_video_device_notify); | 1373 | acpi_video_device_notify); |
2189 | if (ACPI_FAILURE(status)) { | 1374 | if (ACPI_FAILURE(status)) { |
2190 | printk(KERN_WARNING PREFIX | 1375 | printk(KERN_WARNING PREFIX |
2191 | "Cant remove video notify handler\n"); | 1376 | "Can't remove video notify handler\n"); |
2192 | } | 1377 | } |
2193 | if (device->backlight) { | 1378 | if (device->backlight) { |
2194 | sysfs_remove_link(&device->backlight->dev.kobj, "device"); | ||
2195 | backlight_device_unregister(device->backlight); | 1379 | backlight_device_unregister(device->backlight); |
2196 | device->backlight = NULL; | 1380 | device->backlight = NULL; |
2197 | } | 1381 | } |
@@ -2203,7 +1387,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
2203 | thermal_cooling_device_unregister(device->cooling_dev); | 1387 | thermal_cooling_device_unregister(device->cooling_dev); |
2204 | device->cooling_dev = NULL; | 1388 | device->cooling_dev = NULL; |
2205 | } | 1389 | } |
2206 | video_output_unregister(device->output_dev); | ||
2207 | 1390 | ||
2208 | return 0; | 1391 | return 0; |
2209 | } | 1392 | } |
@@ -2338,7 +1521,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
2338 | acpi_bus_generate_proc_event(device, event, 0); | 1521 | acpi_bus_generate_proc_event(device, event, 0); |
2339 | keycode = KEY_BRIGHTNESSDOWN; | 1522 | keycode = KEY_BRIGHTNESSDOWN; |
2340 | break; | 1523 | break; |
2341 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ | 1524 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ |
2342 | if (brightness_switch_enabled) | 1525 | if (brightness_switch_enabled) |
2343 | acpi_video_switch_brightness(video_device, event); | 1526 | acpi_video_switch_brightness(video_device, event); |
2344 | acpi_bus_generate_proc_event(device, event, 0); | 1527 | acpi_bus_generate_proc_event(device, event, 0); |
@@ -2466,10 +1649,6 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
2466 | if (error) | 1649 | if (error) |
2467 | goto err_free_video; | 1650 | goto err_free_video; |
2468 | 1651 | ||
2469 | error = acpi_video_bus_add_fs(device); | ||
2470 | if (error) | ||
2471 | goto err_free_video; | ||
2472 | |||
2473 | mutex_init(&video->device_list_lock); | 1652 | mutex_init(&video->device_list_lock); |
2474 | INIT_LIST_HEAD(&video->video_device_list); | 1653 | INIT_LIST_HEAD(&video->video_device_list); |
2475 | 1654 | ||
@@ -2522,7 +1701,6 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
2522 | acpi_video_bus_stop_devices(video); | 1701 | acpi_video_bus_stop_devices(video); |
2523 | acpi_video_bus_put_devices(video); | 1702 | acpi_video_bus_put_devices(video); |
2524 | kfree(video->attached_array); | 1703 | kfree(video->attached_array); |
2525 | acpi_video_bus_remove_fs(device); | ||
2526 | err_free_video: | 1704 | err_free_video: |
2527 | kfree(video); | 1705 | kfree(video); |
2528 | device->driver_data = NULL; | 1706 | device->driver_data = NULL; |
@@ -2544,7 +1722,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
2544 | 1722 | ||
2545 | acpi_video_bus_stop_devices(video); | 1723 | acpi_video_bus_stop_devices(video); |
2546 | acpi_video_bus_put_devices(video); | 1724 | acpi_video_bus_put_devices(video); |
2547 | acpi_video_bus_remove_fs(device); | ||
2548 | 1725 | ||
2549 | input_unregister_device(video->input); | 1726 | input_unregister_device(video->input); |
2550 | kfree(video->attached_array); | 1727 | kfree(video->attached_array); |
@@ -2584,17 +1761,9 @@ int acpi_video_register(void) | |||
2584 | return 0; | 1761 | return 0; |
2585 | } | 1762 | } |
2586 | 1763 | ||
2587 | #ifdef CONFIG_ACPI_PROCFS | ||
2588 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
2589 | if (!acpi_video_dir) | ||
2590 | return -ENODEV; | ||
2591 | #endif | ||
2592 | |||
2593 | result = acpi_bus_register_driver(&acpi_video_bus); | 1764 | result = acpi_bus_register_driver(&acpi_video_bus); |
2594 | if (result < 0) { | 1765 | if (result < 0) |
2595 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
2596 | return -ENODEV; | 1766 | return -ENODEV; |
2597 | } | ||
2598 | 1767 | ||
2599 | /* | 1768 | /* |
2600 | * When the acpi_video_bus is loaded successfully, increase | 1769 | * When the acpi_video_bus is loaded successfully, increase |
@@ -2617,10 +1786,6 @@ void acpi_video_unregister(void) | |||
2617 | } | 1786 | } |
2618 | acpi_bus_unregister_driver(&acpi_video_bus); | 1787 | acpi_bus_unregister_driver(&acpi_video_bus); |
2619 | 1788 | ||
2620 | #ifdef CONFIG_ACPI_PROCFS | ||
2621 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
2622 | #endif | ||
2623 | |||
2624 | register_count = 0; | 1789 | register_count = 0; |
2625 | 1790 | ||
2626 | return; | 1791 | return; |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index b83676126598..5af3479714f6 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -17,15 +17,14 @@ | |||
17 | * capabilities the graphics cards plugged in support. The check for general | 17 | * capabilities the graphics cards plugged in support. The check for general |
18 | * video capabilities will be triggered by the first caller of | 18 | * video capabilities will be triggered by the first caller of |
19 | * acpi_video_get_capabilities(NULL); which will happen when the first | 19 | * acpi_video_get_capabilities(NULL); which will happen when the first |
20 | * backlight (or display output) switching supporting driver calls: | 20 | * backlight switching supporting driver calls: |
21 | * acpi_video_backlight_support(); | 21 | * acpi_video_backlight_support(); |
22 | * | 22 | * |
23 | * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) | 23 | * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) |
24 | * are available, video.ko should be used to handle the device. | 24 | * are available, video.ko should be used to handle the device. |
25 | * | 25 | * |
26 | * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, | 26 | * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, |
27 | * sony_acpi,... can take care about backlight brightness and display output | 27 | * sony_acpi,... can take care about backlight brightness. |
28 | * switching. | ||
29 | * | 28 | * |
30 | * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) | 29 | * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) |
31 | * this file will not be compiled, acpi_video_get_capabilities() and | 30 | * this file will not be compiled, acpi_video_get_capabilities() and |
@@ -161,8 +160,6 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle) | |||
161 | * | 160 | * |
162 | * if (dmi_name_in_vendors("XY")) { | 161 | * if (dmi_name_in_vendors("XY")) { |
163 | * acpi_video_support |= | 162 | * acpi_video_support |= |
164 | * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR; | ||
165 | * acpi_video_support |= | ||
166 | * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; | 163 | * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; |
167 | *} | 164 | *} |
168 | */ | 165 | */ |
@@ -212,33 +209,8 @@ int acpi_video_backlight_support(void) | |||
212 | EXPORT_SYMBOL(acpi_video_backlight_support); | 209 | EXPORT_SYMBOL(acpi_video_backlight_support); |
213 | 210 | ||
214 | /* | 211 | /* |
215 | * Returns true if video.ko can do display output switching. | 212 | * Use acpi_backlight=vendor/video to force that backlight switching |
216 | * This does not work well/at all with binary graphics drivers | 213 | * is processed by vendor specific acpi drivers or video.ko driver. |
217 | * which disable system io ranges and do it on their own. | ||
218 | */ | ||
219 | int acpi_video_display_switch_support(void) | ||
220 | { | ||
221 | if (!acpi_video_caps_checked) | ||
222 | acpi_video_get_capabilities(NULL); | ||
223 | |||
224 | if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR) | ||
225 | return 0; | ||
226 | else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO) | ||
227 | return 1; | ||
228 | |||
229 | if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR) | ||
230 | return 0; | ||
231 | else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO) | ||
232 | return 1; | ||
233 | |||
234 | return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING; | ||
235 | } | ||
236 | EXPORT_SYMBOL(acpi_video_display_switch_support); | ||
237 | |||
238 | /* | ||
239 | * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video | ||
240 | * To force that backlight or display output switching is processed by vendor | ||
241 | * specific acpi drivers or video.ko driver. | ||
242 | */ | 214 | */ |
243 | static int __init acpi_backlight(char *str) | 215 | static int __init acpi_backlight(char *str) |
244 | { | 216 | { |
@@ -255,19 +227,3 @@ static int __init acpi_backlight(char *str) | |||
255 | return 1; | 227 | return 1; |
256 | } | 228 | } |
257 | __setup("acpi_backlight=", acpi_backlight); | 229 | __setup("acpi_backlight=", acpi_backlight); |
258 | |||
259 | static int __init acpi_display_output(char *str) | ||
260 | { | ||
261 | if (str == NULL || *str == '\0') | ||
262 | return 1; | ||
263 | else { | ||
264 | if (!strcmp("vendor", str)) | ||
265 | acpi_video_support |= | ||
266 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR; | ||
267 | if (!strcmp("video", str)) | ||
268 | acpi_video_support |= | ||
269 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; | ||
270 | } | ||
271 | return 1; | ||
272 | } | ||
273 | __setup("acpi_display_output=", acpi_display_output); | ||
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index f62a50c3ed34..7bfbe40bc43b 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c | |||
@@ -37,15 +37,16 @@ void acpi_enable_wakeup_devices(u8 sleep_state) | |||
37 | container_of(node, struct acpi_device, wakeup_list); | 37 | container_of(node, struct acpi_device, wakeup_list); |
38 | 38 | ||
39 | if (!dev->wakeup.flags.valid | 39 | if (!dev->wakeup.flags.valid |
40 | || !(dev->wakeup.state.enabled || dev->wakeup.prepare_count) | 40 | || sleep_state > (u32) dev->wakeup.sleep_state |
41 | || sleep_state > (u32) dev->wakeup.sleep_state) | 41 | || !(device_may_wakeup(&dev->dev) |
42 | || dev->wakeup.prepare_count)) | ||
42 | continue; | 43 | continue; |
43 | 44 | ||
44 | if (dev->wakeup.state.enabled) | 45 | if (device_may_wakeup(&dev->dev)) |
45 | acpi_enable_wakeup_device_power(dev, sleep_state); | 46 | acpi_enable_wakeup_device_power(dev, sleep_state); |
46 | 47 | ||
47 | /* The wake-up power should have been enabled already. */ | 48 | /* The wake-up power should have been enabled already. */ |
48 | acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number, | 49 | acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
49 | ACPI_GPE_ENABLE); | 50 | ACPI_GPE_ENABLE); |
50 | } | 51 | } |
51 | } | 52 | } |
@@ -63,14 +64,15 @@ void acpi_disable_wakeup_devices(u8 sleep_state) | |||
63 | container_of(node, struct acpi_device, wakeup_list); | 64 | container_of(node, struct acpi_device, wakeup_list); |
64 | 65 | ||
65 | if (!dev->wakeup.flags.valid | 66 | if (!dev->wakeup.flags.valid |
66 | || !(dev->wakeup.state.enabled || dev->wakeup.prepare_count) | 67 | || sleep_state > (u32) dev->wakeup.sleep_state |
67 | || (sleep_state > (u32) dev->wakeup.sleep_state)) | 68 | || !(device_may_wakeup(&dev->dev) |
69 | || dev->wakeup.prepare_count)) | ||
68 | continue; | 70 | continue; |
69 | 71 | ||
70 | acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number, | 72 | acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
71 | ACPI_GPE_DISABLE); | 73 | ACPI_GPE_DISABLE); |
72 | 74 | ||
73 | if (dev->wakeup.state.enabled) | 75 | if (device_may_wakeup(&dev->dev)) |
74 | acpi_disable_wakeup_device_power(dev); | 76 | acpi_disable_wakeup_device_power(dev); |
75 | } | 77 | } |
76 | } | 78 | } |
@@ -84,8 +86,12 @@ int __init acpi_wakeup_device_init(void) | |||
84 | struct acpi_device *dev = container_of(node, | 86 | struct acpi_device *dev = container_of(node, |
85 | struct acpi_device, | 87 | struct acpi_device, |
86 | wakeup_list); | 88 | wakeup_list); |
87 | if (dev->wakeup.flags.always_enabled) | 89 | if (device_can_wakeup(&dev->dev)) { |
88 | dev->wakeup.state.enabled = 1; | 90 | /* Button GPEs are supposed to be always enabled. */ |
91 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
92 | dev->wakeup.gpe_number); | ||
93 | device_set_wakeup_enable(&dev->dev, true); | ||
94 | } | ||
89 | } | 95 | } |
90 | mutex_unlock(&acpi_device_lock); | 96 | mutex_unlock(&acpi_device_lock); |
91 | return 0; | 97 | return 0; |