bk://linux-acpi.bkbits.net/to-akpm len.brown@intel.com|ChangeSet|20050401055946|40179 len.brown # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/04 00:42:58-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # drivers/pci/quirks.c # 2005/04/04 00:42:51-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pci/pci.c # 2005/04/04 00:42:51-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/04/01 11:14:11-08:00 akpm@bix.(none) # Merge bk://linux-acpi.bkbits.net/to-akpm # into bix.(none):/usr/src/bk-acpi # # kernel/power/main.c # 2005/04/01 11:14:06-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/04/01 11:14:06-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pci/pci.c # 2005/04/01 11:14:06-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/e1000/e1000_main.c # 2005/04/01 11:14:06-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/b44.c # 2005/04/01 11:14:06-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/04/01 00:59:46-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-latest-hotplug # into intel.com:/home/lenb/bk/to-akpm # # include/linux/acpi.h # 2005/04/01 00:59:41-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/net/e1000/e1000_main.c # 2005/04/01 00:59:41-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/net/b44.c # 2005/04/01 00:59:41-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/04/01 00:56:27-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-latest-next # into intel.com:/home/lenb/bk/to-akpm # # kernel/power/main.c # 2005/04/01 00:56:22-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pnp/pnpacpi/rsparser.c # 2005/04/01 00:56:22-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/04/01 00:56:22-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pci/pci.c # 2005/04/01 00:56:22-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/i386/pci/irq.c # 2005/04/01 00:56:22-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/04/01 00:07:31-05:00 len.brown@intel.com # [ACPI] PNPACPI vs sound IRQ # # http://bugme.osdl.org/show_bug.cgi?id=4016 # # Written-by: David Shaohua Li # Acked-by: Adam Belay # Signed-off-by: Len Brown # # include/linux/acpi.h # 2005/01/11 21:12:55-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-x86_64/pci.h # 2005/01/11 21:03:54-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-sparc64/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-sparc/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-sh64/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-sh/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-ppc64/pci.h # 2005/01/11 21:03:54-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-ppc/pci.h # 2005/01/11 21:08:28-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-mips/pci.h # 2005/01/11 21:03:54-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-m68k/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-ia64/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-i386/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-h8300/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-arm/pci.h # 2005/01/11 21:06:45-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # include/asm-alpha/pci.h # 2005/01/11 21:04:00-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # drivers/pnp/resource.c # 2005/01/11 21:09:53-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # drivers/pnp/pnpbios/rsparser.c # 2005/01/11 21:10:55-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # drivers/pnp/pnpacpi/rsparser.c # 2005/01/11 21:11:40-05:00 len.brown@intel.com +2 -2 # PNPACPI vs sound IRQ # # drivers/acpi/pci_link.c # 2005/01/11 21:15:10-05:00 len.brown@intel.com +5 -2 # PNPACPI vs sound IRQ # # arch/i386/pci/visws.c # 2005/01/11 21:03:54-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # arch/i386/pci/irq.c # 2005/01/11 21:15:49-05:00 len.brown@intel.com +10 -6 # PNPACPI vs sound IRQ # # arch/frv/mb93090-mb00/pci-irq.c # 2005/04/01 00:07:22-05:00 len.brown@intel.com +1 -1 # PNPACPI vs sound IRQ # # ChangeSet # 2005/03/31 23:23:15-05:00 len.brown@intel.com # [ACPI] update /proc/acpi/processor/*/power even if only C1 support # # Signed-off-by: Venkatesh Pallipadi # Signed-off-by: Len Brown # # drivers/acpi/processor_idle.c # 2005/03/25 21:41:52-05:00 len.brown@intel.com +26 -7 # C1 stats # # ChangeSet # 2005/03/31 22:51:10-05:00 len.brown@intel.com # [ACPI] Evaluate CPEI Processor Override flag # # ACPI 3.0 added a Correctable Platform Error Interrupt (CPEI) # Processor Overide flag to MADT.Platform_Interrupt_Source. # Record the processor that was provided as hint from ACPI. # # Signed-off-by: Ashok Raj # Signed-off-by: Len Brown # # include/linux/acpi.h # 2005/03/21 17:51:34-05:00 len.brown@intel.com +4 -1 # CPEI Processor Override support # # include/asm-ia64/acpi.h # 2005/03/21 17:51:34-05:00 len.brown@intel.com +9 -0 # CPEI Processor Override support # # arch/ia64/kernel/topology.c # 2005/03/21 17:51:34-05:00 len.brown@intel.com +7 -0 # CPEI Processor Override support # # arch/ia64/kernel/mca.c # 2005/03/21 18:22:57-05:00 len.brown@intel.com +1 -1 # CPEI Processor override support # # arch/ia64/kernel/acpi.c # 2005/03/22 16:21:07-05:00 len.brown@intel.com +54 -0 # CPEI Processor Override support # # ChangeSet # 2005/03/31 12:31:39-08:00 akpm@bix.(none) # Merge bk://linux-acpi.bkbits.net/to-akpm # into bix.(none):/usr/src/bk-acpi # # kernel/power/main.c # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/device.h # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/hcd-pci.c # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pci/pci.c # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/acpi/Kconfig # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/i386/kernel/acpi/sleep.c # 2005/03/31 12:31:35-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/31 12:30:20-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # drivers/net/e1000/e1000_main.c # 2005/03/31 12:30:16-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/b44.c # 2005/03/31 12:30:16-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/31 13:12:38-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/26-latest-test # into intel.com:/home/lenb/bk/to-akpm # # include/linux/device.h # 2005/03/31 13:12:34-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/usb/core/hcd-pci.c # 2005/03/31 13:12:34-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/03/31 13:12:34-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pci/pci.c # 2005/03/31 13:12:33-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/31 13:08:00-05:00 len.brown@intel.com # [ACPI] fix build error resulting from merge # # Signed-off-by: Len Brown # # drivers/acpi/button.c # 2005/03/31 13:07:46-05:00 len.brown@intel.com +0 -1 # fix merge # # ChangeSet # 2005/03/30 23:24:18-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/26-latest-ref # into intel.com:/home/lenb/src/26-latest-next # # kernel/power/main.c # 2005/03/30 23:24:13-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/03/30 23:24:13-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/30 23:23:21-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-latest-hotplug # into intel.com:/home/lenb/bk/to-akpm # # drivers/acpi/Kconfig # 2005/03/30 23:23:14-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/30 23:15:47-05:00 len.brown@intel.com # [ACPI] hotplug Processor consideration in acpi_bus_add() # # Signed-off-by: Keiichiro Tokunaga # Signed-off-by: Len Brown # # drivers/acpi/scan.c # 2005/03/27 01:51:44-05:00 len.brown@intel.com +7 -5 # This is to add CPU hotplug consideration to acpi_bus_add() # that now assumes processor objects are always present, # functioning, etc. at least when parent object is present. # But, CPU hotplug is supported today, so we need to change # the assumption. If a processor object has _STA method, we # should respect it. # # ChangeSet # 2005/03/30 22:53:30-05:00 len.brown@intel.com # [ACPI] fix debug-mode build warning in acpi/hotkey.c # # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/hotkey.c # 2005/03/30 08:16:09-05:00 len.brown@intel.com +2 -1 # fix debug-mode build warning in acpi/hotkey.c # # drivers/acpi/hotkey.c: In function `create_polling_proc': # drivers/acpi/hotkey.c:334: warning: ISO C90 forbids mixed declarations and code # # ChangeSet # 2005/03/30 22:12:13-05:00 len.brown@intel.com # [ACPI] fix build warning # # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/ec.c # 2005/03/30 08:15:58-05:00 len.brown@intel.com +1 -1 # drivers/acpi/ec.c: In function `acpi_ec_space_handler': # drivers/acpi/ec.c:641: warning: value computed is not used # # ChangeSet # 2005/03/30 22:04:17-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-stable-dev # into intel.com:/home/lenb/src/26-latest-dev # # drivers/acpi/Kconfig # 2005/03/30 22:04:12-05:00 len.brown@intel.com +7 -0 # Auto merged # # ChangeSet # 2005/03/30 21:56:37-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-stable-acpica # into intel.com:/home/lenb/src/26-stable-dev # # drivers/acpi/Kconfig # 2005/03/30 21:56:33-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/30 21:23:19-05:00 len.brown@intel.com # cleanup: remove unnecessary initializer on static pointers # # Suggested-by: Greg KH # Signed-off-by: Len Brown # # drivers/pci/pci.c # 2005/03/30 21:23:10-05:00 len.brown@intel.com +2 -2 # remove unnecessary initializers on static pointers # # ChangeSet # 2005/03/30 20:50:40-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/26-latest-test # into intel.com:/home/lenb/bk/to-akpm # # kernel/power/main.c # 2005/03/30 20:50:35-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/03/30 20:50:35-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/30 17:01:09-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # drivers/usb/core/hcd-pci.c # 2005/03/30 17:01:04-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/30 12:04:27-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # include/linux/device.h # 2005/03/30 12:04:21-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/03/30 12:04:21-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pci/pci.c # 2005/03/30 12:04:21-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/30 11:40:44-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/26-latest-ref # into intel.com:/home/lenb/src/26-latest-dev # # drivers/pci/quirks.c # 2005/03/30 11:40:29-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/28 22:15:43-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # kernel/power/main.c # 2005/03/28 22:15:34-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/pcmcia/yenta_socket.c # 2005/03/28 22:15:34-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/25 14:10:11-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-stable-dev # into intel.com:/home/lenb/src/26-latest-dev # # drivers/pci/quirks.c # 2005/03/25 14:10:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/acpi/pci_irq.c # 2005/03/25 14:10:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/i386/pci/irq.c # 2005/03/25 14:10:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/i386/kernel/acpi/sleep.c # 2005/03/25 14:10:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/25 14:02:20-05:00 len.brown@intel.com # VIA Interrupt quirk # # Delete quirk_via_bridge() # Restore quirk_via_irqpic() # But now improved to be invoked upon device ENABLE, # only for VIA devices -- not all devices behind VIA bridges # and only in PIC mode. # # http://bugzilla.kernel.org/show_bug.cgi?id=3319 # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Len Brown # # drivers/pci/quirks.c # 2005/03/25 14:02:12-05:00 len.brown@intel.com +24 -16 # VIA quirk # # drivers/acpi/pci_irq.c # 2005/03/25 14:02:12-05:00 len.brown@intel.com +0 -4 # VIA quirk # # arch/i386/pci/irq.c # 2005/03/25 14:02:12-05:00 len.brown@intel.com +0 -5 # VIA quirk # # ChangeSet # 2005/03/25 13:32:40-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-stable-dev # into intel.com:/lenb/src/26-stable-dev # # arch/i386/kernel/acpi/wakeup.S # 2005/03/25 13:32:35-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/i386/kernel/acpi/sleep.c # 2005/03/25 13:32:35-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/25 12:42:31-05:00 len.brown@intel.com # merge # # drivers/acpi/button.c # 2005/03/25 12:42:23-05:00 len.brown@intel.com +1 -3 # merge # # ChangeSet # 2005/03/25 12:03:15-05:00 len.brown@intel.com # [ACPI] PNPACPI parse error # # http://bugzilla.kernel.org/show_bug.cgi?id=3912 # # Written-by: matthieu castet # Acked-by: Shaohua Li # Signed-off-by: Len Brown # # drivers/pnp/pnpacpi/rsparser.c # 2005/03/25 11:20:41-05:00 len.brown@intel.com +10 -1 # [ACPI] PNPACPI parse error # # http://bugzilla.kernel.org/show_bug.cgi?id=3912 # # Written-by: matthieu castet # Acked-by: Shaohua Li # Signed-off-by: Len Brown # # drivers/acpi/scan.c # 2005/03/23 20:39:09-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/acpi/pci_irq.c # 2005/03/23 20:39:09-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/acpi/numa.c # 2005/03/23 20:39:09-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/ia64/kernel/acpi.c # 2005/03/23 20:39:08-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/23 16:16:03-05:00 len.brown@intel.com # [ACPI] gut acpi_pci_choose_state() to avoid conflict # with pending pm_message_t re-definition. # # Signed-off-by: Len Brown # # drivers/pci/pci-acpi.c # 2005/03/23 16:15:52-05:00 len.brown@intel.com +3 -14 # gut acpi_pci_choose_state() # # ChangeSet # 2005/03/19 00:46:50-08:00 akpm@bix.(none) # Merge bk://linux-acpi.bkbits.net/to-akpm # into bix.(none):/usr/src/bk-acpi # # drivers/acpi/Kconfig # 2005/03/19 00:46:41-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/19 01:54:47-05:00 len.brown@intel.com # [ACPI] fix EC access width # http://bugzilla.kernel.org/show_bug.cgi?id=4346 # # From: David Shaohua Li and Luming Yu # Signed-off-by: Len Brown # # drivers/acpi/ec.c # 2005/03/10 21:18:26-05:00 len.brown@intel.com +14 -18 # fix EC access width # # ChangeSet # 2005/03/19 01:12:46-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/26-latest-next # into intel.com:/home/lenb/bk/to-akpm # # drivers/acpi/Kconfig # 2005/03/19 01:12:42-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/19 01:10:05-05:00 len.brown@intel.com # [ACPI] Enable EC Burst Mode # # Fixes several Embedded Controller issues, including # button failure and battery status AE_TIME failure. # # http://bugzilla.kernel.org/show_bug.cgi?id=3851 # # Based on patch by: Andi Kleen # Signed-off-by: Dmitry Torokhov # Signed-off-by: Luming Yu # Signed-off-by: Len Brown # # drivers/acpi/ec.c # 2005/03/19 01:09:54-05:00 len.brown@intel.com +276 -114 # Enable EC Burst Mode # # ChangeSet # 2005/03/19 00:16:18-05:00 len.brown@intel.com # [ACPI] pci_set_power_state() now calls # platform_pci_set_power_state() # and ACPI can answer # # http://bugzilla.kernel.org/show_bug.cgi?id=4277 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/pci/pci.h # 2005/03/03 04:20:56-05:00 len.brown@intel.com +1 -0 # pci_set_power_state() now calls platform_pci_set_power_state() # # drivers/pci/pci.c # 2005/03/03 04:20:56-05:00 len.brown@intel.com +9 -2 # pci_set_power_state() now calls platform_pci_set_power_state() # # drivers/pci/pci-acpi.c # 2005/03/03 04:28:23-05:00 len.brown@intel.com +19 -0 # pci_set_power_state() now calls platform_pci_set_power_state() # # drivers/acpi/bus.c # 2005/03/03 04:20:56-05:00 len.brown@intel.com +7 -1 # pci_set_power_state() now calls platform_pci_set_power_state() # # ChangeSet # 2005/03/19 00:15:48-05:00 len.brown@intel.com # [ACPI] PCI can now get suspend state from firmware # # pci_choose_state() can now call # platform_pci_choose_state() # and ACPI can answer # # http://bugzilla.kernel.org/show_bug.cgi?id=4277 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/pci/pci.h # 2005/03/19 00:15:24-05:00 len.brown@intel.com +3 -0 # add platform_pci_choose_state() # # drivers/pci/pci.c # 2005/03/19 00:15:24-05:00 len.brown@intel.com +7 -0 # add platform_pci_choose_state() # # drivers/pci/pci-acpi.c # 2005/03/19 00:15:24-05:00 len.brown@intel.com +46 -1 # add platform_pci_choose_state() # # ChangeSet # 2005/03/18 18:53:36-05:00 len.brown@intel.com # [ACPI] Bind ACPI and PCI devices # # http://bugzilla.kernel.org/show_bug.cgi?id=4277 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/pci/pci-acpi.c # 2005/03/18 18:53:22-05:00 len.brown@intel.com +54 -3 # Bind PCI to ACPI # # ChangeSet # 2005/03/18 18:45:35-05:00 len.brown@intel.com # [ACPI] Bind PCI devices with ACPI devices # # Implement the framework for binding physical devices # with ACPI devices. A physical bus like PCI bus # should create a 'acpi_bus_type', with: # # .find_device: # For device which has parent such as normal PCI devices. # # .find_bridge: # It's for special devices, such as PCI root bridge # or IDE controller. Such devices generally haven't a # parent or ->bus. We use the special method # to get an ACPI handle. # # Uses new field in struct device: firmware_data # # http://bugzilla.kernel.org/show_bug.cgi?id=4277 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/acpi/glue.c # 2005/03/18 18:45:25-05:00 len.brown@intel.com +362 -0 # # include/linux/device.h # 2005/03/18 18:45:25-05:00 len.brown@intel.com +4 -2 # Bind PCI and ACPI devices # # include/acpi/acpi_bus.h # 2005/03/18 18:45:25-05:00 len.brown@intel.com +21 -0 # Bind PCI and ACPI devices # # drivers/acpi/ibm_acpi.c # 2005/03/18 18:45:25-05:00 len.brown@intel.com +2 -2 # Bind PCI and ACPI devices # # drivers/acpi/glue.c # 2005/03/18 18:45:25-05:00 len.brown@intel.com +0 -0 # BitKeeper file /home/lenb/src/26-latest-next/drivers/acpi/glue.c # # drivers/acpi/Makefile # 2005/03/18 18:45:25-05:00 len.brown@intel.com +1 -1 # Bind PCI and ACPI devices # # ChangeSet # 2005/03/18 18:03:45-05:00 len.brown@intel.com # [ACPI] generic Hot Key support # # See Documentation/acpi-hotkey.txt # # Use cmdline "acpi_specific_hotkey" to enable # legacy platform specific drivers. # # http://bugzilla.kernel.org/show_bug.cgi?id=3887 # # Signed-off-by: Luming Yu # Signed-off-by: Len Brown # # drivers/acpi/hotkey.c # 2005/03/18 18:03:33-05:00 len.brown@intel.com +1018 -0 # # drivers/acpi/hotkey.c # 2005/03/18 18:03:33-05:00 len.brown@intel.com +0 -0 # BitKeeper file /home/lenb/src/26-latest-next/drivers/acpi/hotkey.c # # Documentation/acpi-hotkey.txt # 2005/03/18 18:03:32-05:00 len.brown@intel.com +35 -0 # # include/acpi/acpi_drivers.h # 2005/03/18 18:03:32-05:00 len.brown@intel.com +5 -0 # Generic Hot Key support # # drivers/acpi/toshiba_acpi.c # 2005/03/18 18:03:32-05:00 len.brown@intel.com +5 -0 # Generic Hot Key support # # drivers/acpi/osl.c # 2005/03/18 18:03:32-05:00 len.brown@intel.com +12 -0 # Generic Hot Key support # # drivers/acpi/ibm_acpi.c # 2005/03/18 18:03:32-05:00 len.brown@intel.com +4 -0 # Generic Hot Key support # # drivers/acpi/asus_acpi.c # 2005/03/18 18:03:32-05:00 len.brown@intel.com +4 -0 # Generic Hot Key support # # drivers/acpi/Makefile # 2005/03/18 18:03:32-05:00 len.brown@intel.com +2 -1 # Generic Hot Key support # # drivers/acpi/Kconfig # 2005/03/18 18:03:32-05:00 len.brown@intel.com +9 -0 # Generic Hot Key support # # Documentation/acpi-hotkey.txt # 2005/03/18 18:03:32-05:00 len.brown@intel.com +0 -0 # BitKeeper file /home/lenb/src/26-latest-next/Documentation/acpi-hotkey.txt # # ChangeSet # 2005/03/18 16:43:54-05:00 len.brown@intel.com # [ACPI] S3 Suspend to RAM: fix driver suspend/resume methods # # Drivers should do this: # # .suspend() # pci_disable_device() # # .resume() # pci_enable_device() # # http://bugzilla.kernel.org/show_bug.cgi?id=3469 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/usb/core/hcd-pci.c # 2005/03/18 16:41:51-05:00 len.brown@intel.com +1 -0 # .suspend/.resume: pci_disable_device()/pci_enable_device() # # drivers/pcmcia/yenta_socket.c # 2005/03/03 00:34:31-05:00 len.brown@intel.com +3 -0 # .suspend/.resume: pci_disable_device()/pci_enable_device() # # drivers/net/ne2k-pci.c # 2005/03/18 16:43:35-05:00 len.brown@intel.com +3 -0 # .suspend/.resume: pci_disable_device()/pci_enable_device() # # drivers/net/e1000/e1000_main.c # 2005/03/03 00:33:08-05:00 len.brown@intel.com +1 -2 # .suspend/.resume: pci_disable_device()/pci_enable_device() # # drivers/net/b44.c # 2005/03/03 00:33:59-05:00 len.brown@intel.com +3 -0 # .suspend/.resume: pci_disable_device()/pci_enable_device() # # ChangeSet # 2005/03/18 16:30:29-05:00 len.brown@intel.com # [ACPI] S3 Suspend to RAM: interrupt resume fix # # Delete PCI Interrupt Link Device .resume method -- # it is the device driver's job to request interrupts, # not the Link's job to remember what the devices want. # # This addresses the issue of attempting to run # the ACPI interpreter too early in resume, when # interrupts are still disabled. # # http://bugzilla.kernel.org/show_bug.cgi?id=3469 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/acpi/pci_link.c # 2005/03/02 22:23:50-05:00 len.brown@intel.com +14 -22 # Delete PCI Interrupt Link .resume method # # ChangeSet # 2005/03/18 16:27:13-05:00 len.brown@intel.com # [ACPI] Suspend to RAM fix # # Free some RAM before entering S3 so that upon # resume we can be sure early allocations will succeed. # # http://bugzilla.kernel.org/show_bug.cgi?id=3469 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # kernel/power/main.c # 2005/03/02 22:23:28-05:00 len.brown@intel.com +14 -0 # free RAM before entering S3 # # ChangeSet # 2005/03/18 16:20:46-05:00 len.brown@intel.com # [ACPI] ACPI poweroff fix # # Register an "acpi" system device to be notified of shutdown preparation. # This depends on CONFIG_PM # # http://bugzilla.kernel.org/show_bug.cgi?id=4041 # # Signed-off-by: Alexey Starikovskiy # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # kernel/power/main.c # 2005/03/18 16:20:34-05:00 len.brown@intel.com +1 -1 # ACPI poweroff fix # # include/linux/pm.h # 2005/03/18 16:20:34-05:00 len.brown@intel.com +1 -1 # ACPI poweroff fix # # drivers/base/sys.c # 2005/03/18 16:20:34-05:00 len.brown@intel.com +0 -1 # ACPI poweroff fix # # drivers/acpi/sleep/poweroff.c # 2005/03/18 16:20:34-05:00 len.brown@intel.com +73 -8 # ACPI poweroff fix # # drivers/acpi/sleep/main.c # 2005/03/18 16:20:34-05:00 len.brown@intel.com +32 -42 # ACPI poweroff fix # # ChangeSet # 2005/03/18 16:00:29-05:00 len.brown@intel.com # [ACPI] CONFIG_ACPI now depends on CONFIG_PM # # Signed-off-by: Len Brown # # drivers/acpi/Kconfig # 2005/03/18 16:00:07-05:00 len.brown@intel.com +2 -1 # CONFIG_ACPI now depends on CONFIG_PM # # ChangeSet # 2005/03/18 15:51:24-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/linux-2.6.11 # into intel.com:/home/lenb/src/26-stable-dev # # drivers/acpi/scan.c # 2005/03/18 15:51:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/acpi/pci_irq.c # 2005/03/18 15:51:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # drivers/acpi/numa.c # 2005/03/18 15:51:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/ia64/kernel/acpi.c # 2005/03/18 15:51:07-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/18 15:35:22-05:00 len.brown@intel.com # [ACPI] Allow simultaneous Fixed Feature and Control Method buttons # delete /proc/acpi/button # # http://bugzilla.kernel.org/show_bug.cgi?id=1920 # # Signed-off-by: Alexey Starikovskiy # Signed-off-by: Len Brown # # drivers/acpi/button.c # 2005/03/18 15:35:11-05:00 len.brown@intel.com +3 -249 # Allow simultaneous Fixed Feature and Control Method buttons # delete /proc/acpi/button # # ChangeSet # 2005/03/17 21:53:25-08:00 akpm@bix.(none) # Merge bk://linux-acpi.bkbits.net/to-akpm # into bix.(none):/usr/src/bk-acpi # # drivers/acpi/Kconfig # 2005/03/17 21:53:19-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/i386/kernel/acpi/sleep.c # 2005/03/17 21:53:19-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/18 00:04:06-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/26-latest-test # into intel.com:/home/lenb/bk/to-akpm # # drivers/acpi/Kconfig # 2005/03/18 00:04:01-05:00 len.brown@intel.com +0 -1 # Auto merged # # ChangeSet # 2005/03/17 23:47:07-05:00 len.brown@intel.com # merge # # drivers/acpi/Kconfig # 2005/03/17 23:46:56-05:00 len.brown@intel.com +1 -2 # merge # # ChangeSet # 2005/03/13 18:10:24-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # arch/i386/kernel/acpi/sleep.c # 2005/03/13 18:10:16-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/13 14:08:50-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi # # drivers/acpi/Kconfig # 2005/03/13 14:08:43-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/02 13:40:30-05:00 len.brown@intel.com # [ACPI] update CONFIG_ACPI_CONTAINER Kconfig help # # Signed-off-by: Keiichiro Tokunaga # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/Kconfig # 2005/02/17 12:13:31-05:00 len.brown@intel.com +7 -2 # Import patch fix-help-for-acpi_container.patch # # ChangeSet # 2005/02/08 09:29:08-05:00 len.brown@intel.com # [ACPI] GDT wakeup vector fix # # Written-by: Hiroshi Itoh # Signed-off-by: Len Brown # # arch/i386/kernel/acpi/wakeup.S # 2005/02/08 09:28:53-05:00 len.brown@intel.com +15 -0 # Import patch wakeup_gdt2.patch # # arch/i386/kernel/acpi/sleep.c # 2004/10/18 11:59:32-04:00 len.brown@intel.com +3 -2 # Import patch wakeup_gdt2.patch # diff -Nru a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/acpi-hotkey.txt 2005-04-10 17:05:04 -07:00 @@ -0,0 +1,35 @@ +driver/acpi/hotkey.c implement: +1. /proc/acpi/hotkey/event_config +(event based hotkey or event config interface): +a. add a event based hotkey(event) : +echo "0:bus::action:method:num:num" > event_config + +b. delete a event based hotkey(event): +echo "1:::::num:num" > event_config + +c. modify a event based hotkey(event): +echo "2:bus::action:method:num:num" > event_config + +2. /proc/acpi/hotkey/poll_config +(polling based hotkey or event config interface): +a.add a polling based hotkey(event) : +echo "0:bus:method:action:method:num" > poll_config +this adding command will create a proc file +/proc/acpi/hotkey/method, which is used to get +result of polling. + +b.delete a polling based hotkey(event): +echo "1:::::num" > event_config + +c.modify a polling based hotkey(event): +echo "2:bus:method:action:method:num" > poll_config + +3./proc/acpi/hotkey/action +(interface to call aml method associated with a +specific hotkey(event)) +echo "event_num:event_type:event_argument" > + /proc/acpi/hotkey/action. +The result of the execution of this aml method is +attached to /proc/acpi/hotkey/poll_method, which is dnyamically +created. Please use command "cat /proc/acpi/hotkey/polling_method" +to retrieve it. diff -Nru a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c --- a/arch/frv/mb93090-mb00/pci-irq.c 2005-04-10 17:05:04 -07:00 +++ b/arch/frv/mb93090-mb00/pci-irq.c 2005-04-10 17:05:04 -07:00 @@ -60,7 +60,7 @@ } } -void __init pcibios_penalize_isa_irq(int irq) +void __init pcibios_penalize_isa_irq(int irq, int active) { } diff -Nru a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c --- a/arch/i386/kernel/acpi/sleep.c 2005-04-10 17:05:04 -07:00 +++ b/arch/i386/kernel/acpi/sleep.c 2005-04-10 17:05:04 -07:00 @@ -17,7 +17,7 @@ extern void zap_low_mappings(void); -extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); +extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long,unsigned long)); static void init_low_mapping(pgd_t *pgd, int pgd_limit) { @@ -42,7 +42,8 @@ return 1; init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD); memcpy((void *) acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start); - acpi_copy_wakeup_routine(acpi_wakeup_address); + acpi_copy_wakeup_routine(acpi_wakeup_address, + virt_to_phys((void *)acpi_wakeup_address)); return 0; } diff -Nru a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S --- a/arch/i386/kernel/acpi/wakeup.S 2005-04-10 17:05:04 -07:00 +++ b/arch/i386/kernel/acpi/wakeup.S 2005-04-10 17:05:04 -07:00 @@ -97,6 +97,7 @@ real_magic: .long 0 video_mode: .long 0 video_flags: .long 0 +real_gdt_table: .fill GDT_ENTRIES, 8, 0 real_efer_save_restore: .long 0 real_save_efer_edx: .long 0 real_save_efer_eax: .long 0 @@ -224,6 +225,7 @@ # # Parameters: # %eax: place to copy wakeup routine to +# %edx: the second argument (physical address) # # Returned address is location of code in low memory (past data and stack) # @@ -248,6 +250,9 @@ popl %eax 2: + # save wakeup_start physical address in ecx + movl %edx, %ecx + movl %cr3, %edx movl %edx, real_save_cr3 - wakeup_start (%eax) movl %cr4, %edx @@ -255,6 +260,16 @@ movl %cr0, %edx movl %edx, real_save_cr0 - wakeup_start (%eax) sgdt real_save_gdt - wakeup_start (%eax) + + # gdt body must be addressable from real mode by + # copying it to the lower mem + lea real_gdt_table - wakeup_start (%ecx), %ecx + movl %ecx, real_save_gdt + 2 - wakeup_start (%eax) + xor %ecx, %ecx + movw saved_gdt, %cx + movl saved_gdt + 2, %esi + lea real_gdt_table - wakeup_start (%eax), %edi + rep movsb movl saved_videomode, %edx movl %edx, video_mode - wakeup_start (%eax) diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c 2005-04-10 17:05:04 -07:00 +++ b/arch/i386/pci/irq.c 2005-04-10 17:05:04 -07:00 @@ -1003,30 +1003,33 @@ subsys_initcall(pcibios_irq_init); -static void pirq_penalize_isa_irq(int irq) +static void pirq_penalize_isa_irq(int irq, int active) { /* * If any ISAPnP device reports an IRQ in its list of possible * IRQ's, we try to avoid assigning it to PCI devices. */ - if (irq < 16) - pirq_penalty[irq] += 100; + if (irq < 16) { + if (active) + pirq_penalty[irq] += 1000; + else + pirq_penalty[irq] += 100; + } } -void pcibios_penalize_isa_irq(int irq) +void pcibios_penalize_isa_irq(int irq, int active) { #ifdef CONFIG_ACPI_PCI if (!acpi_noirq) - acpi_penalize_isa_irq(irq); + acpi_penalize_isa_irq(irq, active); else #endif - pirq_penalize_isa_irq(irq); + pirq_penalize_isa_irq(irq, active); } static int pirq_enable_irq(struct pci_dev *dev) { u8 pin; - extern int via_interrupt_line_quirk; struct pci_dev *temp_dev; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); @@ -1081,10 +1084,6 @@ printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin, pci_name(dev), msg); } - /* VIA bridges use interrupt line for apic/pci steering across - the V-Link */ - else if (via_interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15); return 0; } diff -Nru a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c --- a/arch/i386/pci/visws.c 2005-04-10 17:05:04 -07:00 +++ b/arch/i386/pci/visws.c 2005-04-10 17:05:04 -07:00 @@ -21,7 +21,7 @@ int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; -void __init pcibios_penalize_isa_irq(int irq) {} +void __init pcibios_penalize_isa_irq(int irq, int active) {} unsigned int pci_bus0, pci_bus1; diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c 2005-04-10 17:05:04 -07:00 +++ b/arch/ia64/kernel/acpi.c 2005-04-10 17:05:04 -07:00 @@ -11,6 +11,7 @@ * Copyright (C) 2001 Jenna Hall * Copyright (C) 2001 Takayoshi Kochi * Copyright (C) 2002 Erich Focht + * Copyright (C) 2004 Ashok Raj * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -67,6 +68,11 @@ unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; +static unsigned int __initdata acpi_madt_rev; + +unsigned int acpi_cpei_override; +unsigned int acpi_cpei_phys_cpuid; + #define MAX_SAPICS 256 u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = { [0 ... MAX_SAPICS - 1] = -1 }; @@ -267,10 +273,56 @@ (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); platform_intr_list[plintsrc->type] = vector; + if (acpi_madt_rev > 1) { + acpi_cpei_override = plintsrc->plint_flags.cpei_override_flag; + } + + /* + * Save the physical id, so we can check when its being removed + */ + acpi_cpei_phys_cpuid = ((plintsrc->id << 8) | (plintsrc->eid)) & 0xffff; + return 0; } +unsigned int can_cpei_retarget(void) +{ + extern int cpe_vector; + + /* + * Only if CPEI is supported and the override flag + * is present, otherwise return that its re-targettable + * if we are in polling mode. + */ + if (cpe_vector > 0 && !acpi_cpei_override) + return 0; + else + return 1; +} + +unsigned int is_cpu_cpei_target(unsigned int cpu) +{ + unsigned int logical_id; + + logical_id = cpu_logical_id(acpi_cpei_phys_cpuid); + + if (logical_id == cpu) + return 1; + else + return 0; +} + +void set_cpei_target_cpu(unsigned int cpu) +{ + acpi_cpei_phys_cpuid = cpu_physical_id(cpu); +} + +unsigned int get_cpei_target_cpu(void) +{ + return acpi_cpei_phys_cpuid; +} + static int __init acpi_parse_int_src_ovr ( acpi_table_entry_header *header, const unsigned long end) @@ -327,6 +379,8 @@ return -EINVAL; acpi_madt = (struct acpi_table_madt *) __va(phys_addr); + + acpi_madt_rev = acpi_madt->header.revision; /* remember the value for reference after free_initmem() */ #ifdef CONFIG_ITANIUM diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c 2005-04-10 17:05:04 -07:00 +++ b/arch/ia64/kernel/mca.c 2005-04-10 17:05:04 -07:00 @@ -271,7 +271,7 @@ #ifdef CONFIG_ACPI -static int cpe_vector = -1; +int cpe_vector = -1; static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) diff -Nru a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c --- a/arch/ia64/kernel/topology.c 2005-04-10 17:05:04 -07:00 +++ b/arch/ia64/kernel/topology.c 2005-04-10 17:05:04 -07:00 @@ -36,6 +36,13 @@ parent = &sysfs_nodes[cpu_to_node(num)]; #endif /* CONFIG_NUMA */ + /* + * If CPEI cannot be re-targetted, and this is + * CPEI target, then dont create the control file + */ + if (!can_cpei_retarget() && is_cpu_cpei_target(num)) + sysfs_cpus[num].cpu.no_control = 1; + return register_cpu(&sysfs_cpus[num].cpu, num, parent); } diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig --- a/drivers/acpi/Kconfig 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/Kconfig 2005-04-10 17:05:04 -07:00 @@ -3,6 +3,7 @@ # menu "ACPI (Advanced Configuration and Power Interface) Support" + depends on PM depends on !X86_VISWS depends on !IA64_HP_SIM depends on IA64 || X86 @@ -57,7 +58,7 @@ config ACPI_SLEEP bool "Sleep States (EXPERIMENTAL)" depends on X86 - depends on EXPERIMENTAL && PM + depends on EXPERIMENTAL default y ---help--- This option adds support for ACPI suspend states. @@ -123,6 +124,15 @@ Note that this is an ref. implementation only. It may or may not work for your integrated video device. +config ACPI_HOTKEY + tristate "Generic Hotkey" + depends on ACPI_INTERPRETER + depends on EXPERIMENTAL + depends on !IA64_SGI_SN + default m + help + ACPI generic hotkey + config ACPI_FAN tristate "Fan" depends on !IA64_SGI_SN @@ -328,8 +338,13 @@ depends on EXPERIMENTAL default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) ---help--- - This is the ACPI generic container driver which supports - ACPI0004, PNP0A05 and PNP0A06 devices + This allows _physical_ insertion and removal of CPUs and memory. + This can be useful, for example, on NUMA machines that support + ACPI based physical hotplug of nodes, or non-NUMA machines that + support physical cpu/memory hot-plug. + + If one selects "m", this driver can be loaded with + "modprobe acpi_container". config ACPI_HOTPLUG_MEMORY tristate "Memory Hotplug" diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile --- a/drivers/acpi/Makefile 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/Makefile 2005-04-10 17:05:04 -07:00 @@ -36,13 +36,14 @@ endif obj-$(CONFIG_ACPI_BUS) += sleep/ -obj-$(CONFIG_ACPI_BUS) += bus.o +obj-$(CONFIG_ACPI_BUS) += bus.o glue.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_EC) += ec.o obj-$(CONFIG_ACPI_FAN) += fan.o -obj-$(CONFIG_ACPI_VIDEO) += video.o +obj-$(CONFIG_ACPI_VIDEO) += video.o +obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c --- a/drivers/acpi/asus_acpi.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/asus_acpi.c 2005-04-10 17:05:04 -07:00 @@ -1204,6 +1204,10 @@ if (acpi_disabled) return -ENODEV; + if (!acpi_specific_hotkey_enabled){ + printk(KERN_ERR "Using generic hotkey driver\n"); + return -ENODEV; + } asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); if (!asus_proc_dir) { printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c --- a/drivers/acpi/bus.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/bus.c 2005-04-10 17:05:04 -07:00 @@ -212,6 +212,12 @@ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n")); return_VALUE(-ENODEV); } + /* + * Get device's current power state if it's unknown + * This means device power state isn't initialized or previous setting failed + */ + if (device->power.state == ACPI_STATE_UNKNOWN) + acpi_bus_get_power(device->handle, &device->power.state); if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return_VALUE(0); @@ -231,7 +237,7 @@ * On transitions to a high-powered state we first apply power (via * power resources) then evalute _PSx. Conversly for transitions to * a lower-powered state. - */ + */ if (state < device->power.state) { if (device->power.flags.power_resources) { result = acpi_power_transition(device, state); diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c --- a/drivers/acpi/button.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/button.c 2005-04-10 17:05:04 -07:00 @@ -26,9 +26,6 @@ #include #include #include -#include -#include -#include #include #include @@ -36,9 +33,6 @@ #define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_CLASS "button" -#define ACPI_BUTTON_FILE_INFO "info" -#define ACPI_BUTTON_FILE_STATE "state" -#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 #define ACPI_BUTTON_NOTIFY_STATUS 0x80 #define ACPI_BUTTON_SUBCLASS_POWER "power" @@ -70,8 +64,6 @@ static int acpi_button_add (struct acpi_device *device); static int acpi_button_remove (struct acpi_device *device, int type); -static int acpi_button_info_open_fs(struct inode *inode, struct file *file); -static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = ACPI_BUTTON_DRIVER_NAME, @@ -90,191 +82,6 @@ unsigned long pushed; }; -static struct file_operations acpi_button_info_fops = { - .open = acpi_button_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static struct file_operations acpi_button_state_fops = { - .open = acpi_button_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -static struct proc_dir_entry *acpi_button_dir; - -static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_button *button = (struct acpi_button *) seq->private; - - ACPI_FUNCTION_TRACE("acpi_button_info_seq_show"); - - if (!button || !button->device) - return_VALUE(0); - - seq_printf(seq, "type: %s\n", - acpi_device_name(button->device)); - - return_VALUE(0); -} - -static int acpi_button_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); -} - -static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_button *button = (struct acpi_button *) seq->private; - acpi_status status; - unsigned long state; - - ACPI_FUNCTION_TRACE("acpi_button_state_seq_show"); - - if (!button || !button->device) - return_VALUE(0); - - status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state); - if (ACPI_FAILURE(status)) { - seq_printf(seq, "state: unsupported\n"); - } - else{ - seq_printf(seq, "state: %s\n", (state ? "open" : "closed")); - } - - return_VALUE(0); -} - -static int acpi_button_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); -} - -static int -acpi_button_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - struct acpi_button *button = NULL; - - ACPI_FUNCTION_TRACE("acpi_button_add_fs"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - button = acpi_driver_data(device); - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - case ACPI_BUTTON_TYPE_POWERF: - entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, - acpi_button_dir); - break; - case ACPI_BUTTON_TYPE_SLEEP: - case ACPI_BUTTON_TYPE_SLEEPF: - entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, - acpi_button_dir); - break; - case ACPI_BUTTON_TYPE_LID: - entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, - acpi_button_dir); - break; - } - - if (!entry) - return_VALUE(-ENODEV); - entry->owner = THIS_MODULE; - - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - acpi_device_dir(device)->owner = THIS_MODULE; - - /* 'info' [R] */ - entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_BUTTON_FILE_INFO)); - else { - entry->proc_fops = &acpi_button_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } - - /* show lid state [R] */ - if (button->type == ACPI_BUTTON_TYPE_LID) { - entry = create_proc_entry(ACPI_BUTTON_FILE_STATE, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_BUTTON_FILE_INFO)); - else { - entry->proc_fops = &acpi_button_state_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } - } - - return_VALUE(0); -} - - -static int -acpi_button_remove_fs ( - struct acpi_device *device) -{ - struct acpi_button *button = NULL; - - ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); - - button = acpi_driver_data(device); - if (acpi_device_dir(device)) { - if (button->type == ACPI_BUTTON_TYPE_LID) - remove_proc_entry(ACPI_BUTTON_FILE_STATE, - acpi_device_dir(device)); - remove_proc_entry(ACPI_BUTTON_FILE_INFO, - acpi_device_dir(device)); - - remove_proc_entry(acpi_device_bid(device), - acpi_device_dir(device)->parent); - - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - case ACPI_BUTTON_TYPE_POWERF: - remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, - acpi_button_dir); - break; - case ACPI_BUTTON_TYPE_SLEEP: - case ACPI_BUTTON_TYPE_SLEEPF: - remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, - acpi_button_dir); - break; - case ACPI_BUTTON_TYPE_LID: - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, - acpi_button_dir); - break; - } - acpi_device_dir(device) = NULL; - } - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - static void acpi_button_notify ( acpi_handle handle, @@ -310,8 +117,7 @@ ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); - if (!button) - return_ACPI_STATUS(AE_BAD_PARAMETER); + BUG_ON(!button); acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); @@ -327,10 +133,6 @@ acpi_status status = AE_OK; struct acpi_button *button = NULL; - static struct acpi_device *power_button; - static struct acpi_device *sleep_button; - static struct acpi_device *lid_button; - ACPI_FUNCTION_TRACE("acpi_button_add"); if (!device) @@ -391,42 +193,6 @@ goto end; } - /* - * Ensure only one button of each type is used. - */ - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - case ACPI_BUTTON_TYPE_POWERF: - if (!power_button) - power_button = device; - else { - kfree(button); - return_VALUE(-ENODEV); - } - break; - case ACPI_BUTTON_TYPE_SLEEP: - case ACPI_BUTTON_TYPE_SLEEPF: - if (!sleep_button) - sleep_button = device; - else { - kfree(button); - return_VALUE(-ENODEV); - } - break; - case ACPI_BUTTON_TYPE_LID: - if (!lid_button) - lid_button = device; - else { - kfree(button); - return_VALUE(-ENODEV); - } - break; - } - - result = acpi_button_add_fs(device); - if (result) - goto end; - switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler ( @@ -470,7 +236,6 @@ end: if (result) { - acpi_button_remove_fs(device); kfree(button); } @@ -511,8 +276,6 @@ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); - acpi_button_remove_fs(device); - kfree(button); return_VALUE(0); @@ -526,21 +289,14 @@ ACPI_FUNCTION_TRACE("acpi_button_init"); - acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); - if (!acpi_button_dir) - return_VALUE(-ENODEV); - acpi_button_dir->owner = THIS_MODULE; - result = acpi_bus_register_driver(&acpi_button_driver); if (result < 0) { - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return_VALUE(-ENODEV); } return_VALUE(0); } - static void __exit acpi_button_exit (void) { @@ -548,11 +304,8 @@ acpi_bus_unregister_driver(&acpi_button_driver); - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); - return_VOID; } - module_init(acpi_button_init); module_exit(acpi_button_exit); diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c --- a/drivers/acpi/ec.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/ec.c 2005-04-10 17:05:04 -07:00 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -49,17 +50,19 @@ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ +#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ #define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ #define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ -#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ -#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ +#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_COMMAND_READ 0x80 #define ACPI_EC_COMMAND_WRITE 0x81 +#define ACPI_EC_BURST_ENABLE 0x82 +#define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 static int acpi_ec_add (struct acpi_device *device); @@ -87,7 +90,11 @@ struct acpi_generic_address command_addr; struct acpi_generic_address data_addr; unsigned long global_lock; - spinlock_t lock; + unsigned int expect_event; + atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ + atomic_t pending_gpe; + struct semaphore sem; + wait_queue_head_t wait; }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -100,42 +107,122 @@ Transaction Management -------------------------------------------------------------------------- */ -static int -acpi_ec_wait ( - struct acpi_ec *ec, - u8 event) +static inline u32 acpi_ec_read_status(struct acpi_ec *ec) { - u32 acpi_ec_status = 0; - u32 i = ACPI_EC_UDELAY_COUNT; + u32 status = 0; - if (!ec) - return -EINVAL; + acpi_hw_low_level_read(8, &status, &ec->status_addr); + return status; +} + +static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_wait"); - /* Poll the EC status register waiting for the event to occur. */ + ec->expect_event = event; + smp_mb(); + + result = wait_event_interruptible_timeout(ec->wait, + !ec->expect_event, + msecs_to_jiffies(ACPI_EC_DELAY)); + + ec->expect_event = 0; + smp_mb(); + + if (result < 0){ + ACPI_DEBUG_PRINT((ACPI_DB_ERROR," result = %d ", result)); + return_VALUE(result); + } + + /* + * Verify that the event in question has actually happened by + * querying EC status. Do the check even if operation timed-out + * to make sure that we did not miss interrupt. + */ switch (event) { case ACPI_EC_EVENT_OBF: - do { - acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); - if (acpi_ec_status & ACPI_EC_FLAG_OBF) - return 0; - udelay(ACPI_EC_UDELAY); - } while (--i>0); + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) + return_VALUE(0); break; + case ACPI_EC_EVENT_IBE: - do { - acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); - if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) - return 0; - udelay(ACPI_EC_UDELAY); - } while (--i>0); + if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) + return_VALUE(0); break; - default: - return -EINVAL; } - return -ETIME; + return_VALUE(-ETIME); +} + + + +static int +acpi_ec_enter_burst_mode ( + struct acpi_ec *ec) +{ + u32 tmp = 0; + int status = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_enter_burst_mode"); + + status = acpi_ec_read_status(ec); + if (status != -EINVAL && + !(status & ACPI_EC_FLAG_BURST)){ + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"entering burst mode \n")); + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (status){ + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR," status = %d\n", status)); + return_VALUE(-EINVAL); + } + acpi_hw_low_level_read(8, &tmp, &ec->data_addr); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + if(tmp != 0x90 ) {/* Burst ACK byte*/ + ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Ack failed \n")); + return_VALUE(-EINVAL); + } + } else + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"already be in burst mode \n")); + atomic_set(&ec->leaving_burst , 0); + return_VALUE(0); } +static int +acpi_ec_leave_burst_mode ( + struct acpi_ec *ec) +{ + int status =0; + + ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); + + atomic_set(&ec->leaving_burst , 1); + status = acpi_ec_read_status(ec); + if (status != -EINVAL && + (status & ACPI_EC_FLAG_BURST)){ + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"leaving burst mode\n")); + acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr); + status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); + if (status){ + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); + return_VALUE(-EINVAL); + } + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + status = acpi_ec_read_status(ec); + if (status != -EINVAL && + (status & ACPI_EC_FLAG_BURST)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->status fail\n")); + return_VALUE(-EINVAL); + } + }else + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"already be in Non-burst mode \n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"leaving burst mode\n")); + + return_VALUE(0); +} static int acpi_ec_read ( @@ -143,16 +230,15 @@ u8 address, u32 *data) { - acpi_status status = AE_OK; - int result = 0; - unsigned long flags = 0; - u32 glk = 0; + int status = 0; + u32 glk; ACPI_FUNCTION_TRACE("acpi_ec_read"); if (!ec || !data) return_VALUE(-EINVAL); +retry: *data = 0; if (ec->global_lock) { @@ -160,32 +246,50 @@ if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } - - spin_lock_irqsave(&ec->lock, flags); + + WARN_ON(in_interrupt()); + down(&ec->sem); + + if(acpi_ec_enter_burst_mode(ec)) + goto end; acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + if (status) { goto end; + } acpi_hw_low_level_write(8, address, &ec->data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (result) + status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (status){ + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); goto end; - + } acpi_hw_low_level_read(8, data, &ec->data_addr); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); - + end: - spin_unlock_irqrestore(&ec->lock, flags); + acpi_ec_leave_burst_mode(ec); + up(&ec->sem); if (ec->global_lock) acpi_release_global_lock(glk); - return_VALUE(result); + if(atomic_read(&ec->leaving_burst) == 2){ + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); + while(!atomic_read(&ec->pending_gpe)){ + msleep(1); + } + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + goto retry; + } + + return_VALUE(status); } @@ -195,49 +299,80 @@ u8 address, u8 data) { - int result = 0; - acpi_status status = AE_OK; - unsigned long flags = 0; - u32 glk = 0; + int status = 0; + u32 glk; + u32 tmp; ACPI_FUNCTION_TRACE("acpi_ec_write"); if (!ec) return_VALUE(-EINVAL); - +retry: if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->lock, flags); + WARN_ON(in_interrupt()); + down(&ec->sem); + + if(acpi_ec_enter_burst_mode(ec)) + goto end; + + status = acpi_ec_read_status(ec); + if (status != -EINVAL && + !(status & ACPI_EC_FLAG_BURST)){ + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (status) + goto end; + acpi_hw_low_level_read(8, &tmp, &ec->data_addr); + if(tmp != 0x90 ) /* Burst ACK byte*/ + goto end; + } + /*Now we are in burst mode*/ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + if (status){ goto end; + } acpi_hw_low_level_write(8, address, &ec->data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (status){ + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); goto end; + } acpi_hw_low_level_write(8, data, &ec->data_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (result) + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + if (status) goto end; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", data, address)); end: - spin_unlock_irqrestore(&ec->lock, flags); + acpi_ec_leave_burst_mode(ec); + up(&ec->sem); if (ec->global_lock) acpi_release_global_lock(glk); - return_VALUE(result); + if(atomic_read(&ec->leaving_burst) == 2){ + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); + while(!atomic_read(&ec->pending_gpe)){ + msleep(1); + } + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + goto retry; + } + + return_VALUE(status); } /* @@ -289,16 +424,14 @@ struct acpi_ec *ec, u32 *data) { - int result = 0; - acpi_status status = AE_OK; - unsigned long flags = 0; - u32 glk = 0; + int status = 0; + u32 glk; ACPI_FUNCTION_TRACE("acpi_ec_query"); if (!ec || !data) return_VALUE(-EINVAL); - +retry: *data = 0; if (ec->global_lock) { @@ -307,29 +440,43 @@ return_VALUE(-ENODEV); } + down(&ec->sem); + if(acpi_ec_enter_burst_mode(ec)) + 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). */ - spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (result) + status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (status){ + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); goto end; - + } + acpi_hw_low_level_read(8, data, &ec->data_addr); + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); if (!*data) - result = -ENODATA; + status = -ENODATA; end: - spin_unlock_irqrestore(&ec->lock, flags); + acpi_ec_leave_burst_mode(ec); + up(&ec->sem); if (ec->global_lock) acpi_release_global_lock(glk); - return_VALUE(result); + if(atomic_read(&ec->leaving_burst) == 2){ + ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); + while(!atomic_read(&ec->pending_gpe)){ + msleep(1); + } + acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + goto retry; + } + + return_VALUE(status); } @@ -347,42 +494,29 @@ void *ec_cxt) { struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; - u32 value = 0; - unsigned long flags = 0; + u32 value; + int result = -ENODATA; static char object_name[5] = {'_','Q','0','0','\0'}; const char hex[] = {'0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F'}; ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); - if (!ec_cxt) - goto end; + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) + result = acpi_ec_query(ec, &value); - spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_read(8, &value, &ec->command_addr); - spin_unlock_irqrestore(&ec->lock, flags); - - /* TBD: Implement asynch events! - * NOTE: All we care about are EC-SCI's. Other EC events are - * handled via polling (yuck!). This is because some systems - * treat EC-SCIs as level (versus EDGE!) triggered, preventing - * a purely interrupt-driven approach (grumble, grumble). - */ - if (!(value & ACPI_EC_FLAG_SCI)) + if (result) goto end; - if (acpi_ec_query(ec, &value)) - goto end; - object_name[2] = hex[((value >> 4) & 0x0F)]; object_name[3] = hex[(value & 0x0F)]; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); acpi_evaluate_object(ec->handle, object_name, NULL, NULL); - -end: - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + atomic_dec(&ec->pending_gpe); +end: + return; } static u32 @@ -390,6 +524,7 @@ void *data) { acpi_status status = AE_OK; + u32 value; struct acpi_ec *ec = (struct acpi_ec *) data; if (!ec) @@ -397,13 +532,39 @@ acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_ec_gpe_query, ec); + value = acpi_ec_read_status(ec); - if (status == AE_OK) - return ACPI_INTERRUPT_HANDLED; - else - return ACPI_INTERRUPT_NOT_HANDLED; + if((value & ACPI_EC_FLAG_IBF) && + !(value & ACPI_EC_FLAG_BURST) && + (atomic_read(&ec->leaving_burst) == 0)) { + /* + * the embedded controller disables + * burst mode for any reason other + * than the burst disable command + * to process critical event. + */ + atomic_set(&ec->leaving_burst , 2); /* block current pending transaction + and retry */ + wake_up(&ec->wait); + }else { + if ((ec->expect_event == ACPI_EC_EVENT_OBF && + (value & ACPI_EC_FLAG_OBF)) || + (ec->expect_event == ACPI_EC_EVENT_IBE && + !(value & ACPI_EC_FLAG_IBF))) { + ec->expect_event = 0; + wake_up(&ec->wait); + + } + } + + if (value & ACPI_EC_FLAG_SCI){ + atomic_add(1, &ec->pending_gpe) ; + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_ec_gpe_query, ec); + } + + return status == AE_OK ? + ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } /* -------------------------------------------------------------------------- @@ -421,10 +582,8 @@ * The EC object is in the handler context and is needed * when calling the acpi_ec_space_handler. */ - if(function == ACPI_REGION_DEACTIVATE) - *return_context = NULL; - else - *return_context = handler_context; + *return_context = (function != ACPI_REGION_DEACTIVATE) ? + handler_context : NULL; return AE_OK; } @@ -441,7 +600,7 @@ { int result = 0; struct acpi_ec *ec = NULL; - u32 temp = 0; + u64 temp = *value; acpi_integer f_v = 0; int i = 0; @@ -450,10 +609,9 @@ if ((address > 0xFF) || !value || !handler_context) return_VALUE(AE_BAD_PARAMETER); - if(bit_width != 8) { + if (bit_width != 8 && acpi_strict) { printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n"); - if (acpi_strict) - return_VALUE(AE_BAD_PARAMETER); + return_VALUE(AE_BAD_PARAMETER); } ec = (struct acpi_ec *) handler_context; @@ -461,11 +619,11 @@ next_byte: switch (function) { case ACPI_READ: - result = acpi_ec_read(ec, (u8) address, &temp); - *value = (acpi_integer) temp; + temp = 0; + result = acpi_ec_read(ec, (u8) address, (u32 *)&temp); break; case ACPI_WRITE: - result = acpi_ec_write(ec, (u8) address, (u8) *value); + result = acpi_ec_write(ec, (u8) address, (u8) temp); break; default: result = -EINVAL; @@ -474,19 +632,18 @@ } bit_width -= 8; - if(bit_width){ - - if(function == ACPI_READ) - f_v |= (acpi_integer) (*value) << 8*i; - if(function == ACPI_WRITE) - (*value) >>=8; + if (bit_width) { + if (function == ACPI_READ) + f_v |= temp << 8 * i; + if (function == ACPI_WRITE) + temp >>= 8; i++; + address++; goto next_byte; } - - if(function == ACPI_READ){ - f_v |= (acpi_integer) (*value) << 8*i; + if (function == ACPI_READ) { + f_v |= temp << 8 * i; *value = f_v; } @@ -505,8 +662,6 @@ default: return_VALUE(AE_OK); } - - } @@ -555,7 +710,7 @@ acpi_ec_add_fs ( struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *entry; ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); @@ -606,9 +761,9 @@ acpi_ec_add ( struct acpi_device *device) { - int result = 0; - acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; + int result; + acpi_status status; + struct acpi_ec *ec; unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -623,7 +778,10 @@ ec->handle = device->handle; ec->uid = -1; - spin_lock_init(&ec->lock); + atomic_set(&ec->pending_gpe, 0); + atomic_set(&ec->leaving_burst , 1); + init_MUTEX(&ec->sem); + init_waitqueue_head(&ec->wait); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; @@ -637,7 +795,7 @@ if (ec_ecdt && ec_ecdt->uid == uid) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - + acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); kfree(ec_ecdt); @@ -677,7 +835,7 @@ struct acpi_device *device, int type) { - struct acpi_ec *ec = NULL; + struct acpi_ec *ec; ACPI_FUNCTION_TRACE("acpi_ec_remove"); @@ -732,8 +890,8 @@ acpi_ec_start ( struct acpi_device *device) { - acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; + acpi_status status; + struct acpi_ec *ec; ACPI_FUNCTION_TRACE("acpi_ec_start"); @@ -789,8 +947,8 @@ struct acpi_device *device, int type) { - acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; + acpi_status status; + struct acpi_ec *ec; ACPI_FUNCTION_TRACE("acpi_ec_stop"); @@ -832,7 +990,6 @@ status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); if (ACPI_FAILURE(status)) return status; - spin_lock_init(&ec_ecdt->lock); ec_ecdt->global_lock = TRUE; ec_ecdt->handle = handle; @@ -890,7 +1047,7 @@ acpi_status status; struct acpi_table_ecdt *ecdt_ptr; - status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, + status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, (struct acpi_table_header **) &ecdt_ptr); if (ACPI_FAILURE(status)) return -ENODEV; @@ -905,11 +1062,12 @@ return -ENOMEM; memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + init_MUTEX(&ec_ecdt->sem); + init_waitqueue_head(&ec_ecdt->wait); ec_ecdt->command_addr = ecdt_ptr->ec_control; ec_ecdt->status_addr = ecdt_ptr->ec_control; ec_ecdt->data_addr = ecdt_ptr->ec_data; ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; - spin_lock_init(&ec_ecdt->lock); /* use the GL just to be safe */ ec_ecdt->global_lock = TRUE; ec_ecdt->uid = ecdt_ptr->uid; @@ -978,7 +1136,7 @@ static int __init acpi_ec_init (void) { - int result = 0; + int result; ACPI_FUNCTION_TRACE("acpi_ec_init"); diff -Nru a/drivers/acpi/glue.c b/drivers/acpi/glue.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/acpi/glue.c 2005-04-10 17:05:04 -07:00 @@ -0,0 +1,362 @@ +/* + * Link physical devices with ACPI devices support + * + * Copyright (c) 2005 David Shaohua Li + * Copyright (c) 2005 Intel Corp. + * + * This file is released under the GPLv2. + */ +#include +#include +#include +#include +#include + +#define ACPI_GLUE_DEBUG 0 +#if ACPI_GLUE_DEBUG +#define DBG(x...) printk(PREFIX x) +#else +#define DBG(x...) +#endif +static LIST_HEAD(bus_type_list); +static DECLARE_RWSEM(bus_type_sem); + +int register_acpi_bus_type(struct acpi_bus_type *type) +{ + if (acpi_disabled) + return -ENODEV; + if (type && type->bus && type->find_device) { + down_write(&bus_type_sem); + list_add_tail(&type->list, &bus_type_list); + up_write(&bus_type_sem); + DBG("ACPI bus type %s registered\n", type->bus->name); + return 0; + } + return -ENODEV; +} + +EXPORT_SYMBOL(register_acpi_bus_type); + +int unregister_acpi_bus_type(struct acpi_bus_type *type) +{ + if (acpi_disabled) + return 0; + if (type) { + down_write(&bus_type_sem); + list_del_init(&type->list); + up_write(&bus_type_sem); + DBG("ACPI bus type %s unregistered\n", type->bus->name); + return 0; + } + return -ENODEV; +} + +EXPORT_SYMBOL(unregister_acpi_bus_type); + +static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) +{ + struct acpi_bus_type *tmp, *ret = NULL; + + down_read(&bus_type_sem); + list_for_each_entry(tmp, &bus_type_list, list) { + if (tmp->bus == type) { + ret = tmp; + break; + } + } + up_read(&bus_type_sem); + return ret; +} + +static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) +{ + struct acpi_bus_type *tmp; + int ret = -ENODEV; + + down_read(&bus_type_sem); + list_for_each_entry(tmp, &bus_type_list, list) { + if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) { + ret = 0; + break; + } + } + up_read(&bus_type_sem); + return ret; +} + +/* Get PCI root bridge's handle from its segment and bus number */ +struct acpi_find_pci_root { + unsigned int seg; + unsigned int bus; + acpi_handle handle; +}; + +static acpi_status +do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) +{ + int *busnr = (int *)data; + struct acpi_resource_address64 address; + + if (resource->id != ACPI_RSTYPE_ADDRESS16 && + resource->id != ACPI_RSTYPE_ADDRESS32 && + resource->id != ACPI_RSTYPE_ADDRESS64) + return AE_OK; + + acpi_resource_to_address64(resource, &address); + if ((address.address_length > 0) && + (address.resource_type == ACPI_BUS_NUMBER_RANGE)) + *busnr = address.min_address_range; + + return AE_OK; +} + +static int get_root_bridge_busnr(acpi_handle handle) +{ + acpi_status status; + int bus, bbn; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, + (unsigned long *)&bbn); + if (status == AE_NOT_FOUND) { + /* Assume bus = 0 */ + printk(KERN_INFO PREFIX + "Assume root bridge [%s] bus is 0\n", + (char *)buffer.pointer); + status = AE_OK; + bbn = 0; + } + if (ACPI_FAILURE(status)) { + bbn = -ENODEV; + goto exit; + } + if (bbn > 0) + goto exit; + + /* _BBN in some systems return 0 for all root bridges */ + bus = -1; + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + do_root_bridge_busnr_callback, &bus); + /* If _CRS failed, we just use _BBN */ + if (ACPI_FAILURE(status) || (bus == -1)) + goto exit; + /* We select _CRS */ + if (bbn != bus) { + printk(KERN_INFO PREFIX + "_BBN and _CRS returns different value for %s. Select _CRS\n", + (char *)buffer.pointer); + bbn = bus; + } + exit: + acpi_os_free(buffer.pointer); + return bbn; +} + +static acpi_status +find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpi_find_pci_root *find = (struct acpi_find_pci_root *)context; + unsigned long seg, bus; + acpi_status status; + int tmp; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &seg); + if (status == AE_NOT_FOUND) { + /* Assume seg = 0 */ + printk(KERN_INFO PREFIX + "Assume root bridge [%s] segment is 0\n", + (char *)buffer.pointer); + status = AE_OK; + seg = 0; + } + if (ACPI_FAILURE(status)) { + status = AE_CTRL_DEPTH; + goto exit; + } + + tmp = get_root_bridge_busnr(handle); + if (tmp < 0) { + printk(KERN_ERR PREFIX + "Find root bridge failed for %s\n", + (char *)buffer.pointer); + status = AE_CTRL_DEPTH; + goto exit; + } + bus = tmp; + + if (seg == find->seg && bus == find->bus) + find->handle = handle; + status = AE_OK; + exit: + acpi_os_free(buffer.pointer); + return status; +} + +acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) +{ + struct acpi_find_pci_root find = { seg, bus, NULL }; + + acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL); + return find.handle; +} + +/* Get device's handler per its address under its parent */ +struct acpi_find_child { + acpi_handle handle; + acpi_integer address; +}; + +static acpi_status +do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + struct acpi_device_info *info; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_find_child *find = (struct acpi_find_child *)context; + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_SUCCESS(status)) { + info = buffer.pointer; + if (info->address == find->address) + find->handle = handle; + acpi_os_free(buffer.pointer); + } + return AE_OK; +} + +acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address) +{ + struct acpi_find_child find = { NULL, address }; + + if (!parent) + return NULL; + acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, + 1, do_acpi_find_child, &find, NULL); + return find.handle; +} + +EXPORT_SYMBOL(acpi_get_child); + +/* Link ACPI devices with physical devices */ +static void acpi_glue_data_handler(acpi_handle handle, + u32 function, void *context) +{ + /* we provide an empty handler */ +} + +/* Note: a success call will increase reference count by one */ +struct device *acpi_get_physical_device(acpi_handle handle) +{ + acpi_status status; + struct device *dev; + + status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev); + if (ACPI_SUCCESS(status)) + return get_device(dev); + return NULL; +} + +EXPORT_SYMBOL(acpi_get_physical_device); + +static int acpi_bind_one(struct device *dev, acpi_handle handle) +{ + acpi_status status; + + if (dev->firmware_data) { + printk(KERN_WARNING PREFIX + "Drivers changed 'firmware_data' for %s\n", dev->bus_id); + return -EINVAL; + } + get_device(dev); + status = acpi_attach_data(handle, acpi_glue_data_handler, dev); + if (ACPI_FAILURE(status)) { + put_device(dev); + return -EINVAL; + } + dev->firmware_data = handle; + + return 0; +} + +static int acpi_unbind_one(struct device *dev) +{ + if (!dev->firmware_data) + return 0; + if (dev == acpi_get_physical_device(dev->firmware_data)) { + /* acpi_get_physical_device increase refcnt by one */ + put_device(dev); + acpi_detach_data(dev->firmware_data, acpi_glue_data_handler); + dev->firmware_data = NULL; + /* acpi_bind_one increase refcnt by one */ + put_device(dev); + } else { + printk(KERN_ERR PREFIX + "Oops, 'firmware_data' corrupt for %s\n", dev->bus_id); + } + return 0; +} + +static int acpi_platform_notify(struct device *dev) +{ + struct acpi_bus_type *type; + acpi_handle handle; + int ret = -EINVAL; + + if (!dev->bus || !dev->parent) { + /* bridge devices genernally haven't bus or parent */ + ret = acpi_find_bridge_device(dev, &handle); + goto end; + } + type = acpi_get_bus_type(dev->bus); + if (!type) { + printk(KERN_INFO PREFIX "No ACPI bus support for %s\n", + dev->bus_id); + ret = -EINVAL; + goto end; + } + if ((ret = type->find_device(dev, &handle)) != 0) + printk(KERN_INFO PREFIX "Can't get handler for %s\n", + dev->bus_id); + end: + if (!ret) + acpi_bind_one(dev, handle); + +#if ACPI_GLUE_DEBUG + if (!ret) { + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer); + DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); + acpi_os_free(buffer.pointer); + } else + DBG("Device %s -> No ACPI support\n", dev->bus_id); +#endif + + return ret; +} + +static int acpi_platform_notify_remove(struct device *dev) +{ + acpi_unbind_one(dev); + return 0; +} + +static int __init init_acpi_device_notify(void) +{ + if (acpi_disabled) + return 0; + if (platform_notify || platform_notify_remove) { + printk(KERN_ERR PREFIX "Can't use platform_notify\n"); + return 0; + } + platform_notify = acpi_platform_notify; + platform_notify_remove = acpi_platform_notify_remove; + return 0; +} + +arch_initcall(init_acpi_device_notify); diff -Nru a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/acpi/hotkey.c 2005-04-10 17:05:04 -07:00 @@ -0,0 +1,1019 @@ +/* + * hotkey.c - ACPI Hotkey Driver ($Revision:$) + * + * Copyright (C) 2004 Luming Yu + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HOTKEY_ACPI_VERSION "0.1" + +#define HOTKEY_PROC "hotkey" +#define HOTKEY_EV_CONFIG "event_config" +#define HOTKEY_PL_CONFIG "poll_config" +#define HOTKEY_ACTION "action" +#define HOTKEY_INFO "info" + +#define ACPI_HOTK_NAME "Generic Hotkey Driver" +#define ACPI_HOTK_CLASS "Hotkey" +#define ACPI_HOTK_DEVICE_NAME "Hotkey" +#define ACPI_HOTK_HID "Unknown?" +#define ACPI_HOTKEY_COMPONENT 0x20000000 + +#define ACPI_HOTKEY_EVENT 0x1 +#define ACPI_HOTKEY_POLLING 0x2 +#define ACPI_UNDEFINED_EVENT 0xf + +#define MAX_CONFIG_RECORD_LEN 80 +#define MAX_NAME_PATH_LEN 80 +#define MAX_CALL_PARM 80 + +#define IS_EVENT(e) 0xff /* ((e) & 0x40000000) */ +#define IS_POLL(e) 0xff /* (~((e) & 0x40000000)) */ + +#define _COMPONENT ACPI_HOTKEY_COMPONENT +ACPI_MODULE_NAME("acpi_hotkey") + + MODULE_AUTHOR("luming.yu@intel.com"); +MODULE_DESCRIPTION(ACPI_HOTK_NAME); +MODULE_LICENSE("GPL"); + +/* standardized internal hotkey number/event */ +enum { + /* Video Extension event */ + HK_EVENT_CYCLE_OUTPUT_DEVICE = 0x80, + HK_EVENT_OUTPUT_DEVICE_STATUS_CHANGE, + HK_EVENT_CYCLE_DISPLAY_OUTPUT, + HK_EVENT_NEXT_DISPLAY_OUTPUT, + HK_EVENT_PREVIOUS_DISPLAY_OUTPUT, + HK_EVENT_CYCLE_BRIGHTNESS, + HK_EVENT_INCREASE_BRIGHTNESS, + HK_EVENT_DECREASE_BRIGHTNESS, + HK_EVENT_ZERO_BRIGHTNESS, + HK_EVENT_DISPLAY_DEVICE_OFF, + + /* Snd Card event */ + HK_EVENT_VOLUME_MUTE, + HK_EVENT_VOLUME_INCLREASE, + HK_EVENT_VOLUME_DECREASE, + + /* running state control */ + HK_EVENT_ENTERRING_S3, + HK_EVENT_ENTERRING_S4, + HK_EVENT_ENTERRING_S5, +}; + +/* procdir we use */ +static struct proc_dir_entry *hotkey_proc_dir; +static struct proc_dir_entry *hotkey_config; +static struct proc_dir_entry *hotkey_poll_config; +static struct proc_dir_entry *hotkey_action; +static struct proc_dir_entry *hotkey_info; + +/* linkage for all type of hotkey */ +struct acpi_hotkey_link { + struct list_head entries; + int hotkey_type; /* event or polling based hotkey */ + int hotkey_standard_num; /* standardized hotkey(event) number */ +}; + +/* event based hotkey */ +struct acpi_event_hotkey { + struct acpi_hotkey_link hotkey_link; + int flag; + acpi_handle bus_handle; /* bus to install notify handler */ + int external_hotkey_num; /* external hotkey/event number */ + acpi_handle action_handle; /* acpi handle attached aml action method */ + char *action_method; /* action method */ +}; + +/* + * There are two ways to poll status + * 1. directy call read_xxx method, without any arguments passed in + * 2. call write_xxx method, with arguments passed in, you need + * the result is saved in acpi_polling_hotkey.poll_result. + * anthoer read command through polling interface. + * + */ + +/* polling based hotkey */ +struct acpi_polling_hotkey { + struct acpi_hotkey_link hotkey_link; + int flag; + acpi_handle poll_handle; /* acpi handle attached polling method */ + char *poll_method; /* poll method */ + acpi_handle action_handle; /* acpi handle attached action method */ + char *action_method; /* action method */ + void *poll_result; /* polling_result */ + struct proc_dir_entry *proc; +}; + +/* hotkey object union */ +union acpi_hotkey { + struct list_head entries; + struct acpi_hotkey_link link; + struct acpi_event_hotkey event_hotkey; + struct acpi_polling_hotkey poll_hotkey; +}; + +/* hotkey object list */ +struct acpi_hotkey_list { + struct list_head *entries; + int count; +}; + +static int auto_hotkey_add(struct acpi_device *device); +static int auto_hotkey_remove(struct acpi_device *device, int type); + +static struct acpi_driver hotkey_driver = { + .name = ACPI_HOTK_NAME, + .class = ACPI_HOTK_CLASS, + .ids = ACPI_HOTK_HID, + .ops = { + .add = auto_hotkey_add, + .remove = auto_hotkey_remove, + }, +}; + +static int hotkey_open_config(struct inode *inode, struct file *file); +static ssize_t hotkey_write_config(struct file *file, + const char __user * buffer, + size_t count, loff_t * data); +static ssize_t hotkey_write_poll_config(struct file *file, + const char __user * buffer, + size_t count, loff_t * data); +static int hotkey_info_open_fs(struct inode *inode, struct file *file); +static int hotkey_action_open_fs(struct inode *inode, struct file *file); +static ssize_t hotkey_execute_aml_method(struct file *file, + const char __user * buffer, + size_t count, loff_t * data); +static int hotkey_config_seq_show(struct seq_file *seq, void *offset); +static int hotkey_polling_open_fs(struct inode *inode, struct file *file); + +/* event based config */ +static struct file_operations hotkey_config_fops = { + .open = hotkey_open_config, + .read = seq_read, + .write = hotkey_write_config, + .llseek = seq_lseek, + .release = single_release, +}; + +/* polling based config */ +static struct file_operations hotkey_poll_config_fops = { + .open = hotkey_open_config, + .read = seq_read, + .write = hotkey_write_poll_config, + .llseek = seq_lseek, + .release = single_release, +}; + +/* hotkey driver info */ +static struct file_operations hotkey_info_fops = { + .open = hotkey_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* action */ +static struct file_operations hotkey_action_fops = { + .open = hotkey_action_open_fs, + .read = seq_read, + .write = hotkey_execute_aml_method, + .llseek = seq_lseek, + .release = single_release, +}; + +/* polling results */ +static struct file_operations hotkey_polling_fops = { + .open = hotkey_polling_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +struct acpi_hotkey_list global_hotkey_list; /* link all ev or pl hotkey */ +struct list_head hotkey_entries; /* head of the list of hotkey_list */ + +static int hotkey_info_seq_show(struct seq_file *seq, void *offset) +{ + ACPI_FUNCTION_TRACE("hotkey_info_seq_show"); + + seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION); + + return_VALUE(0); +} + +static int hotkey_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, hotkey_info_seq_show, PDE(inode)->data); +} + +static char *format_result(union acpi_object *object) +{ + char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); + + memset(buf, 0, sizeof(union acpi_object)); + + /* Now, just support integer type */ + if (object->type == ACPI_TYPE_INTEGER) + sprintf(buf, "%d", (u32) object->integer.value); + + return buf; +} + +static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_polling_hotkey *poll_hotkey = + (struct acpi_polling_hotkey *)seq->private; + + ACPI_FUNCTION_TRACE("hotkey_polling_seq_show"); + + if (poll_hotkey->poll_result) + seq_printf(seq, "%s", format_result(poll_hotkey->poll_result)); + + return_VALUE(0); +} + +static int hotkey_polling_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, hotkey_polling_seq_show, PDE(inode)->data); +} + +static int hotkey_action_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, hotkey_info_seq_show, PDE(inode)->data); +} + +/* Mapping external hotkey number to standardized hotkey event num */ +static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) +{ + struct list_head *entries, *next; + int val = 0; + + ACPI_FUNCTION_TRACE("hotkey_get_internal_event"); + + list_for_each_safe(entries, next, list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT + && key->event_hotkey.external_hotkey_num == event) + val = key->link.hotkey_standard_num; + else + val = -1; + } + + return_VALUE(val); +} + +static void +acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) +{ + struct acpi_device *device = NULL; + u32 internal_event; + + ACPI_FUNCTION_TRACE("acpi_hotkey_notify_handler"); + + if (acpi_bus_get_device(handle, &device)) + return_VOID; + + internal_event = hotkey_get_internal_event(event, &global_hotkey_list); + acpi_bus_generate_event(device, event, 0); + + return_VOID; +} + +/* Need to invent automatically hotkey add method */ +static int auto_hotkey_add(struct acpi_device *device) +{ + /* Implement me */ + return 0; +} + +/* Need to invent automatically hotkey remove method */ +static int auto_hotkey_remove(struct acpi_device *device, int type) +{ + /* Implement me */ + return 0; +} + +/* Create a proc file for each polling method */ +static int create_polling_proc(union acpi_hotkey *device) +{ + struct proc_dir_entry *proc; + mode_t mode; + + ACPI_FUNCTION_TRACE("create_polling_proc"); + mode = S_IFREG | S_IRUGO | S_IWUGO; + + proc = create_proc_entry(device->poll_hotkey.action_method, + mode, hotkey_proc_dir); + + if (!proc) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Hotkey: Unable to create %s entry\n", + device->poll_hotkey.poll_method)); + return_VALUE(-ENODEV); + } else { + proc->proc_fops = &hotkey_polling_fops; + proc->owner = THIS_MODULE; + proc->data = device; + proc->uid = 0; + proc->gid = 0; + device->poll_hotkey.proc = proc; + } + return_VALUE(0); +} + +static int is_valid_acpi_path(const char *pathname) +{ + acpi_handle handle; + acpi_status status; + ACPI_FUNCTION_TRACE("is_valid_acpi_path"); + + status = acpi_get_handle(NULL, (char *)pathname, &handle); + return_VALUE(!ACPI_FAILURE(status)); +} + +static int is_valid_hotkey(union acpi_hotkey *device) +{ + ACPI_FUNCTION_TRACE("is_valid_hotkey"); + /* Implement valid check */ + return_VALUE(1); +} + +static int hotkey_add(union acpi_hotkey *device) +{ + int status = 0; + struct acpi_device *dev = NULL; + + ACPI_FUNCTION_TRACE("hotkey_add"); + + if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { + status = + acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); + if (status) + return_VALUE(status); + + status = acpi_install_notify_handler(dev->handle, + ACPI_SYSTEM_NOTIFY, + acpi_hotkey_notify_handler, + device); + } else /* Add polling hotkey */ + create_polling_proc(device); + + global_hotkey_list.count++; + + list_add_tail(&device->link.entries, global_hotkey_list.entries); + + return_VALUE(status); +} + +static int hotkey_remove(union acpi_hotkey *device) +{ + struct list_head *entries, *next; + + ACPI_FUNCTION_TRACE("hotkey_remove"); + + list_for_each_safe(entries, next, global_hotkey_list.entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_standard_num == + device->link.hotkey_standard_num) { + list_del(&key->link.entries); + remove_proc_entry(key->poll_hotkey.action_method, + hotkey_proc_dir); + global_hotkey_list.count--; + break; + } + } + return_VALUE(0); +} + +static void hotkey_update(union acpi_hotkey *key) +{ + struct list_head *entries, *next; + + ACPI_FUNCTION_TRACE("hotkey_update"); + + list_for_each_safe(entries, next, global_hotkey_list.entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_standard_num == + key->link.hotkey_standard_num) { + key->event_hotkey.bus_handle = + key->event_hotkey.bus_handle; + key->event_hotkey.external_hotkey_num = + key->event_hotkey.external_hotkey_num; + key->event_hotkey.action_handle = + key->event_hotkey.action_handle; + key->event_hotkey.action_method = + key->event_hotkey.action_method; + break; + } + } + + return_VOID; +} + +static void free_hotkey_device(union acpi_hotkey *key) +{ + struct acpi_device *dev; + int status; + + ACPI_FUNCTION_TRACE("free_hotkey_device"); + + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { + status = + acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); + if (dev->handle) + acpi_remove_notify_handler(dev->handle, + ACPI_SYSTEM_NOTIFY, + acpi_hotkey_notify_handler); + } else + remove_proc_entry(key->poll_hotkey.action_method, + hotkey_proc_dir); + kfree(key); + return_VOID; +} + +static int +init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, + char *method, int std_num, int external_num) +{ + ACPI_FUNCTION_TRACE("init_hotkey_device"); + + key->link.hotkey_type = ACPI_HOTKEY_EVENT; + key->link.hotkey_standard_num = std_num; + key->event_hotkey.flag = 0; + if (is_valid_acpi_path(bus_str)) + acpi_get_handle((acpi_handle) 0, + bus_str, &(key->event_hotkey.bus_handle)); + else + return_VALUE(-ENODEV); + key->event_hotkey.external_hotkey_num = external_num; + if (is_valid_acpi_path(action_str)) + acpi_get_handle((acpi_handle) 0, + action_str, &(key->event_hotkey.action_handle)); + key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL); + strcpy(key->event_hotkey.action_method, method); + + return_VALUE(!is_valid_hotkey(key)); +} + +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) +{ + ACPI_FUNCTION_TRACE("init_poll_hotkey_device"); + + key->link.hotkey_type = ACPI_HOTKEY_POLLING; + key->link.hotkey_standard_num = std_num; + key->poll_hotkey.flag = 0; + if (is_valid_acpi_path(poll_str)) + acpi_get_handle((acpi_handle) 0, + poll_str, &(key->poll_hotkey.poll_handle)); + else + return_VALUE(-ENODEV); + key->poll_hotkey.poll_method = poll_method; + if (is_valid_acpi_path(action_str)) + acpi_get_handle((acpi_handle) 0, + action_str, &(key->poll_hotkey.action_handle)); + key->poll_hotkey.action_method = + kmalloc(sizeof(action_method), GFP_KERNEL); + strcpy(key->poll_hotkey.action_method, action_method); + key->poll_hotkey.poll_result = + (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); + return_VALUE(is_valid_hotkey(key)); +} + +static int check_hotkey_valid(union acpi_hotkey *key, + struct acpi_hotkey_list *list) +{ + ACPI_FUNCTION_TRACE("check_hotkey_valid"); + return_VALUE(0); +} + +static int hotkey_open_config(struct inode *inode, struct file *file) +{ + ACPI_FUNCTION_TRACE("hotkey_open_config"); + return_VALUE(single_open + (file, hotkey_config_seq_show, PDE(inode)->data)); +} + +static int hotkey_config_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; + struct list_head *entries, *next; + char bus_name[ACPI_PATHNAME_MAX] = { 0 }; + char action_name[ACPI_PATHNAME_MAX] = { 0 }; + struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; + struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; + + ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); + + if (!hotkey_list) + goto end; + + list_for_each_safe(entries, next, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { + acpi_get_name(key->event_hotkey.bus_handle, + ACPI_NAME_TYPE_MAX, &bus); + acpi_get_name(key->event_hotkey.action_handle, + ACPI_NAME_TYPE_MAX, &act); + seq_printf(seq, "%s:%s:%s:%d:%d", bus_name, + action_name, + key->event_hotkey.action_method, + key->link.hotkey_standard_num, + key->event_hotkey.external_hotkey_num); + } /* ACPI_HOTKEY_POLLING */ + else { + acpi_get_name(key->poll_hotkey.poll_handle, + ACPI_NAME_TYPE_MAX, &bus); + acpi_get_name(key->poll_hotkey.action_handle, + ACPI_NAME_TYPE_MAX, &act); + seq_printf(seq, "%s:%s:%s:%s:%d", bus_name, + key->poll_hotkey.poll_method, + action_name, + key->poll_hotkey.action_method, + key->link.hotkey_standard_num); + } + } + seq_puts(seq, "\n"); + end: + return_VALUE(0); +} + +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) +{ + char *tmp, *tmp1; + ACPI_FUNCTION_TRACE(("get_parms")); + + sscanf(config_record, "%d", cmd); + + tmp = strchr(config_record, ':'); + tmp++; + tmp1 = strchr(tmp, ':'); + strncpy(bus_handle, tmp, tmp1 - tmp); + bus_handle[tmp1 - tmp] = 0; + + tmp = tmp1; + tmp++; + tmp1 = strchr(tmp, ':'); + strncpy(bus_method, tmp, tmp1 - tmp); + bus_method[tmp1 - tmp] = 0; + + tmp = tmp1; + tmp++; + tmp1 = strchr(tmp, ':'); + strncpy(action_handle, tmp, tmp1 - tmp); + action_handle[tmp1 - tmp] = 0; + + tmp = tmp1; + tmp++; + tmp1 = strchr(tmp, ':'); + strncpy(method, tmp, tmp1 - tmp); + method[tmp1 - tmp] = 0; + + sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num); + return_VALUE(6); +} + +/* count is length for one input record */ +static ssize_t hotkey_write_config(struct file *file, + const char __user * buffer, + size_t count, loff_t * data) +{ + struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; + char config_record[MAX_CONFIG_RECORD_LEN]; + char bus_handle[MAX_NAME_PATH_LEN]; + char bus_method[MAX_NAME_PATH_LEN]; + char action_handle[MAX_NAME_PATH_LEN]; + char method[20]; + int cmd, internal_event_num, external_event_num; + int ret = 0; + union acpi_hotkey *key = NULL; + + ACPI_FUNCTION_TRACE(("hotkey_write_config")); + + if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); + return_VALUE(-EINVAL); + } + + if (copy_from_user(config_record, buffer, count)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); + return_VALUE(-EINVAL); + } + config_record[count] = '\0'; + + ret = get_parms(config_record, + &cmd, + bus_handle, + bus_method, + action_handle, + method, &internal_event_num, &external_event_num); + if (ret != 6) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid data format ret=%d\n", ret)); + return_VALUE(-EINVAL); + } + + key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); + ret = init_hotkey_device(key, bus_handle, action_handle, method, + internal_event_num, external_event_num); + + if (ret || check_hotkey_valid(key, hotkey_list)) { + kfree(key); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); + return_VALUE(-EINVAL); + } + switch (cmd) { + case 0: + hotkey_add(key); + break; + case 1: + hotkey_remove(key); + free_hotkey_device(key); + break; + case 2: + hotkey_update(key); + break; + default: + break; + } + return_VALUE(count); +} + +/* count is length for one input record */ +static ssize_t hotkey_write_poll_config(struct file *file, + const char __user * buffer, + size_t count, loff_t * data) +{ + struct seq_file *m = (struct seq_file *)file->private_data; + struct acpi_hotkey_list *hotkey_list = + (struct acpi_hotkey_list *)m->private; + + char config_record[MAX_CONFIG_RECORD_LEN]; + char polling_handle[MAX_NAME_PATH_LEN]; + char action_handle[MAX_NAME_PATH_LEN]; + char poll_method[20], action_method[20]; + int ret, internal_event_num, cmd, external_event_num; + union acpi_hotkey *key = NULL; + + ACPI_FUNCTION_TRACE("hotkey_write_poll_config"); + + if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); + return_VALUE(-EINVAL); + } + + if (copy_from_user(config_record, buffer, count)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); + return_VALUE(-EINVAL); + } + config_record[count] = '\0'; + + ret = get_parms(config_record, + &cmd, + polling_handle, + poll_method, + action_handle, + action_method, + &internal_event_num, &external_event_num); + + if (ret != 6) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); + return_VALUE(-EINVAL); + } + + key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); + ret = init_poll_hotkey_device(key, polling_handle, poll_method, + action_handle, action_method, + internal_event_num); + if (ret || check_hotkey_valid(key, hotkey_list)) { + kfree(key); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); + return_VALUE(-EINVAL); + } + switch (cmd) { + case 0: + hotkey_add(key); + break; + case 1: + hotkey_remove(key); + break; + case 2: + hotkey_update(key); + break; + default: + break; + } + return_VALUE(count); +} + +/* + * This function evaluates an ACPI method, given an int as parameter, the + * method is searched within the scope of the handle, can be NULL. The output + * of the method is written is output, which can also be NULL + * + * returns 1 if write is successful, 0 else. + */ +static int write_acpi_int(acpi_handle handle, const char *method, int val, + struct acpi_buffer *output) +{ + struct acpi_object_list params; /* list of input parameters (an int here) */ + union acpi_object in_obj; /* the only param we use */ + acpi_status status; + + ACPI_FUNCTION_TRACE("write_acpi_int"); + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = val; + + status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); + + return_VALUE(status == AE_OK); +} + +static int read_acpi_int(acpi_handle handle, const char *method, int *val) +{ + struct acpi_buffer output; + union acpi_object out_obj; + acpi_status status; + + ACPI_FUNCTION_TRACE("read_acpi_int"); + output.length = sizeof(out_obj); + output.pointer = &out_obj; + + status = acpi_evaluate_object(handle, (char *)method, NULL, &output); + *val = out_obj.integer.value; + return_VALUE((status == AE_OK) + && (out_obj.type == ACPI_TYPE_INTEGER)); +} + +static acpi_handle +get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num) +{ + struct list_head *entries, *next; + + list_for_each_safe(entries, next, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT + && key->link.hotkey_standard_num == event_num) { + return (key->event_hotkey.action_handle); + } + } + return (NULL); +} + +static +char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, + int event_num) +{ + struct list_head *entries, *next; + + list_for_each_safe(entries, next, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT && + key->link.hotkey_standard_num == event_num) + return (key->event_hotkey.action_method); + } + return (NULL); +} + +static struct acpi_polling_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event) +{ + struct list_head *entries, *next; + + list_for_each_safe(entries, next, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_POLLING + && key->link.hotkey_standard_num == event) { + return (&key->poll_hotkey); + } + } + return (NULL); +} + +/* + * user call AML method interface: + * Call convention: + * echo "event_num: arg type : value" + * example: echo "1:1:30" > /proc/acpi/action + * Just support 1 integer arg passing to AML method + */ + +static ssize_t hotkey_execute_aml_method(struct file *file, + const char __user * buffer, + size_t count, loff_t * data) +{ + struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; + char arg[MAX_CALL_PARM]; + int event, type, value; + + char *method; + acpi_handle handle; + + ACPI_FUNCTION_TRACE("hotkey_execte_aml_method"); + + if (!hotkey_list || count > MAX_CALL_PARM) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1")); + return_VALUE(-EINVAL); + } + + if (copy_from_user(arg, buffer, count)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2")); + return_VALUE(-EINVAL); + } + + arg[count] = '\0'; + + if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3")); + return_VALUE(-EINVAL); + } + + if (type == ACPI_TYPE_INTEGER) { + handle = get_handle_from_hotkeylist(hotkey_list, event); + method = (char *)get_method_from_hotkeylist(hotkey_list, event); + if (IS_EVENT(event)) + write_acpi_int(handle, method, value, NULL); + else if (IS_POLL(event)) { + struct acpi_polling_hotkey *key; + key = (struct acpi_polling_hotkey *) + get_hotkey_by_event(hotkey_list, event); + read_acpi_int(handle, method, key->poll_result); + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported")); + return_VALUE(-EINVAL); + } + + return_VALUE(count); +} + +static int __init hotkey_init(void) +{ + int result; + mode_t mode = S_IFREG | S_IRUGO | S_IWUGO; + + ACPI_FUNCTION_TRACE("hotkey_init"); + + if (acpi_disabled) + return -ENODEV; + + if (acpi_specific_hotkey_enabled) { + printk("Using specific hotkey driver\n"); + return -ENODEV; + } + + hotkey_proc_dir = proc_mkdir(HOTKEY_PROC, acpi_root_dir); + if (!hotkey_proc_dir) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Hotkey: Unable to create %s entry\n", + HOTKEY_PROC)); + return (-ENODEV); + } + hotkey_proc_dir->owner = THIS_MODULE; + + hotkey_config = + create_proc_entry(HOTKEY_EV_CONFIG, mode, hotkey_proc_dir); + if (!hotkey_config) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Hotkey: Unable to create %s entry\n", + HOTKEY_EV_CONFIG)); + return (-ENODEV); + } else { + hotkey_config->proc_fops = &hotkey_config_fops; + hotkey_config->data = &global_hotkey_list; + hotkey_config->owner = THIS_MODULE; + hotkey_config->uid = 0; + hotkey_config->gid = 0; + } + + hotkey_poll_config = + create_proc_entry(HOTKEY_PL_CONFIG, mode, hotkey_proc_dir); + if (!hotkey_poll_config) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Hotkey: Unable to create %s entry\n", + HOTKEY_EV_CONFIG)); + return (-ENODEV); + } else { + hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; + hotkey_poll_config->data = &global_hotkey_list; + hotkey_poll_config->owner = THIS_MODULE; + hotkey_poll_config->uid = 0; + hotkey_poll_config->gid = 0; + } + + hotkey_action = create_proc_entry(HOTKEY_ACTION, mode, hotkey_proc_dir); + if (!hotkey_action) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Hotkey: Unable to create %s entry\n", + HOTKEY_ACTION)); + return (-ENODEV); + } else { + hotkey_action->proc_fops = &hotkey_action_fops; + hotkey_action->owner = THIS_MODULE; + hotkey_action->uid = 0; + hotkey_action->gid = 0; + } + + hotkey_info = create_proc_entry(HOTKEY_INFO, mode, hotkey_proc_dir); + if (!hotkey_info) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Hotkey: Unable to create %s entry\n", + HOTKEY_INFO)); + return (-ENODEV); + } else { + hotkey_info->proc_fops = &hotkey_info_fops; + hotkey_info->owner = THIS_MODULE; + hotkey_info->uid = 0; + hotkey_info->gid = 0; + } + + result = acpi_bus_register_driver(&hotkey_driver); + if (result < 0) { + remove_proc_entry(HOTKEY_PROC, acpi_root_dir); + return (-ENODEV); + } + global_hotkey_list.count = 0; + global_hotkey_list.entries = &hotkey_entries; + + INIT_LIST_HEAD(&hotkey_entries); + + return (0); +} + +static void __exit hotkey_exit(void) +{ + struct list_head *entries, *next; + + ACPI_FUNCTION_TRACE("hotkey_remove"); + + list_for_each_safe(entries, next, global_hotkey_list.entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + + acpi_os_wait_events_complete(NULL); + list_del(&key->link.entries); + global_hotkey_list.count--; + free_hotkey_device(key); + } + acpi_bus_unregister_driver(&hotkey_driver); + remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); + remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); + remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); + remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); + remove_proc_entry(HOTKEY_PROC, acpi_root_dir); + return; +} + +module_init(hotkey_init); +module_exit(hotkey_exit); diff -Nru a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c --- a/drivers/acpi/ibm_acpi.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/ibm_acpi.c 2005-04-10 17:05:04 -07:00 @@ -1025,7 +1025,7 @@ return 0; } -static int device_add(struct acpi_device *device) +static int ibmacpi_device_add(struct acpi_device *device) { return 0; } @@ -1043,7 +1043,7 @@ memset(ibm->driver, 0, sizeof(struct acpi_driver)); sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name); ibm->driver->ids = ibm->hid; - ibm->driver->ops.add = &device_add; + ibm->driver->ops.add = &ibmacpi_device_add; ret = acpi_bus_register_driver(ibm->driver); if (ret < 0) { @@ -1185,6 +1185,10 @@ if (acpi_disabled) return -ENODEV; + if (!acpi_specific_hotkey_enabled){ + printk(IBM_ERR "Using generic hotkey driver\n"); + return -ENODEV; + } /* these handles are required */ if (IBM_HANDLE_INIT(ec, 1) < 0 || IBM_HANDLE_INIT(hkey, 1) < 0 || diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/osl.c 2005-04-10 17:05:04 -07:00 @@ -71,6 +71,9 @@ extern char line_buf[80]; #endif /*ENABLE_DEBUGGER*/ +int acpi_specific_hotkey_enabled; +EXPORT_SYMBOL(acpi_specific_hotkey_enabled); + static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; @@ -1151,6 +1154,15 @@ } __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); + +int __init +acpi_hotkey_setup(char *str) +{ + acpi_specific_hotkey_enabled = TRUE; + return 1; +} + +__setup("acpi_specific_hotkey", acpi_hotkey_setup); /* * max_cstate is defined in the base kernel so modules can diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c --- a/drivers/acpi/pci_irq.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/pci_irq.c 2005-04-10 17:05:04 -07:00 @@ -391,7 +391,6 @@ u8 pin = 0; int edge_level = ACPI_LEVEL_SENSITIVE; int active_high_low = ACPI_ACTIVE_LOW; - extern int via_interrupt_line_quirk; char *link = NULL; ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); @@ -443,9 +442,6 @@ return_VALUE(0); } } - - if (via_interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15); dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- a/drivers/acpi/pci_link.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/pci_link.c 2005-04-10 17:05:04 -07:00 @@ -72,10 +72,12 @@ u8 active; /* Current IRQ */ u8 edge_level; /* All IRQs */ u8 active_high_low; /* All IRQs */ - u8 initialized; u8 resource_type; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; + u8 initialized:1; + u8 suspend_resume:1; + u8 reserved:6; }; struct acpi_pci_link { @@ -530,6 +532,10 @@ ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); + if (link->irq.suspend_resume) { + acpi_pci_link_set(link, link->irq.active); + link->irq.suspend_resume = 0; + } if (link->irq.initialized) return_VALUE(0); @@ -713,38 +719,24 @@ return_VALUE(result); } - -static int -acpi_pci_link_resume ( - struct acpi_pci_link *link) -{ - ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); - - if (link->irq.active && link->irq.initialized) - return_VALUE(acpi_pci_link_set(link, link->irq.active)); - else - return_VALUE(0); -} - - static int -irqrouter_resume( - struct sys_device *dev) +irqrouter_suspend( + struct sys_device *dev, + u32 state) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; - ACPI_FUNCTION_TRACE("irqrouter_resume"); + ACPI_FUNCTION_TRACE("irqrouter_suspend"); list_for_each(node, &acpi_link.entries) { - link = list_entry(node, struct acpi_pci_link, node); if (!link) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); continue; } - - acpi_pci_link_resume(link); + if (link->irq.active && link->irq.initialized) + link->irq.suspend_resume = 1; } return_VALUE(0); } @@ -812,9 +804,12 @@ * There is no ISA_POSSIBLE weight, so we simply use * the (small) PCI_USING penalty. */ -void acpi_penalize_isa_irq(int irq) +void acpi_penalize_isa_irq(int irq, int active) { - acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; + if (active) + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + else + acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; } /* @@ -856,7 +851,7 @@ static struct sysdev_class irqrouter_sysdev_class = { set_kset_name("irqrouter"), - .resume = irqrouter_resume, + .suspend = irqrouter_suspend, }; diff -Nru a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c --- a/drivers/acpi/processor_idle.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/processor_idle.c 2005-04-10 17:05:04 -07:00 @@ -519,6 +519,29 @@ } +static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr) +{ + int i; + + ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); + + for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) + memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + + /* if info is obtained from pblk/fadt, type equals state */ + pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; + pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; + pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; + + /* the C0 state only exists as a filler in our array, + * and all processors need to support C1 */ + pr->power.states[ACPI_STATE_C0].valid = 1; + pr->power.states[ACPI_STATE_C1].valid = 1; + + return_VALUE(0); +} + + static int acpi_processor_get_power_info_cst (struct acpi_processor *pr) { acpi_status status = 0; @@ -787,10 +810,7 @@ if ((result) || (acpi_processor_power_verify(pr) < 2)) { result = acpi_processor_get_power_info_fadt(pr); if (result) - return_VALUE(result); - - if (acpi_processor_power_verify(pr) < 2) - return_VALUE(-ENODEV); + result = acpi_processor_get_power_info_default_c1(pr); } /* @@ -810,11 +830,10 @@ * CPU as being "idle manageable" */ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { - if (pr->power.states[i].valid) + if (pr->power.states[i].valid) { pr->power.count = i; - if ((pr->power.states[i].valid) && - (pr->power.states[i].type >= ACPI_STATE_C2)) pr->flags.power = 1; + } } return_VALUE(0); diff -Nru a/drivers/acpi/scan.c b/drivers/acpi/scan.c --- a/drivers/acpi/scan.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/scan.c 2005-04-10 17:05:04 -07:00 @@ -1051,13 +1051,15 @@ /* * Status * ------ - * See if the device is present. We always assume that non-Device() - * objects (e.g. thermal zones, power resources, processors, etc.) are - * present, functioning, etc. (at least when parent object is present). - * Note that _STA has a different meaning for some objects (e.g. - * power resources) so we need to be careful how we use it. + * See if the device is present. We always assume that non-Device + * and non-Processor objects (e.g. thermal zones, power resources, + * etc.) are present, functioning, etc. (at least when parent object + * is present). Note that _STA has a different meaning for some + * objects (e.g. power resources) so we need to be careful how we use + * it. */ switch (type) { + case ACPI_BUS_TYPE_PROCESSOR: case ACPI_BUS_TYPE_DEVICE: result = acpi_bus_get_status(device); if (ACPI_FAILURE(result) || !device->status.present) { diff -Nru a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c --- a/drivers/acpi/sleep/main.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/sleep/main.c 2005-04-10 17:05:04 -07:00 @@ -1,6 +1,7 @@ /* * sleep.c - ACPI sleep support. * + * Copyright (c) 2005 Alexey Starikovskiy * Copyright (c) 2004 David Shaohua Li * Copyright (c) 2000-2003 Patrick Mochel * Copyright (c) 2003 Open Source Development Lab @@ -14,7 +15,6 @@ #include #include #include -#include #include #include #include "sleep.h" @@ -27,10 +27,11 @@ extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { - [PM_SUSPEND_ON] = ACPI_STATE_S0, - [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, - [PM_SUSPEND_MEM] = ACPI_STATE_S3, - [PM_SUSPEND_DISK] = ACPI_STATE_S4, + [PM_SUSPEND_ON] = ACPI_STATE_S0, + [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, + [PM_SUSPEND_MEM] = ACPI_STATE_S3, + [PM_SUSPEND_DISK] = ACPI_STATE_S4, + [PM_SUSPEND_MAX] = ACPI_STATE_S5 }; static int init_8259A_after_S1; @@ -44,30 +45,20 @@ * wakeup code to the waking vector. */ +extern int acpi_sleep_prepare(u32 acpi_state); +extern void acpi_power_off(void); + static int acpi_pm_prepare(suspend_state_t pm_state) { u32 acpi_state = acpi_suspend_states[pm_state]; - if (!sleep_states[acpi_state]) + if (!sleep_states[acpi_state]) { + printk("acpi_pm_prepare does not support %d \n", pm_state); return -EPERM; - - /* do we have a wakeup address for S2 and S3? */ - /* Here, we support only S4BIOS, those we set the wakeup address */ - /* S4OS is only supported for now via swsusp.. */ - if (pm_state == PM_SUSPEND_MEM || pm_state == PM_SUSPEND_DISK) { - if (!acpi_wakeup_address) - return -EFAULT; - acpi_set_firmware_waking_vector( - (acpi_physical_address) virt_to_phys( - (void *)acpi_wakeup_address)); } - ACPI_FLUSH_CPU_CACHE(); - acpi_enable_wakeup_device_prep(acpi_state); - acpi_enter_sleep_state_prep(acpi_state); - return 0; + return acpi_sleep_prepare(acpi_state); } - /** * acpi_pm_enter - Actually enter a sleep state. * @pm_state: State we're entering. @@ -92,11 +83,9 @@ return error; } - local_irq_save(flags); acpi_enable_wakeup_device(acpi_state); - switch (pm_state) - { + switch (pm_state) { case PM_SUSPEND_STANDBY: barrier(); status = acpi_enter_sleep_state(acpi_state); @@ -112,6 +101,10 @@ else do_suspend_lowlevel_s4bios(); break; + case PM_SUSPEND_MAX: + acpi_power_off(); + break; + default: return -EINVAL; } @@ -126,11 +119,9 @@ if (pm_state > PM_SUSPEND_STANDBY) acpi_restore_state_mem(); - return ACPI_SUCCESS(status) ? 0 : -EFAULT; } - /** * acpi_pm_finish - Finish up suspend sequence. * @pm_state: State we're coming out of. @@ -156,27 +147,26 @@ return 0; } - int acpi_suspend(u32 acpi_state) { suspend_state_t states[] = { - [1] = PM_SUSPEND_STANDBY, - [3] = PM_SUSPEND_MEM, - [4] = PM_SUSPEND_DISK, + [1] = PM_SUSPEND_STANDBY, + [3] = PM_SUSPEND_MEM, + [4] = PM_SUSPEND_DISK, + [5] = PM_SUSPEND_MAX }; - if (acpi_state <= 4 && states[acpi_state]) + if (acpi_state < 6 && states[acpi_state]) return pm_suspend(states[acpi_state]); return -EINVAL; } static struct pm_ops acpi_pm_ops = { - .prepare = acpi_pm_prepare, - .enter = acpi_pm_enter, - .finish = acpi_pm_finish, + .prepare = acpi_pm_prepare, + .enter = acpi_pm_enter, + .finish = acpi_pm_finish, }; - /* * Toshiba fails to preserve interrupts over S1, reinitialization * of 8259 is needed after S1 resume. @@ -190,16 +180,16 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { - .callback = init_ints_after_s1, - .ident = "Toshiba Satellite 4030cdt", - .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), }, - }, - { }, + .callback = init_ints_after_s1, + .ident = "Toshiba Satellite 4030cdt", + .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, + }, + {}, }; static int __init acpi_sleep_init(void) { - int i = 0; + int i = 0; dmi_check_system(acpisleep_dmi_table); @@ -207,7 +197,7 @@ return 0; printk(KERN_INFO PREFIX "(supports"); - for (i=0; i < ACPI_S_STATE_COUNT; i++) { + for (i = 0; i < ACPI_S_STATE_COUNT; i++) { acpi_status status; u8 type_a, type_b; status = acpi_get_sleep_type_data(i, &type_a, &type_b); diff -Nru a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c --- a/drivers/acpi/sleep/poweroff.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/sleep/poweroff.c 2005-04-10 17:05:04 -07:00 @@ -3,35 +3,100 @@ * * AKA S5, but it is independent of whether or not the kernel supports * any other sleep support in the system. + * + * Copyright (c) 2005 Alexey Starikovskiy + * + * This file is released under the GPLv2. */ #include #include #include #include +#include +#include #include "sleep.h" -static void -acpi_power_off (void) +int acpi_sleep_prepare(u32 acpi_state) { - printk("%s called\n",__FUNCTION__); + /* Flag to do not allow second time invocation for S5 state */ + static int shutdown_prepared = 0; +#ifdef CONFIG_ACPI_SLEEP + /* do we have a wakeup address for S2 and S3? */ + /* Here, we support only S4BIOS, those we set the wakeup address */ + /* S4OS is only supported for now via swsusp.. */ + if (acpi_state == ACPI_STATE_S3 || acpi_state == ACPI_STATE_S4) { + if (!acpi_wakeup_address) { + return -EFAULT; + } + acpi_set_firmware_waking_vector((acpi_physical_address) + virt_to_phys((void *) + acpi_wakeup_address)); + + } + ACPI_FLUSH_CPU_CACHE(); + acpi_enable_wakeup_device_prep(acpi_state); +#endif + if (acpi_state == ACPI_STATE_S5) { + /* Check if we were already called */ + if (shutdown_prepared) + return 0; + acpi_wakeup_gpe_poweroff_prepare(); + shutdown_prepared = 1; + } + acpi_enter_sleep_state_prep(acpi_state); + return 0; +} + +void acpi_power_off(void) +{ + printk("%s called\n", __FUNCTION__); + acpi_sleep_prepare(ACPI_STATE_S5); + local_irq_disable(); /* Some SMP machines only can poweroff in boot CPU */ set_cpus_allowed(current, cpumask_of_cpu(0)); - acpi_wakeup_gpe_poweroff_prepare(); - acpi_enter_sleep_state_prep(ACPI_STATE_S5); - ACPI_DISABLE_IRQS(); acpi_enter_sleep_state(ACPI_STATE_S5); } +#ifdef CONFIG_PM + +static int acpi_shutdown(struct sys_device *x) +{ + return acpi_sleep_prepare(ACPI_STATE_S5); +} + +static struct sysdev_class acpi_sysclass = { + set_kset_name("acpi"), + .shutdown = acpi_shutdown +}; + +static struct sys_device device_acpi = { + .id = 0, + .cls = &acpi_sysclass, +}; + +#endif + static int acpi_poweroff_init(void) { if (!acpi_disabled) { u8 type_a, type_b; acpi_status status; - status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); - if (ACPI_SUCCESS(status)) + status = + acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { pm_power_off = acpi_power_off; +#ifdef CONFIG_PM + { + int error; + error = sysdev_class_register(&acpi_sysclass); + if (!error) + error = sysdev_register(&device_acpi); + return error; + } +#endif + } } return 0; } diff -Nru a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c --- a/drivers/acpi/toshiba_acpi.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/acpi/toshiba_acpi.c 2005-04-10 17:05:04 -07:00 @@ -529,6 +529,11 @@ if (acpi_disabled) return -ENODEV; + + if (!acpi_specific_hotkey_enabled){ + printk(MY_INFO "Using generic hotkey driver\n"); + return -ENODEV; + } /* simple device detection: look for HCI method */ if (is_valid_acpi_path(METHOD_HCI_1)) method_hci = METHOD_HCI_1; diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c --- a/drivers/base/sys.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/base/sys.c 2005-04-10 17:05:04 -07:00 @@ -21,7 +21,6 @@ #include #include - extern struct subsystem devices_subsys; #define to_sysdev(k) container_of(k, struct sys_device, kobj) diff -Nru a/drivers/net/b44.c b/drivers/net/b44.c --- a/drivers/net/b44.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/net/b44.c 2005-04-10 17:05:04 -07:00 @@ -1927,6 +1927,7 @@ b44_free_rings(bp); spin_unlock_irq(&bp->lock); + pci_disable_device(pdev); return 0; } @@ -1936,6 +1937,8 @@ struct b44 *bp = netdev_priv(dev); pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); if (!netif_running(dev)) return 0; diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/net/e1000/e1000_main.c 2005-04-10 17:05:04 -07:00 @@ -3118,8 +3118,7 @@ pci_set_power_state(pdev, 0); pci_restore_state(pdev); ret = pci_enable_device(pdev); - if (pdev->is_busmaster) - pci_set_master(pdev); + pci_set_master(pdev); pci_enable_wake(pdev, 3, 0); pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c --- a/drivers/net/ne2k-pci.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/net/ne2k-pci.c 2005-04-10 17:05:04 -07:00 @@ -660,6 +660,7 @@ netif_device_detach(dev); pci_save_state(pdev); + pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; @@ -671,6 +672,8 @@ pci_set_power_state(pdev, 0); pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); NS8390_init(dev, 1); netif_device_attach(dev); diff -Nru a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c --- a/drivers/pci/pci-acpi.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pci/pci-acpi.c 2005-04-10 17:05:04 -07:00 @@ -1,9 +1,10 @@ /* * File: pci-acpi.c - * Purpose: Provide PCI supports in ACPI + * Purpose: Provide PCI support in ACPI * - * Copyright (C) 2004 Intel - * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) + * Copyright (C) 2005 David Shaohua Li + * Copyright (C) 2004 Tom Long Nguyen + * Copyright (C) 2004 Intel Corp. */ #include @@ -16,6 +17,7 @@ #include #include +#include "pci.h" static u32 ctrlset_buf[3] = {0, 0, 0}; static u32 global_ctrlsets = 0; @@ -207,3 +209,105 @@ return status; } EXPORT_SYMBOL(pci_osc_control_set); + +/* + * _SxD returns the D-state with the highest power + * (lowest D-state number) supported in the S-state "x". + * + * If the devices does not have a _PRW + * (Power Resources for Wake) supporting system wakeup from "x" + * then the OS is free to choose a lower power (higher number + * D-state) than the return value from _SxD. + * + * But if _PRW is enabled at S-state "x", the OS + * must not choose a power lower than _SxD -- + * unless the device has an _SxW method specifying + * the lowest power (highest D-state number) the device + * may enter while still able to wake the system. + * + * ie. depending on global OS policy: + * + * if (_PRW at S-state x) + * choose from highest power _SxD to lowest power _SxW + * else // no _PRW at S-state x + * choose highest power _SxD or any lower power + * + * currently we simply return _SxD, if present. + */ + +static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state) +{ + /* TBD */ + + return -ENODEV; +} + +static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); + static int state_conv[] = { + [0] = 0, + [1] = 1, + [2] = 2, + [3] = 3, + [4] = 3 + }; + int acpi_state = state_conv[(int __force) state]; + + if (!handle) + return -ENODEV; + return acpi_bus_set_power(handle, acpi_state); +} + + +/* ACPI bus type */ +static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) +{ + struct pci_dev * pci_dev; + acpi_integer addr; + + pci_dev = to_pci_dev(dev); + /* Please ref to ACPI spec for the syntax of _ADR */ + addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr); + if (!*handle) + return -ENODEV; + return 0; +} + +static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) +{ + int num; + unsigned int seg, bus; + + /* + * The string should be the same as root bridge's name + * Please look at 'pci_scan_bus_parented' + */ + num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus); + if (num != 2) + return -ENODEV; + *handle = acpi_get_pci_rootbridge_handle(seg, bus); + if (!*handle) + return -ENODEV; + return 0; +} + +static struct acpi_bus_type pci_acpi_bus = { + .bus = &pci_bus_type, + .find_device = pci_acpi_find_device, + .find_bridge = pci_acpi_find_root_bridge, +}; + +static int __init pci_acpi_init(void) +{ + int ret; + + ret = register_acpi_bus_type(&pci_acpi_bus); + if (ret) + return 0; + platform_pci_choose_state = acpi_pci_choose_state; + platform_pci_set_power_state = acpi_pci_set_power_state; + return 0; +} +arch_initcall(pci_acpi_init); diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pci/pci.c 2005-04-10 17:05:04 -07:00 @@ -234,7 +234,7 @@ * -EIO if device does not support PCI PM. * 0 if we can successfully change the power state. */ - +int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t); int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { @@ -298,8 +298,15 @@ msleep(10); else if (state == PCI_D2 || dev->current_state == PCI_D2) udelay(200); - dev->current_state = state; + /* + * Give firmware a chance to be called, such as ACPI _PRx, _PSx + * Firmware method after natice method ? + */ + if (platform_pci_set_power_state) + platform_pci_set_power_state(dev, state); + + dev->current_state = state; return 0; } @@ -312,12 +319,19 @@ * Returns PCI power state suitable for given device and given system * message. */ +int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { + int ret; if (!pci_find_capability(dev, PCI_CAP_ID_PM)) return PCI_D0; + if (platform_pci_choose_state) { + ret = platform_pci_choose_state(dev, state); + if (ret >= 0) + state = ret; + } switch (state) { case 0: return PCI_D0; case 3: return PCI_D3hot; diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h --- a/drivers/pci/pci.h 2005-04-10 17:05:04 -07:00 +++ b/drivers/pci/pci.h 2005-04-10 17:05:04 -07:00 @@ -11,6 +11,10 @@ void (*alignf)(void *, struct resource *, unsigned long, unsigned long), void *alignf_data); +/* Firmware callbacks */ +extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); +extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); + /* PCI /proc functions */ #ifdef CONFIG_PROC_FS extern int pci_proc_attach_device(struct pci_dev *dev); diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pci/quirks.c 2005-04-10 17:05:04 -07:00 @@ -18,6 +18,7 @@ #include #include #include +#include /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ @@ -465,9 +466,6 @@ * non-x86 architectures (yes Via exists on PPC among other places), * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get * interrupts delivered properly. - * - * TODO: When we have device-specific interrupt routers, - * quirk_via_irqpic will go away from quirks. */ /* @@ -492,6 +490,29 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); +static void __devinit quirk_via_irqpic(struct pci_dev *dev) +{ + u8 irq, new_irq; + +#ifdef CONFIG_X86_IO_APIC + if (nr_ioapics && !skip_ioapic_setup) + return; +#endif +#ifdef CONFIG_ACPI + if (acpi_irq_model != ACPI_IRQ_MODEL_PIC) + return; +#endif + new_irq = dev->irq & 0xf; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + if (new_irq != irq) { + printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n", + pci_name(dev), irq, new_irq); + udelay(15); /* unknown if delay really needed */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); + } +} +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic); + /* * PIIX3 USB: We have to disable USB interrupts that are * hardwired to PIRQD# and may be shared with an @@ -681,19 +702,6 @@ } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); -/* - * VIA northbridges care about PCI_INTERRUPT_LINE - */ -int via_interrupt_line_quirk; - -static void __devinit quirk_via_bridge(struct pci_dev *pdev) -{ - if(pdev->devfn == 0) { - printk(KERN_INFO "PCI: Via IRQ fixup\n"); - via_interrupt_line_quirk = 1; - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge ); /* * Serverworks CSB5 IDE does not fully support native mode diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pcmcia/yenta_socket.c 2005-04-10 17:05:04 -07:00 @@ -1032,6 +1032,7 @@ pci_save_state(dev); pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); + pci_disable_device(dev); /* * Some laptops (IBM T22) do not like us putting the Cardbus @@ -1055,6 +1056,8 @@ pci_restore_state(dev); pci_write_config_dword(dev, 16*4, socket->saved_state[0]); pci_write_config_dword(dev, 17*4, socket->saved_state[1]); + pci_enable_device(dev); + pci_set_master(dev); if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); diff -Nru a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c --- a/drivers/pnp/pnpacpi/rsparser.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pnp/pnpacpi/rsparser.c 2005-04-10 17:05:04 -07:00 @@ -160,7 +160,7 @@ acpi_register_gsi(res->data.irq.interrupts[0], res->data.irq.edge_level, res->data.irq.active_high_low)); - pcibios_penalize_isa_irq(res->data.irq.interrupts[0]); + pcibios_penalize_isa_irq(res->data.irq.interrupts[0], 1); } break; @@ -171,7 +171,7 @@ acpi_register_gsi(res->data.extended_irq.interrupts[0], res->data.extended_irq.edge_level, res->data.extended_irq.active_high_low)); - pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0]); + pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0], 1); } break; case ACPI_RSTYPE_DMA: @@ -444,6 +444,7 @@ struct acpipnp_parse_option_s { struct pnp_option *option; + struct pnp_option *option_independent; struct pnp_dev *dev; }; @@ -507,7 +508,14 @@ parse_data->option = option; break; case ACPI_RSTYPE_END_DPF: - return AE_CTRL_TERMINATE; + /*only one EndDependentFn is allowed*/ + if (!parse_data->option_independent) { + pnp_warn("PnPACPI: more than one EndDependentFn"); + return AE_ERROR; + } + parse_data->option = parse_data->option_independent; + parse_data->option_independent = NULL; + break; default: pnp_warn("PnPACPI: unknown resource type %d", res->id); return AE_ERROR; @@ -525,6 +533,7 @@ parse_data.option = pnp_register_independent_option(dev); if (!parse_data.option) return AE_ERROR; + parse_data.option_independent = parse_data.option; parse_data.dev = dev; status = acpi_walk_resources(handle, METHOD_NAME__PRS, pnpacpi_option_resource, &parse_data); diff -Nru a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c --- a/drivers/pnp/pnpbios/rsparser.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pnp/pnpbios/rsparser.c 2005-04-10 17:05:04 -07:00 @@ -64,7 +64,7 @@ } res->irq_resource[i].start = res->irq_resource[i].end = (unsigned long) irq; - pcibios_penalize_isa_irq(irq); + pcibios_penalize_isa_irq(irq, 1); } } diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c --- a/drivers/pnp/resource.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/pnp/resource.c 2005-04-10 17:05:04 -07:00 @@ -102,7 +102,7 @@ for (i = 0; i < 16; i++) if (test_bit(i, data->map)) - pcibios_penalize_isa_irq(i); + pcibios_penalize_isa_irq(i, 0); } #endif return 0; diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c 2005-04-10 17:05:04 -07:00 +++ b/drivers/usb/core/hcd-pci.c 2005-04-10 17:05:04 -07:00 @@ -349,6 +349,7 @@ usb_hc_died (hcd); } + pci_enable_device(dev); return retval; } EXPORT_SYMBOL (usb_hcd_pci_resume); diff -Nru a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h --- a/include/acpi/acpi_bus.h 2005-04-10 17:05:04 -07:00 +++ b/include/acpi/acpi_bus.h 2005-04-10 17:05:04 -07:00 @@ -336,6 +336,27 @@ int acpi_create_dir(struct acpi_device *); void acpi_remove_dir(struct acpi_device *); + +/* + * Bind physical devices with ACPI devices + */ +#include +struct acpi_bus_type { + struct list_head list; + struct bus_type *bus; + /* For general devices under the bus*/ + int (*find_device)(struct device *, acpi_handle*); + /* For bridges, such as PCI root bridge, IDE controller */ + int (*find_bridge)(struct device *, acpi_handle *); +}; +int register_acpi_bus_type(struct acpi_bus_type *); +int unregister_acpi_bus_type(struct acpi_bus_type *); +struct device *acpi_get_physical_device(acpi_handle); +/* helper */ +acpi_handle acpi_get_child(acpi_handle, acpi_integer); +acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); +#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data)) + #endif /*CONFIG_ACPI_BUS*/ #endif /*__ACPI_BUS_H__*/ diff -Nru a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h --- a/include/acpi/acpi_drivers.h 2005-04-10 17:05:04 -07:00 +++ b/include/acpi/acpi_drivers.h 2005-04-10 17:05:04 -07:00 @@ -108,5 +108,10 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type); +/* -------------------------------------------------------------------------- + Hot Keys + -------------------------------------------------------------------------- */ + +extern int acpi_specific_hotkey_enabled; #endif /*__ACPI_DRIVERS_H__*/ diff -Nru a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h --- a/include/asm-alpha/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-alpha/pci.h 2005-04-10 17:05:04 -07:00 @@ -58,7 +58,7 @@ extern void pcibios_set_master(struct pci_dev *dev); -extern inline void pcibios_penalize_isa_irq(int irq) +extern inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-arm/pci.h b/include/asm-arm/pci.h --- a/include/asm-arm/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-arm/pci.h 2005-04-10 17:05:04 -07:00 @@ -14,7 +14,7 @@ /* No special bus mastering setup handling */ } -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-h8300/pci.h b/include/asm-h8300/pci.h --- a/include/asm-h8300/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-h8300/pci.h 2005-04-10 17:05:04 -07:00 @@ -15,7 +15,7 @@ /* No special bus mastering setup handling */ } -extern inline void pcibios_penalize_isa_irq(int irq) +extern inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-i386/pci.h b/include/asm-i386/pci.h --- a/include/asm-i386/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-i386/pci.h 2005-04-10 17:05:04 -07:00 @@ -27,7 +27,7 @@ struct pci_bus * pcibios_scan_root(int bus); void pcibios_set_master(struct pci_dev *dev); -void pcibios_penalize_isa_irq(int irq); +void pcibios_penalize_isa_irq(int irq, int active); struct irq_routing_table *pcibios_get_irq_routing_table(void); int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); diff -Nru a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h --- a/include/asm-ia64/acpi.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-ia64/acpi.h 2005-04-10 17:05:04 -07:00 @@ -98,6 +98,15 @@ int acpi_request_vector (u32 int_type); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); +/* + * Record the cpei override flag and current logical cpu. This is + * useful for CPU removal. + */ +extern unsigned int can_cpei_retarget(void); +extern unsigned int is_cpu_cpei_target(unsigned int cpu); +extern void set_cpei_target_cpu(unsigned int cpu); +extern unsigned int get_cpei_target_cpu(void); + #ifdef CONFIG_ACPI_NUMA /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/ #define MAX_PXM_DOMAINS (256) diff -Nru a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h --- a/include/asm-ia64/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-ia64/pci.h 2005-04-10 17:05:04 -07:00 @@ -47,7 +47,7 @@ } static inline void -pcibios_penalize_isa_irq (int irq) +pcibios_penalize_isa_irq (int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-m68k/pci.h b/include/asm-m68k/pci.h --- a/include/asm-m68k/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-m68k/pci.h 2005-04-10 17:05:04 -07:00 @@ -43,7 +43,7 @@ /* No special bus mastering setup handling */ } -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-mips/pci.h b/include/asm-mips/pci.h --- a/include/asm-mips/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-mips/pci.h 2005-04-10 17:05:04 -07:00 @@ -69,7 +69,7 @@ extern void pcibios_set_master(struct pci_dev *dev); -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h --- a/include/asm-ppc/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-ppc/pci.h 2005-04-10 17:05:04 -07:00 @@ -37,7 +37,7 @@ /* No special bus mastering setup handling */ } -extern inline void pcibios_penalize_isa_irq(int irq) +extern inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h --- a/include/asm-ppc64/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-ppc64/pci.h 2005-04-10 17:05:04 -07:00 @@ -37,7 +37,7 @@ /* No special bus mastering setup handling */ } -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-sh/pci.h b/include/asm-sh/pci.h --- a/include/asm-sh/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-sh/pci.h 2005-04-10 17:05:04 -07:00 @@ -36,7 +36,7 @@ extern void pcibios_set_master(struct pci_dev *dev); -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-sh64/pci.h b/include/asm-sh64/pci.h --- a/include/asm-sh64/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-sh64/pci.h 2005-04-10 17:05:04 -07:00 @@ -26,7 +26,7 @@ /* * Set penalize isa irq function */ -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h --- a/include/asm-sparc/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-sparc/pci.h 2005-04-10 17:05:04 -07:00 @@ -20,7 +20,7 @@ /* No special bus mastering setup handling */ } -extern inline void pcibios_penalize_isa_irq(int irq) +extern inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h --- a/include/asm-sparc64/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-sparc64/pci.h 2005-04-10 17:05:04 -07:00 @@ -23,7 +23,7 @@ /* No special bus mastering setup handling */ } -static inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } diff -Nru a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h --- a/include/asm-x86_64/pci.h 2005-04-10 17:05:04 -07:00 +++ b/include/asm-x86_64/pci.h 2005-04-10 17:05:04 -07:00 @@ -33,7 +33,7 @@ extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value); void pcibios_set_master(struct pci_dev *dev); -void pcibios_penalize_isa_irq(int irq); +void pcibios_penalize_isa_irq(int irq, int active); struct irq_routing_table *pcibios_get_irq_routing_table(void); int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h --- a/include/linux/acpi.h 2005-04-10 17:05:04 -07:00 +++ b/include/linux/acpi.h 2005-04-10 17:05:04 -07:00 @@ -202,7 +202,10 @@ u8 eid; u8 iosapic_vector; u32 global_irq; - u32 reserved; + struct { + u32 cpei_override_flag:1; + u32 reserved:31; + } plint_flags; } __attribute__ ((packed)); enum acpi_interrupt_id { @@ -458,7 +461,7 @@ struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev); -void acpi_penalize_isa_irq(int irq); +void acpi_penalize_isa_irq(int irq, int active); #ifdef CONFIG_ACPI_DEALLOCATE_IRQ void acpi_pci_irq_disable (struct pci_dev *dev); diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h 2005-04-10 17:05:04 -07:00 +++ b/include/linux/device.h 2005-04-10 17:05:04 -07:00 @@ -269,8 +269,10 @@ struct device_driver *driver; /* which driver has allocated this device */ void *driver_data; /* data private to the driver */ - void *platform_data; /* Platform specific data (e.g. ACPI, - BIOS data relevant to device) */ + void *platform_data; /* Platform specific data, device + core doesn't touch it */ + void *firmware_data; /* Firmware specific data (e.g. ACPI, + BIOS data),reserved for device core*/ struct dev_pm_info power; u32 detach_state; /* State to enter when device is diff -Nru a/include/linux/pm.h b/include/linux/pm.h --- a/include/linux/pm.h 2005-04-10 17:05:04 -07:00 +++ b/include/linux/pm.h 2005-04-10 17:05:04 -07:00 @@ -175,7 +175,7 @@ }; extern void pm_set_ops(struct pm_ops *); - +extern struct pm_ops *pm_ops; extern int pm_suspend(suspend_state_t state); diff -Nru a/kernel/power/main.c b/kernel/power/main.c --- a/kernel/power/main.c 2005-04-10 17:05:04 -07:00 +++ b/kernel/power/main.c 2005-04-10 17:05:04 -07:00 @@ -19,6 +19,9 @@ #include "power.h" +/*This is just an arbitrary number */ +#define FREE_PAGE_NUMBER (100) + DECLARE_MUTEX(pm_sem); struct pm_ops * pm_ops = NULL; @@ -49,6 +52,7 @@ static int suspend_prepare(suspend_state_t state) { int error = 0; + unsigned int free_pages; if (!pm_ops || !pm_ops->enter) return -EPERM; @@ -60,6 +64,16 @@ goto Thaw; } + if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) { + pr_debug("PM: free some memory\n"); + shrink_all_memory(FREE_PAGE_NUMBER - free_pages); + if (nr_free_pages() < FREE_PAGE_NUMBER) { + error = -ENOMEM; + printk(KERN_ERR "PM: No enough memory\n"); + goto Thaw; + } + } + if (pm_ops->prepare) { if ((error = pm_ops->prepare(state))) goto Thaw; @@ -190,7 +204,7 @@ int pm_suspend(suspend_state_t state) { - if (state > PM_SUSPEND_ON && state < PM_SUSPEND_MAX) + if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) return enter_state(state); return -EINVAL; }