GIT 2685e3e10687065f48a8d2b2b7fd95655ba15d78 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git#test commit 1f54ac7844f7a14186a41a38fb7acdcf6a277f9a Author: akpm@osdl.org Date: Mon Aug 21 18:53:00 2006 -0400 ACPI: consolidate functions in acpi ec driver Unify the following functions: acpi_ec_poll_read() acpi_ec_poll_write() acpi_ec_poll_query() acpi_ec_intr_read() acpi_ec_intr_write() acpi_ec_intr_query() into: acpi_ec_poll_transaction() acpi_ec_intr_transaction() These new functions take as arguments an ACPI EC command, a few bytes to write to the EC data register and a buffer for a few bytes to read from the EC data register. The old _read(), _write(), _query() are just special cases of these functions. Then unified the code in acpi_ec_poll_transaction() and acpi_ec_intr_transaction() a little more. Both functions are now just wrappers around the new acpi_ec_transaction_unlocked() function. The latter contains the EC access logic, the two original function now just do their special way of locking and call the the new function for the actual work. This saves a lot of very similar code. The primary reason for doing this, however, is that my driver for MSI 270 laptops needs to issue some non-standard EC commands in a safe way. Due to this I added a new exported function similar to ec_write()/ec_write() which is called ec_transaction() and is essentially just a wrapper around acpi_ec_{poll,intr}_transaction(). Signed-off-by: Lennart Poettering Acked-by: Luming Yu Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 37a009117555ef06afff837f9e56d6931f50e226 Author: Marek W Date: Mon Aug 14 22:37:20 2006 -0700 ASUS ACPI: W3000 support Add support for W3000 (W3V) and indirectly fixes an issue with kmilo under KDE (it was triggering excessive LCD read error messages by querying asus_acpi module) allowing people (I am probably the only one who tested this) with W3000 to run kmilo. Cc: Karol Kozimor Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 10906c1321c6aa7803bdc3d14e543bcadc80e989 Author: Jiri Kosina Date: Thu Aug 24 00:36:19 2006 -0400 ACPI: acpi_pci_link_set() can allocate with either GFP_ATOMIC or GFP_KERNEL acpi_pci_link_set() allocates both with interrupts on and with interrupts off (resume-time), so check interrupts and decide on GFP_ATOMIC or GFP_KERNEL at run-time. Signed-off-by: Jiri Kosina Signed-off-by: Len Brown commit 439a00734e2065c468ae11586ae85af2bfa5fb49 Author: Dmitry Torokhov Date: Wed Aug 23 23:18:06 2006 -0400 ACPI: fix potential OOPS in power driver with CONFIG_ACPI_DEBUG device was set to null and used before set in a debug printk Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown commit df6fd31995cb2e38b2a7e94bc8f1559b8f55404e Author: Starikovskiy, Alexey Y Date: Fri Aug 18 11:23:00 2006 -0400 ACPI: relax BAD_MADT_ENTRY check to allow LSAPIC variable length string UIDs ACPI 3.0 appended a variable length UID string to the LAPIC structure as part of support for > 256 processors. So the BAD_MADT_ENTRY() sanity check can no longer compare for equality with a fixed structure length. Signed-off-by: Alexey Y Starikovskiy Signed-off-by: Len Brown commit d68909f4c3eee09c13d4e5c86512c6c075553dbd Author: Len Brown Date: Wed Aug 16 19:16:58 2006 -0400 ACPI: avoid irqrouter_resume might_sleep oops on resume from S4 __might_sleep+0x8e/0x93 acpi_os_wait_semaphore+0x50/0xa3 acpi_ut_acquire_mutex+0x28/0x6a acpi_ns_get_node+0x46/0x88 acpi_ns_evaluate+0x2d/0xfc acpi_rs_set_srs_method_data+0xc5/0xe1 acpi_set_current_resources+0x31/0x3f acpi_pci_link_set+0xfc/0x1a5 irqrouter_resume+0x48/0x5f and __might_sleep+0x8e/0x93 kmem_cache_alloc+0x2a/0x8f acpi_evaluate_integer+0x32/0x96 acpi_bus_get_status+0x30/0x84 acpi_pci_link_set+0x12a/0x1a5 irqrouter_resume+0x48/0x5f http://bugzilla.kernel.org/show_bug.cgi?id=6810 Signed-off-by: Len Brown commit 5672bde6355f2d12c49df1eec083d25afe489063 Author: Handle X Date: Mon Aug 14 22:37:27 2006 -0700 ACPI: hotkey.c fixes, fix for potential crash of hotkey.c While going through the code, I found out some memory leaks and potential crashes in drivers/acpi/hotkey.c Please find the patch to fix them. This patch does the following, 1. Fixes memory leaks in error paths of hotkey_write_config 2. Fixes freeing unallocated pointers in the error paths of hotkey_write_config 3. Uses a loop instead of linear searching for parsing the userspace input in get_params 4. Uses array of char * instead of passing 4 pointer parameters explicitly into the init_{poll_}hotkey_* static functions Signed-off-by: Andrew Morton Acked-by: Luming Yu Signed-off-by: Len Brown commit 4e6e6504a4572dee3afcb0925ce92ad559e1e0db Author: William Morrrow Date: Mon Aug 14 22:37:31 2006 -0700 ACPI: Handle BIOS that resumes from S3 to suspend routine rather than resume vector A BIOS has been found that resumes from S3 to the routine that invoked suspend, ignoring the resume vector. This appears to the OS as a failed S3 attempt. This same system suspend/resume's properly with Windows. It is possible to invoke the protected mode register restore routine (which would normally restore the sysenter registers) when the BIOS returns from S3. This has no effect on a correctly running system and repairs the damage from the deviant BIOS. Signed-off-by: William Morrow Signed-off-by: Jordan Crouse Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit f62d31ee2f2f453b07107465fea54540cab418eb Author: Venkatesh Pallipadi Date: Wed Aug 16 01:20:01 2006 -0400 ACPI: Support Processor Native C-state using Intel "mwait" instruction. Newer Intel processors (eg: Core Duo), support processor native C-state using mwait instructions. Refer: Intel Architecture Software Developer's Manual http://www.intel.com/design/Pentium4/manuals/253668.htm Platform firmware exports the support for Native C-state to OS using ACPI _PDC and _CST methods. Refer: Intel Processor Vendor-Specific ACPI: Interface Specification http://www.intel.com/technology/iapc/acpi/downloads/302223.htm With Processor Native C-state, we use 'mwait' instruction on the processor to enter different C-states (C1, C2, C3). We won't use the special IO ports to enter C-state and no SMM mode etc required to enter C-state. Overall this will mean better C-state support. One major advantage of using mwait for all C-states is, with this and "treat interrupt as break event" feature of mwait, we can now get accurate timing for the time spent in C1, C2, .. states. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown commit b5240b32b9b2b75917c478d768191862a2b190cc Author: Kristen Carlson Accardi Date: Wed Jul 26 13:32:00 2006 -0400 ACPIPHP: allow acpiphp to build without ACPI_DOCK Change the build options for acpiphp so that it may build without being dependent on the ACPI_DOCK option, but yet does not allow the option of acpiphp being built-in when dock is built as a module. This does not change the previous patch for ACPI_IBM_DOCK Kconfig. For the following matrix of config options, I built an i386 kernel. Dock acpiphp should it build? confirmed y y y y y n y y y m y y m y no - acpiphp should acpiphp was convert to m converted to m m n y y m m y y n y y y n n y y n m y y Signed-off-by: Anil S Keshavamurthy Signed-off-by: Kristen Carlson Accardi Signed-off-by: Len Brown commit 07dd4855e7fffeb50565826e5e736509ee8f6129 Author: Yasunori Goto Date: Mon Aug 14 22:37:32 2006 -0700 ACPI: memory hotplug: remove useless message at boot time This is to remove noisy useless message at boot. The message is a ton of "ACPI Exception (acpi_memory-0492): AE_ERROR, handle is no memory device" In my emulation, number of memory devices are not so many (only 6), but, this messages are displayed 114 times. It is showed by acpi_memory_register_notify_handler() which is called by acpi_walk_namespace(). acpi_walk_namespace() parses all of ACPI's namespace and execute acpi_memory_register_notify_handler(). So, it is called for all of the device which is defined in namespace. If the parsing device is not memory, acpi_memhotplug ignores it due to "no match" and will parse next device. This is normal route, not an exception. Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit e9a315bcae3b9e0c54fb68ef90d0095956314480 Author: Randy Dunlap Date: Mon Aug 14 22:37:24 2006 -0700 ACPI: verbose on kset/kobject_register errors Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 7daef60721e03809c7e5f8aa8491df4190f6b56f Author: Randy Dunlap Date: Mon Aug 14 22:37:24 2006 -0700 ACPI: add message if firmware_register() init fails Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit b20d2aeb0ad322cbe7fd9120acae6118231b17a3 Author: Len Brown Date: Tue Aug 15 23:21:37 2006 -0400 ACPI: skip smart battery init when acpi=off Signed-off-by: Len Brown commit 4d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbe Author: Pavel Machek Date: Mon Aug 14 22:37:22 2006 -0700 ACPI: fix boot with acpi=off Fix acpi_ac/battery boot with acpi=off Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 0ee6a17389ceef65f1a86c38872fa98f08489022 Author: Jean Delvare Date: Fri Aug 11 08:30:31 2006 +0200 ACPI: fix kfree in i2c_ec error path Signed-off-by: Jean Delvare Signed-off-by: Len Brown commit 5b9c9bf6c92274a6eb74fc8f86586ab592a7a1ec Author: Kristen Carlson Accardi Date: Wed Jul 26 13:59:00 2006 -0400 ACPI: add Dock Station driver to MAINTAINERS file Signed-off-by: Kristen Carlson Accardi Signed-off-by: Len Brown commit 16a74744231e57e354253567490ab9e4ccd2d605 Author: Bjorn Helgaas Date: Wed Apr 5 08:47:00 2006 -0400 PCI: quirk to disable e100 interrupt if RESET failed to Without this quirk, e100 can be pulling on a shared interrupt line when another device (eg. USB) loads, causing the interrupt to scream and get disabled. http://bugzilla.kernel.org/show_bug.cgi?id=5918 Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown commit 9805cb76f7bcd3108e012270d9ef2fd8ea3bea55 Author: Len Brown Date: Tue Jul 25 13:30:57 2006 -0400 ACPI: restore some dmesg to DEBUG-only, ala 2.6.17 The ACPI_EXCEPTION() patch enabled a bunch of messages to print even in the non-DEBUG kernel. Need to change a couple back, and note that ACPI_EXCEPTION takes no \n, but ACPI_DEBUG_PRINT does. No context for object [%p]\n Device `[%s]' is not power manageable\n Signed-off-by: Len Brown commit 9b6d97b64eff08b368375efcf9c1d01eba582ea2 Author: Randy Dunlap Date: Wed Jul 12 02:08:00 2006 -0400 ACPI: scan: handle kset/kobject errors Check and handle kset_register() and kobject_register() init errors. Signed-off-by: Randy Dunlap Signed-off-by: Len Brown commit d568df84f987a9321c1f5826a6c8678ef2bb2b70 Author: Randy Dunlap Date: Wed Jul 12 01:47:00 2006 -0400 ACPI: handle firmware_register init errors Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- diff --git a/MAINTAINERS b/MAINTAINERS index 21116cc..3bab239 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -889,6 +889,12 @@ M: rdunlap@xenotime.net T: git http://tali.admingilde.org/git/linux-docbook.git S: Maintained +DOCKING STATION DRIVER +P: Kristen Carlson Accardi +M: kristen.c.accardi@intel.com +L: linux-acpi@vger.kernel.org +S: Maintained + DOUBLETALK DRIVER P: James R. Van Zandt M: jrv@vanzandt.mv.com diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 0db6387..ee003bc 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -59,7 +59,7 @@ #endif /* X86 */ #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ - ((acpi_table_entry_header *)entry)->length != sizeof(*entry)) + ((acpi_table_entry_header *)entry)->length < sizeof(*entry)) #define PREFIX "ACPI: " diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c index 25db49e..aeb89ba 100644 --- a/arch/i386/kernel/acpi/cstate.c +++ b/arch/i386/kernel/acpi/cstate.c @@ -10,6 +10,7 @@ #include #include #include #include +#include #include #include @@ -41,5 +42,131 @@ void acpi_processor_power_init_bm_check( flags->bm_check = 1; } } - EXPORT_SYMBOL(acpi_processor_power_init_bm_check); + +/* The code below handles the Native cstate entry (with monitor-mwait pair) */ + +struct cstate_entry_s { + struct { + unsigned int eax; + unsigned int ecx; + } states[ACPI_PROCESSOR_MAX_POWER]; +}; +static struct cstate_entry_s *cpu_cstate_entry; /* per CPU ptr */ + +#define MWAIT_SUBSTATE_MASK (0xf) +#define MWAIT_SUBSTATE_SIZE (4) + +#define CPUID_MWAIT_LEAF (5) +#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) +#define CPUID5_ECX_INTERRUPT_BREAK (0x2) + +#define MWAIT_ECX_INTERRUPT_BREAK (0x1) + +#define NATIVE_CSTATE_BEYOND_HALT (2) + +int acpi_processor_native_cstate_check(unsigned int cpu, + struct acpi_processor_cx *cx, struct acpi_power_register *reg) +{ + struct cstate_entry_s *percpu_entry; + struct cpuinfo_x86 *c = cpu_data + cpu; + + cpumask_t saved_mask; + int retval; + unsigned int eax, ebx, ecx, edx; + unsigned int edx_part; + unsigned int cstate_type; /* C-state type and not ACPI C-state type */ + unsigned int num_cstate_subtype; + + if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF ) + return -1; + + if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT) + return -1; + + percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu); + percpu_entry->states[cx->index].eax = 0; + percpu_entry->states[cx->index].ecx = 0; + + /* Make sure we are running on right CPU */ + saved_mask = current->cpus_allowed; + retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); + if (retval) + return -1; + + cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx); + + /* Check whether this particular cx_type (in CST) is supported or not */ + cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1; + edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE); + num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK; + + retval = 0; + if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) { + retval = -1; + goto out; + } + + /* Use the hint in CST */ + percpu_entry->states[cx->index].eax = cx->address; + + /* Check whether this CPU supports mwait ecx extensions */ + if (ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED && + ecx & CPUID5_ECX_INTERRUPT_BREAK) { + percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK; + } + + printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d state\n", + cx->type); + +out: + set_cpus_allowed(current, saved_mask); + return retval; +} +EXPORT_SYMBOL(acpi_processor_native_cstate_check); + +int acpi_processor_native_cstate_enter(struct acpi_processor_cx *cx) +{ + unsigned int cpu = smp_processor_id(); + + struct cstate_entry_s *percpu_entry; + + percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu); + + /* + * Native c-states with monitor-mwait and interrupt break support + * will treat interrupts as break event, even with interrupts disabled. + */ + if ((percpu_entry->states[cx->index].ecx & MWAIT_ECX_INTERRUPT_BREAK)) { + mwait_idle_hints(percpu_entry->states[cx->index].eax, + percpu_entry->states[cx->index].ecx); + return 1; + } + + local_irq_enable(); + mwait_idle_hints(percpu_entry->states[cx->index].eax, + percpu_entry->states[cx->index].ecx); + return 0; +} +EXPORT_SYMBOL(acpi_processor_native_cstate_enter); + +static int native_cstate_init(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + if (c->x86_vendor != X86_VENDOR_INTEL) + return -1; + + cpu_cstate_entry = alloc_percpu(struct cstate_entry_s); + return 0; +} + +static void native_cstate_exit(void) +{ + if (cpu_cstate_entry) { + free_percpu(cpu_cstate_entry); + cpu_cstate_entry = NULL; + } +} + +arch_initcall(native_cstate_init); +__exitcall(native_cstate_exit); diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index 9f408ee..b781b38 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S @@ -292,7 +292,10 @@ ENTRY(do_suspend_lowlevel) pushl $3 call acpi_enter_sleep_state addl $4, %esp - ret + +# In case of S3 failure, we'll emerge here. Jump +# to ret_point to recover + jmp ret_point .p2align 4,,7 ret_point: call restore_registers diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 8657c73..24b7e3b 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -236,19 +236,23 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait); * through MWAIT. Whenever someone changes need_resched, we would be woken * up from MWAIT (without an IPI). */ -static void mwait_idle(void) +void mwait_idle_hints(unsigned long eax, unsigned long ecx) { - local_irq_enable(); - - while (!need_resched()) { + if (!need_resched()) { __monitor((void *)¤t_thread_info()->flags, 0, 0); smp_mb(); - if (need_resched()) - break; - __mwait(0, 0); + if (!need_resched()) + __mwait(eax, ecx); } } +static void mwait_idle(void) +{ + local_irq_enable(); + while (!need_resched()) + mwait_idle_hints(0, 0); +} + void __devinit select_idle_routine(const struct cpuinfo_x86 *c) { if (cpu_has(c, X86_FEATURE_MWAIT)) { diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 99761b8..0176556 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -55,7 +55,7 @@ #include #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ - ((acpi_table_entry_header *)entry)->length != sizeof(*entry)) + ((acpi_table_entry_header *)entry)->length < sizeof(*entry)) #define PREFIX "ACPI: " diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index bb6745d..ca625db 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -236,19 +236,23 @@ void cpu_idle (void) * through MWAIT. Whenever someone changes need_resched, we would be woken * up from MWAIT (without an IPI). */ -static void mwait_idle(void) +void mwait_idle_hints(unsigned long eax, unsigned long ecx) { - local_irq_enable(); - - while (!need_resched()) { + if (!need_resched()) { __monitor((void *)¤t_thread_info()->flags, 0, 0); smp_mb(); - if (need_resched()) - break; - __mwait(0, 0); + if (!need_resched()) + __mwait(eax, ecx); } } +static void mwait_idle(void) +{ + local_irq_enable(); + while (!need_resched()) + mwait_idle_hints(0,0); +} + void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) { static int printed; diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 96309b9..11abc7b 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -285,6 +285,8 @@ static int __init acpi_ac_init(void) { int result; + if (acpi_disabled) + return -ENODEV; acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index b0d4b14..1dda370 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -484,10 +484,8 @@ acpi_memory_register_notify_handler(acpi status = is_memory_device(handle); - if (ACPI_FAILURE(status)){ - ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device")); + if (ACPI_FAILURE(status)) return AE_OK; /* continue */ - } status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify, NULL); @@ -503,10 +501,8 @@ acpi_memory_deregister_notify_handler(ac status = is_memory_device(handle); - if (ACPI_FAILURE(status)){ - ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device")); + if (ACPI_FAILURE(status)) return AE_OK; /* continue */ - } status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index e9ee4c5..ebc033f 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -138,6 +138,7 @@ struct asus_hotk { S2x, //S200 (J1 reported), Victor MP-XP7210 W1N, //W1000N W5A, //W5A + W3V, //W3030V xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N //(Centrino) END_MODEL @@ -376,6 +377,17 @@ static struct model_data model_conf[END_ .display_get = "\\ADVG"}, { + .name = "W3V", + .mt_mled = "MLED", + .mt_wled = "WLED", + .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\BKLT", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\INFB"}, + + { .name = "xxN", .mt_mled = "MLED", /* WLED present, but not controlled by ACPI */ @@ -1097,6 +1109,8 @@ static int asus_model_match(char *model) return A4G; else if (strncmp(model, "W1N", 3) == 0) return W1N; + else if (strncmp(model, "W3V", 3) == 0) + return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; else @@ -1200,9 +1214,10 @@ static int asus_hotk_get_info(void) hotk->methods->mt_wled = NULL; /* L5D's WLED is not controlled by ACPI */ else if (strncmp(string, "M2N", 3) == 0 || + strncmp(string, "W3V", 3) == 0 || strncmp(string, "S1N", 3) == 0) hotk->methods->mt_wled = "WLED"; - /* M2N and S1N have a usable WLED */ + /* M2N, S1N and W3V have a usable WLED */ else if (asus_info) { if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) hotk->methods->mled_status = NULL; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 6e52217..9810e2a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -757,6 +757,9 @@ static int __init acpi_battery_init(void { int result; + if (acpi_disabled) + return -ENODEV; + acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b297769..279c4ba 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,8 @@ int acpi_bus_get_device(acpi_handle hand status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); if (ACPI_FAILURE(status) || !*device) { - ACPI_EXCEPTION((AE_INFO, status, "No context for object [%p]", handle)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", + handle)); return -ENODEV; } @@ -192,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handl /* Make sure this is a valid target state */ if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", device->kobj.name)); return -ENODEV; } @@ -738,7 +740,10 @@ static int __init acpi_init(void) return -ENODEV; } - firmware_register(&acpi_subsys); + result = firmware_register(&acpi_subsys); + if (result < 0) + printk(KERN_WARNING "%s: firmware_register error: %d\n", + __FUNCTION__, result); result = acpi_bus_init(); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e5d7963..a0dcbad 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -122,12 +122,12 @@ union acpi_ec { static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event); static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event); -static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data); -static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data); -static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data); -static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data); -static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data); -static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data); +static int acpi_ec_poll_transaction(union acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len); +static int acpi_ec_intr_transaction(union acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len); static void acpi_ec_gpe_poll_query(void *ec_cxt); static void acpi_ec_gpe_intr_query(void *ec_cxt); static u32 acpi_ec_gpe_poll_handler(void *data); @@ -302,110 +302,95 @@ end: } #endif /* ACPI_FUTURE_USAGE */ -static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data) +static int acpi_ec_transaction(union acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { if (acpi_ec_poll_mode) - return acpi_ec_poll_read(ec, address, data); + return acpi_ec_poll_transaction(ec, command, wdata, wdata_len, rdata, rdata_len); else - return acpi_ec_intr_read(ec, address, data); + return acpi_ec_intr_transaction(ec, command, wdata, wdata_len, rdata, rdata_len); +} +static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data) +{ + int result; + u8 d; + result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, &address, 1, &d, 1); + *data = d; + return result; } static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data) { - if (acpi_ec_poll_mode) - return acpi_ec_poll_write(ec, address, data); - else - return acpi_ec_intr_write(ec, address, data); + u8 wdata[2] = { address, data }; + return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, wdata, 2, NULL, 0); } -static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) + +static int acpi_ec_transaction_unlocked(union acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - acpi_status status = AE_OK; - int result = 0; - u32 glk = 0; + int result; + acpi_hw_low_level_write(8, command, &ec->common.command_addr); - if (!ec || !data) - return -EINVAL; + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + return result; - *data = 0; + for (; wdata_len > 0; wdata_len --) { - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } + acpi_hw_low_level_write(8, *(wdata++), &ec->common.data_addr); - if (down_interruptible(&ec->poll.sem)) { - result = -ERESTARTSYS; - goto end_nosem; - } - - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, - &ec->common.command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + return result; + } - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (result) - goto end; - acpi_hw_low_level_read(8, data, &ec->common.data_addr); + for (; rdata_len > 0; rdata_len --) { + u32 d; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", - *data, address)); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + return result; - end: - up(&ec->poll.sem); -end_nosem: - if (ec->common.global_lock) - acpi_release_global_lock(glk); + acpi_hw_low_level_read(8, &d, &ec->common.data_addr); + *(rdata++) = (u8) d; + } - return result; + return 0; } -static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) +static int acpi_ec_poll_transaction(union acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - int result = 0; acpi_status status = AE_OK; + int result; u32 glk = 0; - - if (!ec) + if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) return -EINVAL; + if (rdata) + memset(rdata, 0, rdata_len); + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return -ENODEV; - } + } if (down_interruptible(&ec->poll.sem)) { result = -ERESTARTSYS; goto end_nosem; } - - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, - &ec->common.command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - - acpi_hw_low_level_write(8, data, &ec->common.data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) - goto end; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", - data, address)); - - end: + result = acpi_ec_transaction_unlocked(ec, command, + wdata, wdata_len, + rdata, rdata_len); up(&ec->poll.sem); + end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -413,16 +398,18 @@ end_nosem: return result; } -static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data) +static int acpi_ec_intr_transaction(union acpi_ec *ec, u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - int status = 0; + int status; u32 glk; - - if (!ec || !data) + if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) return -EINVAL; - *data = 0; + if (rdata) + memset(rdata, 0, rdata_len); if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); @@ -438,72 +425,12 @@ static int acpi_ec_intr_read(union acpi_ printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); goto end; } - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); - } - - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) { - printk(KERN_DEBUG PREFIX "read EC, OB not full\n"); - goto end; - } - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", - *data, address)); - - end: - up(&ec->intr.sem); - - if (ec->common.global_lock) - acpi_release_global_lock(glk); - - return status; -} - -static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data) -{ - int status = 0; - u32 glk; - - - if (!ec) - return -EINVAL; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } - - WARN_ON(in_interrupt()); - down(&ec->intr.sem); - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - - acpi_hw_low_level_write(8, address, &ec->common.data_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - acpi_hw_low_level_write(8, data, &ec->common.data_addr); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", - data, address)); + status = acpi_ec_transaction_unlocked(ec, command, + wdata, wdata_len, + rdata, rdata_len); +end: up(&ec->intr.sem); if (ec->common.global_lock) @@ -554,106 +481,44 @@ int ec_write(u8 addr, u8 val) EXPORT_SYMBOL(ec_write); -static int acpi_ec_query(union acpi_ec *ec, u32 * data) -{ - if (acpi_ec_poll_mode) - return acpi_ec_poll_query(ec, data); - else - return acpi_ec_intr_query(ec, data); -} -static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) +extern int ec_transaction(u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len) { - int result = 0; - acpi_status status = AE_OK; - u32 glk = 0; - - - if (!ec || !data) - return -EINVAL; - - *data = 0; - - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } - - /* - * Query the EC to find out which _Qxx method we need to evaluate. - * Note that successful completion of the query causes the ACPI_EC_SCI - * bit to be cleared (and thus clearing the interrupt source). - */ - if (down_interruptible(&ec->poll.sem)) { - result = -ERESTARTSYS; - goto end_nosem; - } - - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, - &ec->common.command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (result) - goto end; + union acpi_ec *ec; - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - if (!*data) - result = -ENODATA; + if (!first_ec) + return -ENODEV; - end: - up(&ec->poll.sem); -end_nosem: - if (ec->common.global_lock) - acpi_release_global_lock(glk); + ec = acpi_driver_data(first_ec); - return result; + return acpi_ec_transaction(ec, command, wdata, wdata_len, rdata, rdata_len); } -static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data) -{ - int status = 0; - u32 glk; +EXPORT_SYMBOL(ec_transaction); - if (!ec || !data) - return -EINVAL; - *data = 0; +static int acpi_ec_query(union acpi_ec *ec, u32 * data) { + int result; + u8 d; - if (ec->common.global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return -ENODEV; - } + if (!ec || !data) + return -EINVAL; - down(&ec->intr.sem); + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (status) { - printk(KERN_DEBUG PREFIX "query EC, IB not empty\n"); - goto end; - } - /* - * Query the EC to find out which _Qxx method we need to evaluate. - * Note that successful completion of the query causes the ACPI_EC_SCI - * bit to be cleared (and thus clearing the interrupt source). - */ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) { - printk(KERN_DEBUG PREFIX "query EC, OB not full\n"); - goto end; - } - - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - if (!*data) - status = -ENODATA; + result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); + if (result) + return result; - end: - up(&ec->intr.sem); + if (!d) + return -ENODATA; - if (ec->common.global_lock) - acpi_release_global_lock(glk); - - return status; + *data = d; + return 0; } /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index 32c9d88..1ba2db6 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c @@ -91,6 +91,14 @@ enum { HK_EVENT_ENTERRING_S5, }; +enum conf_entry_enum { + bus_handle = 0, + bus_method = 1, + action_handle = 2, + method = 3, + LAST_CONF_ENTRY +}; + /* procdir we use */ static struct proc_dir_entry *hotkey_proc_dir; static struct proc_dir_entry *hotkey_config; @@ -244,19 +252,15 @@ static int hotkey_info_open_fs(struct in static char *format_result(union acpi_object *object) { - char *buf = NULL; - - buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); - if (buf) - memset(buf, 0, RESULT_STR_LEN); - else - goto do_fail; + char *buf; + buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL); + if (!buf) + return NULL; /* Now, just support integer type */ if (object->type == ACPI_TYPE_INTEGER) sprintf(buf, "%d\n", (u32) object->integer.value); - do_fail: - return (buf); + return buf; } static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) @@ -486,98 +490,102 @@ static void free_hotkey_device(union acp static void free_hotkey_buffer(union acpi_hotkey *key) { + /* key would never be null, action method could be */ kfree(key->event_hotkey.action_method); } static void free_poll_hotkey_buffer(union acpi_hotkey *key) { + /* key would never be null, others could be*/ kfree(key->poll_hotkey.action_method); kfree(key->poll_hotkey.poll_method); kfree(key->poll_hotkey.poll_result); } static int -init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, - char *method, int std_num, int external_num) +init_hotkey_device(union acpi_hotkey *key, char **config_entry, + int std_num, int external_num) { acpi_handle tmp_handle; acpi_status status = AE_OK; - if (std_num < 0 || IS_POLL(std_num) || !key) goto do_fail; - if (!bus_str || !action_str || !method) + if (!config_entry[bus_handle] || !config_entry[action_handle] + || !config_entry[method]) goto do_fail; key->link.hotkey_type = ACPI_HOTKEY_EVENT; key->link.hotkey_standard_num = std_num; key->event_hotkey.flag = 0; - key->event_hotkey.action_method = method; + key->event_hotkey.action_method = config_entry[method]; - status = - acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle)); + status = acpi_get_handle(NULL, config_entry[bus_handle], + &(key->event_hotkey.bus_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; key->event_hotkey.external_hotkey_num = external_num; - status = - acpi_get_handle(NULL, action_str, + status = acpi_get_handle(NULL, config_entry[action_handle], &(key->event_hotkey.action_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = acpi_get_handle(key->event_hotkey.action_handle, - method, &tmp_handle); + config_entry[method], &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; return AE_OK; - do_fail: +do_fail_zero: + key->event_hotkey.action_method = NULL; +do_fail: return -ENODEV; } static int -init_poll_hotkey_device(union acpi_hotkey *key, - char *poll_str, - char *poll_method, - char *action_str, char *action_method, int std_num) +init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry, + int std_num) { acpi_status status = AE_OK; acpi_handle tmp_handle; - if (std_num < 0 || IS_EVENT(std_num) || !key) goto do_fail; - - if (!poll_str || !poll_method || !action_str || !action_method) + if (!config_entry[bus_handle] ||!config_entry[bus_method] || + !config_entry[action_handle] || !config_entry[method]) goto do_fail; key->link.hotkey_type = ACPI_HOTKEY_POLLING; key->link.hotkey_standard_num = std_num; key->poll_hotkey.flag = 0; - key->poll_hotkey.poll_method = poll_method; - key->poll_hotkey.action_method = action_method; + key->poll_hotkey.poll_method = config_entry[bus_method]; + key->poll_hotkey.action_method = config_entry[method]; - status = - acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle)); + status = acpi_get_handle(NULL, config_entry[bus_handle], + &(key->poll_hotkey.poll_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = acpi_get_handle(key->poll_hotkey.poll_handle, - poll_method, &tmp_handle); + config_entry[bus_method], &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = - acpi_get_handle(NULL, action_str, + acpi_get_handle(NULL, config_entry[action_handle], &(key->poll_hotkey.action_handle)); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; status = acpi_get_handle(key->poll_hotkey.action_handle, - action_method, &tmp_handle); + config_entry[method], &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail; + goto do_fail_zero; key->poll_hotkey.poll_result = (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!key->poll_hotkey.poll_result) - goto do_fail; + goto do_fail_zero; return AE_OK; - do_fail: + +do_fail_zero: + key->poll_hotkey.poll_method = NULL; + key->poll_hotkey.action_method = NULL; +do_fail: return -ENODEV; } @@ -652,17 +660,18 @@ static int hotkey_poll_config_seq_show(s } static int -get_parms(char *config_record, - int *cmd, - char **bus_handle, - char **bus_method, - char **action_handle, - char **method, int *internal_event_num, int *external_event_num) +get_parms(char *config_record, int *cmd, char **config_entry, + int *internal_event_num, int *external_event_num) { +/* the format of *config_record = + * "1:\d+:*" : "cmd:internal_event_num" + * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" : + * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num" + */ char *tmp, *tmp1, count; + int i; sscanf(config_record, "%d", cmd); - if (*cmd == 1) { if (sscanf(config_record, "%d:%d", cmd, internal_event_num) != 2) @@ -674,59 +683,27 @@ get_parms(char *config_record, if (!tmp) goto do_fail; tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - - count = tmp1 - tmp; - *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*bus_handle) - goto do_fail; - strncpy(*bus_handle, tmp, count); - *(*bus_handle + count) = 0; - - tmp = tmp1; - tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - count = tmp1 - tmp; - *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*bus_method) - goto do_fail; - strncpy(*bus_method, tmp, count); - *(*bus_method + count) = 0; - - tmp = tmp1; - tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - count = tmp1 - tmp; - *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*action_handle) - goto do_fail; - strncpy(*action_handle, tmp, count); - *(*action_handle + count) = 0; - - tmp = tmp1; - tmp++; - tmp1 = strchr(tmp, ':'); - if (!tmp1) - goto do_fail; - count = tmp1 - tmp; - *method = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!*method) - goto do_fail; - strncpy(*method, tmp, count); - *(*method + count) = 0; - - if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <= - 0) - goto do_fail; - - return 6; - do_fail: + for (i = 0; i < LAST_CONF_ENTRY; i++) { + tmp1 = strchr(tmp, ':'); + if (!tmp1) { + goto do_fail; + } + count = tmp1 - tmp; + config_entry[i] = kzalloc(count + 1, GFP_KERNEL); + if (!config_entry[i]) + goto handle_failure; + strncpy(config_entry[i], tmp, count); + tmp = tmp1 + 1; + } + if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0) + goto handle_failure; + if (!IS_OTHERS(*internal_event_num)) { + return 6; + } +handle_failure: + while (i-- > 0) + kfree(config_entry[i]); +do_fail: return -1; } @@ -736,50 +713,34 @@ static ssize_t hotkey_write_config(struc size_t count, loff_t * data) { char *config_record = NULL; - char *bus_handle = NULL; - char *bus_method = NULL; - char *action_handle = NULL; - char *method = NULL; + char *config_entry[LAST_CONF_ENTRY]; int cmd, internal_event_num, external_event_num; int ret = 0; - union acpi_hotkey *key = NULL; + union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL); + if (!key) + return -ENOMEM; - config_record = (char *)kmalloc(count + 1, GFP_KERNEL); - if (!config_record) + config_record = kzalloc(count + 1, GFP_KERNEL); + if (!config_record) { + kfree(key); return -ENOMEM; + } if (copy_from_user(config_record, buffer, count)) { kfree(config_record); + kfree(key); printk(KERN_ERR PREFIX "Invalid data\n"); return -EINVAL; } - config_record[count] = 0; - - ret = get_parms(config_record, - &cmd, - &bus_handle, - &bus_method, - &action_handle, - &method, &internal_event_num, &external_event_num); - + ret = get_parms(config_record, &cmd, config_entry, + &internal_event_num, &external_event_num); kfree(config_record); - if (IS_OTHERS(internal_event_num)) - goto do_fail; if (ret != 6) { - do_fail: - kfree(bus_handle); - kfree(bus_method); - kfree(action_handle); - kfree(method); printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret); return -EINVAL; } - key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - if (!key) - goto do_fail; - memset(key, 0, sizeof(union acpi_hotkey)); if (cmd == 1) { union acpi_hotkey *tmp = NULL; tmp = get_hotkey_by_event(&global_hotkey_list, @@ -791,34 +752,19 @@ static ssize_t hotkey_write_config(struc goto cont_cmd; } if (IS_EVENT(internal_event_num)) { - kfree(bus_method); - ret = init_hotkey_device(key, bus_handle, action_handle, method, - internal_event_num, - external_event_num); - } else - ret = init_poll_hotkey_device(key, bus_handle, bus_method, - action_handle, method, - internal_event_num); - if (ret) { - kfree(bus_handle); - kfree(action_handle); - if (IS_EVENT(internal_event_num)) - free_hotkey_buffer(key); - else - free_poll_hotkey_buffer(key); - kfree(key); - printk(KERN_ERR PREFIX "Invalid hotkey\n"); - return -EINVAL; + if (init_hotkey_device(key, config_entry, + internal_event_num, external_event_num)) + goto init_hotkey_fail; + } else { + if (init_poll_hotkey_device(key, config_entry, + internal_event_num)) + goto init_poll_hotkey_fail; } - - cont_cmd: - kfree(bus_handle); - kfree(action_handle); - +cont_cmd: switch (cmd) { case 0: - if (get_hotkey_by_event - (&global_hotkey_list, key->link.hotkey_standard_num)) + if (get_hotkey_by_event(&global_hotkey_list, + key->link.hotkey_standard_num)) goto fail_out; else hotkey_add(key); @@ -827,6 +773,7 @@ static ssize_t hotkey_write_config(struc hotkey_remove(key); break; case 2: + /* key is kfree()ed if matched*/ if (hotkey_update(key)) goto fail_out; break; @@ -835,11 +782,22 @@ static ssize_t hotkey_write_config(struc break; } return count; - fail_out: - if (IS_EVENT(internal_event_num)) - free_hotkey_buffer(key); - else - free_poll_hotkey_buffer(key); + +init_poll_hotkey_fail: /* failed init_poll_hotkey_device */ + kfree(config_entry[bus_method]); + config_entry[bus_method] = NULL; +init_hotkey_fail: /* failed init_hotkey_device */ + kfree(config_entry[method]); +fail_out: + kfree(config_entry[bus_handle]); + kfree(config_entry[action_handle]); + /* No double free since elements =NULL for error cases */ + if (IS_EVENT(internal_event_num)) { + if (config_entry[bus_method]) + kfree(config_entry[bus_method]); + free_hotkey_buffer(key); /* frees [method] */ + } else + free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */ kfree(key); printk(KERN_ERR PREFIX "invalid key\n"); return -EINVAL; @@ -923,10 +881,9 @@ static ssize_t hotkey_execute_aml_method union acpi_hotkey *key; - arg = (char *)kmalloc(count + 1, GFP_KERNEL); + arg = kzalloc(count + 1, GFP_KERNEL); if (!arg) return -ENOMEM; - arg[count] = 0; if (copy_from_user(arg, buffer, count)) { kfree(arg); diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c index 84239d5..6809c28 100644 --- a/drivers/acpi/i2c_ec.c +++ b/drivers/acpi/i2c_ec.c @@ -330,7 +330,7 @@ static int acpi_ec_hc_add(struct acpi_de status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n")); - kfree(ec_hc->smbus); + kfree(ec_hc); kfree(smbus); return -EIO; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b7d1514..507f051 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -746,6 +746,16 @@ acpi_status acpi_os_wait_semaphore(acpi_ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); + /* + * This can be called during resume with interrupts off. + * Like boot-time, we should be single threaded and will + * always get the lock if we try -- timeout or not. + * If this doesn't succeed, then we will oops courtesy of + * might_sleep() in down(). + */ + if (!down_trylock(sem)) + return AE_OK; + switch (timeout) { /* * No Wait: diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 7f3e7e7..d53bd98 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -307,7 +307,7 @@ static int acpi_pci_link_set(struct acpi if (!link || !irq) return -EINVAL; - resource = kmalloc(sizeof(*resource) + 1, GFP_ATOMIC); + resource = kmalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); if (!resource) return -ENOMEM; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fec225d..fe67a8a 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -216,10 +216,8 @@ static int acpi_power_off_device(acpi_ha { int result = 0; acpi_status status = AE_OK; - struct acpi_device *device = NULL; struct acpi_power_resource *resource = NULL; - result = acpi_power_get_context(handle, &resource); if (result) return result; @@ -230,13 +228,13 @@ static int acpi_power_off_device(acpi_ha if (resource->references) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is still in use, dereferencing\n", - device->pnp.bus_id)); + resource->device->pnp.bus_id)); return 0; } if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", - device->pnp.bus_id)); + resource->device->pnp.bus_id)); return 0; } @@ -251,8 +249,7 @@ static int acpi_power_off_device(acpi_ha return -ENOEXEC; /* Update the power resource's _device_ power state */ - device = resource->device; - device->power.state = ACPI_STATE_D3; + resource->device->power.state = ACPI_STATE_D3; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n", resource->name)); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7106606..58f12ca 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -216,6 +216,69 @@ static void acpi_safe_halt(void) current_thread_info()->status |= TS_POLLING; } + +static int acpi_cstate_enter(struct acpi_processor_cx *cstate) +{ + u32 t1, t2 = 0; + u32 timing_valid = 0, retval = 0xffffffff; + + if (cstate->entry_type == ACPI_CSTATE_NATIVE) { + /* Native C-state */ + /* Get start time (ticks) */ + t1 = inl(acpi_fadt.xpm_tmr_blk.address); + /* Invoke C-state */ + timing_valid = acpi_processor_native_cstate_enter(cstate); + if (timing_valid) { + /* Get end time (ticks) */ + t2 = inl(acpi_fadt.xpm_tmr_blk.address); + /* Re-enable interrupts */ + local_irq_enable(); + retval = ticks_elapsed(t1, t2); + } + return retval; + } else if (cstate->type == ACPI_STATE_C1) { + /* + * Non-native C1-state handling is a special case + * Invoke C1. + * Use the appropriate idle routine, the one that would + * be used without acpi C-states. + */ + if (pm_idle_save) + pm_idle_save(); + else + acpi_safe_halt(); + + /* + * TBD: Can't get time duration while in C1, as resumes + * go to an ISR rather than here. Need to + * instrument base interrupt handler. + */ + return retval; + } else { + /* Non-native C2, C3, ... states */ + current_thread_info()->status &= ~TS_POLLING; + smp_mb__after_clear_bit(); + if (need_resched()) { + current_thread_info()->status |= TS_POLLING; + local_irq_enable(); + return 0; + } + + /* Get start time (ticks) */ + t1 = inl(acpi_fadt.xpm_tmr_blk.address); + /* Invoke C2 */ + inb(cstate->address); + /* Dummy op - must do something useless after P_LVL2 read */ + t2 = inl(acpi_fadt.xpm_tmr_blk.address); + /* Get end time (ticks) */ + t2 = inl(acpi_fadt.xpm_tmr_blk.address); + /* Re-enable interrupts */ + local_irq_enable(); + current_thread_info()->status |= TS_POLLING; + return ticks_elapsed(t1, t2); + } +} + static atomic_t c3_cpu_count; static void acpi_processor_idle(void) @@ -224,7 +287,6 @@ static void acpi_processor_idle(void) struct acpi_processor_cx *cx = NULL; struct acpi_processor_cx *next_state = NULL; int sleep_ticks = 0; - u32 t1, t2 = 0; pr = processors[smp_processor_id()]; if (!pr) @@ -325,59 +387,29 @@ #endif * ------ * Invoke the current Cx state to put the processor to sleep. */ - if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) { - current_thread_info()->status &= ~TS_POLLING; - smp_mb__after_clear_bit(); - if (need_resched()) { - current_thread_info()->status |= TS_POLLING; - local_irq_enable(); - return; - } - } - switch (cx->type) { case ACPI_STATE_C1: - /* - * Invoke C1. - * Use the appropriate idle routine, the one that would - * be used without acpi C-states. - */ - if (pm_idle_save) - pm_idle_save(); - else - acpi_safe_halt(); - - /* - * TBD: Can't get time duration while in C1, as resumes - * go to an ISR rather than here. Need to instrument - * base interrupt handler. - */ - sleep_ticks = 0xFFFFFFFF; + /* Invoke C1 */ + sleep_ticks = acpi_cstate_enter(cx); break; case ACPI_STATE_C2: - /* Get start time (ticks) */ - t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C2 */ - inb(cx->address); - /* Dummy wait op - must do something useless after P_LVL2 read - because chipsets cannot guarantee that STPCLK# signal - gets asserted in time to freeze execution properly. */ - t2 = inl(acpi_fadt.xpm_tmr_blk.address); - /* Get end time (ticks) */ - t2 = inl(acpi_fadt.xpm_tmr_blk.address); + sleep_ticks = acpi_cstate_enter(cx); #ifdef CONFIG_GENERIC_TIME /* TSC halts in C2, so notify users */ mark_tsc_unstable(); #endif - /* Re-enable interrupts */ - local_irq_enable(); - current_thread_info()->status |= TS_POLLING; - /* Compute time (ticks) that we were actually asleep */ - sleep_ticks = - ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; + + if (sleep_ticks != -1) { + int overhead = (cx->latency_ticks + C2_OVERHEAD); + if (sleep_ticks > overhead) + sleep_ticks -= overhead; + else + sleep_ticks = 0; + } break; case ACPI_STATE_C3: @@ -397,31 +429,29 @@ #endif ACPI_FLUSH_CPU_CACHE(); } - /* Get start time (ticks) */ - t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C3 */ - inb(cx->address); - /* Dummy wait op (see above) */ - t2 = inl(acpi_fadt.xpm_tmr_blk.address); - /* Get end time (ticks) */ - t2 = inl(acpi_fadt.xpm_tmr_blk.address); + sleep_ticks = acpi_cstate_enter(cx); + +#ifdef CONFIG_GENERIC_TIME + /* TSC halts in C3, so notify users */ + mark_tsc_unstable(); +#endif + if (pr->flags.bm_check) { /* Enable bus master arbitration */ atomic_dec(&c3_cpu_count); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, - ACPI_MTX_DO_NOT_LOCK); + ACPI_MTX_DO_NOT_LOCK); + } + + if (sleep_ticks != -1) { + int overhead = (cx->latency_ticks + C3_OVERHEAD); + if (sleep_ticks > overhead) + sleep_ticks -= overhead; + else + sleep_ticks = 0; } -#ifdef CONFIG_GENERIC_TIME - /* TSC halts in C3, so notify users */ - mark_tsc_unstable(); -#endif - /* Re-enable interrupts */ - local_irq_enable(); - current_thread_info()->status |= TS_POLLING; - /* Compute time (ticks) that we were actually asleep */ - sleep_ticks = - ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; break; default: @@ -624,20 +654,16 @@ #endif return 0; } -static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) +static int acpi_processor_get_power_info_default(struct acpi_processor *pr) { - - /* Zero initialize all the C-states info. */ - memset(pr->power.states, 0, sizeof(pr->power.states)); - - /* set the first C-State to C1 */ - pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; - - /* the C0 state only exists as a filler in our array, - * and all processors need to support C1 */ + if (!pr->power.states[ACPI_STATE_C1].valid) { + /* set the first C-State to C1 */ + /* all processors need to support C1 */ + pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; + pr->power.states[ACPI_STATE_C1].valid = 1; + } + /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; - pr->power.states[ACPI_STATE_C1].valid = 1; - return 0; } @@ -654,12 +680,7 @@ static int acpi_processor_get_power_info if (nocst) return -ENODEV; - current_count = 1; - - /* Zero initialize C2 onwards and prepare for fresh CST lookup */ - for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(&(pr->power.states[i]), 0, - sizeof(struct acpi_processor_cx)); + current_count = 0; status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -714,22 +735,36 @@ static int acpi_processor_get_power_info (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) continue; - cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ? - 0 : reg->address; - /* There should be an easy way to extract an integer... */ obj = (union acpi_object *)&(element->package.elements[1]); if (obj->type != ACPI_TYPE_INTEGER) continue; cx.type = obj->integer.value; - - if ((cx.type != ACPI_STATE_C1) && - (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) - continue; - - if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3)) - continue; + /* + * Some buggy BIOSes won't list C1 in _CST - + * Let acpi_processor_get_power_info_default() handle them later + */ + if (i == 1 && cx.type != ACPI_STATE_C1) + current_count++; + + cx.address = reg->address; + cx.index = current_count + 1; + + cx.entry_type = ACPI_CSTATE_NONNATIVE; + if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { + if (acpi_processor_native_cstate_check + (pr->id, &cx, reg) == 0) { + cx.entry_type = ACPI_CSTATE_NATIVE; + } else if (cx.type != ACPI_STATE_C1) { + /* + * C1 is a special case where FIXED_HARDWARE + * is handled in non-native way. + * Otherwise, ignore this info and continue. + */ + continue; + } + } obj = (union acpi_object *)&(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) @@ -763,10 +798,6 @@ static int acpi_processor_get_power_info ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", current_count)); - /* Validate number of power states discovered */ - if (current_count < 2) - status = -EFAULT; - end: kfree(buffer.pointer); @@ -934,12 +965,15 @@ static int acpi_processor_get_power_info /* NOTE: the idle thread may not be running while calling * this function */ - /* Adding C1 state */ - acpi_processor_get_power_info_default_c1(pr); + /* Zero initialize all the C-states info. */ + memset(pr->power.states, 0, sizeof(pr->power.states)); + result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) acpi_processor_get_power_info_fadt(pr); + acpi_processor_get_power_info_default(pr); + pr->power.count = acpi_processor_power_verify(pr); /* diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index db7b350..62bef0b 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -1714,6 +1714,9 @@ static int __init acpi_sbs_init(void) { int result = 0; + if (acpi_disabled) + return -ENODEV; + init_MUTEX(&sbs_sem); if (capacity_mode != DEF_CAPACITY_UNIT diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5fcb50c..698a154 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -113,6 +114,8 @@ static struct kset acpi_namespace_kset = static void acpi_device_register(struct acpi_device *device, struct acpi_device *parent) { + int err; + /* * Linkage * ------- @@ -138,7 +141,10 @@ static void acpi_device_register(struct device->kobj.parent = &parent->kobj; device->kobj.ktype = &ktype_acpi_ns; device->kobj.kset = &acpi_namespace_kset; - kobject_register(&device->kobj); + err = kobject_register(&device->kobj); + if (err < 0) + printk(KERN_WARNING "%s: kobject_register error: %d\n", + __FUNCTION__, err); create_sysfs_device_files(device); } @@ -1450,7 +1456,9 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; - kset_register(&acpi_namespace_kset); + result = kset_register(&acpi_namespace_kset); + if (result < 0) + printk(KERN_ERR PREFIX "kset_register error: %d\n", result); result = bus_register(&acpi_bus_type); if (result) { diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index f48227f..d0d84c4 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -262,7 +262,7 @@ acpi_evaluate_integer(acpi_handle handle if (!data) return AE_BAD_PARAMETER; - element = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); if (!element) return AE_NO_MEMORY; diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 3c148ea..8a60f39 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -76,7 +76,7 @@ config HOTPLUG_PCI_IBM config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on ACPI_DOCK && HOTPLUG_PCI + depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI) help Say Y here if you have a system that supports PCI Hotplug using ACPI. diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index fb08bc9..04618d4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1518,6 +1518,63 @@ static void __devinit quirk_netmos(struc } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); +static void __devinit quirk_e100_interrupt(struct pci_dev *dev) +{ + u16 command; + u32 bar; + u8 __iomem *csr; + u8 cmd_hi; + + switch (dev->device) { + /* PCI IDs taken from drivers/net/e100.c */ + case 0x1029: + case 0x1030 ... 0x1034: + case 0x1038 ... 0x103E: + case 0x1050 ... 0x1057: + case 0x1059: + case 0x1064 ... 0x106B: + case 0x1091 ... 0x1095: + case 0x1209: + case 0x1229: + case 0x2449: + case 0x2459: + case 0x245D: + case 0x27DC: + break; + default: + return; + } + + /* + * Some firmware hands off the e100 with interrupts enabled, + * which can cause a flood of interrupts if packets are + * received before the driver attaches to the device. So + * disable all e100 interrupts here. The driver will + * re-enable them when it's ready. + */ + pci_read_config_word(dev, PCI_COMMAND, &command); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar); + + if (!(command & PCI_COMMAND_MEMORY) || !bar) + return; + + csr = ioremap(bar, 8); + if (!csr) { + printk(KERN_WARNING "PCI: Can't map %s e100 registers\n", + pci_name(dev)); + return; + } + + cmd_hi = readb(csr + 3); + if (cmd_hi == 0) { + printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts " + "enabled, disabling\n", pci_name(dev)); + writeb(1, csr + 3); + } + + iounmap(csr); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt); static void __devinit fixup_rev1_53c810(struct pci_dev* dev) { diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h index c5472be..e72bfdd 100644 --- a/include/acpi/pdc_intel.h +++ b/include/acpi/pdc_intel.h @@ -13,6 +13,7 @@ #define ACPI_PDC_SMP_P_SWCOORD (0x0020) #define ACPI_PDC_SMP_C_SWCOORD (0x0040) #define ACPI_PDC_SMP_T_SWCOORD (0x0080) #define ACPI_PDC_C_C1_FFH (0x0100) +#define ACPI_PDC_C_C2C3_FFH (0x0200) #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ ACPI_PDC_C_C1_HALT | \ @@ -23,8 +24,10 @@ #define ACPI_PDC_EST_CAPABILITY_SWSMP (A ACPI_PDC_SMP_P_SWCOORD | \ ACPI_PDC_P_FFH) -#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ - ACPI_PDC_SMP_C1PT | \ - ACPI_PDC_C_C1_HALT) +#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ + ACPI_PDC_SMP_C1PT | \ + ACPI_PDC_C_C1_HALT | \ + ACPI_PDC_C_C1_FFH | \ + ACPI_PDC_C_C2C3_FFH) #endif /* __PDC_INTEL_H__ */ diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 9dd5b75..dd97a03 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -29,6 +29,9 @@ #define DOMAIN_COORD_TYPE_SW_ALL 0xfc #define DOMAIN_COORD_TYPE_SW_ANY 0xfd #define DOMAIN_COORD_TYPE_HW_ALL 0xfe +#define ACPI_CSTATE_NONNATIVE (0) +#define ACPI_CSTATE_NATIVE (1) + /* Power Management */ struct acpi_processor_cx; @@ -58,6 +61,8 @@ struct acpi_processor_cx { u8 valid; u8 type; u32 address; + u8 entry_type; + u8 index; u32 latency; u32 latency_ticks; u32 power; @@ -206,6 +211,9 @@ void arch_acpi_processor_init_pdc(struct #ifdef ARCH_HAS_POWER_INIT void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, unsigned int cpu); +int acpi_processor_native_cstate_check(unsigned int cpu, + struct acpi_processor_cx *cx, struct acpi_power_register *reg); +int acpi_processor_native_cstate_enter(struct acpi_processor_cx *cstate); #else static inline void acpi_processor_power_init_bm_check(struct acpi_processor_flags @@ -214,6 +222,16 @@ static inline void acpi_processor_power_ flags->bm_check = 1; return; } +static inline int acpi_processor_native_cstate_check(unsigned int cpu, + struct acpi_processor_cx *cx, struct acpi_power_register *reg) +{ + return -1; +} +static inline int acpi_processor_native_cstate_enter( + struct acpi_processor_cx *cstate) +{ + return 0; +} #endif /* in processor_perflib.c */ diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index b32346d..9c93b5b 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -312,6 +312,8 @@ static inline void __mwait(unsigned long : :"a" (eax), "c" (ecx)); } +extern void mwait_idle_hints(unsigned long eax, unsigned long ecx); + /* from system description table in BIOS. Mostly for MCA use, but others may find it useful. */ extern unsigned int machine_id; diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 3b3c121..55532b1 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -469,6 +469,8 @@ static inline void __mwait(unsigned long : :"a" (eax), "c" (ecx)); } +extern void mwait_idle_hints(unsigned long eax, unsigned long ecx); + #define stack_current() \ ({ \ struct thread_info *ti; \ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 88b5dfd..2b0c955 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -494,6 +494,9 @@ #ifdef CONFIG_ACPI_EC extern int ec_read(u8 addr, u8 *val); extern int ec_write(u8 addr, u8 val); +extern int ec_transaction(u8 command, + const u8 *wdata, unsigned wdata_len, + u8 *rdata, unsigned rdata_len); #endif /*CONFIG_ACPI_EC*/