aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig31
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_memhotplug.c13
-rw-r--r--drivers/acpi/blacklist.c10
-rw-r--r--drivers/acpi/bus.c4
-rw-r--r--drivers/acpi/container.c6
-rw-r--r--drivers/acpi/events/evmisc.c33
-rw-r--r--drivers/acpi/events/evregion.c15
-rw-r--r--drivers/acpi/events/evxface.c6
-rw-r--r--drivers/acpi/executer/excreate.c5
-rw-r--r--drivers/acpi/executer/exsystem.c30
-rw-r--r--drivers/acpi/executer/exutils.c104
-rw-r--r--drivers/acpi/hardware/hwsleep.c5
-rw-r--r--drivers/acpi/ibm_acpi.c2761
-rw-r--r--drivers/acpi/namespace/nseval.c11
-rw-r--r--drivers/acpi/namespace/nsinit.c7
-rw-r--r--drivers/acpi/namespace/nsxfeval.c11
-rw-r--r--drivers/acpi/power.c20
-rw-r--r--drivers/acpi/processor_core.c4
-rw-r--r--drivers/acpi/processor_idle.c11
-rw-r--r--drivers/acpi/resources/rscreate.c25
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--drivers/acpi/sleep/proc.c16
-rw-r--r--drivers/acpi/tables.c57
-rw-r--r--drivers/acpi/thermal.c3
-rw-r--r--drivers/acpi/video.c38
26 files changed, 259 insertions, 2972 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 7c49e103cf8f..e905c950fd7b 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -7,6 +7,7 @@ menu "ACPI (Advanced Configuration and Power Interface) Support"
7 depends on !X86_VISWS 7 depends on !X86_VISWS
8 depends on !IA64_HP_SIM 8 depends on !IA64_HP_SIM
9 depends on IA64 || X86 9 depends on IA64 || X86
10 depends on PM
10 11
11config ACPI 12config ACPI
12 bool "ACPI Support" 13 bool "ACPI Support"
@@ -84,8 +85,8 @@ config ACPI_PROCFS
84 depends on ACPI 85 depends on ACPI
85 default y 86 default y
86 ---help--- 87 ---help---
87 Procfs interface for ACPI is made optional for back-compatible. 88 The Procfs interface for ACPI is made optional for backward compatibility.
88 As the same functions are duplicated in sysfs interface 89 As the same functions are duplicated in the sysfs interface
89 and this proc interface will be removed some time later, 90 and this proc interface will be removed some time later,
90 it's marked as deprecated. 91 it's marked as deprecated.
91 ( /proc/acpi/debug_layer && debug_level are deprecated by 92 ( /proc/acpi/debug_layer && debug_level are deprecated by
@@ -217,32 +218,6 @@ config ACPI_ASUS
217 NOTE: This driver is deprecated and will probably be removed soon, 218 NOTE: This driver is deprecated and will probably be removed soon,
218 use asus-laptop instead. 219 use asus-laptop instead.
219 220
220config ACPI_IBM
221 tristate "IBM ThinkPad Laptop Extras"
222 depends on X86
223 select BACKLIGHT_CLASS_DEVICE
224 ---help---
225 This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
226 support for Fn-Fx key combinations, Bluetooth control, video
227 output switching, ThinkLight control, UltraBay eject and more.
228 For more information about this driver see <file:Documentation/ibm-acpi.txt>
229 and <http://ibm-acpi.sf.net/> .
230
231 If you have an IBM ThinkPad laptop, say Y or M here.
232
233config ACPI_IBM_DOCK
234 bool "Legacy Docking Station Support"
235 depends on ACPI_IBM
236 depends on ACPI_DOCK=n
237 default n
238 ---help---
239 Allows the ibm_acpi driver to handle docking station events.
240 This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will
241 allow locking and removing the laptop from the docking station,
242 but will not properly connect PCI devices.
243
244 If you are not sure, say N here.
245
246config ACPI_TOSHIBA 221config ACPI_TOSHIBA
247 tristate "Toshiba Laptop Extras" 222 tristate "Toshiba Laptop Extras"
248 depends on X86 223 depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 9623aac9f450..b6266e79af00 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
56obj-$(CONFIG_ACPI_DEBUG) += debug.o 56obj-$(CONFIG_ACPI_DEBUG) += debug.o
57obj-$(CONFIG_ACPI_NUMA) += numa.o 57obj-$(CONFIG_ACPI_NUMA) += numa.o
58obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o 58obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
59obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
60obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 59obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
61obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o 60obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
62obj-y += cm_sbs.o 61obj-y += cm_sbs.o
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index c26172671fd8..e65628a03085 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -44,11 +44,6 @@ MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
44MODULE_DESCRIPTION("Hotplug Mem Driver"); 44MODULE_DESCRIPTION("Hotplug Mem Driver");
45MODULE_LICENSE("GPL"); 45MODULE_LICENSE("GPL");
46 46
47/* ACPI _STA method values */
48#define ACPI_MEMORY_STA_PRESENT (0x00000001UL)
49#define ACPI_MEMORY_STA_ENABLED (0x00000002UL)
50#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL)
51
52/* Memory Device States */ 47/* Memory Device States */
53#define MEMORY_INVALID_STATE 0 48#define MEMORY_INVALID_STATE 0
54#define MEMORY_POWER_ON_STATE 1 49#define MEMORY_POWER_ON_STATE 1
@@ -204,9 +199,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
204 * Check for device status. Device should be 199 * Check for device status. Device should be
205 * present/enabled/functioning. 200 * present/enabled/functioning.
206 */ 201 */
207 if (!((current_status & ACPI_MEMORY_STA_PRESENT) 202 if (!((current_status & ACPI_STA_DEVICE_PRESENT)
208 && (current_status & ACPI_MEMORY_STA_ENABLED) 203 && (current_status & ACPI_STA_DEVICE_ENABLED)
209 && (current_status & ACPI_MEMORY_STA_FUNCTIONAL))) 204 && (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
210 return -ENODEV; 205 return -ENODEV;
211 206
212 return 0; 207 return 0;
@@ -286,7 +281,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
286 return -ENODEV; 281 return -ENODEV;
287 282
288 /* Check for device status. Device should be disabled */ 283 /* Check for device status. Device should be disabled */
289 if (current_status & ACPI_MEMORY_STA_ENABLED) 284 if (current_status & ACPI_STA_DEVICE_ENABLED)
290 return -EINVAL; 285 return -EINVAL;
291 286
292 return 0; 287 return 0;
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index f289fd41e77d..3ec110ce00c8 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -79,11 +79,17 @@ static int __init blacklist_by_year(void)
79{ 79{
80 int year = dmi_get_year(DMI_BIOS_DATE); 80 int year = dmi_get_year(DMI_BIOS_DATE);
81 /* Doesn't exist? Likely an old system */ 81 /* Doesn't exist? Likely an old system */
82 if (year == -1) 82 if (year == -1) {
83 printk(KERN_ERR PREFIX "no DMI BIOS year, "
84 "acpi=force is required to enable ACPI\n" );
83 return 1; 85 return 1;
86 }
84 /* 0? Likely a buggy new BIOS */ 87 /* 0? Likely a buggy new BIOS */
85 if (year == 0) 88 if (year == 0) {
89 printk(KERN_ERR PREFIX "DMI BIOS year==0, "
90 "assuming ACPI-capable machine\n" );
86 return 0; 91 return 0;
92 }
87 if (year < CONFIG_ACPI_BLACKLIST_YEAR) { 93 if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
88 printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " 94 printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
89 "acpi=force is required to enable ACPI\n", 95 "acpi=force is required to enable ACPI\n",
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index dd49ea0d0ed3..e5084ececb6f 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -103,7 +103,9 @@ int acpi_bus_get_status(struct acpi_device *device)
103 else if (device->parent) 103 else if (device->parent)
104 device->status = device->parent->status; 104 device->status = device->parent->status;
105 else 105 else
106 STRUCT_TO_INT(device->status) = 0x0F; 106 STRUCT_TO_INT(device->status) =
107 ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
108 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
107 109
108 if (device->status.functional && !device->status.present) { 110 if (device->status.functional && !device->status.present) {
109 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " 111 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 0930d9413dfa..0dd3bf7c0ed1 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -49,8 +49,6 @@ MODULE_AUTHOR("Anil S Keshavamurthy");
49MODULE_DESCRIPTION("ACPI container driver"); 49MODULE_DESCRIPTION("ACPI container driver");
50MODULE_LICENSE("GPL"); 50MODULE_LICENSE("GPL");
51 51
52#define ACPI_STA_PRESENT (0x00000001)
53
54static int acpi_container_add(struct acpi_device *device); 52static int acpi_container_add(struct acpi_device *device);
55static int acpi_container_remove(struct acpi_device *device, int type); 53static int acpi_container_remove(struct acpi_device *device, int type);
56 54
@@ -75,13 +73,13 @@ static int is_device_present(acpi_handle handle)
75 73
76 status = acpi_get_handle(handle, "_STA", &temp); 74 status = acpi_get_handle(handle, "_STA", &temp);
77 if (ACPI_FAILURE(status)) 75 if (ACPI_FAILURE(status))
78 return 1; /* _STA not found, assmue device present */ 76 return 1; /* _STA not found, assume device present */
79 77
80 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 78 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
81 if (ACPI_FAILURE(status)) 79 if (ACPI_FAILURE(status))
82 return 0; /* Firmware error */ 80 return 0; /* Firmware error */
83 81
84 return ((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT); 82 return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
85} 83}
86 84
87/*******************************************************************/ 85/*******************************************************************/
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index d572700197f3..cae786ca8600 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -196,11 +196,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
196 notify_info->notify.value = (u16) notify_value; 196 notify_info->notify.value = (u16) notify_value;
197 notify_info->notify.handler_obj = handler_obj; 197 notify_info->notify.handler_obj = handler_obj;
198 198
199 acpi_ex_relinquish_interpreter(); 199 acpi_ex_exit_interpreter();
200 200
201 acpi_ev_notify_dispatch(notify_info); 201 acpi_ev_notify_dispatch(notify_info);
202 202
203 acpi_ex_reacquire_interpreter(); 203 status = acpi_ex_enter_interpreter();
204 if (ACPI_FAILURE(status)) {
205 return_ACPI_STATUS(status);
206 }
207
204 } 208 }
205 209
206 if (!handler_obj) { 210 if (!handler_obj) {
@@ -423,6 +427,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void)
423 * the global lock appear as a standard mutex on the OS side. 427 * the global lock appear as a standard mutex on the OS side.
424 * 428 *
425 *****************************************************************************/ 429 *****************************************************************************/
430static acpi_thread_id acpi_ev_global_lock_thread_id;
431static int acpi_ev_global_lock_acquired;
426 432
427acpi_status acpi_ev_acquire_global_lock(u16 timeout) 433acpi_status acpi_ev_acquire_global_lock(u16 timeout)
428{ 434{
@@ -435,11 +441,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
435 * Only one thread can acquire the GL at a time, the global_lock_mutex 441 * Only one thread can acquire the GL at a time, the global_lock_mutex
436 * enforces this. This interface releases the interpreter if we must wait. 442 * enforces this. This interface releases the interpreter if we must wait.
437 */ 443 */
438 status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); 444 status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
445 if (status == AE_TIME) {
446 if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
447 acpi_ev_global_lock_acquired++;
448 return AE_OK;
449 }
450 }
451
452 if (ACPI_FAILURE(status)) {
453 status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
454 }
439 if (ACPI_FAILURE(status)) { 455 if (ACPI_FAILURE(status)) {
440 return_ACPI_STATUS(status); 456 return_ACPI_STATUS(status);
441 } 457 }
442 458
459 acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
460 acpi_ev_global_lock_acquired++;
461
443 /* 462 /*
444 * Make sure that a global lock actually exists. If not, just treat 463 * Make sure that a global lock actually exists. If not, just treat
445 * the lock as a standard mutex. 464 * the lock as a standard mutex.
@@ -506,6 +525,11 @@ acpi_status acpi_ev_release_global_lock(void)
506 return_ACPI_STATUS(AE_NOT_ACQUIRED); 525 return_ACPI_STATUS(AE_NOT_ACQUIRED);
507 } 526 }
508 527
528 acpi_ev_global_lock_acquired--;
529 if (acpi_ev_global_lock_acquired > 0) {
530 return AE_OK;
531 }
532
509 if (acpi_gbl_global_lock_present) { 533 if (acpi_gbl_global_lock_present) {
510 534
511 /* Allow any thread to release the lock */ 535 /* Allow any thread to release the lock */
@@ -529,7 +553,8 @@ acpi_status acpi_ev_release_global_lock(void)
529 acpi_gbl_global_lock_acquired = FALSE; 553 acpi_gbl_global_lock_acquired = FALSE;
530 554
531 /* Release the local GL mutex */ 555 /* Release the local GL mutex */
532 556 acpi_ev_global_lock_thread_id = NULL;
557 acpi_ev_global_lock_acquired = 0;
533 acpi_os_release_mutex(acpi_gbl_global_lock_mutex); 558 acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
534 return_ACPI_STATUS(status); 559 return_ACPI_STATUS(status);
535} 560}
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index e99f0c435a47..96b0e8431748 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
291 u32 bit_width, acpi_integer * value) 291 u32 bit_width, acpi_integer * value)
292{ 292{
293 acpi_status status; 293 acpi_status status;
294 acpi_status status2;
294 acpi_adr_space_handler handler; 295 acpi_adr_space_handler handler;
295 acpi_adr_space_setup region_setup; 296 acpi_adr_space_setup region_setup;
296 union acpi_operand_object *handler_desc; 297 union acpi_operand_object *handler_desc;
@@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
344 * setup will potentially execute control methods 345 * setup will potentially execute control methods
345 * (e.g., _REG method for this region) 346 * (e.g., _REG method for this region)
346 */ 347 */
347 acpi_ex_relinquish_interpreter(); 348 acpi_ex_exit_interpreter();
348 349
349 status = region_setup(region_obj, ACPI_REGION_ACTIVATE, 350 status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
350 handler_desc->address_space.context, 351 handler_desc->address_space.context,
@@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
352 353
353 /* Re-enter the interpreter */ 354 /* Re-enter the interpreter */
354 355
355 acpi_ex_reacquire_interpreter(); 356 status2 = acpi_ex_enter_interpreter();
357 if (ACPI_FAILURE(status2)) {
358 return_ACPI_STATUS(status2);
359 }
356 360
357 /* Check for failure of the Region Setup */ 361 /* Check for failure of the Region Setup */
358 362
@@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
405 * exit the interpreter because the handler *might* block -- we don't 409 * exit the interpreter because the handler *might* block -- we don't
406 * know what it will do, so we can't hold the lock on the intepreter. 410 * know what it will do, so we can't hold the lock on the intepreter.
407 */ 411 */
408 acpi_ex_relinquish_interpreter(); 412 acpi_ex_exit_interpreter();
409 } 413 }
410 414
411 /* Call the handler */ 415 /* Call the handler */
@@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
426 * We just returned from a non-default handler, we must re-enter the 430 * We just returned from a non-default handler, we must re-enter the
427 * interpreter 431 * interpreter
428 */ 432 */
429 acpi_ex_reacquire_interpreter(); 433 status2 = acpi_ex_enter_interpreter();
434 if (ACPI_FAILURE(status2)) {
435 return_ACPI_STATUS(status2);
436 }
430 } 437 }
431 438
432 return_ACPI_STATUS(status); 439 return_ACPI_STATUS(status);
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 685a103a3587..a3379bafa676 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -768,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
768 return (AE_BAD_PARAMETER); 768 return (AE_BAD_PARAMETER);
769 } 769 }
770 770
771 /* Must lock interpreter to prevent race conditions */ 771 status = acpi_ex_enter_interpreter();
772 if (ACPI_FAILURE(status)) {
773 return (status);
774 }
772 775
773 acpi_ex_enter_interpreter();
774 status = acpi_ev_acquire_global_lock(timeout); 776 status = acpi_ev_acquire_global_lock(timeout);
775 acpi_ex_exit_interpreter(); 777 acpi_ex_exit_interpreter();
776 778
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 7c38528a7e83..ae97812681a3 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -583,7 +583,10 @@ acpi_ex_create_method(u8 * aml_start,
583 * Get the sync_level. If method is serialized, a mutex will be 583 * Get the sync_level. If method is serialized, a mutex will be
584 * created for this method when it is parsed. 584 * created for this method when it is parsed.
585 */ 585 */
586 if (method_flags & AML_METHOD_SERIALIZED) { 586 if (acpi_gbl_all_methods_serialized) {
587 obj_desc->method.sync_level = 0;
588 obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
589 } else if (method_flags & AML_METHOD_SERIALIZED) {
587 /* 590 /*
588 * ACPI 1.0: sync_level = 0 591 * ACPI 1.0: sync_level = 0
589 * ACPI 2.0: sync_level = sync_level in method declaration 592 * ACPI 2.0: sync_level = sync_level in method declaration
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index 9460baff3032..b2edf620ba89 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem")
66acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) 66acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
67{ 67{
68 acpi_status status; 68 acpi_status status;
69 acpi_status status2;
69 70
70 ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); 71 ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
71 72
@@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
78 79
79 /* We must wait, so unlock the interpreter */ 80 /* We must wait, so unlock the interpreter */
80 81
81 acpi_ex_relinquish_interpreter(); 82 acpi_ex_exit_interpreter();
82 83
83 status = acpi_os_wait_semaphore(semaphore, 1, timeout); 84 status = acpi_os_wait_semaphore(semaphore, 1, timeout);
84 85
@@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
88 89
89 /* Reacquire the interpreter */ 90 /* Reacquire the interpreter */
90 91
91 acpi_ex_reacquire_interpreter(); 92 status2 = acpi_ex_enter_interpreter();
93 if (ACPI_FAILURE(status2)) {
94
95 /* Report fatal error, could not acquire interpreter */
96
97 return_ACPI_STATUS(status2);
98 }
92 } 99 }
93 100
94 return_ACPI_STATUS(status); 101 return_ACPI_STATUS(status);
@@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
112acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) 119acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
113{ 120{
114 acpi_status status; 121 acpi_status status;
122 acpi_status status2;
115 123
116 ACPI_FUNCTION_TRACE(ex_system_wait_mutex); 124 ACPI_FUNCTION_TRACE(ex_system_wait_mutex);
117 125
@@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
124 132
125 /* We must wait, so unlock the interpreter */ 133 /* We must wait, so unlock the interpreter */
126 134
127 acpi_ex_relinquish_interpreter(); 135 acpi_ex_exit_interpreter();
128 136
129 status = acpi_os_acquire_mutex(mutex, timeout); 137 status = acpi_os_acquire_mutex(mutex, timeout);
130 138
@@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
134 142
135 /* Reacquire the interpreter */ 143 /* Reacquire the interpreter */
136 144
137 acpi_ex_reacquire_interpreter(); 145 status2 = acpi_ex_enter_interpreter();
146 if (ACPI_FAILURE(status2)) {
147
148 /* Report fatal error, could not acquire interpreter */
149
150 return_ACPI_STATUS(status2);
151 }
138 } 152 }
139 153
140 return_ACPI_STATUS(status); 154 return_ACPI_STATUS(status);
@@ -195,18 +209,20 @@ acpi_status acpi_ex_system_do_stall(u32 how_long)
195 209
196acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) 210acpi_status acpi_ex_system_do_suspend(acpi_integer how_long)
197{ 211{
212 acpi_status status;
213
198 ACPI_FUNCTION_ENTRY(); 214 ACPI_FUNCTION_ENTRY();
199 215
200 /* Since this thread will sleep, we must release the interpreter */ 216 /* Since this thread will sleep, we must release the interpreter */
201 217
202 acpi_ex_relinquish_interpreter(); 218 acpi_ex_exit_interpreter();
203 219
204 acpi_os_sleep(how_long); 220 acpi_os_sleep(how_long);
205 221
206 /* And now we must get the interpreter again */ 222 /* And now we must get the interpreter again */
207 223
208 acpi_ex_reacquire_interpreter(); 224 status = acpi_ex_enter_interpreter();
209 return (AE_OK); 225 return (status);
210} 226}
211 227
212/******************************************************************************* 228/*******************************************************************************
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 6b0aeccbb69b..aea461f3a48c 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base);
76 * 76 *
77 * PARAMETERS: None 77 * PARAMETERS: None
78 * 78 *
79 * RETURN: None 79 * RETURN: Status
80 * 80 *
81 * DESCRIPTION: Enter the interpreter execution region. Failure to enter 81 * DESCRIPTION: Enter the interpreter execution region. Failure to enter
82 * the interpreter region is a fatal system error. Used in 82 * the interpreter region is a fatal system error
83 * conjunction with exit_interpreter.
84 * 83 *
85 ******************************************************************************/ 84 ******************************************************************************/
86 85
87void acpi_ex_enter_interpreter(void) 86acpi_status acpi_ex_enter_interpreter(void)
88{ 87{
89 acpi_status status; 88 acpi_status status;
90 89
@@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void)
92 91
93 status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); 92 status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
94 if (ACPI_FAILURE(status)) { 93 if (ACPI_FAILURE(status)) {
95 ACPI_ERROR((AE_INFO, 94 ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
96 "Could not acquire AML Interpreter mutex"));
97 } 95 }
98 96
99 return_VOID; 97 return_ACPI_STATUS(status);
100}
101
102/*******************************************************************************
103 *
104 * FUNCTION: acpi_ex_reacquire_interpreter
105 *
106 * PARAMETERS: None
107 *
108 * RETURN: None
109 *
110 * DESCRIPTION: Reacquire the interpreter execution region from within the
111 * interpreter code. Failure to enter the interpreter region is a
112 * fatal system error. Used in conjuction with
113 * relinquish_interpreter
114 *
115 ******************************************************************************/
116
117void acpi_ex_reacquire_interpreter(void)
118{
119 ACPI_FUNCTION_TRACE(ex_reacquire_interpreter);
120
121 /*
122 * If the global serialized flag is set, do not release the interpreter,
123 * since it was not actually released by acpi_ex_relinquish_interpreter.
124 * This forces the interpreter to be single threaded.
125 */
126 if (!acpi_gbl_all_methods_serialized) {
127 acpi_ex_enter_interpreter();
128 }
129
130 return_VOID;
131} 98}
132 99
133/******************************************************************************* 100/*******************************************************************************
@@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void)
138 * 105 *
139 * RETURN: None 106 * RETURN: None
140 * 107 *
141 * DESCRIPTION: Exit the interpreter execution region. This is the top level 108 * DESCRIPTION: Exit the interpreter execution region
142 * routine used to exit the interpreter when all processing has 109 *
143 * been completed. 110 * Cases where the interpreter is unlocked:
111 * 1) Completion of the execution of a control method
112 * 2) Method blocked on a Sleep() AML opcode
113 * 3) Method blocked on an Acquire() AML opcode
114 * 4) Method blocked on a Wait() AML opcode
115 * 5) Method blocked to acquire the global lock
116 * 6) Method blocked to execute a serialized control method that is
117 * already executing
118 * 7) About to invoke a user-installed opregion handler
144 * 119 *
145 ******************************************************************************/ 120 ******************************************************************************/
146 121
@@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void)
152 127
153 status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); 128 status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
154 if (ACPI_FAILURE(status)) { 129 if (ACPI_FAILURE(status)) {
155 ACPI_ERROR((AE_INFO, 130 ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
156 "Could not release AML Interpreter mutex"));
157 }
158
159 return_VOID;
160}
161
162/*******************************************************************************
163 *
164 * FUNCTION: acpi_ex_relinquish_interpreter
165 *
166 * PARAMETERS: None
167 *
168 * RETURN: None
169 *
170 * DESCRIPTION: Exit the interpreter execution region, from within the
171 * interpreter - before attempting an operation that will possibly
172 * block the running thread.
173 *
174 * Cases where the interpreter is unlocked internally
175 * 1) Method to be blocked on a Sleep() AML opcode
176 * 2) Method to be blocked on an Acquire() AML opcode
177 * 3) Method to be blocked on a Wait() AML opcode
178 * 4) Method to be blocked to acquire the global lock
179 * 5) Method to be blocked waiting to execute a serialized control method
180 * that is currently executing
181 * 6) About to invoke a user-installed opregion handler
182 *
183 ******************************************************************************/
184
185void acpi_ex_relinquish_interpreter(void)
186{
187 ACPI_FUNCTION_TRACE(ex_relinquish_interpreter);
188
189 /*
190 * If the global serialized flag is set, do not release the interpreter.
191 * This forces the interpreter to be single threaded.
192 */
193 if (!acpi_gbl_all_methods_serialized) {
194 acpi_ex_exit_interpreter();
195 } 131 }
196 132
197 return_VOID; 133 return_VOID;
@@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void)
205 * 141 *
206 * RETURN: none 142 * RETURN: none
207 * 143 *
208 * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is 144 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
209 * 32-bit, as determined by the revision of the DSDT. 145 * belongs to a 32-bit ACPI table.
210 * 146 *
211 ******************************************************************************/ 147 ******************************************************************************/
212 148
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 8fa93125fd4c..c84b1faba28c 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -300,6 +300,11 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
300 /* 300 /*
301 * 2) Enable all wakeup GPEs 301 * 2) Enable all wakeup GPEs
302 */ 302 */
303 status = acpi_hw_disable_all_gpes();
304 if (ACPI_FAILURE(status)) {
305 return_ACPI_STATUS(status);
306 }
307
303 acpi_gbl_system_awake_and_running = FALSE; 308 acpi_gbl_system_awake_and_running = FALSE;
304 309
305 status = acpi_hw_enable_all_wakeup_gpes(); 310 status = acpi_hw_enable_all_wakeup_gpes();
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
deleted file mode 100644
index 4cc534e36e81..000000000000
--- a/drivers/acpi/ibm_acpi.c
+++ /dev/null
@@ -1,2761 +0,0 @@
1/*
2 * ibm_acpi.c - IBM ThinkPad ACPI Extras
3 *
4 *
5 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
6 * Copyright (C) 2006 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define IBM_VERSION "0.13"
24
25/*
26 * Changelog:
27 *
28 * 2006-11-22 0.13 new maintainer
29 * changelog now lives in git commit history, and will
30 * not be updated further in-file.
31 *
32 * 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels
33 * 2005-03-17 0.11 support for 600e, 770x
34 * thanks to Jamie Lentin <lentinj@dial.pipex.com>
35 * support for 770e, G41
36 * G40 and G41 don't have a thinklight
37 * temperatures no longer experimental
38 * experimental brightness control
39 * experimental volume control
40 * experimental fan enable/disable
41 * 2005-01-16 0.10 fix module loading on R30, R31
42 * 2005-01-16 0.9 support for 570, R30, R31
43 * ultrabay support on A22p, A3x
44 * limit arg for cmos, led, beep, drop experimental status
45 * more capable led control on A21e, A22p, T20-22, X20
46 * experimental temperatures and fan speed
47 * experimental embedded controller register dump
48 * mark more functions as __init, drop incorrect __exit
49 * use MODULE_VERSION
50 * thanks to Henrik Brix Andersen <brix@gentoo.org>
51 * fix parameter passing on module loading
52 * thanks to Rusty Russell <rusty@rustcorp.com.au>
53 * thanks to Jim Radford <radford@blackbean.org>
54 * 2004-11-08 0.8 fix init error case, don't return from a macro
55 * thanks to Chris Wright <chrisw@osdl.org>
56 * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
57 * fix led control on A21e
58 * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
59 * 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20
60 * proc file format changed
61 * video_switch command
62 * experimental cmos control
63 * experimental led control
64 * experimental acpi sounds
65 * 2004-09-16 0.4 support for module parameters
66 * hotkey mask can be prefixed by 0x
67 * video output switching
68 * video expansion control
69 * ultrabay eject support
70 * removed lcd brightness/on/off control, didn't work
71 * 2004-08-17 0.3 support for R40
72 * lcd off, brightness control
73 * thinklight on/off
74 * 2004-08-14 0.2 support for T series, X20
75 * bluetooth enable/disable
76 * hotkey events disabled by default
77 * removed fan control, currently useless
78 * 2004-08-09 0.1 initial release, support for X series
79 */
80
81#include <linux/kernel.h>
82#include <linux/module.h>
83#include <linux/init.h>
84#include <linux/types.h>
85#include <linux/string.h>
86
87#include <linux/proc_fs.h>
88#include <linux/backlight.h>
89#include <asm/uaccess.h>
90
91#include <linux/dmi.h>
92#include <linux/jiffies.h>
93#include <linux/workqueue.h>
94
95#include <acpi/acpi_drivers.h>
96#include <acpi/acnamesp.h>
97
98#define IBM_NAME "ibm"
99#define IBM_DESC "IBM ThinkPad ACPI Extras"
100#define IBM_FILE "ibm_acpi"
101#define IBM_URL "http://ibm-acpi.sf.net/"
102
103MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
104MODULE_DESCRIPTION(IBM_DESC);
105MODULE_VERSION(IBM_VERSION);
106MODULE_LICENSE("GPL");
107
108#define IBM_DIR IBM_NAME
109
110#define IBM_LOG IBM_FILE ": "
111#define IBM_ERR KERN_ERR IBM_LOG
112#define IBM_NOTICE KERN_NOTICE IBM_LOG
113#define IBM_INFO KERN_INFO IBM_LOG
114#define IBM_DEBUG KERN_DEBUG IBM_LOG
115
116#define IBM_MAX_ACPI_ARGS 3
117
118#define __unused __attribute__ ((unused))
119
120static int experimental;
121module_param(experimental, int, 0);
122
123static acpi_handle root_handle = NULL;
124
125#define IBM_HANDLE(object, parent, paths...) \
126 static acpi_handle object##_handle; \
127 static acpi_handle *object##_parent = &parent##_handle; \
128 static char *object##_path; \
129 static char *object##_paths[] = { paths }
130
131IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
132 "\\_SB.PCI.ISA.EC", /* 570 */
133 "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
134 "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
135 "\\_SB.PCI0.AD4S.EC0", /* i1400, R30 */
136 "\\_SB.PCI0.ICH3.EC0", /* R31 */
137 "\\_SB.PCI0.LPC.EC", /* all others */
138 );
139
140IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
141 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
142 "\\_SB.PCI0.VID0", /* 770e */
143 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
144 "\\_SB.PCI0.AGP.VID", /* all others */
145 ); /* R30, R31 */
146
147IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
148
149IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */
150 "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */
151 "\\CMS", /* R40, R40e */
152 ); /* all others */
153#ifdef CONFIG_ACPI_IBM_DOCK
154IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
155 "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
156 "\\_SB.PCI0.PCI1.DOCK", /* all others */
157 "\\_SB.PCI.ISA.SLCE", /* 570 */
158 ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
159#endif
160IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
161 "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
162 "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
163 "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
164 ); /* A21e, R30, R31 */
165
166IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
167 "_EJ0", /* all others */
168 ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
169
170IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
171 "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
172 ); /* all others */
173
174IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
175 "_EJ0", /* 770x */
176 ); /* all others */
177
178/* don't list other alternatives as we install a notify handler on the 570 */
179IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
180
181IBM_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */
182 "^HKEY", /* R30, R31 */
183 "HKEY", /* all others */
184 ); /* 570 */
185
186IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
187IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */
188
189IBM_HANDLE(led, ec, "SLED", /* 570 */
190 "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
191 "LED", /* all others */
192 ); /* R30, R31 */
193
194IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
195IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */
196IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */
197IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */
198
199IBM_HANDLE(gfan, ec, "GFAN", /* 570 */
200 "\\FSPD", /* 600e/x, 770e, 770x */
201 ); /* all others */
202
203IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
204 "JFNS", /* 770x-JL */
205 ); /* all others */
206
207#define IBM_HKEY_HID "IBM0068"
208#define IBM_PCI_HID "PNP0A03"
209
210enum thermal_access_mode {
211 IBMACPI_THERMAL_NONE = 0, /* No thermal support */
212 IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */
213 IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */
214 IBMACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */
215 IBMACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */
216};
217
218#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
219struct ibm_thermal_sensors_struct {
220 s32 temp[IBMACPI_MAX_THERMAL_SENSORS];
221};
222
223/*
224 * FAN ACCESS MODES
225 *
226 * IBMACPI_FAN_RD_ACPI_GFAN:
227 * ACPI GFAN method: returns fan level
228 *
229 * see IBMACPI_FAN_WR_ACPI_SFAN
230 * EC 0x2f not available if GFAN exists
231 *
232 * IBMACPI_FAN_WR_ACPI_SFAN:
233 * ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
234 *
235 * EC 0x2f might be available *for reading*, but never for writing.
236 *
237 * IBMACPI_FAN_WR_TPEC:
238 * ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported
239 * on almost all ThinkPads
240 *
241 * Fan speed changes of any sort (including those caused by the
242 * disengaged mode) are usually done slowly by the firmware as the
243 * maximum ammount of fan duty cycle change per second seems to be
244 * limited.
245 *
246 * Reading is not available if GFAN exists.
247 * Writing is not available if SFAN exists.
248 *
249 * Bits
250 * 7 automatic mode engaged;
251 * (default operation mode of the ThinkPad)
252 * fan level is ignored in this mode.
253 * 6 disengage mode (takes precedence over bit 7);
254 * not available on all thinkpads. May disable
255 * the tachometer, and speeds up fan to 100% duty-cycle,
256 * which speeds it up far above the standard RPM
257 * levels. It is not impossible that it could cause
258 * hardware damage.
259 * 5-3 unused in some models. Extra bits for fan level
260 * in others, but still useless as all values above
261 * 7 map to the same speed as level 7 in these models.
262 * 2-0 fan level (0..7 usually)
263 * 0x00 = stop
264 * 0x07 = max (set when temperatures critical)
265 * Some ThinkPads may have other levels, see
266 * IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
267 *
268 * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
269 * boot. Apparently the EC does not intialize it, so unless ACPI DSDT
270 * does so, its initial value is meaningless (0x07).
271 *
272 * For firmware bugs, refer to:
273 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
274 *
275 * ----
276 *
277 * ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
278 * Main fan tachometer reading (in RPM)
279 *
280 * This register is present on all ThinkPads with a new-style EC, and
281 * it is known not to be present on the A21m/e, and T22, as there is
282 * something else in offset 0x84 according to the ACPI DSDT. Other
283 * ThinkPads from this same time period (and earlier) probably lack the
284 * tachometer as well.
285 *
286 * Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
287 * was never fixed by IBM to report the EC firmware version string
288 * probably support the tachometer (like the early X models), so
289 * detecting it is quite hard. We need more data to know for sure.
290 *
291 * FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
292 * might result.
293 *
294 * FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this
295 * register is not invalidated in ThinkPads that disable tachometer
296 * readings. Thus, the tachometer readings go stale.
297 *
298 * For firmware bugs, refer to:
299 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
300 *
301 * IBMACPI_FAN_WR_ACPI_FANS:
302 * ThinkPad X31, X40, X41. Not available in the X60.
303 *
304 * FANS ACPI handle: takes three arguments: low speed, medium speed,
305 * high speed. ACPI DSDT seems to map these three speeds to levels
306 * as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
307 * (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
308 *
309 * The speeds are stored on handles
310 * (FANA:FAN9), (FANC:FANB), (FANE:FAND).
311 *
312 * There are three default speed sets, acessible as handles:
313 * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
314 *
315 * ACPI DSDT switches which set is in use depending on various
316 * factors.
317 *
318 * IBMACPI_FAN_WR_TPEC is also available and should be used to
319 * command the fan. The X31/X40/X41 seems to have 8 fan levels,
320 * but the ACPI tables just mention level 7.
321 */
322
323enum fan_status_access_mode {
324 IBMACPI_FAN_NONE = 0, /* No fan status or control */
325 IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */
326 IBMACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */
327};
328
329enum fan_control_access_mode {
330 IBMACPI_FAN_WR_NONE = 0, /* No fan control */
331 IBMACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */
332 IBMACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */
333 IBMACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */
334};
335
336enum fan_control_commands {
337 IBMACPI_FAN_CMD_SPEED = 0x0001, /* speed command */
338 IBMACPI_FAN_CMD_LEVEL = 0x0002, /* level command */
339 IBMACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd,
340 * and also watchdog cmd */
341};
342
343enum { /* Fan control constants */
344 fan_status_offset = 0x2f, /* EC register 0x2f */
345 fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
346 * 0x84 must be read before 0x85 */
347
348 IBMACPI_FAN_EC_DISENGAGED = 0x40, /* EC mode: tachometer
349 * disengaged */
350 IBMACPI_FAN_EC_AUTO = 0x80, /* EC mode: auto fan
351 * control */
352};
353
354static char *ibm_thinkpad_ec_found = NULL;
355
356struct ibm_struct {
357 char *name;
358 char param[32];
359
360 char *hid;
361 struct acpi_driver *driver;
362
363 int (*init) (void);
364 int (*read) (char *);
365 int (*write) (char *);
366 void (*exit) (void);
367
368 void (*notify) (struct ibm_struct *, u32);
369 acpi_handle *handle;
370 int type;
371 struct acpi_device *device;
372
373 int driver_registered;
374 int proc_created;
375 int init_called;
376 int notify_installed;
377
378 int experimental;
379};
380
381static struct proc_dir_entry *proc_dir = NULL;
382
383static struct backlight_device *ibm_backlight_device = NULL;
384
385#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
386#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
387#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
388
389static int acpi_evalf(acpi_handle handle,
390 void *res, char *method, char *fmt, ...)
391{
392 char *fmt0 = fmt;
393 struct acpi_object_list params;
394 union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
395 struct acpi_buffer result, *resultp;
396 union acpi_object out_obj;
397 acpi_status status;
398 va_list ap;
399 char res_type;
400 int success;
401 int quiet;
402
403 if (!*fmt) {
404 printk(IBM_ERR "acpi_evalf() called with empty format\n");
405 return 0;
406 }
407
408 if (*fmt == 'q') {
409 quiet = 1;
410 fmt++;
411 } else
412 quiet = 0;
413
414 res_type = *(fmt++);
415
416 params.count = 0;
417 params.pointer = &in_objs[0];
418
419 va_start(ap, fmt);
420 while (*fmt) {
421 char c = *(fmt++);
422 switch (c) {
423 case 'd': /* int */
424 in_objs[params.count].integer.value = va_arg(ap, int);
425 in_objs[params.count++].type = ACPI_TYPE_INTEGER;
426 break;
427 /* add more types as needed */
428 default:
429 printk(IBM_ERR "acpi_evalf() called "
430 "with invalid format character '%c'\n", c);
431 return 0;
432 }
433 }
434 va_end(ap);
435
436 if (res_type != 'v') {
437 result.length = sizeof(out_obj);
438 result.pointer = &out_obj;
439 resultp = &result;
440 } else
441 resultp = NULL;
442
443 status = acpi_evaluate_object(handle, method, &params, resultp);
444
445 switch (res_type) {
446 case 'd': /* int */
447 if (res)
448 *(int *)res = out_obj.integer.value;
449 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
450 break;
451 case 'v': /* void */
452 success = status == AE_OK;
453 break;
454 /* add more types as needed */
455 default:
456 printk(IBM_ERR "acpi_evalf() called "
457 "with invalid format character '%c'\n", res_type);
458 return 0;
459 }
460
461 if (!success && !quiet)
462 printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
463 method, fmt0, status);
464
465 return success;
466}
467
468static void __unused acpi_print_int(acpi_handle handle, char *method)
469{
470 int i;
471
472 if (acpi_evalf(handle, &i, method, "d"))
473 printk(IBM_INFO "%s = 0x%x\n", method, i);
474 else
475 printk(IBM_ERR "error calling %s\n", method);
476}
477
478static char *next_cmd(char **cmds)
479{
480 char *start = *cmds;
481 char *end;
482
483 while ((end = strchr(start, ',')) && end == start)
484 start = end + 1;
485
486 if (!end)
487 return NULL;
488
489 *end = 0;
490 *cmds = end + 1;
491 return start;
492}
493
494static int ibm_acpi_driver_init(void)
495{
496 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
497 printk(IBM_INFO "%s\n", IBM_URL);
498
499 if (ibm_thinkpad_ec_found)
500 printk(IBM_INFO "ThinkPad EC firmware %s\n",
501 ibm_thinkpad_ec_found);
502
503 return 0;
504}
505
506static int driver_read(char *p)
507{
508 int len = 0;
509
510 len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
511 len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
512
513 return len;
514}
515
516static int hotkey_supported;
517static int hotkey_mask_supported;
518static int hotkey_orig_status;
519static int hotkey_orig_mask;
520
521static int hotkey_get(int *status, int *mask)
522{
523 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
524 return 0;
525
526 if (hotkey_mask_supported)
527 if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
528 return 0;
529
530 return 1;
531}
532
533static int hotkey_set(int status, int mask)
534{
535 int i;
536
537 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
538 return 0;
539
540 if (hotkey_mask_supported)
541 for (i = 0; i < 32; i++) {
542 int bit = ((1 << i) & mask) != 0;
543 if (!acpi_evalf(hkey_handle,
544 NULL, "MHKM", "vdd", i + 1, bit))
545 return 0;
546 }
547
548 return 1;
549}
550
551static int hotkey_init(void)
552{
553 /* hotkey not supported on 570 */
554 hotkey_supported = hkey_handle != NULL;
555
556 if (hotkey_supported) {
557 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
558 A30, R30, R31, T20-22, X20-21, X22-24 */
559 hotkey_mask_supported =
560 acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
561
562 if (!hotkey_get(&hotkey_orig_status, &hotkey_orig_mask))
563 return -ENODEV;
564 }
565
566 return 0;
567}
568
569static int hotkey_read(char *p)
570{
571 int status, mask;
572 int len = 0;
573
574 if (!hotkey_supported) {
575 len += sprintf(p + len, "status:\t\tnot supported\n");
576 return len;
577 }
578
579 if (!hotkey_get(&status, &mask))
580 return -EIO;
581
582 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
583 if (hotkey_mask_supported) {
584 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
585 len += sprintf(p + len,
586 "commands:\tenable, disable, reset, <mask>\n");
587 } else {
588 len += sprintf(p + len, "mask:\t\tnot supported\n");
589 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
590 }
591
592 return len;
593}
594
595static int hotkey_write(char *buf)
596{
597 int status, mask;
598 char *cmd;
599 int do_cmd = 0;
600
601 if (!hotkey_supported)
602 return -ENODEV;
603
604 if (!hotkey_get(&status, &mask))
605 return -EIO;
606
607 while ((cmd = next_cmd(&buf))) {
608 if (strlencmp(cmd, "enable") == 0) {
609 status = 1;
610 } else if (strlencmp(cmd, "disable") == 0) {
611 status = 0;
612 } else if (strlencmp(cmd, "reset") == 0) {
613 status = hotkey_orig_status;
614 mask = hotkey_orig_mask;
615 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
616 /* mask set */
617 } else if (sscanf(cmd, "%x", &mask) == 1) {
618 /* mask set */
619 } else
620 return -EINVAL;
621 do_cmd = 1;
622 }
623
624 if (do_cmd && !hotkey_set(status, mask))
625 return -EIO;
626
627 return 0;
628}
629
630static void hotkey_exit(void)
631{
632 if (hotkey_supported)
633 hotkey_set(hotkey_orig_status, hotkey_orig_mask);
634}
635
636static void hotkey_notify(struct ibm_struct *ibm, u32 event)
637{
638 int hkey;
639
640 if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
641 acpi_bus_generate_event(ibm->device, event, hkey);
642 else {
643 printk(IBM_ERR "unknown hotkey event %d\n", event);
644 acpi_bus_generate_event(ibm->device, event, 0);
645 }
646}
647
648static int bluetooth_supported;
649
650static int bluetooth_init(void)
651{
652 /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
653 G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
654 bluetooth_supported = hkey_handle &&
655 acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
656
657 return 0;
658}
659
660static int bluetooth_status(void)
661{
662 int status;
663
664 if (!bluetooth_supported ||
665 !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
666 status = 0;
667
668 return status;
669}
670
671static int bluetooth_read(char *p)
672{
673 int len = 0;
674 int status = bluetooth_status();
675
676 if (!bluetooth_supported)
677 len += sprintf(p + len, "status:\t\tnot supported\n");
678 else if (!(status & 1))
679 len += sprintf(p + len, "status:\t\tnot installed\n");
680 else {
681 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
682 len += sprintf(p + len, "commands:\tenable, disable\n");
683 }
684
685 return len;
686}
687
688static int bluetooth_write(char *buf)
689{
690 int status = bluetooth_status();
691 char *cmd;
692 int do_cmd = 0;
693
694 if (!bluetooth_supported)
695 return -ENODEV;
696
697 while ((cmd = next_cmd(&buf))) {
698 if (strlencmp(cmd, "enable") == 0) {
699 status |= 2;
700 } else if (strlencmp(cmd, "disable") == 0) {
701 status &= ~2;
702 } else
703 return -EINVAL;
704 do_cmd = 1;
705 }
706
707 if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
708 return -EIO;
709
710 return 0;
711}
712
713static int wan_supported;
714
715static int wan_init(void)
716{
717 wan_supported = hkey_handle &&
718 acpi_evalf(hkey_handle, NULL, "GWAN", "qv");
719
720 return 0;
721}
722
723static int wan_status(void)
724{
725 int status;
726
727 if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
728 status = 0;
729
730 return status;
731}
732
733static int wan_read(char *p)
734{
735 int len = 0;
736 int status = wan_status();
737
738 if (!wan_supported)
739 len += sprintf(p + len, "status:\t\tnot supported\n");
740 else if (!(status & 1))
741 len += sprintf(p + len, "status:\t\tnot installed\n");
742 else {
743 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
744 len += sprintf(p + len, "commands:\tenable, disable\n");
745 }
746
747 return len;
748}
749
750static int wan_write(char *buf)
751{
752 int status = wan_status();
753 char *cmd;
754 int do_cmd = 0;
755
756 if (!wan_supported)
757 return -ENODEV;
758
759 while ((cmd = next_cmd(&buf))) {
760 if (strlencmp(cmd, "enable") == 0) {
761 status |= 2;
762 } else if (strlencmp(cmd, "disable") == 0) {
763 status &= ~2;
764 } else
765 return -EINVAL;
766 do_cmd = 1;
767 }
768
769 if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
770 return -EIO;
771
772 return 0;
773}
774
775enum video_access_mode {
776 IBMACPI_VIDEO_NONE = 0,
777 IBMACPI_VIDEO_570, /* 570 */
778 IBMACPI_VIDEO_770, /* 600e/x, 770e, 770x */
779 IBMACPI_VIDEO_NEW, /* all others */
780};
781
782static enum video_access_mode video_supported;
783static int video_orig_autosw;
784
785static int video_init(void)
786{
787 int ivga;
788
789 if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
790 /* G41, assume IVGA doesn't change */
791 vid_handle = vid2_handle;
792
793 if (!vid_handle)
794 /* video switching not supported on R30, R31 */
795 video_supported = IBMACPI_VIDEO_NONE;
796 else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
797 /* 570 */
798 video_supported = IBMACPI_VIDEO_570;
799 else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
800 /* 600e/x, 770e, 770x */
801 video_supported = IBMACPI_VIDEO_770;
802 else
803 /* all others */
804 video_supported = IBMACPI_VIDEO_NEW;
805
806 return 0;
807}
808
809static int video_status(void)
810{
811 int status = 0;
812 int i;
813
814 if (video_supported == IBMACPI_VIDEO_570) {
815 if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
816 status = i & 3;
817 } else if (video_supported == IBMACPI_VIDEO_770) {
818 if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
819 status |= 0x01 * i;
820 if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
821 status |= 0x02 * i;
822 } else if (video_supported == IBMACPI_VIDEO_NEW) {
823 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
824 if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
825 status |= 0x02 * i;
826
827 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
828 if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
829 status |= 0x01 * i;
830 if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
831 status |= 0x08 * i;
832 }
833
834 return status;
835}
836
837static int video_autosw(void)
838{
839 int autosw = 0;
840
841 if (video_supported == IBMACPI_VIDEO_570)
842 acpi_evalf(vid_handle, &autosw, "SWIT", "d");
843 else if (video_supported == IBMACPI_VIDEO_770 ||
844 video_supported == IBMACPI_VIDEO_NEW)
845 acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
846
847 return autosw & 1;
848}
849
850static int video_read(char *p)
851{
852 int status = video_status();
853 int autosw = video_autosw();
854 int len = 0;
855
856 if (!video_supported) {
857 len += sprintf(p + len, "status:\t\tnot supported\n");
858 return len;
859 }
860
861 len += sprintf(p + len, "status:\t\tsupported\n");
862 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
863 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
864 if (video_supported == IBMACPI_VIDEO_NEW)
865 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
866 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
867 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
868 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
869 if (video_supported == IBMACPI_VIDEO_NEW)
870 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
871 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
872 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
873
874 return len;
875}
876
877static int video_switch(void)
878{
879 int autosw = video_autosw();
880 int ret;
881
882 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
883 return -EIO;
884 ret = video_supported == IBMACPI_VIDEO_570 ?
885 acpi_evalf(ec_handle, NULL, "_Q16", "v") :
886 acpi_evalf(vid_handle, NULL, "VSWT", "v");
887 acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
888
889 return ret;
890}
891
892static int video_expand(void)
893{
894 if (video_supported == IBMACPI_VIDEO_570)
895 return acpi_evalf(ec_handle, NULL, "_Q17", "v");
896 else if (video_supported == IBMACPI_VIDEO_770)
897 return acpi_evalf(vid_handle, NULL, "VEXP", "v");
898 else
899 return acpi_evalf(NULL, NULL, "\\VEXP", "v");
900}
901
902static int video_switch2(int status)
903{
904 int ret;
905
906 if (video_supported == IBMACPI_VIDEO_570) {
907 ret = acpi_evalf(NULL, NULL,
908 "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
909 } else if (video_supported == IBMACPI_VIDEO_770) {
910 int autosw = video_autosw();
911 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
912 return -EIO;
913
914 ret = acpi_evalf(vid_handle, NULL,
915 "ASWT", "vdd", status * 0x100, 0);
916
917 acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
918 } else {
919 ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
920 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
921 }
922
923 return ret;
924}
925
926static int video_write(char *buf)
927{
928 char *cmd;
929 int enable, disable, status;
930
931 if (!video_supported)
932 return -ENODEV;
933
934 enable = disable = 0;
935
936 while ((cmd = next_cmd(&buf))) {
937 if (strlencmp(cmd, "lcd_enable") == 0) {
938 enable |= 0x01;
939 } else if (strlencmp(cmd, "lcd_disable") == 0) {
940 disable |= 0x01;
941 } else if (strlencmp(cmd, "crt_enable") == 0) {
942 enable |= 0x02;
943 } else if (strlencmp(cmd, "crt_disable") == 0) {
944 disable |= 0x02;
945 } else if (video_supported == IBMACPI_VIDEO_NEW &&
946 strlencmp(cmd, "dvi_enable") == 0) {
947 enable |= 0x08;
948 } else if (video_supported == IBMACPI_VIDEO_NEW &&
949 strlencmp(cmd, "dvi_disable") == 0) {
950 disable |= 0x08;
951 } else if (strlencmp(cmd, "auto_enable") == 0) {
952 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
953 return -EIO;
954 } else if (strlencmp(cmd, "auto_disable") == 0) {
955 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0))
956 return -EIO;
957 } else if (strlencmp(cmd, "video_switch") == 0) {
958 if (!video_switch())
959 return -EIO;
960 } else if (strlencmp(cmd, "expand_toggle") == 0) {
961 if (!video_expand())
962 return -EIO;
963 } else
964 return -EINVAL;
965 }
966
967 if (enable || disable) {
968 status = (video_status() & 0x0f & ~disable) | enable;
969 if (!video_switch2(status))
970 return -EIO;
971 }
972
973 return 0;
974}
975
976static void video_exit(void)
977{
978 acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw);
979}
980
981static int light_supported;
982static int light_status_supported;
983
984static int light_init(void)
985{
986 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
987 light_supported = (cmos_handle || lght_handle) && !ledb_handle;
988
989 if (light_supported)
990 /* light status not supported on
991 570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
992 light_status_supported = acpi_evalf(ec_handle, NULL,
993 "KBLT", "qv");
994
995 return 0;
996}
997
998static int light_read(char *p)
999{
1000 int len = 0;
1001 int status = 0;
1002
1003 if (!light_supported) {
1004 len += sprintf(p + len, "status:\t\tnot supported\n");
1005 } else if (!light_status_supported) {
1006 len += sprintf(p + len, "status:\t\tunknown\n");
1007 len += sprintf(p + len, "commands:\ton, off\n");
1008 } else {
1009 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
1010 return -EIO;
1011 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
1012 len += sprintf(p + len, "commands:\ton, off\n");
1013 }
1014
1015 return len;
1016}
1017
1018static int light_write(char *buf)
1019{
1020 int cmos_cmd, lght_cmd;
1021 char *cmd;
1022 int success;
1023
1024 if (!light_supported)
1025 return -ENODEV;
1026
1027 while ((cmd = next_cmd(&buf))) {
1028 if (strlencmp(cmd, "on") == 0) {
1029 cmos_cmd = 0x0c;
1030 lght_cmd = 1;
1031 } else if (strlencmp(cmd, "off") == 0) {
1032 cmos_cmd = 0x0d;
1033 lght_cmd = 0;
1034 } else
1035 return -EINVAL;
1036
1037 success = cmos_handle ?
1038 acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
1039 acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
1040 if (!success)
1041 return -EIO;
1042 }
1043
1044 return 0;
1045}
1046
1047static int _sta(acpi_handle handle)
1048{
1049 int status;
1050
1051 if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
1052 status = 0;
1053
1054 return status;
1055}
1056
1057#ifdef CONFIG_ACPI_IBM_DOCK
1058#define dock_docked() (_sta(dock_handle) & 1)
1059
1060static int dock_read(char *p)
1061{
1062 int len = 0;
1063 int docked = dock_docked();
1064
1065 if (!dock_handle)
1066 len += sprintf(p + len, "status:\t\tnot supported\n");
1067 else if (!docked)
1068 len += sprintf(p + len, "status:\t\tundocked\n");
1069 else {
1070 len += sprintf(p + len, "status:\t\tdocked\n");
1071 len += sprintf(p + len, "commands:\tdock, undock\n");
1072 }
1073
1074 return len;
1075}
1076
1077static int dock_write(char *buf)
1078{
1079 char *cmd;
1080
1081 if (!dock_docked())
1082 return -ENODEV;
1083
1084 while ((cmd = next_cmd(&buf))) {
1085 if (strlencmp(cmd, "undock") == 0) {
1086 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
1087 !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
1088 return -EIO;
1089 } else if (strlencmp(cmd, "dock") == 0) {
1090 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
1091 return -EIO;
1092 } else
1093 return -EINVAL;
1094 }
1095
1096 return 0;
1097}
1098
1099static void dock_notify(struct ibm_struct *ibm, u32 event)
1100{
1101 int docked = dock_docked();
1102 int pci = ibm->hid && strstr(ibm->hid, IBM_PCI_HID);
1103
1104 if (event == 1 && !pci) /* 570 */
1105 acpi_bus_generate_event(ibm->device, event, 1); /* button */
1106 else if (event == 1 && pci) /* 570 */
1107 acpi_bus_generate_event(ibm->device, event, 3); /* dock */
1108 else if (event == 3 && docked)
1109 acpi_bus_generate_event(ibm->device, event, 1); /* button */
1110 else if (event == 3 && !docked)
1111 acpi_bus_generate_event(ibm->device, event, 2); /* undock */
1112 else if (event == 0 && docked)
1113 acpi_bus_generate_event(ibm->device, event, 3); /* dock */
1114 else {
1115 printk(IBM_ERR "unknown dock event %d, status %d\n",
1116 event, _sta(dock_handle));
1117 acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
1118 }
1119}
1120#endif
1121
1122static int bay_status_supported;
1123static int bay_status2_supported;
1124static int bay_eject_supported;
1125static int bay_eject2_supported;
1126
1127static int bay_init(void)
1128{
1129 bay_status_supported = bay_handle &&
1130 acpi_evalf(bay_handle, NULL, "_STA", "qv");
1131 bay_status2_supported = bay2_handle &&
1132 acpi_evalf(bay2_handle, NULL, "_STA", "qv");
1133
1134 bay_eject_supported = bay_handle && bay_ej_handle &&
1135 (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
1136 bay_eject2_supported = bay2_handle && bay2_ej_handle &&
1137 (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
1138
1139 return 0;
1140}
1141
1142#define bay_occupied(b) (_sta(b##_handle) & 1)
1143
1144static int bay_read(char *p)
1145{
1146 int len = 0;
1147 int occupied = bay_occupied(bay);
1148 int occupied2 = bay_occupied(bay2);
1149 int eject, eject2;
1150
1151 len += sprintf(p + len, "status:\t\t%s\n", bay_status_supported ?
1152 (occupied ? "occupied" : "unoccupied") :
1153 "not supported");
1154 if (bay_status2_supported)
1155 len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
1156 "occupied" : "unoccupied");
1157
1158 eject = bay_eject_supported && occupied;
1159 eject2 = bay_eject2_supported && occupied2;
1160
1161 if (eject && eject2)
1162 len += sprintf(p + len, "commands:\teject, eject2\n");
1163 else if (eject)
1164 len += sprintf(p + len, "commands:\teject\n");
1165 else if (eject2)
1166 len += sprintf(p + len, "commands:\teject2\n");
1167
1168 return len;
1169}
1170
1171static int bay_write(char *buf)
1172{
1173 char *cmd;
1174
1175 if (!bay_eject_supported && !bay_eject2_supported)
1176 return -ENODEV;
1177
1178 while ((cmd = next_cmd(&buf))) {
1179 if (bay_eject_supported && strlencmp(cmd, "eject") == 0) {
1180 if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
1181 return -EIO;
1182 } else if (bay_eject2_supported &&
1183 strlencmp(cmd, "eject2") == 0) {
1184 if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
1185 return -EIO;
1186 } else
1187 return -EINVAL;
1188 }
1189
1190 return 0;
1191}
1192
1193static void bay_notify(struct ibm_struct *ibm, u32 event)
1194{
1195 acpi_bus_generate_event(ibm->device, event, 0);
1196}
1197
1198static int cmos_read(char *p)
1199{
1200 int len = 0;
1201
1202 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
1203 R30, R31, T20-22, X20-21 */
1204 if (!cmos_handle)
1205 len += sprintf(p + len, "status:\t\tnot supported\n");
1206 else {
1207 len += sprintf(p + len, "status:\t\tsupported\n");
1208 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
1209 }
1210
1211 return len;
1212}
1213
1214static int cmos_eval(int cmos_cmd)
1215{
1216 if (cmos_handle)
1217 return acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd);
1218 else
1219 return 1;
1220}
1221
1222static int cmos_write(char *buf)
1223{
1224 char *cmd;
1225 int cmos_cmd;
1226
1227 if (!cmos_handle)
1228 return -EINVAL;
1229
1230 while ((cmd = next_cmd(&buf))) {
1231 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
1232 cmos_cmd >= 0 && cmos_cmd <= 21) {
1233 /* cmos_cmd set */
1234 } else
1235 return -EINVAL;
1236
1237 if (!cmos_eval(cmos_cmd))
1238 return -EIO;
1239 }
1240
1241 return 0;
1242}
1243
1244enum led_access_mode {
1245 IBMACPI_LED_NONE = 0,
1246 IBMACPI_LED_570, /* 570 */
1247 IBMACPI_LED_OLD, /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
1248 IBMACPI_LED_NEW, /* all others */
1249};
1250static enum led_access_mode led_supported;
1251
1252static int led_init(void)
1253{
1254 if (!led_handle)
1255 /* led not supported on R30, R31 */
1256 led_supported = IBMACPI_LED_NONE;
1257 else if (strlencmp(led_path, "SLED") == 0)
1258 /* 570 */
1259 led_supported = IBMACPI_LED_570;
1260 else if (strlencmp(led_path, "SYSL") == 0)
1261 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
1262 led_supported = IBMACPI_LED_OLD;
1263 else
1264 /* all others */
1265 led_supported = IBMACPI_LED_NEW;
1266
1267 return 0;
1268}
1269
1270#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
1271
1272static int led_read(char *p)
1273{
1274 int len = 0;
1275
1276 if (!led_supported) {
1277 len += sprintf(p + len, "status:\t\tnot supported\n");
1278 return len;
1279 }
1280 len += sprintf(p + len, "status:\t\tsupported\n");
1281
1282 if (led_supported == IBMACPI_LED_570) {
1283 /* 570 */
1284 int i, status;
1285 for (i = 0; i < 8; i++) {
1286 if (!acpi_evalf(ec_handle,
1287 &status, "GLED", "dd", 1 << i))
1288 return -EIO;
1289 len += sprintf(p + len, "%d:\t\t%s\n",
1290 i, led_status(status));
1291 }
1292 }
1293
1294 len += sprintf(p + len, "commands:\t"
1295 "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
1296
1297 return len;
1298}
1299
1300/* off, on, blink */
1301static const int led_sled_arg1[] = { 0, 1, 3 };
1302static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
1303static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
1304static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
1305
1306#define EC_HLCL 0x0c
1307#define EC_HLBL 0x0d
1308#define EC_HLMS 0x0e
1309
1310static int led_write(char *buf)
1311{
1312 char *cmd;
1313 int led, ind, ret;
1314
1315 if (!led_supported)
1316 return -ENODEV;
1317
1318 while ((cmd = next_cmd(&buf))) {
1319 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
1320 return -EINVAL;
1321
1322 if (strstr(cmd, "off")) {
1323 ind = 0;
1324 } else if (strstr(cmd, "on")) {
1325 ind = 1;
1326 } else if (strstr(cmd, "blink")) {
1327 ind = 2;
1328 } else
1329 return -EINVAL;
1330
1331 if (led_supported == IBMACPI_LED_570) {
1332 /* 570 */
1333 led = 1 << led;
1334 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
1335 led, led_sled_arg1[ind]))
1336 return -EIO;
1337 } else if (led_supported == IBMACPI_LED_OLD) {
1338 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
1339 led = 1 << led;
1340 ret = ec_write(EC_HLMS, led);
1341 if (ret >= 0)
1342 ret =
1343 ec_write(EC_HLBL, led * led_exp_hlbl[ind]);
1344 if (ret >= 0)
1345 ret =
1346 ec_write(EC_HLCL, led * led_exp_hlcl[ind]);
1347 if (ret < 0)
1348 return ret;
1349 } else {
1350 /* all others */
1351 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
1352 led, led_led_arg1[ind]))
1353 return -EIO;
1354 }
1355 }
1356
1357 return 0;
1358}
1359
1360static int beep_read(char *p)
1361{
1362 int len = 0;
1363
1364 if (!beep_handle)
1365 len += sprintf(p + len, "status:\t\tnot supported\n");
1366 else {
1367 len += sprintf(p + len, "status:\t\tsupported\n");
1368 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
1369 }
1370
1371 return len;
1372}
1373
1374static int beep_write(char *buf)
1375{
1376 char *cmd;
1377 int beep_cmd;
1378
1379 if (!beep_handle)
1380 return -ENODEV;
1381
1382 while ((cmd = next_cmd(&buf))) {
1383 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
1384 beep_cmd >= 0 && beep_cmd <= 17) {
1385 /* beep_cmd set */
1386 } else
1387 return -EINVAL;
1388 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
1389 return -EIO;
1390 }
1391
1392 return 0;
1393}
1394
1395static int acpi_ec_read(int i, u8 * p)
1396{
1397 int v;
1398
1399 if (ecrd_handle) {
1400 if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
1401 return 0;
1402 *p = v;
1403 } else {
1404 if (ec_read(i, p) < 0)
1405 return 0;
1406 }
1407
1408 return 1;
1409}
1410
1411static int acpi_ec_write(int i, u8 v)
1412{
1413 if (ecwr_handle) {
1414 if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
1415 return 0;
1416 } else {
1417 if (ec_write(i, v) < 0)
1418 return 0;
1419 }
1420
1421 return 1;
1422}
1423
1424static enum thermal_access_mode thermal_read_mode;
1425
1426static int thermal_init(void)
1427{
1428 u8 t, ta1, ta2;
1429 int i;
1430 int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
1431
1432 if (ibm_thinkpad_ec_found && experimental) {
1433 /*
1434 * Direct EC access mode: sensors at registers
1435 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
1436 * non-implemented, thermal sensors return 0x80 when
1437 * not available
1438 */
1439
1440 ta1 = ta2 = 0;
1441 for (i = 0; i < 8; i++) {
1442 if (likely(acpi_ec_read(0x78 + i, &t))) {
1443 ta1 |= t;
1444 } else {
1445 ta1 = 0;
1446 break;
1447 }
1448 if (likely(acpi_ec_read(0xC0 + i, &t))) {
1449 ta2 |= t;
1450 } else {
1451 ta1 = 0;
1452 break;
1453 }
1454 }
1455 if (ta1 == 0) {
1456 /* This is sheer paranoia, but we handle it anyway */
1457 if (acpi_tmp7) {
1458 printk(IBM_ERR
1459 "ThinkPad ACPI EC access misbehaving, "
1460 "falling back to ACPI TMPx access mode\n");
1461 thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
1462 } else {
1463 printk(IBM_ERR
1464 "ThinkPad ACPI EC access misbehaving, "
1465 "disabling thermal sensors access\n");
1466 thermal_read_mode = IBMACPI_THERMAL_NONE;
1467 }
1468 } else {
1469 thermal_read_mode =
1470 (ta2 != 0) ?
1471 IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8;
1472 }
1473 } else if (acpi_tmp7) {
1474 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
1475 /* 600e/x, 770e, 770x */
1476 thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT;
1477 } else {
1478 /* Standard ACPI TMPx access, max 8 sensors */
1479 thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
1480 }
1481 } else {
1482 /* temperatures not supported on 570, G4x, R30, R31, R32 */
1483 thermal_read_mode = IBMACPI_THERMAL_NONE;
1484 }
1485
1486 return 0;
1487}
1488
1489static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
1490{
1491 int i, t;
1492 s8 tmp;
1493 char tmpi[] = "TMPi";
1494
1495 if (!s)
1496 return -EINVAL;
1497
1498 switch (thermal_read_mode) {
1499#if IBMACPI_MAX_THERMAL_SENSORS >= 16
1500 case IBMACPI_THERMAL_TPEC_16:
1501 for (i = 0; i < 8; i++) {
1502 if (!acpi_ec_read(0xC0 + i, &tmp))
1503 return -EIO;
1504 s->temp[i + 8] = tmp * 1000;
1505 }
1506 /* fallthrough */
1507#endif
1508 case IBMACPI_THERMAL_TPEC_8:
1509 for (i = 0; i < 8; i++) {
1510 if (!acpi_ec_read(0x78 + i, &tmp))
1511 return -EIO;
1512 s->temp[i] = tmp * 1000;
1513 }
1514 return (thermal_read_mode == IBMACPI_THERMAL_TPEC_16) ? 16 : 8;
1515
1516 case IBMACPI_THERMAL_ACPI_UPDT:
1517 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
1518 return -EIO;
1519 for (i = 0; i < 8; i++) {
1520 tmpi[3] = '0' + i;
1521 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
1522 return -EIO;
1523 s->temp[i] = (t - 2732) * 100;
1524 }
1525 return 8;
1526
1527 case IBMACPI_THERMAL_ACPI_TMP07:
1528 for (i = 0; i < 8; i++) {
1529 tmpi[3] = '0' + i;
1530 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
1531 return -EIO;
1532 s->temp[i] = t * 1000;
1533 }
1534 return 8;
1535
1536 case IBMACPI_THERMAL_NONE:
1537 default:
1538 return 0;
1539 }
1540}
1541
1542static int thermal_read(char *p)
1543{
1544 int len = 0;
1545 int n, i;
1546 struct ibm_thermal_sensors_struct t;
1547
1548 n = thermal_get_sensors(&t);
1549 if (unlikely(n < 0))
1550 return n;
1551
1552 len += sprintf(p + len, "temperatures:\t");
1553
1554 if (n > 0) {
1555 for (i = 0; i < (n - 1); i++)
1556 len += sprintf(p + len, "%d ", t.temp[i] / 1000);
1557 len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
1558 } else
1559 len += sprintf(p + len, "not supported\n");
1560
1561 return len;
1562}
1563
1564static u8 ecdump_regs[256];
1565
1566static int ecdump_read(char *p)
1567{
1568 int len = 0;
1569 int i, j;
1570 u8 v;
1571
1572 len += sprintf(p + len, "EC "
1573 " +00 +01 +02 +03 +04 +05 +06 +07"
1574 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
1575 for (i = 0; i < 256; i += 16) {
1576 len += sprintf(p + len, "EC 0x%02x:", i);
1577 for (j = 0; j < 16; j++) {
1578 if (!acpi_ec_read(i + j, &v))
1579 break;
1580 if (v != ecdump_regs[i + j])
1581 len += sprintf(p + len, " *%02x", v);
1582 else
1583 len += sprintf(p + len, " %02x", v);
1584 ecdump_regs[i + j] = v;
1585 }
1586 len += sprintf(p + len, "\n");
1587 if (j != 16)
1588 break;
1589 }
1590
1591 /* These are way too dangerous to advertise openly... */
1592#if 0
1593 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
1594 " (<offset> is 00-ff, <value> is 00-ff)\n");
1595 len += sprintf(p + len, "commands:\t0x<offset> <value> "
1596 " (<offset> is 00-ff, <value> is 0-255)\n");
1597#endif
1598 return len;
1599}
1600
1601static int ecdump_write(char *buf)
1602{
1603 char *cmd;
1604 int i, v;
1605
1606 while ((cmd = next_cmd(&buf))) {
1607 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
1608 /* i and v set */
1609 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
1610 /* i and v set */
1611 } else
1612 return -EINVAL;
1613 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
1614 if (!acpi_ec_write(i, v))
1615 return -EIO;
1616 } else
1617 return -EINVAL;
1618 }
1619
1620 return 0;
1621}
1622
1623static int brightness_offset = 0x31;
1624
1625static int brightness_get(struct backlight_device *bd)
1626{
1627 u8 level;
1628 if (!acpi_ec_read(brightness_offset, &level))
1629 return -EIO;
1630
1631 level &= 0x7;
1632
1633 return level;
1634}
1635
1636static int brightness_read(char *p)
1637{
1638 int len = 0;
1639 int level;
1640
1641 if ((level = brightness_get(NULL)) < 0) {
1642 len += sprintf(p + len, "level:\t\tunreadable\n");
1643 } else {
1644 len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
1645 len += sprintf(p + len, "commands:\tup, down\n");
1646 len += sprintf(p + len, "commands:\tlevel <level>"
1647 " (<level> is 0-7)\n");
1648 }
1649
1650 return len;
1651}
1652
1653#define BRIGHTNESS_UP 4
1654#define BRIGHTNESS_DOWN 5
1655
1656static int brightness_set(int value)
1657{
1658 int cmos_cmd, inc, i;
1659 int current_value = brightness_get(NULL);
1660
1661 value &= 7;
1662
1663 cmos_cmd = value > current_value ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
1664 inc = value > current_value ? 1 : -1;
1665 for (i = current_value; i != value; i += inc) {
1666 if (!cmos_eval(cmos_cmd))
1667 return -EIO;
1668 if (!acpi_ec_write(brightness_offset, i + inc))
1669 return -EIO;
1670 }
1671
1672 return 0;
1673}
1674
1675static int brightness_write(char *buf)
1676{
1677 int level;
1678 int new_level;
1679 char *cmd;
1680
1681 while ((cmd = next_cmd(&buf))) {
1682 if ((level = brightness_get(NULL)) < 0)
1683 return level;
1684 level &= 7;
1685
1686 if (strlencmp(cmd, "up") == 0) {
1687 new_level = level == 7 ? 7 : level + 1;
1688 } else if (strlencmp(cmd, "down") == 0) {
1689 new_level = level == 0 ? 0 : level - 1;
1690 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
1691 new_level >= 0 && new_level <= 7) {
1692 /* new_level set */
1693 } else
1694 return -EINVAL;
1695
1696 brightness_set(new_level);
1697 }
1698
1699 return 0;
1700}
1701
1702static int brightness_update_status(struct backlight_device *bd)
1703{
1704 return brightness_set(bd->props.brightness);
1705}
1706
1707static struct backlight_ops ibm_backlight_data = {
1708 .get_brightness = brightness_get,
1709 .update_status = brightness_update_status,
1710};
1711
1712static int brightness_init(void)
1713{
1714 ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
1715 &ibm_backlight_data);
1716 if (IS_ERR(ibm_backlight_device)) {
1717 printk(IBM_ERR "Could not register backlight device\n");
1718 return PTR_ERR(ibm_backlight_device);
1719 }
1720
1721 ibm_backlight_device->props.max_brightness = 7;
1722
1723 return 0;
1724}
1725
1726static void brightness_exit(void)
1727{
1728 if (ibm_backlight_device) {
1729 backlight_device_unregister(ibm_backlight_device);
1730 ibm_backlight_device = NULL;
1731 }
1732}
1733
1734static int volume_offset = 0x30;
1735
1736static int volume_read(char *p)
1737{
1738 int len = 0;
1739 u8 level;
1740
1741 if (!acpi_ec_read(volume_offset, &level)) {
1742 len += sprintf(p + len, "level:\t\tunreadable\n");
1743 } else {
1744 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
1745 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
1746 len += sprintf(p + len, "commands:\tup, down, mute\n");
1747 len += sprintf(p + len, "commands:\tlevel <level>"
1748 " (<level> is 0-15)\n");
1749 }
1750
1751 return len;
1752}
1753
1754#define VOLUME_DOWN 0
1755#define VOLUME_UP 1
1756#define VOLUME_MUTE 2
1757
1758static int volume_write(char *buf)
1759{
1760 int cmos_cmd, inc, i;
1761 u8 level, mute;
1762 int new_level, new_mute;
1763 char *cmd;
1764
1765 while ((cmd = next_cmd(&buf))) {
1766 if (!acpi_ec_read(volume_offset, &level))
1767 return -EIO;
1768 new_mute = mute = level & 0x40;
1769 new_level = level = level & 0xf;
1770
1771 if (strlencmp(cmd, "up") == 0) {
1772 if (mute)
1773 new_mute = 0;
1774 else
1775 new_level = level == 15 ? 15 : level + 1;
1776 } else if (strlencmp(cmd, "down") == 0) {
1777 if (mute)
1778 new_mute = 0;
1779 else
1780 new_level = level == 0 ? 0 : level - 1;
1781 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
1782 new_level >= 0 && new_level <= 15) {
1783 /* new_level set */
1784 } else if (strlencmp(cmd, "mute") == 0) {
1785 new_mute = 0x40;
1786 } else
1787 return -EINVAL;
1788
1789 if (new_level != level) { /* mute doesn't change */
1790 cmos_cmd = new_level > level ? VOLUME_UP : VOLUME_DOWN;
1791 inc = new_level > level ? 1 : -1;
1792
1793 if (mute && (!cmos_eval(cmos_cmd) ||
1794 !acpi_ec_write(volume_offset, level)))
1795 return -EIO;
1796
1797 for (i = level; i != new_level; i += inc)
1798 if (!cmos_eval(cmos_cmd) ||
1799 !acpi_ec_write(volume_offset, i + inc))
1800 return -EIO;
1801
1802 if (mute && (!cmos_eval(VOLUME_MUTE) ||
1803 !acpi_ec_write(volume_offset,
1804 new_level + mute)))
1805 return -EIO;
1806 }
1807
1808 if (new_mute != mute) { /* level doesn't change */
1809 cmos_cmd = new_mute ? VOLUME_MUTE : VOLUME_UP;
1810
1811 if (!cmos_eval(cmos_cmd) ||
1812 !acpi_ec_write(volume_offset, level + new_mute))
1813 return -EIO;
1814 }
1815 }
1816
1817 return 0;
1818}
1819
1820static enum fan_status_access_mode fan_status_access_mode;
1821static enum fan_control_access_mode fan_control_access_mode;
1822static enum fan_control_commands fan_control_commands;
1823
1824static int fan_control_status_known;
1825static u8 fan_control_initial_status;
1826
1827static void fan_watchdog_fire(struct work_struct *ignored);
1828static int fan_watchdog_maxinterval;
1829static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
1830
1831static int fan_init(void)
1832{
1833 fan_status_access_mode = IBMACPI_FAN_NONE;
1834 fan_control_access_mode = IBMACPI_FAN_WR_NONE;
1835 fan_control_commands = 0;
1836 fan_control_status_known = 1;
1837 fan_watchdog_maxinterval = 0;
1838
1839 if (gfan_handle) {
1840 /* 570, 600e/x, 770e, 770x */
1841 fan_status_access_mode = IBMACPI_FAN_RD_ACPI_GFAN;
1842 } else {
1843 /* all other ThinkPads: note that even old-style
1844 * ThinkPad ECs supports the fan control register */
1845 if (likely(acpi_ec_read(fan_status_offset,
1846 &fan_control_initial_status))) {
1847 fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
1848
1849 /* In some ThinkPads, neither the EC nor the ACPI
1850 * DSDT initialize the fan status, and it ends up
1851 * being set to 0x07 when it *could* be either
1852 * 0x07 or 0x80.
1853 *
1854 * Enable for TP-1Y (T43), TP-78 (R51e),
1855 * TP-76 (R52), TP-70 (T43, R52), which are known
1856 * to be buggy. */
1857 if (fan_control_initial_status == 0x07 &&
1858 ibm_thinkpad_ec_found &&
1859 ((ibm_thinkpad_ec_found[0] == '1' &&
1860 ibm_thinkpad_ec_found[1] == 'Y') ||
1861 (ibm_thinkpad_ec_found[0] == '7' &&
1862 (ibm_thinkpad_ec_found[1] == '6' ||
1863 ibm_thinkpad_ec_found[1] == '8' ||
1864 ibm_thinkpad_ec_found[1] == '0'))
1865 )) {
1866 printk(IBM_NOTICE
1867 "fan_init: initial fan status is "
1868 "unknown, assuming it is in auto "
1869 "mode\n");
1870 fan_control_status_known = 0;
1871 }
1872 } else {
1873 printk(IBM_ERR
1874 "ThinkPad ACPI EC access misbehaving, "
1875 "fan status and control unavailable\n");
1876 return 0;
1877 }
1878 }
1879
1880 if (sfan_handle) {
1881 /* 570, 770x-JL */
1882 fan_control_access_mode = IBMACPI_FAN_WR_ACPI_SFAN;
1883 fan_control_commands |=
1884 IBMACPI_FAN_CMD_LEVEL | IBMACPI_FAN_CMD_ENABLE;
1885 } else {
1886 if (!gfan_handle) {
1887 /* gfan without sfan means no fan control */
1888 /* all other models implement TP EC 0x2f control */
1889
1890 if (fans_handle) {
1891 /* X31, X40, X41 */
1892 fan_control_access_mode =
1893 IBMACPI_FAN_WR_ACPI_FANS;
1894 fan_control_commands |=
1895 IBMACPI_FAN_CMD_SPEED |
1896 IBMACPI_FAN_CMD_LEVEL |
1897 IBMACPI_FAN_CMD_ENABLE;
1898 } else {
1899 fan_control_access_mode = IBMACPI_FAN_WR_TPEC;
1900 fan_control_commands |=
1901 IBMACPI_FAN_CMD_LEVEL |
1902 IBMACPI_FAN_CMD_ENABLE;
1903 }
1904 }
1905 }
1906
1907 return 0;
1908}
1909
1910static int fan_get_status(u8 *status)
1911{
1912 u8 s;
1913
1914 /* TODO:
1915 * Add IBMACPI_FAN_RD_ACPI_FANS ? */
1916
1917 switch (fan_status_access_mode) {
1918 case IBMACPI_FAN_RD_ACPI_GFAN:
1919 /* 570, 600e/x, 770e, 770x */
1920
1921 if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
1922 return -EIO;
1923
1924 if (likely(status))
1925 *status = s & 0x07;
1926
1927 break;
1928
1929 case IBMACPI_FAN_RD_TPEC:
1930 /* all except 570, 600e/x, 770e, 770x */
1931 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
1932 return -EIO;
1933
1934 if (likely(status))
1935 *status = s;
1936
1937 break;
1938
1939 default:
1940 return -ENXIO;
1941 }
1942
1943 return 0;
1944}
1945
1946static int fan_get_speed(unsigned int *speed)
1947{
1948 u8 hi, lo;
1949
1950 switch (fan_status_access_mode) {
1951 case IBMACPI_FAN_RD_TPEC:
1952 /* all except 570, 600e/x, 770e, 770x */
1953 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
1954 !acpi_ec_read(fan_rpm_offset + 1, &hi)))
1955 return -EIO;
1956
1957 if (likely(speed))
1958 *speed = (hi << 8) | lo;
1959
1960 break;
1961
1962 default:
1963 return -ENXIO;
1964 }
1965
1966 return 0;
1967}
1968
1969static void fan_exit(void)
1970{
1971 cancel_delayed_work(&fan_watchdog_task);
1972 flush_scheduled_work();
1973}
1974
1975static void fan_watchdog_reset(void)
1976{
1977 static int fan_watchdog_active = 0;
1978
1979 if (fan_watchdog_active)
1980 cancel_delayed_work(&fan_watchdog_task);
1981
1982 if (fan_watchdog_maxinterval > 0) {
1983 fan_watchdog_active = 1;
1984 if (!schedule_delayed_work(&fan_watchdog_task,
1985 msecs_to_jiffies(fan_watchdog_maxinterval
1986 * 1000))) {
1987 printk(IBM_ERR "failed to schedule the fan watchdog, "
1988 "watchdog will not trigger\n");
1989 }
1990 } else
1991 fan_watchdog_active = 0;
1992}
1993
1994static int fan_read(char *p)
1995{
1996 int len = 0;
1997 int rc;
1998 u8 status;
1999 unsigned int speed = 0;
2000
2001 switch (fan_status_access_mode) {
2002 case IBMACPI_FAN_RD_ACPI_GFAN:
2003 /* 570, 600e/x, 770e, 770x */
2004 if ((rc = fan_get_status(&status)) < 0)
2005 return rc;
2006
2007 len += sprintf(p + len, "status:\t\t%s\n"
2008 "level:\t\t%d\n",
2009 (status != 0) ? "enabled" : "disabled", status);
2010 break;
2011
2012 case IBMACPI_FAN_RD_TPEC:
2013 /* all except 570, 600e/x, 770e, 770x */
2014 if ((rc = fan_get_status(&status)) < 0)
2015 return rc;
2016
2017 if (unlikely(!fan_control_status_known)) {
2018 if (status != fan_control_initial_status)
2019 fan_control_status_known = 1;
2020 else
2021 /* Return most likely status. In fact, it
2022 * might be the only possible status */
2023 status = IBMACPI_FAN_EC_AUTO;
2024 }
2025
2026 len += sprintf(p + len, "status:\t\t%s\n",
2027 (status != 0) ? "enabled" : "disabled");
2028
2029 /* No ThinkPad boots on disengaged mode, we can safely
2030 * assume the tachometer is online if fan control status
2031 * was unknown */
2032 if ((rc = fan_get_speed(&speed)) < 0)
2033 return rc;
2034
2035 len += sprintf(p + len, "speed:\t\t%d\n", speed);
2036
2037 if (status & IBMACPI_FAN_EC_DISENGAGED)
2038 /* Disengaged mode takes precedence */
2039 len += sprintf(p + len, "level:\t\tdisengaged\n");
2040 else if (status & IBMACPI_FAN_EC_AUTO)
2041 len += sprintf(p + len, "level:\t\tauto\n");
2042 else
2043 len += sprintf(p + len, "level:\t\t%d\n", status);
2044 break;
2045
2046 case IBMACPI_FAN_NONE:
2047 default:
2048 len += sprintf(p + len, "status:\t\tnot supported\n");
2049 }
2050
2051 if (fan_control_commands & IBMACPI_FAN_CMD_LEVEL) {
2052 len += sprintf(p + len, "commands:\tlevel <level>");
2053
2054 switch (fan_control_access_mode) {
2055 case IBMACPI_FAN_WR_ACPI_SFAN:
2056 len += sprintf(p + len, " (<level> is 0-7)\n");
2057 break;
2058
2059 default:
2060 len += sprintf(p + len, " (<level> is 0-7, "
2061 "auto, disengaged)\n");
2062 break;
2063 }
2064 }
2065
2066 if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE)
2067 len += sprintf(p + len, "commands:\tenable, disable\n"
2068 "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
2069 "1-120 (seconds))\n");
2070
2071 if (fan_control_commands & IBMACPI_FAN_CMD_SPEED)
2072 len += sprintf(p + len, "commands:\tspeed <speed>"
2073 " (<speed> is 0-65535)\n");
2074
2075 return len;
2076}
2077
2078static int fan_set_level(int level)
2079{
2080 switch (fan_control_access_mode) {
2081 case IBMACPI_FAN_WR_ACPI_SFAN:
2082 if (level >= 0 && level <= 7) {
2083 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
2084 return -EIO;
2085 } else
2086 return -EINVAL;
2087 break;
2088
2089 case IBMACPI_FAN_WR_ACPI_FANS:
2090 case IBMACPI_FAN_WR_TPEC:
2091 if ((level != IBMACPI_FAN_EC_AUTO) &&
2092 (level != IBMACPI_FAN_EC_DISENGAGED) &&
2093 ((level < 0) || (level > 7)))
2094 return -EINVAL;
2095
2096 if (!acpi_ec_write(fan_status_offset, level))
2097 return -EIO;
2098 else
2099 fan_control_status_known = 1;
2100 break;
2101
2102 default:
2103 return -ENXIO;
2104 }
2105 return 0;
2106}
2107
2108static int fan_set_enable(void)
2109{
2110 u8 s;
2111 int rc;
2112
2113 switch (fan_control_access_mode) {
2114 case IBMACPI_FAN_WR_ACPI_FANS:
2115 case IBMACPI_FAN_WR_TPEC:
2116 if ((rc = fan_get_status(&s)) < 0)
2117 return rc;
2118
2119 /* Don't go out of emergency fan mode */
2120 if (s != 7)
2121 s = IBMACPI_FAN_EC_AUTO;
2122
2123 if (!acpi_ec_write(fan_status_offset, s))
2124 return -EIO;
2125 else
2126 fan_control_status_known = 1;
2127 break;
2128
2129 case IBMACPI_FAN_WR_ACPI_SFAN:
2130 if ((rc = fan_get_status(&s)) < 0)
2131 return rc;
2132
2133 s &= 0x07;
2134
2135 /* Set fan to at least level 4 */
2136 if (s < 4)
2137 s = 4;
2138
2139 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
2140 return -EIO;
2141 break;
2142
2143 default:
2144 return -ENXIO;
2145 }
2146 return 0;
2147}
2148
2149static int fan_set_disable(void)
2150{
2151 switch (fan_control_access_mode) {
2152 case IBMACPI_FAN_WR_ACPI_FANS:
2153 case IBMACPI_FAN_WR_TPEC:
2154 if (!acpi_ec_write(fan_status_offset, 0x00))
2155 return -EIO;
2156 else
2157 fan_control_status_known = 1;
2158 break;
2159
2160 case IBMACPI_FAN_WR_ACPI_SFAN:
2161 if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
2162 return -EIO;
2163 break;
2164
2165 default:
2166 return -ENXIO;
2167 }
2168 return 0;
2169}
2170
2171static int fan_set_speed(int speed)
2172{
2173 switch (fan_control_access_mode) {
2174 case IBMACPI_FAN_WR_ACPI_FANS:
2175 if (speed >= 0 && speed <= 65535) {
2176 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
2177 speed, speed, speed))
2178 return -EIO;
2179 } else
2180 return -EINVAL;
2181 break;
2182
2183 default:
2184 return -ENXIO;
2185 }
2186 return 0;
2187}
2188
2189static int fan_write_cmd_level(const char *cmd, int *rc)
2190{
2191 int level;
2192
2193 if (strlencmp(cmd, "level auto") == 0)
2194 level = IBMACPI_FAN_EC_AUTO;
2195 else if (strlencmp(cmd, "level disengaged") == 0)
2196 level = IBMACPI_FAN_EC_DISENGAGED;
2197 else if (sscanf(cmd, "level %d", &level) != 1)
2198 return 0;
2199
2200 if ((*rc = fan_set_level(level)) == -ENXIO)
2201 printk(IBM_ERR "level command accepted for unsupported "
2202 "access mode %d", fan_control_access_mode);
2203
2204 return 1;
2205}
2206
2207static int fan_write_cmd_enable(const char *cmd, int *rc)
2208{
2209 if (strlencmp(cmd, "enable") != 0)
2210 return 0;
2211
2212 if ((*rc = fan_set_enable()) == -ENXIO)
2213 printk(IBM_ERR "enable command accepted for unsupported "
2214 "access mode %d", fan_control_access_mode);
2215
2216 return 1;
2217}
2218
2219static int fan_write_cmd_disable(const char *cmd, int *rc)
2220{
2221 if (strlencmp(cmd, "disable") != 0)
2222 return 0;
2223
2224 if ((*rc = fan_set_disable()) == -ENXIO)
2225 printk(IBM_ERR "disable command accepted for unsupported "
2226 "access mode %d", fan_control_access_mode);
2227
2228 return 1;
2229}
2230
2231static int fan_write_cmd_speed(const char *cmd, int *rc)
2232{
2233 int speed;
2234
2235 /* TODO:
2236 * Support speed <low> <medium> <high> ? */
2237
2238 if (sscanf(cmd, "speed %d", &speed) != 1)
2239 return 0;
2240
2241 if ((*rc = fan_set_speed(speed)) == -ENXIO)
2242 printk(IBM_ERR "speed command accepted for unsupported "
2243 "access mode %d", fan_control_access_mode);
2244
2245 return 1;
2246}
2247
2248static int fan_write_cmd_watchdog(const char *cmd, int *rc)
2249{
2250 int interval;
2251
2252 if (sscanf(cmd, "watchdog %d", &interval) != 1)
2253 return 0;
2254
2255 if (interval < 0 || interval > 120)
2256 *rc = -EINVAL;
2257 else
2258 fan_watchdog_maxinterval = interval;
2259
2260 return 1;
2261}
2262
2263static int fan_write(char *buf)
2264{
2265 char *cmd;
2266 int rc = 0;
2267
2268 while (!rc && (cmd = next_cmd(&buf))) {
2269 if (!((fan_control_commands & IBMACPI_FAN_CMD_LEVEL) &&
2270 fan_write_cmd_level(cmd, &rc)) &&
2271 !((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
2272 (fan_write_cmd_enable(cmd, &rc) ||
2273 fan_write_cmd_disable(cmd, &rc) ||
2274 fan_write_cmd_watchdog(cmd, &rc))) &&
2275 !((fan_control_commands & IBMACPI_FAN_CMD_SPEED) &&
2276 fan_write_cmd_speed(cmd, &rc))
2277 )
2278 rc = -EINVAL;
2279 else if (!rc)
2280 fan_watchdog_reset();
2281 }
2282
2283 return rc;
2284}
2285
2286static void fan_watchdog_fire(struct work_struct *ignored)
2287{
2288 printk(IBM_NOTICE "fan watchdog: enabling fan\n");
2289 if (fan_set_enable()) {
2290 printk(IBM_ERR "fan watchdog: error while enabling fan\n");
2291 /* reschedule for later */
2292 fan_watchdog_reset();
2293 }
2294}
2295
2296static struct ibm_struct ibms[] = {
2297 {
2298 .name = "driver",
2299 .init = ibm_acpi_driver_init,
2300 .read = driver_read,
2301 },
2302 {
2303 .name = "hotkey",
2304 .hid = IBM_HKEY_HID,
2305 .init = hotkey_init,
2306 .read = hotkey_read,
2307 .write = hotkey_write,
2308 .exit = hotkey_exit,
2309 .notify = hotkey_notify,
2310 .handle = &hkey_handle,
2311 .type = ACPI_DEVICE_NOTIFY,
2312 },
2313 {
2314 .name = "bluetooth",
2315 .init = bluetooth_init,
2316 .read = bluetooth_read,
2317 .write = bluetooth_write,
2318 },
2319 {
2320 .name = "wan",
2321 .init = wan_init,
2322 .read = wan_read,
2323 .write = wan_write,
2324 .experimental = 1,
2325 },
2326 {
2327 .name = "video",
2328 .init = video_init,
2329 .read = video_read,
2330 .write = video_write,
2331 .exit = video_exit,
2332 },
2333 {
2334 .name = "light",
2335 .init = light_init,
2336 .read = light_read,
2337 .write = light_write,
2338 },
2339#ifdef CONFIG_ACPI_IBM_DOCK
2340 {
2341 .name = "dock",
2342 .read = dock_read,
2343 .write = dock_write,
2344 .notify = dock_notify,
2345 .handle = &dock_handle,
2346 .type = ACPI_SYSTEM_NOTIFY,
2347 },
2348 {
2349 .name = "dock",
2350 .hid = IBM_PCI_HID,
2351 .notify = dock_notify,
2352 .handle = &pci_handle,
2353 .type = ACPI_SYSTEM_NOTIFY,
2354 },
2355#endif
2356 {
2357 .name = "bay",
2358 .init = bay_init,
2359 .read = bay_read,
2360 .write = bay_write,
2361 .notify = bay_notify,
2362 .handle = &bay_handle,
2363 .type = ACPI_SYSTEM_NOTIFY,
2364 },
2365 {
2366 .name = "cmos",
2367 .read = cmos_read,
2368 .write = cmos_write,
2369 },
2370 {
2371 .name = "led",
2372 .init = led_init,
2373 .read = led_read,
2374 .write = led_write,
2375 },
2376 {
2377 .name = "beep",
2378 .read = beep_read,
2379 .write = beep_write,
2380 },
2381 {
2382 .name = "thermal",
2383 .init = thermal_init,
2384 .read = thermal_read,
2385 },
2386 {
2387 .name = "ecdump",
2388 .read = ecdump_read,
2389 .write = ecdump_write,
2390 .experimental = 1,
2391 },
2392 {
2393 .name = "brightness",
2394 .read = brightness_read,
2395 .write = brightness_write,
2396 .init = brightness_init,
2397 .exit = brightness_exit,
2398 },
2399 {
2400 .name = "volume",
2401 .read = volume_read,
2402 .write = volume_write,
2403 },
2404 {
2405 .name = "fan",
2406 .read = fan_read,
2407 .write = fan_write,
2408 .init = fan_init,
2409 .exit = fan_exit,
2410 .experimental = 1,
2411 },
2412};
2413
2414static int dispatch_read(char *page, char **start, off_t off, int count,
2415 int *eof, void *data)
2416{
2417 struct ibm_struct *ibm = data;
2418 int len;
2419
2420 if (!ibm || !ibm->read)
2421 return -EINVAL;
2422
2423 len = ibm->read(page);
2424 if (len < 0)
2425 return len;
2426
2427 if (len <= off + count)
2428 *eof = 1;
2429 *start = page + off;
2430 len -= off;
2431 if (len > count)
2432 len = count;
2433 if (len < 0)
2434 len = 0;
2435
2436 return len;
2437}
2438
2439static int dispatch_write(struct file *file, const char __user * userbuf,
2440 unsigned long count, void *data)
2441{
2442 struct ibm_struct *ibm = data;
2443 char *kernbuf;
2444 int ret;
2445
2446 if (!ibm || !ibm->write)
2447 return -EINVAL;
2448
2449 kernbuf = kmalloc(count + 2, GFP_KERNEL);
2450 if (!kernbuf)
2451 return -ENOMEM;
2452
2453 if (copy_from_user(kernbuf, userbuf, count)) {
2454 kfree(kernbuf);
2455 return -EFAULT;
2456 }
2457
2458 kernbuf[count] = 0;
2459 strcat(kernbuf, ",");
2460 ret = ibm->write(kernbuf);
2461 if (ret == 0)
2462 ret = count;
2463
2464 kfree(kernbuf);
2465
2466 return ret;
2467}
2468
2469static void dispatch_notify(acpi_handle handle, u32 event, void *data)
2470{
2471 struct ibm_struct *ibm = data;
2472
2473 if (!ibm || !ibm->notify)
2474 return;
2475
2476 ibm->notify(ibm, event);
2477}
2478
2479static int __init setup_notify(struct ibm_struct *ibm)
2480{
2481 acpi_status status;
2482 int ret;
2483
2484 if (!*ibm->handle)
2485 return 0;
2486
2487 ret = acpi_bus_get_device(*ibm->handle, &ibm->device);
2488 if (ret < 0) {
2489 printk(IBM_ERR "%s device not present\n", ibm->name);
2490 return 0;
2491 }
2492
2493 acpi_driver_data(ibm->device) = ibm;
2494 sprintf(acpi_device_class(ibm->device), "%s/%s", IBM_NAME, ibm->name);
2495
2496 status = acpi_install_notify_handler(*ibm->handle, ibm->type,
2497 dispatch_notify, ibm);
2498 if (ACPI_FAILURE(status)) {
2499 printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
2500 ibm->name, status);
2501 return -ENODEV;
2502 }
2503 ibm->notify_installed = 1;
2504 return 0;
2505}
2506
2507static int __init ibm_device_add(struct acpi_device *device)
2508{
2509 return 0;
2510}
2511
2512static int __init register_driver(struct ibm_struct *ibm)
2513{
2514 int ret;
2515
2516 ibm->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
2517 if (!ibm->driver) {
2518 printk(IBM_ERR "kmalloc(ibm->driver) failed\n");
2519 return -1;
2520 }
2521
2522 sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name);
2523 ibm->driver->ids = ibm->hid;
2524 ibm->driver->ops.add = &ibm_device_add;
2525
2526 ret = acpi_bus_register_driver(ibm->driver);
2527 if (ret < 0) {
2528 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
2529 ibm->hid, ret);
2530 kfree(ibm->driver);
2531 }
2532
2533 return ret;
2534}
2535
2536static int __init ibm_init(struct ibm_struct *ibm)
2537{
2538 int ret;
2539 struct proc_dir_entry *entry;
2540
2541 if (ibm->experimental && !experimental)
2542 return 0;
2543
2544 if (ibm->hid) {
2545 ret = register_driver(ibm);
2546 if (ret < 0)
2547 return ret;
2548 ibm->driver_registered = 1;
2549 }
2550
2551 if (ibm->init) {
2552 ret = ibm->init();
2553 if (ret != 0)
2554 return ret;
2555 ibm->init_called = 1;
2556 }
2557
2558 if (ibm->read) {
2559 entry = create_proc_entry(ibm->name,
2560 S_IFREG | S_IRUGO | S_IWUSR,
2561 proc_dir);
2562 if (!entry) {
2563 printk(IBM_ERR "unable to create proc entry %s\n",
2564 ibm->name);
2565 return -ENODEV;
2566 }
2567 entry->owner = THIS_MODULE;
2568 entry->data = ibm;
2569 entry->read_proc = &dispatch_read;
2570 if (ibm->write)
2571 entry->write_proc = &dispatch_write;
2572 ibm->proc_created = 1;
2573 }
2574
2575 if (ibm->notify) {
2576 ret = setup_notify(ibm);
2577 if (ret < 0)
2578 return ret;
2579 }
2580
2581 return 0;
2582}
2583
2584static void ibm_exit(struct ibm_struct *ibm)
2585{
2586 if (ibm->notify_installed)
2587 acpi_remove_notify_handler(*ibm->handle, ibm->type,
2588 dispatch_notify);
2589
2590 if (ibm->proc_created)
2591 remove_proc_entry(ibm->name, proc_dir);
2592
2593 if (ibm->init_called && ibm->exit)
2594 ibm->exit();
2595
2596 if (ibm->driver_registered) {
2597 acpi_bus_unregister_driver(ibm->driver);
2598 kfree(ibm->driver);
2599 }
2600}
2601
2602static void __init ibm_handle_init(char *name,
2603 acpi_handle * handle, acpi_handle parent,
2604 char **paths, int num_paths, char **path)
2605{
2606 int i;
2607 acpi_status status;
2608
2609 for (i = 0; i < num_paths; i++) {
2610 status = acpi_get_handle(parent, paths[i], handle);
2611 if (ACPI_SUCCESS(status)) {
2612 *path = paths[i];
2613 return;
2614 }
2615 }
2616
2617 *handle = NULL;
2618}
2619
2620#define IBM_HANDLE_INIT(object) \
2621 ibm_handle_init(#object, &object##_handle, *object##_parent, \
2622 object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
2623
2624static int __init set_ibm_param(const char *val, struct kernel_param *kp)
2625{
2626 unsigned int i;
2627
2628 for (i = 0; i < ARRAY_SIZE(ibms); i++)
2629 if (strcmp(ibms[i].name, kp->name) == 0 && ibms[i].write) {
2630 if (strlen(val) > sizeof(ibms[i].param) - 2)
2631 return -ENOSPC;
2632 strcpy(ibms[i].param, val);
2633 strcat(ibms[i].param, ",");
2634 return 0;
2635 }
2636
2637 return -EINVAL;
2638}
2639
2640#define IBM_PARAM(feature) \
2641 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
2642
2643IBM_PARAM(hotkey);
2644IBM_PARAM(bluetooth);
2645IBM_PARAM(video);
2646IBM_PARAM(light);
2647#ifdef CONFIG_ACPI_IBM_DOCK
2648IBM_PARAM(dock);
2649#endif
2650IBM_PARAM(bay);
2651IBM_PARAM(cmos);
2652IBM_PARAM(led);
2653IBM_PARAM(beep);
2654IBM_PARAM(ecdump);
2655IBM_PARAM(brightness);
2656IBM_PARAM(volume);
2657IBM_PARAM(fan);
2658
2659static void acpi_ibm_exit(void)
2660{
2661 int i;
2662
2663 for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
2664 ibm_exit(&ibms[i]);
2665
2666 if (proc_dir)
2667 remove_proc_entry(IBM_DIR, acpi_root_dir);
2668
2669 if (ibm_thinkpad_ec_found)
2670 kfree(ibm_thinkpad_ec_found);
2671}
2672
2673static char* __init check_dmi_for_ec(void)
2674{
2675 struct dmi_device *dev = NULL;
2676 char ec_fw_string[18];
2677
2678 /*
2679 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
2680 * X32 or newer, all Z series; Some models must have an
2681 * up-to-date BIOS or they will not be detected.
2682 *
2683 * See http://thinkwiki.org/wiki/List_of_DMI_IDs
2684 */
2685 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
2686 if (sscanf(dev->name,
2687 "IBM ThinkPad Embedded Controller -[%17c",
2688 ec_fw_string) == 1) {
2689 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
2690 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
2691 return kstrdup(ec_fw_string, GFP_KERNEL);
2692 }
2693 }
2694 return NULL;
2695}
2696
2697static int __init acpi_ibm_init(void)
2698{
2699 int ret, i;
2700
2701 if (acpi_disabled)
2702 return -ENODEV;
2703
2704 /* ec is required because many other handles are relative to it */
2705 IBM_HANDLE_INIT(ec);
2706 if (!ec_handle) {
2707 printk(IBM_ERR "ec object not found\n");
2708 return -ENODEV;
2709 }
2710
2711 /* Models with newer firmware report the EC in DMI */
2712 ibm_thinkpad_ec_found = check_dmi_for_ec();
2713
2714 /* these handles are not required */
2715 IBM_HANDLE_INIT(vid);
2716 IBM_HANDLE_INIT(vid2);
2717 IBM_HANDLE_INIT(ledb);
2718 IBM_HANDLE_INIT(led);
2719 IBM_HANDLE_INIT(hkey);
2720 IBM_HANDLE_INIT(lght);
2721 IBM_HANDLE_INIT(cmos);
2722#ifdef CONFIG_ACPI_IBM_DOCK
2723 IBM_HANDLE_INIT(dock);
2724#endif
2725 IBM_HANDLE_INIT(pci);
2726 IBM_HANDLE_INIT(bay);
2727 if (bay_handle)
2728 IBM_HANDLE_INIT(bay_ej);
2729 IBM_HANDLE_INIT(bay2);
2730 if (bay2_handle)
2731 IBM_HANDLE_INIT(bay2_ej);
2732 IBM_HANDLE_INIT(beep);
2733 IBM_HANDLE_INIT(ecrd);
2734 IBM_HANDLE_INIT(ecwr);
2735 IBM_HANDLE_INIT(fans);
2736 IBM_HANDLE_INIT(gfan);
2737 IBM_HANDLE_INIT(sfan);
2738
2739 proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
2740 if (!proc_dir) {
2741 printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
2742 acpi_ibm_exit();
2743 return -ENODEV;
2744 }
2745 proc_dir->owner = THIS_MODULE;
2746
2747 for (i = 0; i < ARRAY_SIZE(ibms); i++) {
2748 ret = ibm_init(&ibms[i]);
2749 if (ret >= 0 && *ibms[i].param)
2750 ret = ibms[i].write(ibms[i].param);
2751 if (ret < 0) {
2752 acpi_ibm_exit();
2753 return ret;
2754 }
2755 }
2756
2757 return 0;
2758}
2759
2760module_init(acpi_ibm_init);
2761module_exit(acpi_ibm_exit);
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index aa6370c67ec1..26fd0dd6953d 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
154 * Execute the method via the interpreter. The interpreter is locked 154 * Execute the method via the interpreter. The interpreter is locked
155 * here before calling into the AML parser 155 * here before calling into the AML parser
156 */ 156 */
157 acpi_ex_enter_interpreter(); 157 status = acpi_ex_enter_interpreter();
158 if (ACPI_FAILURE(status)) {
159 return_ACPI_STATUS(status);
160 }
161
158 status = acpi_ps_execute_method(info); 162 status = acpi_ps_execute_method(info);
159 acpi_ex_exit_interpreter(); 163 acpi_ex_exit_interpreter();
160 } else { 164 } else {
@@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
178 * resolution, we must lock it because we could access an opregion. 182 * resolution, we must lock it because we could access an opregion.
179 * The opregion access code assumes that the interpreter is locked. 183 * The opregion access code assumes that the interpreter is locked.
180 */ 184 */
181 acpi_ex_enter_interpreter(); 185 status = acpi_ex_enter_interpreter();
186 if (ACPI_FAILURE(status)) {
187 return_ACPI_STATUS(status);
188 }
182 189
183 /* Function has a strange interface */ 190 /* Function has a strange interface */
184 191
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 33db2241044e..c4ab615f77fe 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -214,7 +214,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
214 u32 level, void *context, void **return_value) 214 u32 level, void *context, void **return_value)
215{ 215{
216 acpi_object_type type; 216 acpi_object_type type;
217 acpi_status status = AE_OK; 217 acpi_status status;
218 struct acpi_init_walk_info *info = 218 struct acpi_init_walk_info *info =
219 (struct acpi_init_walk_info *)context; 219 (struct acpi_init_walk_info *)context;
220 struct acpi_namespace_node *node = 220 struct acpi_namespace_node *node =
@@ -268,7 +268,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
268 /* 268 /*
269 * Must lock the interpreter before executing AML code 269 * Must lock the interpreter before executing AML code
270 */ 270 */
271 acpi_ex_enter_interpreter(); 271 status = acpi_ex_enter_interpreter();
272 if (ACPI_FAILURE(status)) {
273 return (status);
274 }
272 275
273 /* 276 /*
274 * Each of these types can contain executable AML code within the 277 * Each of these types can contain executable AML code within the
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 7ac6ace50059..8904d0fae6a2 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -170,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle,
170 struct acpi_buffer *return_buffer) 170 struct acpi_buffer *return_buffer)
171{ 171{
172 acpi_status status; 172 acpi_status status;
173 acpi_status status2;
173 struct acpi_evaluate_info *info; 174 struct acpi_evaluate_info *info;
174 acpi_size buffer_space_needed; 175 acpi_size buffer_space_needed;
175 u32 i; 176 u32 i;
@@ -328,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle,
328 * Delete the internal return object. NOTE: Interpreter must be 329 * Delete the internal return object. NOTE: Interpreter must be
329 * locked to avoid race condition. 330 * locked to avoid race condition.
330 */ 331 */
331 acpi_ex_enter_interpreter(); 332 status2 = acpi_ex_enter_interpreter();
333 if (ACPI_SUCCESS(status2)) {
332 334
333 /* Remove one reference on the return object (should delete it) */ 335 /* Remove one reference on the return object (should delete it) */
334 336
335 acpi_ut_remove_reference(info->return_object); 337 acpi_ut_remove_reference(info->return_object);
336 acpi_ex_exit_interpreter(); 338 acpi_ex_exit_interpreter();
339 }
337 } 340 }
338 341
339 cleanup: 342 cleanup:
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 1ef338545dfe..4ffecd179702 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -436,8 +436,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
436 cl = &device->power.states[device->power.state].resources; 436 cl = &device->power.states[device->power.state].resources;
437 tl = &device->power.states[state].resources; 437 tl = &device->power.states[state].resources;
438 438
439 device->power.state = ACPI_STATE_UNKNOWN;
440
441 if (!cl->count && !tl->count) { 439 if (!cl->count && !tl->count) {
442 result = -ENODEV; 440 result = -ENODEV;
443 goto end; 441 goto end;
@@ -468,12 +466,15 @@ int acpi_power_transition(struct acpi_device *device, int state)
468 goto end; 466 goto end;
469 } 467 }
470 468
471 /* We shouldn't change the state till all above operations succeed */ 469 end:
472 device->power.state = state; 470 if (result) {
473 end: 471 device->power.state = ACPI_STATE_UNKNOWN;
474 if (result)
475 printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n", 472 printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
476 device->pnp.bus_id, state); 473 device->pnp.bus_id, state);
474 } else {
475 /* We shouldn't change the state till all above operations succeed */
476 device->power.state = state;
477 }
477 478
478 return result; 479 return result;
479} 480}
@@ -687,13 +688,6 @@ static int acpi_power_resume(struct acpi_device *device)
687 return result; 688 return result;
688 689
689 mutex_lock(&resource->resource_lock); 690 mutex_lock(&resource->resource_lock);
690 if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) &&
691 list_empty(&resource->reference)) {
692 mutex_unlock(&resource->resource_lock);
693 result = acpi_power_off_device(device->handle, NULL);
694 return result;
695 }
696
697 if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && 691 if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
698 !list_empty(&resource->reference)) { 692 !list_empty(&resource->reference)) {
699 ref = container_of(resource->reference.next, struct acpi_power_reference, node); 693 ref = container_of(resource->reference.next, struct acpi_power_reference, node);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 99d1516d1e70..f7de02a6f497 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -70,8 +70,6 @@
70#define ACPI_PROCESSOR_LIMIT_USER 0 70#define ACPI_PROCESSOR_LIMIT_USER 0
71#define ACPI_PROCESSOR_LIMIT_THERMAL 1 71#define ACPI_PROCESSOR_LIMIT_THERMAL 1
72 72
73#define ACPI_STA_PRESENT 0x00000001
74
75#define _COMPONENT ACPI_PROCESSOR_COMPONENT 73#define _COMPONENT ACPI_PROCESSOR_COMPONENT
76ACPI_MODULE_NAME("processor_core"); 74ACPI_MODULE_NAME("processor_core");
77 75
@@ -779,7 +777,7 @@ static int is_processor_present(acpi_handle handle)
779 777
780 778
781 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 779 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
782 if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) { 780 if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
783 ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); 781 ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
784 return 0; 782 return 0;
785 } 783 }
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 60773005b8af..ae0654cd11ea 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -51,14 +51,6 @@
51#include <asm/apic.h> 51#include <asm/apic.h>
52#endif 52#endif
53 53
54/*
55 * Include the apic definitions for x86 to have the APIC timer related defines
56 * available also for UP (on SMP it gets magically included via linux/smp.h).
57 */
58#ifdef CONFIG_X86
59#include <asm/apic.h>
60#endif
61
62#include <asm/io.h> 54#include <asm/io.h>
63#include <asm/uaccess.h> 55#include <asm/uaccess.h>
64 56
@@ -268,6 +260,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
268 struct acpi_processor_cx *cx) 260 struct acpi_processor_cx *cx)
269{ 261{
270 struct acpi_processor_power *pwr = &pr->power; 262 struct acpi_processor_power *pwr = &pr->power;
263 u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2;
271 264
272 /* 265 /*
273 * Check, if one of the previous states already marked the lapic 266 * Check, if one of the previous states already marked the lapic
@@ -276,7 +269,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
276 if (pwr->timer_broadcast_on_state < state) 269 if (pwr->timer_broadcast_on_state < state)
277 return; 270 return;
278 271
279 if (cx->type >= ACPI_STATE_C2) 272 if (cx->type >= type)
280 pr->power.timer_broadcast_on_state = state; 273 pr->power.timer_broadcast_on_state = state;
281} 274}
282 275
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 1358c06a969c..cc48ab05676c 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -191,6 +191,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
191 user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); 191 user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
192 192
193 for (index = 0; index < number_of_elements; index++) { 193 for (index = 0; index < number_of_elements; index++) {
194 int source_name_index = 2;
195 int source_index_index = 3;
196
194 /* 197 /*
195 * Point user_prt past this current structure 198 * Point user_prt past this current structure
196 * 199 *
@@ -261,10 +264,28 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
261 } 264 }
262 265
263 /* 266 /*
267 * If BIOS erroneously reversed the _PRT source_name and source_index,
268 * then reverse them back.
269 */
270 if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) {
271 if (acpi_gbl_enable_interpreter_slack) {
272 source_name_index = 3;
273 source_index_index = 2;
274 printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n");
275 } else {
276 ACPI_ERROR((AE_INFO,
277 "(PRT[%X].source_index) Need Integer, found %s",
278 index,
279 acpi_ut_get_object_type_name(sub_object_list[3])));
280 return_ACPI_STATUS(AE_BAD_DATA);
281 }
282 }
283
284 /*
264 * 3) Third subobject: Dereference the PRT.source_name 285 * 3) Third subobject: Dereference the PRT.source_name
265 * The name may be unresolved (slack mode), so allow a null object 286 * The name may be unresolved (slack mode), so allow a null object
266 */ 287 */
267 obj_desc = sub_object_list[2]; 288 obj_desc = sub_object_list[source_name_index];
268 if (obj_desc) { 289 if (obj_desc) {
269 switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { 290 switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
270 case ACPI_TYPE_LOCAL_REFERENCE: 291 case ACPI_TYPE_LOCAL_REFERENCE:
@@ -339,7 +360,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
339 360
340 /* 4) Fourth subobject: Dereference the PRT.source_index */ 361 /* 4) Fourth subobject: Dereference the PRT.source_index */
341 362
342 obj_desc = sub_object_list[3]; 363 obj_desc = sub_object_list[source_index_index];
343 if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { 364 if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
344 user_prt->source_index = (u32) obj_desc->integer.value; 365 user_prt->source_index = (u32) obj_desc->integer.value;
345 } else { 366 } else {
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index bb0e0da39fb1..d80dd84e5bfd 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1068,7 +1068,9 @@ acpi_add_single_object(struct acpi_device **child,
1068 } 1068 }
1069 break; 1069 break;
1070 default: 1070 default:
1071 STRUCT_TO_INT(device->status) = 0x0F; 1071 STRUCT_TO_INT(device->status) =
1072 ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
1073 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
1072 break; 1074 break;
1073 } 1075 }
1074 1076
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index ccc11b33d89c..2d912b71e543 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -350,21 +350,31 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
350{ 350{
351 struct list_head *node, *next; 351 struct list_head *node, *next;
352 352
353 seq_printf(seq, "Device Sleep state Status\n"); 353 seq_printf(seq, "Device\tS-state\t Status Sysfs node\n");
354 354
355 spin_lock(&acpi_device_lock); 355 spin_lock(&acpi_device_lock);
356 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 356 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
357 struct acpi_device *dev = 357 struct acpi_device *dev =
358 container_of(node, struct acpi_device, wakeup_list); 358 container_of(node, struct acpi_device, wakeup_list);
359 struct device *ldev;
359 360
360 if (!dev->wakeup.flags.valid) 361 if (!dev->wakeup.flags.valid)
361 continue; 362 continue;
362 spin_unlock(&acpi_device_lock); 363 spin_unlock(&acpi_device_lock);
363 seq_printf(seq, "%4s %4d %s%8s\n", 364
365 ldev = acpi_get_physical_device(dev->handle);
366 seq_printf(seq, "%s\t S%d\t%c%-8s ",
364 dev->pnp.bus_id, 367 dev->pnp.bus_id,
365 (u32) dev->wakeup.sleep_state, 368 (u32) dev->wakeup.sleep_state,
366 dev->wakeup.flags.run_wake ? "*" : "", 369 dev->wakeup.flags.run_wake ? '*' : ' ',
367 dev->wakeup.state.enabled ? "enabled" : "disabled"); 370 dev->wakeup.state.enabled ? "enabled" : "disabled");
371 if (ldev)
372 seq_printf(seq, "%s:%s",
373 ldev->bus ? ldev->bus->name : "no-bus",
374 ldev->bus_id);
375 seq_printf(seq, "\n");
376 put_device(ldev);
377
368 spin_lock(&acpi_device_lock); 378 spin_lock(&acpi_device_lock);
369 } 379 }
370 spin_unlock(&acpi_device_lock); 380 spin_unlock(&acpi_device_lock);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 849e2c361804..c3419182c9a7 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -42,7 +42,9 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
42 42
43static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; 43static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
44 44
45void acpi_table_print_madt_entry(struct acpi_subtable_header * header) 45static int acpi_apic_instance __initdata;
46
47void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
46{ 48{
47 if (!header) 49 if (!header)
48 return; 50 return;
@@ -183,8 +185,10 @@ acpi_table_parse_entries(char *id,
183 if (!handler) 185 if (!handler)
184 return -EINVAL; 186 return -EINVAL;
185 187
186 /* Locate the table (if exists). There should only be one. */ 188 if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
187 acpi_get_table(id, 0, &table_header); 189 acpi_get_table(id, acpi_apic_instance, &table_header);
190 else
191 acpi_get_table(id, 0, &table_header);
188 192
189 if (!table_header) { 193 if (!table_header) {
190 printk(KERN_WARNING PREFIX "%4.4s not present\n", id); 194 printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
@@ -237,10 +241,15 @@ acpi_table_parse_madt(enum acpi_madt_type id,
237int __init acpi_table_parse(char *id, acpi_table_handler handler) 241int __init acpi_table_parse(char *id, acpi_table_handler handler)
238{ 242{
239 struct acpi_table_header *table = NULL; 243 struct acpi_table_header *table = NULL;
244
240 if (!handler) 245 if (!handler)
241 return -EINVAL; 246 return -EINVAL;
242 247
243 acpi_get_table(id, 0, &table); 248 if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
249 acpi_get_table(id, acpi_apic_instance, &table);
250 else
251 acpi_get_table(id, 0, &table);
252
244 if (table) { 253 if (table) {
245 handler(table); 254 handler(table);
246 return 0; 255 return 0;
@@ -248,6 +257,31 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
248 return 1; 257 return 1;
249} 258}
250 259
260/*
261 * The BIOS is supposed to supply a single APIC/MADT,
262 * but some report two. Provide a knob to use either.
263 * (don't you wish instance 0 and 1 were not the same?)
264 */
265static void __init check_multiple_madt(void)
266{
267 struct acpi_table_header *table = NULL;
268
269 acpi_get_table(ACPI_SIG_MADT, 2, &table);
270 if (table) {
271 printk(KERN_WARNING PREFIX
272 "BIOS bug: multiple APIC/MADT found,"
273 " using %d\n", acpi_apic_instance);
274 printk(KERN_WARNING PREFIX
275 "If \"acpi_apic_instance=%d\" works better, "
276 "notify linux-acpi@vger.kernel.org\n",
277 acpi_apic_instance ? 0 : 2);
278
279 } else
280 acpi_apic_instance = 0;
281
282 return;
283}
284
251/* 285/*
252 * acpi_table_init() 286 * acpi_table_init()
253 * 287 *
@@ -257,9 +291,22 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
257 * result: sdt_entry[] is initialized 291 * result: sdt_entry[] is initialized
258 */ 292 */
259 293
260
261int __init acpi_table_init(void) 294int __init acpi_table_init(void)
262{ 295{
263 acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); 296 acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
297 check_multiple_madt();
298 return 0;
299}
300
301static int __init acpi_parse_apic_instance(char *str)
302{
303
304 acpi_apic_instance = simple_strtoul(str, NULL, 0);
305
306 printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n",
307 acpi_apic_instance);
308
264 return 0; 309 return 0;
265} 310}
311
312early_param("acpi_apic_instance", acpi_parse_apic_instance);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 0ae8b9310cbf..589b98b7b216 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -758,7 +758,8 @@ static void acpi_thermal_check(void *data)
758 del_timer(&(tz->timer)); 758 del_timer(&(tz->timer));
759 } else { 759 } else {
760 if (timer_pending(&(tz->timer))) 760 if (timer_pending(&(tz->timer)))
761 mod_timer(&(tz->timer), (HZ * sleep_time) / 1000); 761 mod_timer(&(tz->timer),
762 jiffies + (HZ * sleep_time) / 1000);
762 else { 763 else {
763 tz->timer.data = (unsigned long)tz; 764 tz->timer.data = (unsigned long)tz;
764 tz->timer.function = acpi_thermal_run; 765 tz->timer.function = acpi_thermal_run;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 0771b434feb2..00d25b347255 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -102,9 +102,9 @@ struct acpi_video_bus_cap {
102 102
103struct acpi_video_device_attrib { 103struct acpi_video_device_attrib {
104 u32 display_index:4; /* A zero-based instance of the Display */ 104 u32 display_index:4; /* A zero-based instance of the Display */
105 u32 display_port_attachment:4; /*This field differenates displays type */ 105 u32 display_port_attachment:4; /*This field differentiates the display type */
106 u32 display_type:4; /*Describe the specific type in use */ 106 u32 display_type:4; /*Describe the specific type in use */
107 u32 vendor_specific:4; /*Chipset Vendor Specifi */ 107 u32 vendor_specific:4; /*Chipset Vendor Specific */
108 u32 bios_can_detect:1; /*BIOS can detect the device */ 108 u32 bios_can_detect:1; /*BIOS can detect the device */
109 u32 depend_on_vga:1; /*Non-VGA output device whose power is related to 109 u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
110 the VGA device. */ 110 the VGA device. */
@@ -484,16 +484,16 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video,
484 * 0. The system BIOS should NOT automatically switch(toggle) 484 * 0. The system BIOS should NOT automatically switch(toggle)
485 * the active display output. 485 * the active display output.
486 * 1. The system BIOS should automatically switch (toggle) the 486 * 1. The system BIOS should automatically switch (toggle) the
487 * active display output. No swich event. 487 * active display output. No switch event.
488 * 2. The _DGS value should be locked. 488 * 2. The _DGS value should be locked.
489 * 3. The system BIOS should not automatically switch (toggle) the 489 * 3. The system BIOS should not automatically switch (toggle) the
490 * active display output, but instead generate the display switch 490 * active display output, but instead generate the display switch
491 * event notify code. 491 * event notify code.
492 * lcd_flag : 492 * lcd_flag :
493 * 0. The system BIOS should automatically control the brightness level 493 * 0. The system BIOS should automatically control the brightness level
494 * of the LCD, when the power changes from AC to DC 494 * of the LCD when the power changes from AC to DC
495 * 1. The system BIOS should NOT automatically control the brightness 495 * 1. The system BIOS should NOT automatically control the brightness
496 * level of the LCD, when the power changes from AC to DC. 496 * level of the LCD when the power changes from AC to DC.
497 * Return Value: 497 * Return Value:
498 * -1 wrong arg. 498 * -1 wrong arg.
499 */ 499 */
@@ -525,7 +525,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
525 * Return Value: 525 * Return Value:
526 * None 526 * None
527 * 527 *
528 * Find out all required AML method defined under the output 528 * Find out all required AML methods defined under the output
529 * device. 529 * device.
530 */ 530 */
531 531
@@ -636,7 +636,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
636 * Return Value: 636 * Return Value:
637 * None 637 * None
638 * 638 *
639 * Find out all required AML method defined under the video bus device. 639 * Find out all required AML methods defined under the video bus device.
640 */ 640 */
641 641
642static void acpi_video_bus_find_cap(struct acpi_video_bus *video) 642static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
@@ -681,19 +681,19 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
681 * to check well known required nodes. 681 * to check well known required nodes.
682 */ 682 */
683 683
684 /* Does this device able to support video switching ? */ 684 /* Does this device support video switching? */
685 if (video->cap._DOS) { 685 if (video->cap._DOS) {
686 video->flags.multihead = 1; 686 video->flags.multihead = 1;
687 status = 0; 687 status = 0;
688 } 688 }
689 689
690 /* Does this device able to retrieve a retrieve a video ROM ? */ 690 /* Does this device support retrieving a video ROM? */
691 if (video->cap._ROM) { 691 if (video->cap._ROM) {
692 video->flags.rom = 1; 692 video->flags.rom = 1;
693 status = 0; 693 status = 0;
694 } 694 }
695 695
696 /* Does this device able to configure which video device to POST ? */ 696 /* Does this device support configuring which video device to POST? */
697 if (video->cap._GPD && video->cap._SPD && video->cap._VPO) { 697 if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
698 video->flags.post = 1; 698 video->flags.post = 1;
699 status = 0; 699 status = 0;
@@ -860,7 +860,7 @@ acpi_video_device_write_brightness(struct file *file,
860 if (level > 100) 860 if (level > 100)
861 return -EFAULT; 861 return -EFAULT;
862 862
863 /* validate though the list of available levels */ 863 /* validate through the list of available levels */
864 for (i = 0; i < dev->brightness->count; i++) 864 for (i = 0; i < dev->brightness->count; i++)
865 if (level == dev->brightness->levels[i]) { 865 if (level == dev->brightness->levels[i]) {
866 if (ACPI_SUCCESS 866 if (ACPI_SUCCESS
@@ -1065,10 +1065,10 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
1065 printk(KERN_WARNING PREFIX 1065 printk(KERN_WARNING PREFIX
1066 "The motherboard VGA device is not listed as a possible POST device.\n"); 1066 "The motherboard VGA device is not listed as a possible POST device.\n");
1067 printk(KERN_WARNING PREFIX 1067 printk(KERN_WARNING PREFIX
1068 "This indicate a BIOS bug. Please contact the manufacturer.\n"); 1068 "This indicates a BIOS bug. Please contact the manufacturer.\n");
1069 } 1069 }
1070 printk("%lx\n", options); 1070 printk("%lx\n", options);
1071 seq_printf(seq, "can POST: <intgrated video>"); 1071 seq_printf(seq, "can POST: <integrated video>");
1072 if (options & 2) 1072 if (options & 2)
1073 seq_printf(seq, " <PCI video>"); 1073 seq_printf(seq, " <PCI video>");
1074 if (options & 4) 1074 if (options & 4)
@@ -1102,7 +1102,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
1102 seq_printf(seq, "<not supported>\n"); 1102 seq_printf(seq, "<not supported>\n");
1103 goto end; 1103 goto end;
1104 } 1104 }
1105 seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]); 1105 seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
1106 1106
1107 end: 1107 end:
1108 return 0; 1108 return 0;
@@ -1156,7 +1156,7 @@ acpi_video_bus_write_POST(struct file *file,
1156 if (opt > 3) 1156 if (opt > 3)
1157 return -EFAULT; 1157 return -EFAULT;
1158 1158
1159 /* just in case an OEM 'forget' the motherboard... */ 1159 /* just in case an OEM 'forgot' the motherboard... */
1160 options |= 1; 1160 options |= 1;
1161 1161
1162 if (options & (1ul << opt)) { 1162 if (options & (1ul << opt)) {
@@ -1527,13 +1527,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1527/* 1527/*
1528 * Arg: 1528 * Arg:
1529 * video : video bus device 1529 * video : video bus device
1530 * event : Nontify Event 1530 * event : notify event
1531 * 1531 *
1532 * Return: 1532 * Return:
1533 * < 0 : error 1533 * < 0 : error
1534 * 1534 *
1535 * 1. Find out the current active output device. 1535 * 1. Find out the current active output device.
1536 * 2. Identify the next output device to switch 1536 * 2. Identify the next output device to switch to.
1537 * 3. call _DSS to do actual switch. 1537 * 3. call _DSS to do actual switch.
1538 */ 1538 */
1539 1539
@@ -1723,12 +1723,12 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
1723 device = video->device; 1723 device = video->device;
1724 1724
1725 switch (event) { 1725 switch (event) {
1726 case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur, 1726 case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
1727 * most likely via hotkey. */ 1727 * most likely via hotkey. */
1728 acpi_bus_generate_event(device, event, 0); 1728 acpi_bus_generate_event(device, event, 0);
1729 break; 1729 break;
1730 1730
1731 case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video 1731 case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
1732 * connector. */ 1732 * connector. */
1733 acpi_video_device_enumerate(video); 1733 acpi_video_device_enumerate(video);
1734 acpi_video_device_rebind(video); 1734 acpi_video_device_rebind(video);