bk://linux-acpi.bkbits.net/to-akpm len.brown@intel.com|ChangeSet|20050319070218|21733 len.brown # This is a BitKeeper generated diff -Nru style patch. # # 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/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/18 00:00:20-05:00 len.brown@intel.com # merge # # drivers/acpi/Kconfig # 2005/03/18 00:00:12-05:00 len.brown@intel.com +1 -2 # merge # # 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/17 23:26:54-05:00 len.brown@intel.com # [ACPI] build fix in acpi_pci_irq_disable() # # bk-acpi-acpi_pci_irq_disable-build-fix.patch # # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/pci_irq.c # 2005/03/12 04:57:08-05:00 len.brown@intel.com +2 -2 # build fix in acpi_pci_irq_disable() # # ChangeSet # 2005/03/15 11:43:06-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/bk/26-latest-ref # into intel.com:/home/lenb/src/26-latest-dev # # arch/i386/kernel/acpi/sleep.c # 2005/03/15 11:43:00-05:00 len.brown@intel.com +0 -0 # Auto merged # # 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/09 23:46:24-05:00 len.brown@intel.com # [ACPI] ACPICA 20050309 from Bob Moore # # The string-to-buffer implicit conversion code has been # modified again after a change to the ACPI specification. # In order to match the behavior of the other major ACPI # implementation, the target buffer is no longer truncated # if the source string is smaller than an existing target # buffer. This change requires an update to the ACPI spec, # and should eliminate the recent AE_AML_BUFFER_LIMIT issues. # # The "implicit return" support was rewritten to a new # algorithm that solves the general case. Rather than # attempt to determine when a method is about to exit, # the result of every ASL operator is saved momentarily # until the very next ASL operator is executed. Therefore, # no matter how the method exits, there will always be a # saved implicit return value. This feature is only enabled # with the acpi_gbl_enable_interpreter_slack flag which # Linux enables unless "acpi=strict". This should # eliminate AE_AML_NO_RETURN_VALUE errors. # # Implemented implicit conversion support for the predicate # (operand) of the If, Else, and While operators. String and # Buffer arguments are automatically converted to Integers. # # Changed the string-to-integer conversion behavior to match # the new ACPI errata: "If no integer object exists, a new # integer is created. The ASCII string is interpreted as a # hexadecimal constant. Each string character is interpreted # as a hexadecimal value ('0'-'9', 'A'-'F', 'a', 'f'), # starting with the first character as the most significant # digit, and ending with the first non-hexadecimal character # or end-of-string." This means that the first non-hex # character terminates the conversion and this is the code # that was changed. # # Fixed a problem where the ObjectType operator would fail # (fault) when used on an Index of a Package which pointed # to a null package element. The operator now properly # returns zero (Uninitialized) in this case. # # Fixed a problem where the While operator used excessive # memory by not properly popping the result stack during # execution. There was no memory leak after execution, # however. (Code provided by Valery Podrezov.) # # Fixed a problem where references to control methods within # Package objects caused the method to be invoked, instead # of producing a reference object pointing to the method. # # Restructured and simplified the pswalk.c module # (acpi_ps_delete_parse_tree) to improve performance and reduce # code size. (Code provided by Alexey Starikovskiy.) # # Signed-off-by: Len Brown # # include/acpi/acstruct.h # 2005/03/09 23:41:38-05:00 len.brown@intel.com +1 -0 # ACPICA 20050309 # # include/acpi/acinterp.h # 2005/03/09 23:41:38-05:00 len.brown@intel.com +0 -1 # ACPICA 20050309 # # include/acpi/acdispat.h # 2005/03/09 23:41:38-05:00 len.brown@intel.com +10 -0 # ACPICA 20050309 # # include/acpi/acconfig.h # 2005/03/09 23:41:38-05:00 len.brown@intel.com +1 -1 # ACPICA 20050309 # # drivers/acpi/utilities/utmisc.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +15 -9 # ACPICA 20050309 # # drivers/acpi/utilities/utcopy.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +15 -4 # ACPICA 20050309 # # drivers/acpi/parser/pswalk.c # 2005/03/09 23:41:41-05:00 len.brown@intel.com +31 -223 # ACPICA 20050309 # # drivers/acpi/parser/psparse.c # 2005/03/09 23:41:41-05:00 len.brown@intel.com +34 -8 # ACPICA 20050309 # # drivers/acpi/executer/exstorob.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +16 -11 # ACPICA 20050309 # # drivers/acpi/executer/exstoren.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +2 -5 # ACPICA 20050309 # # drivers/acpi/executer/exresolv.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +6 -0 # ACPICA 20050309 # # drivers/acpi/executer/exmisc.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +3 -2 # ACPICA 20050309 # # drivers/acpi/dispatcher/dswexec.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +46 -15 # ACPICA 20050309 # # drivers/acpi/dispatcher/dsutils.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +132 -34 # ACPICA 20050309 # # drivers/acpi/dispatcher/dsopcode.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +8 -0 # ACPICA 20050309 # # drivers/acpi/dispatcher/dsmethod.c # 2005/03/09 23:41:42-05:00 len.brown@intel.com +10 -1 # ACPICA 20050309 # # ChangeSet # 2005/03/09 01:38:15-05:00 len.brown@intel.com # [ACPI] limit scope of various globals to static # # Signed-off-by: Adrian Bunk # Signed-off-by: Len Brown # # include/linux/acpi.h # 2005/01/26 16:09:44-05:00 len.brown@intel.com +0 -2 # static # # include/acpi/processor.h # 2005/01/26 16:14:00-05:00 len.brown@intel.com +0 -2 # static # # include/acpi/acpi_bus.h # 2005/01/26 16:15:37-05:00 len.brown@intel.com +0 -1 # static # # drivers/acpi/video.c # 2005/01/26 16:35:07-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/toshiba_acpi.c # 2005/01/26 16:23:18-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/thermal.c # 2005/01/26 16:22:54-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/scan.c # 2005/01/26 16:16:02-05:00 len.brown@intel.com +8 -4 # static # # drivers/acpi/processor_throttling.c # 2005/01/26 16:14:19-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/processor_thermal.c # 2005/01/26 16:13:47-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/processor_core.c # 2005/01/26 16:48:14-05:00 len.brown@intel.com +3 -3 # static # # drivers/acpi/power.c # 2005/01/26 16:11:21-05:00 len.brown@intel.com +5 -5 # static # # drivers/acpi/pci_irq.c # 2005/01/26 16:10:10-05:00 len.brown@intel.com +2 -2 # static # # drivers/acpi/osl.c # 2005/01/26 16:00:15-05:00 len.brown@intel.com +5 -5 # static # # drivers/acpi/ibm_acpi.c # 2005/01/26 15:42:24-05:00 len.brown@intel.com +2 -2 # static # # drivers/acpi/fan.c # 2005/01/26 15:40:22-05:00 len.brown@intel.com +7 -7 # static # # drivers/acpi/ec.c # 2005/01/26 14:06:06-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/debug.c # 2005/01/26 13:59:33-05:00 len.brown@intel.com +2 -2 # static # # drivers/acpi/container.c # 2005/01/26 13:59:05-05:00 len.brown@intel.com +2 -2 # static # # drivers/acpi/button.c # 2005/01/26 13:58:34-05:00 len.brown@intel.com +2 -2 # static # # drivers/acpi/battery.c # 2005/01/26 13:58:07-05:00 len.brown@intel.com +1 -1 # static # # drivers/acpi/ac.c # 2005/01/26 13:57:37-05:00 len.brown@intel.com +9 -9 # static # # ChangeSet # 2005/03/09 01:31:00-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/numa.c # 2005/03/09 01:30:56-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/09 01:29:06-05:00 len.brown@intel.com # [ACPI] fix acpi_numa_init() build warning # # Signed-off-by: Randy Dunlap # Signed-off-by: Len Brown # # drivers/acpi/numa.c # 2005/03/09 01:09:45-05:00 len.brown@intel.com +1 -1 # warning: non-ANSI function declaration # # # ChangeSet # 2005/03/09 00:32:09-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/pci_irq.c # 2005/03/09 00:32:02-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/09 00:02:51-05:00 len.brown@intel.com # [ACPI] Allow 4 digits when printing PCI segments # to be consistent with the rest of the kernel. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Len Brown # # drivers/acpi/pci_root.c # 2005/02/15 16:10:14-05:00 len.brown@intel.com +2 -2 # Allow 4 digits when printing PCI segments # # ChangeSet # 2005/03/08 23:59:02-05:00 len.brown@intel.com # [ACPI] Make PCI device -> interrupt link associations explicit, # # ACPI: PCI Interrupt 0000:00:0f.2[A] -> Link [IUSB] -> GSI 10 (level, low) -> IRQ 10 # # Previously, you could sometimes infer an association based on the output # when an interrupt link is enabled, but when interrupt links are shared # among several PCI devices, you could only make the inference for the first # device to be enabled. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Len Brown # # include/acpi/acpi_drivers.h # 2005/02/15 10:46:08-05:00 len.brown@intel.com +2 -1 # Make PCI device -> interrupt link associations explicit # # drivers/acpi/pci_link.c # 2005/02/15 11:16:53-05:00 len.brown@intel.com +9 -5 # Make PCI device -> interrupt link associations explicit # # drivers/acpi/pci_irq.c # 2005/02/15 11:37:51-05:00 len.brown@intel.com +20 -10 # Make PCI device -> interrupt link associations explicit # # ChangeSet # 2005/03/08 23:56:24-05:00 len.brown@intel.com # [ACPI] PNPACPI should ignore vendor-defined resources # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Len Brown # # drivers/pnp/pnpacpi/rsparser.c # 2005/02/11 14:43:12-05:00 len.brown@intel.com +5 -4 # Don't complain about vendor-defined resources, just ignore them. # And make warning messages a little more consistent. # # ChangeSet # 2005/03/03 23:21:29-05:00 len.brown@intel.com # [ACPI] fix [ACPI_MTX_Hardware] AE_TIME warning # which resulted from enabling the wake-on-RTC feature # # http://bugme.osdl.org/show_bug.cgi?id=3967 # # Signed-off-by: David Shaohua Li # Signed-off-by: Len Brown # # drivers/acpi/events/evxface.c # 2004/12/30 02:39:01-05:00 len.brown@intel.com +3 -1 # fix [ACPI_MTX_Hardware] AE_TIME warnings resulting from wake-on-RTC fix # # ChangeSet # 2005/03/03 19:55:50-05:00 len.brown@intel.com # [ACPI] ACPICA 20050303 from Bob Moore for AE_AML_BUFFER_LIMIT issue. # # It turns out that tightening up the interpreter to truncate buffers # per the ACPI spec was a bad idea -- BIOS' in the field depended # on old behaviour. Instead, we'll endeavor to update the ACPI spec # to reflect industry practice in this area. # # http://bugme.osdl.org/show_bug.cgi?id=4263 # # Signed-off-by: Len Brown # # include/acpi/acconfig.h # 2005/03/03 19:55:39-05:00 len.brown@intel.com +1 -1 # ACPICA 20050303 # # drivers/acpi/executer/exstorob.c # 2005/03/03 19:55:38-05:00 len.brown@intel.com +2 -0 # ACPICA 20050303 # # ChangeSet # 2005/03/02 20:54:36-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/scan.c # 2005/03/02 20:54:31-05:00 len.brown@intel.com +0 -0 # Auto merged # # arch/ia64/kernel/acpi.c # 2005/03/02 20:54:31-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2005/03/02 14:13:39-05:00 len.brown@intel.com # [ACPI] fix sysfs "eject" file # # This fixes a if-statement in setup_sys_fs_device_files(). It seems to # assume that 'struct acpi_device_flags.ejectable' indicates whether a device # has _EJ0 or not. But this is not a right assumption. It indicates whether # a device has _EJ0|_EJD (See acpi_bus_get_flags() function). # # setup_sys_fs_device_files() creates 'eject' file for devices that have _EJ0 # control method under a corresponding directory in # /sys/firmware/acpi/namespace/ACPI/. 'eject' file is used to trigger # hot-removal function from userland. # # # # Signed-off-by: Keiichiro Tokunaga # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/scan.c # 2005/02/23 04:48:12-05:00 len.brown@intel.com +9 -1 # Import patch acpi-fix-a-if-statement-in-setup_sys_fs_device_files.patch # # ChangeSet # 2005/03/02 14:06:18-05:00 len.brown@intel.com # [ACPI] fix ACPI container driver's notify handler. # # Previously, the handler tried to make a container device be offline if an # ACPI_NOTIFY_BUS/DEVICE_CHECK notification is performed on the device was # present and has its acpi_device. But, the condition is weird. Whenever # the notification is performed, there should be only the following two # conditions: # # 1. the device is present, but does not have its acpi_device. # 2. the device is not present, but has its acpi_device. # # #1 is a hot-addition case, which was handled properly also in previous # handler. #2 is a surprising hot-removal case, which was not handled in # previous handler. # # Signed-off-by: Keiichiro Tokunaga # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/container.c # 2005/02/23 04:48:06-05:00 len.brown@intel.com +8 -3 # Import patch acpi-fix-containers-notify-handler-to-handle-proper-cases-properly.patch # # ChangeSet # 2005/03/02 14:02:55-05:00 len.brown@intel.com # [ACPI] fix kobject_hotplug() use by ACPI processor and container drivers # # A while ago, the drivers used their own function # 'processor_run_sbin_hotplug() and container_run_sbin_hotplug()' to notify # the agent script using /sbin/hotplug mechanism. But, they were changed to # use kobject_hotplug() instead and this has caused a side effect. # # The container driver was supposed to invoke a container.agent (user mode # agent script) using /sbin/hotplug mechanism, but after the changes, it is # not able to call the agent any more and kobject_hotplug() in the # container.c became to invoke a namespace.agent instead if exists. So, I # would like to use the namespace.agent to handle container hotplug event (or # something else) and let the agent to call proper agent (e.g. # container.agent). But, there is an issue we need to solve. When the # namespace.agent is called, a path name of associated kobject is passed as a # DEVPATH (e.g./sys/firmware/ acpi/namespace/ACPI/_SB/DEV0). However, the # agent would not know what device is associated with the DEVPATH nor which # agents to call since the DEVPATH name depends on platform. The attached # patch is to add .hotplug_ops member to acpi_namespace_kset structure and # let it to set a driver name attached to the target kobject into the envp[] # variable as a DRV_NAME element. With this, the namespace.agent can call # proper agents (e.g. container.agent) by refering the DRV_NAME. # # Signed-off-by: Keiichiro Tokunaga # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/scan.c # 2005/02/23 04:48:05-05:00 len.brown@intel.com +25 -0 # Import patch fix-an-issue-in-acpi-processor-and-container-drivers-related-with-kobject_hotplug.patch # # ChangeSet # 2005/03/02 13:57:35-05:00 len.brown@intel.com # [ACPI] flush TLB in init_low_mappings() # # From: Li Shaohua # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # arch/i386/kernel/acpi/sleep.c # 2005/02/23 04:48:04-05:00 len.brown@intel.com +2 -1 # Import patch acpi-flush-tlb-when-pagetable-changed.patch # # ChangeSet # 2005/03/02 13:54:47-05:00 len.brown@intel.com # [ACPI] enhance fan output in error path # # Currently, fan.c ignores errors from acpi_bus_get_power. On compaq evo # notebook that leads to very confusing empty output. # # From: Pavel Machek # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # drivers/acpi/fan.c # 2005/02/23 04:48:03-05:00 len.brown@intel.com +8 -11 # Import patch acpi-report-errors-in-fanc.patch # # ChangeSet # 2005/03/02 13:36:53-05:00 len.brown@intel.com # [ACPI] CONFIG_ACPI_NUMA build fix # # Signed-off-by: Andrew Morton # Signed-off-by: Len Brown # # arch/ia64/kernel/acpi.c # 2005/02/23 04:47:50-05:00 len.brown@intel.com +1 -1 # Import patch ia64-acpi-build-fix.patch # # ChangeSet # 2005/03/01 15:26:20-05:00 len.brown@intel.com # [ACPI] ACPICA 20050228 from Bob Moore # # Fixed a problem where the result of an Index() operator # (an object reference) must increment the reference count # on the target object for the life of the object reference. # # Implemented AML Interpreter and Debugger support for # the new ACPI 3.0 Extended Address (IO, Memory, Space), # QwordSpace, DwordSpace, and WordSpace resource descriptors. # # Implemented support in the _OSI method for the ACPI 3.0 # "Extended Address Space Descriptor" string, indicating # interpreter support for the descriptors above. # # Implemented header support for the new ACPI 3.0 FADT # flag bits. # # Implemented header support for the new ACPI 3.0 PCI Express # bits for the PM1 status/enable registers. # # Updated header support for the MADT processor local Apic # struct and MADT platform interrupt source struct for new # ACPI 3.0 fields. # # Implemented header support for the SRAT and SLIT ACPI # tables. # # Signed-off-by: Len Brown # # include/acpi/platform/acenv.h # 2005/03/01 15:20:35-05:00 len.brown@intel.com +2 -0 # ACPICA 20050228 # # include/acpi/actypes.h # 2005/03/01 15:14:22-05:00 len.brown@intel.com +18 -15 # ACPICA 20050228 # # include/acpi/actbl2.h # 2005/03/01 15:14:22-05:00 len.brown@intel.com +68 -11 # ACPICA 20050228 # # include/acpi/actbl.h # 2005/03/01 15:14:22-05:00 len.brown@intel.com +3 -1 # ACPICA 20050228 # # include/acpi/aclocal.h # 2005/03/01 15:14:23-05:00 len.brown@intel.com +4 -0 # ACPICA 20050228 # # include/acpi/acdisasm.h # 2005/03/01 15:14:23-05:00 len.brown@intel.com +5 -0 # ACPICA 20050228 # # include/acpi/acconfig.h # 2005/03/01 15:14:23-05:00 len.brown@intel.com +2 -2 # ACPICA 20050228 # # drivers/acpi/utilities/utmisc.c # 2005/03/01 15:14:26-05:00 len.brown@intel.com +12 -8 # ACPICA 20050228 # # drivers/acpi/utilities/utglobal.c # 2005/03/01 15:14:26-05:00 len.brown@intel.com +9 -1 # ACPICA 20050228 # # drivers/acpi/utilities/utdelete.c # 2005/03/01 15:14:26-05:00 len.brown@intel.com +17 -1 # ACPICA 20050228 # # drivers/acpi/resources/rslist.c # 2005/03/01 15:14:25-05:00 len.brown@intel.com +1 -0 # ACPICA 20050228 # # drivers/acpi/resources/rsdump.c # 2005/03/01 15:14:25-05:00 len.brown@intel.com +13 -10 # ACPICA 20050228 # # drivers/acpi/resources/rscalc.c # 2005/03/01 15:14:25-05:00 len.brown@intel.com +14 -0 # ACPICA 20050228 # # drivers/acpi/resources/rsaddr.c # 2005/03/01 15:14:25-05:00 len.brown@intel.com +82 -64 # ACPICA 20050228 # # drivers/acpi/parser/psopcode.c # 2005/03/01 15:14:25-05:00 len.brown@intel.com +1 -1 # ACPICA 20050228 # # drivers/acpi/executer/exoparg2.c # 2005/03/01 15:14:25-05:00 len.brown@intel.com +6 -0 # ACPICA 20050228 # # ChangeSet # 2005/02/17 01:50:15-05:00 len.brown@intel.com # [ACPI] Add ACPI-based memory hot plug driver. # # The ACPI based memory hot plug driver patch supports physical hotplug # operations on memory. This driver fields notifications for memory add # and remove operations from firmware and notifies the VM of the affected # memory ranges. Accordingly, this driver also maintains and updates the # states of all the memory ranges. This driver is useful on hardware which # helps firmware generating ACPI events for every physical hotplug # operation of memory boards on the system during runtime. # # Signed-off-by: Dave Hansen # Signed-off-by: Naveen B S # Signed-off-by: Matt Tolentino # Signed-off-by: Len Brown # # drivers/acpi/acpi_memhotplug.c # 2005/01/17 08:37:54-05:00 len.brown@intel.com +542 -0 # Import patch acpi_memhp_driver.patch # # drivers/acpi/acpi_memhotplug.c # 2005/01/17 08:37:54-05:00 len.brown@intel.com +0 -0 # BitKeeper file /home/lenb/src/26-latest-hotplug/drivers/acpi/acpi_memhotplug.c # # drivers/acpi/Makefile # 2005/01/17 08:37:54-05:00 len.brown@intel.com +1 -0 # Import patch acpi_memhp_driver.patch # # drivers/acpi/Kconfig # 2005/01/17 09:09:09-05:00 len.brown@intel.com +21 -0 # Import patch acpi_memhp_driver.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-03-20 16:31:54 -08: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/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c --- a/arch/i386/kernel/acpi/sleep.c 2005-03-20 16:31:54 -08:00 +++ b/arch/i386/kernel/acpi/sleep.c 2005-03-20 16:31:54 -08:00 @@ -8,7 +8,7 @@ #include #include #include - +#include /* address in low memory of the wakeup routine. */ unsigned long acpi_wakeup_address = 0; @@ -27,6 +27,7 @@ set_pgd(pgd, *(pgd+USER_PTRS_PER_PGD)); pgd_ofs++, pgd++; } + flush_tlb_all(); } /** diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c 2005-03-20 16:31:54 -08:00 +++ b/arch/ia64/kernel/acpi.c 2005-03-20 16:31:54 -08:00 @@ -771,7 +771,7 @@ #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -#ifdef CONFIG_NUMA +#ifdef CONFIG_ACPI_NUMA acpi_status __init acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) { diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig --- a/drivers/acpi/Kconfig 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/Kconfig 2005-03-20 16:31:54 -08: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 @@ -331,6 +341,26 @@ This is the ACPI generic container driver which supports ACPI0004, PNP0A05 and PNP0A06 devices +config ACPI_HOTPLUG_MEMORY + tristate "Memory Hotplug" + depends on ACPI + depends on MEMORY_HOTPLUG + default n + help + This driver adds supports for ACPI Memory Hotplug. This driver + provides support for fielding notifications on ACPI memory + devices (PNP0C80) which represent memory ranges that may be + onlined or offlined during runtime. + + Enabling this driver assumes that your platform hardware + and firmware have support for hot-plugging physical memory. If + your system does not support physically adding or ripping out + memory DIMMs at some platfrom defined granularity (individually + or as a bank) at runtime, then you need not enable this driver. + + If one selects "m," this driver can be loaded using the following + command: + $>modprobe acpi_memhotplug endif # ACPI endmenu diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile --- a/drivers/acpi/Makefile 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/Makefile 2005-03-20 16:31:54 -08: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 @@ -55,3 +56,4 @@ obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o +obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c --- a/drivers/acpi/ac.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/ac.c 2005-03-20 16:31:54 -08:00 @@ -51,8 +51,8 @@ MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); MODULE_LICENSE("GPL"); -int acpi_ac_add (struct acpi_device *device); -int acpi_ac_remove (struct acpi_device *device, int type); +static int acpi_ac_add (struct acpi_device *device); +static int acpi_ac_remove (struct acpi_device *device, int type); static int acpi_ac_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_ac_driver = { @@ -108,9 +108,9 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_ac_dir; +static struct proc_dir_entry *acpi_ac_dir; -int acpi_ac_seq_show(struct seq_file *seq, void *offset) +static int acpi_ac_seq_show(struct seq_file *seq, void *offset) { struct acpi_ac *ac = (struct acpi_ac *) seq->private; @@ -200,7 +200,7 @@ Driver Model -------------------------------------------------------------------------- */ -void +static void acpi_ac_notify ( acpi_handle handle, u32 event, @@ -232,7 +232,7 @@ } -int +static int acpi_ac_add ( struct acpi_device *device) { @@ -286,7 +286,7 @@ } -int +static int acpi_ac_remove ( struct acpi_device *device, int type) @@ -315,7 +315,7 @@ } -int __init +static int __init acpi_ac_init (void) { int result = 0; @@ -337,7 +337,7 @@ } -void __exit +static void __exit acpi_ac_exit (void) { ACPI_FUNCTION_TRACE("acpi_ac_exit"); diff -Nru a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/acpi/acpi_memhotplug.c 2005-03-20 16:31:54 -08:00 @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2004 Intel Corporation + * + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * ACPI based HotPlug driver that supports Memory Hotplug + * This driver fields notifications from firmare for memory add + * and remove operations and alerts the VM of the affected memory + * ranges. + */ + +#include +#include +#include +#include +#include +#include + + +#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL +#define ACPI_MEMORY_DEVICE_CLASS "memory" +#define ACPI_MEMORY_DEVICE_HID "PNP0C80" +#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver" +#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" + +#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT + +ACPI_MODULE_NAME ("acpi_memory") +MODULE_AUTHOR("Naveen B S "); +MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +/* ACPI _STA method values */ +#define ACPI_MEMORY_STA_PRESENT (0x00000001UL) +#define ACPI_MEMORY_STA_ENABLED (0x00000002UL) +#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL) + +/* Memory Device States */ +#define MEMORY_INVALID_STATE 0 +#define MEMORY_POWER_ON_STATE 1 +#define MEMORY_POWER_OFF_STATE 2 + +static int acpi_memory_device_add (struct acpi_device *device); +static int acpi_memory_device_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_memory_device_driver = { + .name = ACPI_MEMORY_DEVICE_DRIVER_NAME, + .class = ACPI_MEMORY_DEVICE_CLASS, + .ids = ACPI_MEMORY_DEVICE_HID, + .ops = { + .add = acpi_memory_device_add, + .remove = acpi_memory_device_remove, + }, +}; + +struct acpi_memory_device { + acpi_handle handle; + unsigned int state; /* State of the memory device */ + unsigned short cache_attribute; /* memory cache attribute */ + unsigned short read_write_attribute;/* memory read/write attribute */ + u64 start_addr; /* Memory Range start physical addr */ + u64 end_addr; /* Memory Range end physical addr */ +}; + + +static int +acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) +{ + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_resource *resource = NULL; + struct acpi_resource_address64 address64; + + ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources"); + + /* Get the range from the _CRS */ + status = acpi_get_current_resources(mem_device->handle, &buffer); + if (ACPI_FAILURE(status)) + return_VALUE(-EINVAL); + + resource = (struct acpi_resource *) buffer.pointer; + status = acpi_resource_to_address64(resource, &address64); + if (ACPI_SUCCESS(status)) { + if (address64.resource_type == ACPI_MEMORY_RANGE) { + /* Populate the structure */ + mem_device->cache_attribute = + address64.attribute.memory.cache_attribute; + mem_device->read_write_attribute = + address64.attribute.memory.read_write_attribute; + mem_device->start_addr = address64.min_address_range; + mem_device->end_addr = address64.max_address_range; + } + } + + acpi_os_free(buffer.pointer); + return_VALUE(0); +} + +static int +acpi_memory_get_device(acpi_handle handle, + struct acpi_memory_device **mem_device) +{ + acpi_status status; + acpi_handle phandle; + struct acpi_device *device = NULL; + struct acpi_device *pdevice = NULL; + + ACPI_FUNCTION_TRACE("acpi_memory_get_device"); + + if (!acpi_bus_get_device(handle, &device) && device) + goto end; + + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_get_parent\n")); + return_VALUE(-EINVAL); + } + + /* Get the parent device */ + status = acpi_bus_get_device(phandle, &pdevice); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_bus_get_device\n")); + return_VALUE(-EINVAL); + } + + /* + * Now add the notified device. This creates the acpi_device + * and invokes .add function + */ + status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_bus_add\n")); + return_VALUE(-EINVAL); + } + +end: + *mem_device = acpi_driver_data(device); + if (!(*mem_device)) { + printk(KERN_ERR "\n driver data not found" ); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + +static int +acpi_memory_check_device(struct acpi_memory_device *mem_device) +{ + unsigned long current_status; + + ACPI_FUNCTION_TRACE("acpi_memory_check_device"); + + /* Get device present/absent information from the _STA */ + if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA", + NULL, ¤t_status))) + return_VALUE(-ENODEV); + /* + * Check for device status. Device should be + * present/enabled/functioning. + */ + if (!((current_status & ACPI_MEMORY_STA_PRESENT) + && (current_status & ACPI_MEMORY_STA_ENABLED) + && (current_status & ACPI_MEMORY_STA_FUNCTIONAL))) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + +static int +acpi_memory_enable_device(struct acpi_memory_device *mem_device) +{ + int result; + + ACPI_FUNCTION_TRACE("acpi_memory_enable_device"); + + /* Get the range from the _CRS */ + result = acpi_memory_get_device_resources(mem_device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "\nget_device_resources failed\n")); + mem_device->state = MEMORY_INVALID_STATE; + return result; + } + + /* + * Tell the VM there is more memory here... + * Note: Assume that this function returns zero on success + */ + result = add_memory(mem_device->start_addr, + (mem_device->end_addr - mem_device->start_addr) + 1, + mem_device->read_write_attribute); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "\nadd_memory failed\n")); + mem_device->state = MEMORY_INVALID_STATE; + return result; + } + + return result; +} + +static int +acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + unsigned long current_status; + + ACPI_FUNCTION_TRACE("acpi_memory_powerdown_device"); + + /* Issue the _EJ0 command */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + status = acpi_evaluate_object(mem_device->handle, + "_EJ0", &arg_list, NULL); + /* Return on _EJ0 failure */ + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n")); + return_VALUE(-ENODEV); + } + + /* Evalute _STA to check if the device is disabled */ + status = acpi_evaluate_integer(mem_device->handle, "_STA", + NULL, ¤t_status); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + /* Check for device status. Device should be disabled */ + if (current_status & ACPI_MEMORY_STA_ENABLED) + return_VALUE(-EINVAL); + + return_VALUE(0); +} + +static int +acpi_memory_disable_device(struct acpi_memory_device *mem_device) +{ + int result; + u64 start = mem_device->start_addr; + u64 len = mem_device->end_addr - start + 1; + unsigned long attr = mem_device->read_write_attribute; + + ACPI_FUNCTION_TRACE("acpi_memory_disable_device"); + + /* + * Ask the VM to offline this memory range. + * Note: Assume that this function returns zero on success + */ + result = remove_memory(start, len, attr); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n")); + return_VALUE(result); + } + + /* Power-off and eject the device */ + result = acpi_memory_powerdown_device(mem_device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Device Power Down failed.\n")); + /* Set the status of the device to invalid */ + mem_device->state = MEMORY_INVALID_STATE; + return result; + } + + mem_device->state = MEMORY_POWER_OFF_STATE; + return result; +} + +static void +acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_memory_device *mem_device; + struct acpi_device *device; + + ACPI_FUNCTION_TRACE("acpi_memory_device_notify"); + + switch (event) { + case ACPI_NOTIFY_BUS_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "\nReceived BUS CHECK notification for device\n")); + /* Fall Through */ + case ACPI_NOTIFY_DEVICE_CHECK: + if (event == ACPI_NOTIFY_DEVICE_CHECK) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "\nReceived DEVICE CHECK notification for device\n")); + if (acpi_memory_get_device(handle, &mem_device)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in finding driver data\n")); + return_VOID; + } + + if (!acpi_memory_check_device(mem_device)) { + if (acpi_memory_enable_device(mem_device)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_memory_enable_device\n")); + } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "\nReceived EJECT REQUEST notification for device\n")); + + if (acpi_bus_get_device(handle, &device)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Device doesn't exist\n")); + break; + } + mem_device = acpi_driver_data(device); + if (!mem_device) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Driver Data is NULL\n")); + break; + } + + /* + * Currently disabling memory device from kernel mode + * TBD: Can also be disabled from user mode scripts + * TBD: Can also be disabled by Callback registration + * with generic sysfs driver + */ + if (acpi_memory_disable_device(mem_device)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_memory_disable_device\n")); + /* + * TBD: Invoke acpi_bus_remove to cleanup data structures + */ + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + +static int +acpi_memory_device_add(struct acpi_device *device) +{ + int result; + struct acpi_memory_device *mem_device = NULL; + + ACPI_FUNCTION_TRACE("acpi_memory_device_add"); + + if (!device) + return_VALUE(-EINVAL); + + mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL); + if (!mem_device) + return_VALUE(-ENOMEM); + memset(mem_device, 0, sizeof(struct acpi_memory_device)); + + mem_device->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS); + acpi_driver_data(device) = mem_device; + + /* Get the range from the _CRS */ + result = acpi_memory_get_device_resources(mem_device); + if (result) { + kfree(mem_device); + return_VALUE(result); + } + + /* Set the device state */ + mem_device->state = MEMORY_POWER_ON_STATE; + + printk(KERN_INFO "%s \n", acpi_device_name(device)); + + return_VALUE(result); +} + +static int +acpi_memory_device_remove (struct acpi_device *device, int type) +{ + struct acpi_memory_device *mem_device = NULL; + + ACPI_FUNCTION_TRACE("acpi_memory_device_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + mem_device = (struct acpi_memory_device *) acpi_driver_data(device); + kfree(mem_device); + + return_VALUE(0); +} + +/* + * Helper function to check for memory device + */ +static acpi_status +is_memory_device(acpi_handle handle) +{ + char *hardware_id; + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_device_info *info; + + ACPI_FUNCTION_TRACE("is_memory_device"); + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(AE_ERROR); + + info = buffer.pointer; + if (!(info->valid & ACPI_VALID_HID)) { + acpi_os_free(buffer.pointer); + return_ACPI_STATUS(AE_ERROR); + } + + hardware_id = info->hardware_id.value; + if ((hardware_id == NULL) || + (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID))) + status = AE_ERROR; + + acpi_os_free(buffer.pointer); + return_ACPI_STATUS(status); +} + +static acpi_status +acpi_memory_register_notify_handler (acpi_handle handle, + u32 level, void *ctxt, void **retv) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_register_notify_handler"); + + status = is_memory_device(handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(AE_OK); /* continue */ + + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + acpi_memory_device_notify, NULL); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + return_ACPI_STATUS(AE_OK); /* continue */ + } + + return_ACPI_STATUS(status); +} + +static acpi_status +acpi_memory_deregister_notify_handler (acpi_handle handle, + u32 level, void *ctxt, void **retv) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_deregister_notify_handler"); + + status = is_memory_device(handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(AE_OK); /* continue */ + + status = acpi_remove_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + return_ACPI_STATUS(AE_OK); /* continue */ + } + + return_ACPI_STATUS(status); +} + +static int __init +acpi_memory_device_init (void) +{ + int result; + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_device_init"); + + result = acpi_bus_register_driver(&acpi_memory_device_driver); + + if (result < 0) + return_VALUE(-ENODEV); + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_memory_register_notify_handler, + NULL, NULL); + + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n")); + acpi_bus_unregister_driver(&acpi_memory_device_driver); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + +static void __exit +acpi_memory_device_exit (void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_device_exit"); + + /* + * Adding this to un-install notification handlers for all the device + * handles. + */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_memory_deregister_notify_handler, + NULL, NULL); + + if (ACPI_FAILURE (status)) + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n")); + + acpi_bus_unregister_driver(&acpi_memory_device_driver); + + return_VOID; +} + +module_init(acpi_memory_device_init); +module_exit(acpi_memory_device_exit); + + diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c --- a/drivers/acpi/asus_acpi.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/asus_acpi.c 2005-03-20 16:31:54 -08: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/battery.c b/drivers/acpi/battery.c --- a/drivers/acpi/battery.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/battery.c 2005-03-20 16:31:54 -08:00 @@ -341,7 +341,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_battery_dir; +static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_read_info(struct seq_file *seq, void *offset) { int result = 0; diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c --- a/drivers/acpi/bus.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/bus.c 2005-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 +++ b/drivers/acpi/button.c 2005-03-20 16:31:54 -08:00 @@ -275,7 +275,7 @@ Driver Interface -------------------------------------------------------------------------- */ -void +static void acpi_button_notify ( acpi_handle handle, u32 event, @@ -302,7 +302,7 @@ } -acpi_status +static acpi_status acpi_button_notify_fixed ( void *data) { diff -Nru a/drivers/acpi/container.c b/drivers/acpi/container.c --- a/drivers/acpi/container.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/container.c 2005-03-20 16:31:54 -08:00 @@ -177,13 +177,18 @@ printk("Container driver received %s event\n", (type == ACPI_NOTIFY_BUS_CHECK)? "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK"); + status = acpi_bus_get_device(handle, &device); if (present) { - status = acpi_bus_get_device(handle, &device); if (ACPI_FAILURE(status) || !device) { result = container_device_add(&device, handle); if (!result) - kobject_hotplug(&device->kobj, KOBJ_ONLINE); - } else { + kobject_hotplug(&device->kobj, + KOBJ_ONLINE); + else + printk("Failed to add container\n"); + } + } else { + if (ACPI_SUCCESS(status)) { /* device exist and this is a remove request */ kobject_hotplug(&device->kobj, KOBJ_OFFLINE); } @@ -255,7 +260,7 @@ } -int __init +static int __init acpi_container_init(void) { int result = 0; @@ -276,7 +281,7 @@ return(0); } -void __exit +static void __exit acpi_container_exit(void) { int action = UNINSTALL_NOTIFY_HANDLER; diff -Nru a/drivers/acpi/debug.c b/drivers/acpi/debug.c --- a/drivers/acpi/debug.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/debug.c 2005-03-20 16:31:54 -08:00 @@ -35,7 +35,7 @@ }; #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } -const struct acpi_dlayer acpi_debug_layers[] = +static const struct acpi_dlayer acpi_debug_layers[] = { ACPI_DEBUG_INIT(ACPI_UTILITIES), ACPI_DEBUG_INIT(ACPI_HARDWARE), @@ -53,7 +53,7 @@ ACPI_DEBUG_INIT(ACPI_TOOLS), }; -const struct acpi_dlevel acpi_debug_levels[] = +static const struct acpi_dlevel acpi_debug_levels[] = { ACPI_DEBUG_INIT(ACPI_LV_ERROR), ACPI_DEBUG_INIT(ACPI_LV_WARN), diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c --- a/drivers/acpi/dispatcher/dsmethod.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/dispatcher/dsmethod.c 2005-03-20 16:31:54 -08:00 @@ -448,7 +448,16 @@ */ walk_state->return_desc = return_desc; } - else { + + /* + * The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) { /* * Delete the return value if it will not be used by the * calling method diff -Nru a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c --- a/drivers/acpi/dispatcher/dsopcode.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/dispatcher/dsopcode.c 2005-03-20 16:31:54 -08:00 @@ -1010,6 +1010,10 @@ * has been bubbled up the tree */ if (op->common.value.arg) { + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return (walk_state); + /* Return statement has an immediate operand */ status = acpi_ds_create_operands (walk_state, op->common.value.arg); @@ -1036,6 +1040,10 @@ } else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return (walk_state); + /* * The return value has come from a previous calculation. * diff -Nru a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c --- a/drivers/acpi/dispatcher/dsutils.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/dispatcher/dsutils.c 2005-03-20 16:31:54 -08:00 @@ -54,10 +54,120 @@ ACPI_MODULE_NAME ("dsutils") +/******************************************************************************* + * + * FUNCTION: acpi_ds_clear_implicit_return + * + * PARAMETERS: walk_state - Current State + * + * RETURN: None. + * + * DESCRIPTION: Clear and remove a reference on an implicit return value. Used + * to delete "stale" return values (if enabled, the return value + * from every operator is saved at least momentarily, in case the + * parent method exits.) + * + ******************************************************************************/ + +void +acpi_ds_clear_implicit_return ( + struct acpi_walk_state *walk_state) +{ + ACPI_FUNCTION_NAME ("ds_clear_implicit_return"); + + + /* + * Slack must be enabled for this feature + */ + if (!acpi_gbl_enable_interpreter_slack) { + return; + } + + if (walk_state->implicit_return_obj) { + /* + * Delete any "stale" implicit return. However, in + * complex statements, the implicit return value can be + * bubbled up several levels. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Removing reference on stale implicit return obj %p\n", + walk_state->implicit_return_obj)); + + acpi_ut_remove_reference (walk_state->implicit_return_obj); + walk_state->implicit_return_obj = NULL; + } +} + + #ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * + * FUNCTION: acpi_ds_do_implicit_return + * + * PARAMETERS: return_desc - The return value + * walk_state - Current State + * add_reference - True if a reference should be added to the + * return object + * + * RETURN: TRUE if implicit return enabled, FALSE otherwise + * + * DESCRIPTION: Implements the optional "implicit return". We save the result + * of every ASL operator and control method invocation in case the + * parent method exit. Before storing a new return value, we + * delete the previous return value. + * + ******************************************************************************/ + +u8 +acpi_ds_do_implicit_return ( + union acpi_operand_object *return_desc, + struct acpi_walk_state *walk_state, + u8 add_reference) +{ + ACPI_FUNCTION_NAME ("ds_do_implicit_return"); + + + /* + * Slack must be enabled for this feature, and we must + * have a valid return object + */ + if ((!acpi_gbl_enable_interpreter_slack) || + (!return_desc)) { + return (FALSE); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Result %p will be implicitly returned; Prev=%p\n", + return_desc, + walk_state->implicit_return_obj)); + + /* + * Delete any "stale" implicit return value first. However, in + * complex statements, the implicit return value can be + * bubbled up several levels, so we don't clear the value if it + * is the same as the return_desc. + */ + if (walk_state->implicit_return_obj) { + if (walk_state->implicit_return_obj == return_desc) { + return (TRUE); + } + acpi_ds_clear_implicit_return (walk_state); + } + + /* Save the implicit return value, add a reference if requested */ + + walk_state->implicit_return_obj = return_desc; + if (add_reference) { + acpi_ut_add_reference (return_desc); + } + + return (TRUE); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ds_is_result_used * * PARAMETERS: Op - Current Op @@ -76,7 +186,6 @@ { const struct acpi_opcode_info *parent_info; - ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op); @@ -88,6 +197,19 @@ } /* + * We know that this operator is not a + * Return() operator (would not come here.) The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE); + + /* + * Now determine if the parent will use the result + * * If there is no parent, or the parent is a scope_op, we are executing * at the method level. An executing method typically has no parent, * since each method is parsed separately. A method invoked externally @@ -95,29 +217,10 @@ */ if ((!op->common.parent) || (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { - /* - * If this is the last statement in the method, we know it is not a - * Return() operator (would not come here.) The following code is the - * optional support for a so-called "implicit return". Some AML code - * assumes that the last value of the method is "implicitly" returned - * to the caller. Just save the last result as the return value. - * NOTE: this is optional because the ASL language does not actually - * support this behavior. - */ - if ((acpi_gbl_enable_interpreter_slack) && - (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) { - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Result of [%s] will be implicitly returned\n", - acpi_ps_get_opcode_name (op->common.aml_opcode))); - - /* Use the top of the result stack as the implicit return value */ - - walk_state->return_desc = walk_state->results->results.obj_desc[0]; - return_VALUE (TRUE); - } - /* No parent, the return value cannot possibly be used */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n", + acpi_ps_get_opcode_name (op->common.aml_opcode))); return_VALUE (FALSE); } @@ -262,9 +365,8 @@ } if (!acpi_ds_is_result_used (op, walk_state)) { - /* - * Must pop the result stack (obj_desc should be equal to result_obj) - */ + /* Must pop the result stack (obj_desc should be equal to result_obj) */ + status = acpi_ds_result_pop (&obj_desc, walk_state); if (ACPI_SUCCESS (status)) { acpi_ut_remove_reference (result_obj); @@ -338,9 +440,8 @@ ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state); - /* - * Remove a reference on each operand on the stack - */ + /* Remove a reference on each operand on the stack */ + for (i = 0; i < walk_state->num_operands; i++) { /* * Remove a reference to all operands, including both @@ -407,11 +508,7 @@ return_ACPI_STATUS (status); } - /* - * All prefixes have been handled, and the name is - * in name_string - */ - + /* All prefixes have been handled, and the name is in name_string */ /* * Special handling for buffer_field declarations. This is a deferred @@ -586,7 +683,8 @@ * * FUNCTION: acpi_ds_create_operands * - * PARAMETERS: first_arg - First argument of a parser argument tree + * PARAMETERS: walk_state - Current state + * first_arg - First argument of a parser argument tree * * RETURN: Status * diff -Nru a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c --- a/drivers/acpi/dispatcher/dswexec.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/dispatcher/dswexec.c 2005-03-20 16:31:54 -08:00 @@ -91,6 +91,7 @@ union acpi_operand_object *result_obj) { acpi_status status = AE_OK; union acpi_operand_object *obj_desc; + union acpi_operand_object *local_obj_desc = NULL; ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state); @@ -130,12 +131,17 @@ } /* - * Result of predicate evaluation currently must - * be a number + * Result of predicate evaluation must be an Integer + * object. Implicitly convert the argument if necessary. */ - if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER) { + status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Bad predicate (not a number) obj_desc=%p State=%p Type=%X\n", + "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n", obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc))); status = AE_AML_OPERAND_TYPE; @@ -144,13 +150,13 @@ /* Truncate the predicate to 32-bits if necessary */ - acpi_ex_truncate_for32bit_table (obj_desc); + acpi_ex_truncate_for32bit_table (local_obj_desc); /* * Save the result of the predicate evaluation on * the control stack */ - if (obj_desc->integer.value) { + if (local_obj_desc->integer.value) { walk_state->control_state->common.value = TRUE; } else { @@ -170,12 +176,15 @@ /* Break to debugger to display result */ - ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state)); /* * Delete the predicate result object (we know that * we don't need it anymore) */ + if (local_obj_desc != obj_desc) { + acpi_ut_remove_reference (local_obj_desc); + } acpi_ut_remove_reference (obj_desc); walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; @@ -306,9 +315,10 @@ case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: - /* most operators with arguments */ - /* Start a new result/operand state */ - + /* + * Most operators with arguments. + * Start a new result/operand state + */ status = acpi_ds_result_stack_push (walk_state); break; @@ -471,20 +481,41 @@ /* 1 Operand, 0 external_result, 0 internal_result */ status = acpi_ds_exec_end_control_op (walk_state, op); - if (ACPI_FAILURE (status)) { - break; - } - status = acpi_ds_result_stack_pop (walk_state); + /* Make sure to properly pop the result stack */ + + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_pop (walk_state); + } + else if (status == AE_CTRL_PENDING) { + status = acpi_ds_result_stack_pop (walk_state); + if (ACPI_SUCCESS (status)) { + status = AE_CTRL_PENDING; + } + } break; case AML_TYPE_METHOD_CALL: + /* + * If the method is referenced from within a package + * declaration, it is not a invocation of the method, just + * a reference to it. + */ + if ((op->asl.parent) && + ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) || + (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op)); + op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object; + acpi_ut_add_reference (op->asl.value.arg->asl.node->object); + return_ACPI_STATUS (AE_OK); + } + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op)); /* - * (AML_METHODCALL) Op->Value->Arg->Node contains + * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains * the method Node pointer */ /* next_op points to the op that holds the method name */ diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c --- a/drivers/acpi/ec.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/ec.c 2005-03-20 16:31:54 -08: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++; + (u8)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); } - - } @@ -514,7 +669,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_ec_dir; +static struct proc_dir_entry *acpi_ec_dir; static int @@ -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/events/evxface.c b/drivers/acpi/events/evxface.c --- a/drivers/acpi/events/evxface.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/events/evxface.c 2005-03-20 16:31:54 -08:00 @@ -149,7 +149,9 @@ acpi_gbl_fixed_event_handlers[event].handler = handler; acpi_gbl_fixed_event_handlers[event].context = context; - status = acpi_enable_event (event, 0); + status = acpi_clear_event (event); + if (ACPI_SUCCESS(status)) + status = acpi_enable_event (event, 0); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n")); diff -Nru a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c --- a/drivers/acpi/executer/exmisc.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/executer/exmisc.c 2005-03-20 16:31:54 -08:00 @@ -95,6 +95,7 @@ switch (obj_desc->reference.opcode) { case AML_LOCAL_OP: case AML_ARG_OP: + case AML_DEBUG_OP: /* The referenced object is the pseudo-node for the local/arg */ @@ -103,7 +104,7 @@ default: - ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n", + ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -121,7 +122,7 @@ default: - ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n", + ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); return_ACPI_STATUS (AE_TYPE); } diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c --- a/drivers/acpi/executer/exoparg2.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/executer/exoparg2.c 2005-03-20 16:31:54 -08:00 @@ -442,6 +442,12 @@ return_desc->reference.object = operand[0]; } + /* + * Add a reference to the target package/buffer/string for the life + * of the index. + */ + acpi_ut_add_reference (operand[0]); + /* Complete the Index reference object */ return_desc->reference.opcode = AML_INDEX_OP; diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c --- a/drivers/acpi/executer/exresolv.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/executer/exresolv.c 2005-03-20 16:31:54 -08:00 @@ -422,6 +422,12 @@ * This could of course in turn be another reference object. */ obj_desc = *(obj_desc->reference.where); + if (!obj_desc) { + /* NULL package elements are allowed */ + + type = 0; /* Uninitialized */ + goto exit; + } break; diff -Nru a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c --- a/drivers/acpi/executer/exstoren.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/executer/exstoren.c 2005-03-20 16:31:54 -08:00 @@ -206,7 +206,6 @@ { union acpi_operand_object *actual_src_desc; acpi_status status = AE_OK; - acpi_object_type original_src_type; ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc); @@ -223,8 +222,7 @@ return_ACPI_STATUS (status); } - original_src_type = ACPI_GET_OBJECT_TYPE (source_desc); - if (original_src_type != ACPI_GET_OBJECT_TYPE (dest_desc)) { + if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) { /* * The source type does not match the type of the destination. * Perform the "implicit conversion" of the source to the current type @@ -275,8 +273,7 @@ * Note: There is different store behavior depending on the original * source type */ - status = acpi_ex_store_buffer_to_buffer (original_src_type, actual_src_desc, - dest_desc); + status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc); break; case ACPI_TYPE_PACKAGE: diff -Nru a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c --- a/drivers/acpi/executer/exstorob.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/executer/exstorob.c 2005-03-20 16:31:54 -08:00 @@ -66,7 +66,6 @@ acpi_status acpi_ex_store_buffer_to_buffer ( - acpi_object_type original_src_type, union acpi_operand_object *source_desc, union acpi_operand_object *target_desc) { @@ -77,9 +76,8 @@ ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc); - /* - * We know that source_desc is a buffer by now - */ + /* We know that source_desc is a buffer by now */ + buffer = (u8 *) source_desc->buffer.pointer; length = source_desc->buffer.length; @@ -105,7 +103,17 @@ ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length); ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length); +#ifdef ACPI_OBSOLETE_BEHAVIOR + /* + * NOTE: ACPI versions up to 3.0 specified that the buffer must be + * truncated if the string is smaller than the buffer. However, "other" + * implementations of ACPI never did this and thus became the defacto + * standard. ACPi 3.0_a changes this behavior such that the buffer + * is no longer truncated. + */ + /* + * OBSOLETE BEHAVIOR: * If the original source was a string, we must truncate the buffer, * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer * copy must not truncate the original buffer. @@ -115,6 +123,7 @@ target_desc->buffer.length = length; } +#endif } else { /* Truncate the source, copy only what will fit */ @@ -159,9 +168,8 @@ ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc); - /* - * We know that source_desc is a string by now. - */ + /* We know that source_desc is a string by now */ + buffer = (u8 *) source_desc->string.pointer; length = source_desc->string.length; @@ -185,9 +193,8 @@ */ if (target_desc->string.pointer && (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - /* - * Only free if not a pointer into the DSDT - */ + /* Only free if not a pointer into the DSDT */ + ACPI_MEM_FREE (target_desc->string.pointer); } diff -Nru a/drivers/acpi/fan.c b/drivers/acpi/fan.c --- a/drivers/acpi/fan.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/fan.c 2005-03-20 16:31:54 -08:00 @@ -50,8 +50,8 @@ MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); MODULE_LICENSE("GPL"); -int acpi_fan_add (struct acpi_device *device); -int acpi_fan_remove (struct acpi_device *device, int type); +static int acpi_fan_add (struct acpi_device *device); +static int acpi_fan_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_fan_driver = { .name = ACPI_FAN_DRIVER_NAME, @@ -72,27 +72,24 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_fan_dir; +static struct proc_dir_entry *acpi_fan_dir; static int acpi_fan_read_state (struct seq_file *seq, void *offset) { - struct acpi_fan *fan = (struct acpi_fan *) seq->private; + struct acpi_fan *fan = seq->private; int state = 0; ACPI_FUNCTION_TRACE("acpi_fan_read_state"); - if (!fan) - goto end; - - if (acpi_bus_get_power(fan->handle, &state)) - goto end; - - seq_printf(seq, "status: %s\n", - !state?"on":"off"); - -end: + if (fan) { + if (acpi_bus_get_power(fan->handle, &state)) + seq_printf(seq, "status: ERROR\n"); + else + seq_printf(seq, "status: %s\n", + !state?"on":"off"); + } return_VALUE(0); } @@ -197,7 +194,7 @@ Driver Interface -------------------------------------------------------------------------- */ -int +static int acpi_fan_add ( struct acpi_device *device) { @@ -243,7 +240,7 @@ } -int +static int acpi_fan_remove ( struct acpi_device *device, int type) @@ -265,7 +262,7 @@ } -int __init +static int __init acpi_fan_init (void) { int result = 0; @@ -287,7 +284,7 @@ } -void __exit +static void __exit acpi_fan_exit (void) { ACPI_FUNCTION_TRACE("acpi_fan_exit"); 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-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 @@ -0,0 +1,1018 @@ +/* + * 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; + + ACPI_FUNCTION_TRACE("create_polling_proc"); + mode_t 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-03-20 16:31:54 -08:00 +++ b/drivers/acpi/ibm_acpi.c 2005-03-20 16:31:54 -08:00 @@ -155,7 +155,7 @@ int experimental; }; -struct proc_dir_entry *proc_dir = NULL; +static struct proc_dir_entry *proc_dir = NULL; #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -856,7 +856,7 @@ return 0; } -struct ibm_struct ibms[] = { +static struct ibm_struct ibms[] = { { .name = "driver", .init = driver_init, @@ -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/numa.c b/drivers/acpi/numa.c --- a/drivers/acpi/numa.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/numa.c 2005-03-20 16:31:54 -08:00 @@ -170,7 +170,7 @@ int __init -acpi_numa_init() +acpi_numa_init(void) { int result; diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/osl.c 2005-03-20 16:31:54 -08: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; @@ -563,7 +566,7 @@ } /* TODO: Change code to take advantage of driver model more */ -void +static void acpi_os_derive_pci_id_2 ( acpi_handle rhandle, /* upper bound */ acpi_handle chandle, /* current node */ @@ -1071,7 +1074,7 @@ } EXPORT_SYMBOL(acpi_os_signal); -int __init +static int __init acpi_os_name_setup(char *str) { char *p = acpi_os_name; @@ -1101,7 +1104,7 @@ * empty string disables _OSI * TBD additional string adds to _OSI */ -int __init +static int __init acpi_osi_setup(char *str) { if (str == NULL || *str == '\0') { @@ -1119,7 +1122,7 @@ __setup("acpi_osi=", acpi_osi_setup); /* enable serialization to combat AE_ALREADY_EXISTS errors */ -int __init +static int __init acpi_serialize_setup(char *str) { printk(KERN_INFO PREFIX "serialize enabled\n"); @@ -1140,7 +1143,7 @@ * Run-time events on the same GPE this flag is available * to tell Linux to keep the wake-time GPEs enabled at run-time. */ -int __init +static int __init acpi_wake_gpes_always_on_setup(char *str) { printk(KERN_INFO PREFIX "wake GPEs not disabled\n"); @@ -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/parser/psopcode.c b/drivers/acpi/parser/psopcode.c --- a/drivers/acpi/parser/psopcode.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/parser/psopcode.c 2005-03-20 16:31:54 -08:00 @@ -522,7 +522,7 @@ /* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), /* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), /* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), -/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), /* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), /* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), diff -Nru a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c --- a/drivers/acpi/parser/psparse.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/parser/psparse.c 2005-03-20 16:31:54 -08:00 @@ -1187,8 +1187,8 @@ previous_walk_state = walk_state; - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, State=%p\n", - walk_state->return_desc, walk_state)); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, implicit_value=%p State=%p\n", + walk_state->return_desc, walk_state->implicit_return_obj, walk_state)); /* Check if we have restarted a preempted walk */ @@ -1200,8 +1200,20 @@ * If the method return value is not used by the parent, * The object is deleted */ - status = acpi_ds_restart_control_method (walk_state, - previous_walk_state->return_desc); + if (!previous_walk_state->return_desc) { + status = acpi_ds_restart_control_method (walk_state, + previous_walk_state->implicit_return_obj); + } + else { + /* + * We have a valid return value, delete any implicit + * return value. + */ + acpi_ds_clear_implicit_return (previous_walk_state); + + status = acpi_ds_restart_control_method (walk_state, + previous_walk_state->return_desc); + } if (ACPI_SUCCESS (status)) { walk_state->walk_type |= ACPI_WALK_METHOD_RESTART; } @@ -1218,12 +1230,26 @@ * value (if any) */ else if (previous_walk_state->caller_return_desc) { - *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; /* NULL if no return value */ + if (previous_walk_state->implicit_return_obj) { + *(previous_walk_state->caller_return_desc) = previous_walk_state->implicit_return_obj; + } + else { + /* NULL if no return value */ + + *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; + } } - else if (previous_walk_state->return_desc) { - /* Caller doesn't want it, must delete it */ + else { + if (previous_walk_state->return_desc) { + /* Caller doesn't want it, must delete it */ - acpi_ut_remove_reference (previous_walk_state->return_desc); + acpi_ut_remove_reference (previous_walk_state->return_desc); + } + if (previous_walk_state->implicit_return_obj) { + /* Caller doesn't want it, must delete it */ + + acpi_ut_remove_reference (previous_walk_state->implicit_return_obj); + } } acpi_ds_delete_walk_state (previous_walk_state); diff -Nru a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c --- a/drivers/acpi/parser/pswalk.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/parser/pswalk.c 2005-03-20 16:31:54 -08:00 @@ -44,7 +44,6 @@ #include #include -#include #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("pswalk") @@ -52,256 +51,65 @@ /******************************************************************************* * - * FUNCTION: acpi_ps_get_next_walk_op + * FUNCTION: acpi_ps_delete_parse_tree * - * PARAMETERS: walk_state - Current state of the walk - * Op - Current Op to be walked - * ascending_callback - Procedure called when Op is complete + * PARAMETERS: subtree_root - Root of tree (or subtree) to delete * - * RETURN: Status + * RETURN: None * - * DESCRIPTION: Get the next Op in a walk of the parse tree. + * DESCRIPTION: Delete a portion of or an entire parse tree. * ******************************************************************************/ -acpi_status -acpi_ps_get_next_walk_op ( - struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - acpi_parse_upwards ascending_callback) +void +acpi_ps_delete_parse_tree ( + union acpi_parse_object *subtree_root) { - union acpi_parse_object *next; - union acpi_parse_object *parent; - union acpi_parse_object *grand_parent; - acpi_status status; + union acpi_parse_object *op = subtree_root; + union acpi_parse_object *next = NULL; + union acpi_parse_object *parent = NULL; - ACPI_FUNCTION_TRACE_PTR ("ps_get_next_walk_op", op); + ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root); - /* Check for a argument only if we are descending in the tree */ + /* Visit all nodes in the subtree */ - if (walk_state->next_op_info != ACPI_NEXT_OP_UPWARD) { - /* Look for an argument or child of the current op */ + while (op) { + /* Check if we are not ascending */ - next = acpi_ps_get_arg (op, 0); - if (next) { - /* Still going downward in tree (Op is not completed yet) */ + if (op != parent) { + /* Look for an argument or child of the current op */ - walk_state->prev_op = op; - walk_state->next_op = next; - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; + next = acpi_ps_get_arg (op, 0); + if (next) { + /* Still going downward in tree (Op is not completed yet) */ - return_ACPI_STATUS (AE_OK); + op = next; + continue; + } } /* - * No more children, this Op is complete. Save Next and Parent - * in case the Op object gets deleted by the callback routine + * No more children, this Op is complete. */ - next = op->common.next; - parent = op->common.parent; + next = op->common.next; + parent = op->common.parent; - walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = ascending_callback (walk_state); + acpi_ps_free_op (op); /* * If we are back to the starting point, the walk is complete. */ - if (op == walk_state->origin) { - /* Reached the point of origin, the walk is complete */ - - walk_state->prev_op = op; - walk_state->next_op = NULL; - - return_ACPI_STATUS (status); + if (op == subtree_root) { + return_VOID; } - - /* - * Check for a sibling to the current op. A sibling means - * we are still going "downward" in the tree. - */ if (next) { - /* There is a sibling, it will be next */ - - walk_state->prev_op = op; - walk_state->next_op = next; - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; - - /* Continue downward */ - - return_ACPI_STATUS (status); - } - - /* - * Drop into the loop below because we are moving upwards in - * the tree - */ - } - else { - /* - * We are resuming a walk, and we were (are) going upward in the tree. - * So, we want to drop into the parent loop below. - */ - parent = op; - } - - /* - * Look for a sibling of the current Op's parent - * Continue moving up the tree until we find a node that has not been - * visited, or we get back to where we started. - */ - while (parent) { - /* We are moving up the tree, therefore this parent Op is complete */ - - grand_parent = parent->common.parent; - next = parent->common.next; - - walk_state->op = parent; - walk_state->op_info = acpi_ps_get_opcode_info (parent->common.aml_opcode); - walk_state->opcode = parent->common.aml_opcode; - - status = ascending_callback (walk_state); - - /* - * If we are back to the starting point, the walk is complete. - */ - if (parent == walk_state->origin) { - /* Reached the point of origin, the walk is complete */ - - walk_state->prev_op = parent; - walk_state->next_op = NULL; - - return_ACPI_STATUS (status); + op = next; } - - /* - * If there is a sibling to this parent (it is not the starting point - * Op), then we will visit it. - */ - if (next) { - /* found sibling of parent */ - - walk_state->prev_op = parent; - walk_state->next_op = next; - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; - - return_ACPI_STATUS (status); + else { + op = parent; } - - /* No siblings, no errors, just move up one more level in the tree */ - - op = parent; - parent = grand_parent; - walk_state->prev_op = op; } - - - /* - * Got all the way to the top of the tree, we must be done! - * However, the code should have terminated in the loop above - */ - walk_state->next_op = NULL; - - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ps_delete_completed_op - * - * PARAMETERS: State - Walk state - * Op - Completed op - * - * RETURN: AE_OK - * - * DESCRIPTION: Callback function for acpi_ps_get_next_walk_op(). Used during - * acpi_ps_delete_parse tree to delete Op objects when all sub-objects - * have been visited (and deleted.) - * - ******************************************************************************/ - -acpi_status -acpi_ps_delete_completed_op ( - struct acpi_walk_state *walk_state) -{ - - acpi_ps_free_op (walk_state->op); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ps_delete_parse_tree - * - * PARAMETERS: subtree_root - Root of tree (or subtree) to delete - * - * RETURN: None - * - * DESCRIPTION: Delete a portion of or an entire parse tree. - * - ******************************************************************************/ - -void -acpi_ps_delete_parse_tree ( - union acpi_parse_object *subtree_root) -{ - struct acpi_walk_state *walk_state; - struct acpi_thread_state *thread; - acpi_status status; - - - ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root); - - - if (!subtree_root) { - return_VOID; - } - - /* Create and initialize a new walk list */ - - thread = acpi_ut_create_thread_state (); - if (!thread) { - return_VOID; - } - - walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread); - if (!walk_state) { - return_VOID; - } - - walk_state->parse_flags = 0; - walk_state->descending_callback = NULL; - walk_state->ascending_callback = NULL; - - walk_state->origin = subtree_root; - walk_state->next_op = subtree_root; - - /* Head downward in the tree */ - - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; - - /* Visit all nodes in the subtree */ - - while (walk_state->next_op) { - status = acpi_ps_get_next_walk_op (walk_state, walk_state->next_op, - acpi_ps_delete_completed_op); - if (ACPI_FAILURE (status)) { - break; - } - } - - /* We are done with this walk */ - - acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread)); - acpi_ds_delete_walk_state (walk_state); - return_VOID; } - - diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c --- a/drivers/acpi/pci_irq.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/pci_irq.c 2005-03-20 16:31:54 -08:00 @@ -42,8 +42,8 @@ #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME ("pci_irq") -struct acpi_prt_list acpi_prt; -DEFINE_SPINLOCK(acpi_prt_lock); +static struct acpi_prt_list acpi_prt; +static DEFINE_SPINLOCK(acpi_prt_lock); /* -------------------------------------------------------------------------- PCI IRQ Routing Table (PRT) Support @@ -281,7 +281,8 @@ int device, int pin, int *edge_level, - int *active_high_low) + int *active_high_low, + char **link) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); @@ -301,7 +302,8 @@ } if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low); + irq = acpi_pci_link_get_irq(entry->link.handle, + entry->link.index, edge_level, active_high_low, link); if (irq < 0) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); return_VALUE(-1); @@ -327,7 +329,8 @@ struct pci_dev *dev, int pin, int *edge_level, - int *active_high_low) + int *active_high_low, + char **link) { struct pci_dev *bridge = dev; int irq = -1; @@ -360,7 +363,7 @@ } irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), - pin, edge_level, active_high_low); + pin, edge_level, active_high_low, link); } if (irq < 0) { @@ -389,6 +392,7 @@ 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"); @@ -411,21 +415,23 @@ * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low); + irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, + &edge_level, &active_high_low, &link); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (irq < 0) - irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low); + irq = acpi_pci_irq_derive(dev, pin, &edge_level, + &active_high_low, &link); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. */ if (irq < 0) { - printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI", + printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI", pci_name(dev), ('A' + pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq >= 0 && (dev->irq <= 0xF)) { @@ -443,9 +449,13 @@ dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); - printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u " - "(%s, %s) -> IRQ %d\n", - pci_name(dev), 'A' + pin, irq, + printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", + pci_name(dev), 'A' + pin); + + if (link) + printk("Link [%s] -> ", link); + + printk("GSI %u (%s, %s) -> IRQ %d\n", irq, (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); @@ -482,14 +492,14 @@ * First we check the PCI IRQ routing table (PRT) for an IRQ. */ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low); + &edge_level, &active_high_low, NULL); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (gsi < 0) gsi = acpi_pci_irq_derive(dev, pin, - &edge_level, &active_high_low); + &edge_level, &active_high_low, NULL); if (gsi < 0) return_VOID; diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- a/drivers/acpi/pci_link.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/pci_link.c 2005-03-20 16:31:54 -08: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 { @@ -522,12 +524,18 @@ static int acpi_irq_balance; /* 0: static, 1: balance */ -static int acpi_pci_link_allocate(struct acpi_pci_link* link) { - int irq; - int i; +static int acpi_pci_link_allocate( + struct acpi_pci_link *link) +{ + int irq; + int i; 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); @@ -597,8 +605,9 @@ acpi_pci_link_get_irq ( acpi_handle handle, int index, - int* edge_level, - int* active_high_low) + int *edge_level, + int *active_high_low, + char **name) { int result = 0; struct acpi_device *device = NULL; @@ -634,6 +643,7 @@ if (edge_level) *edge_level = link->irq.edge_level; if (active_high_low) *active_high_low = link->irq.active_high_low; + if (name) *name = acpi_device_bid(link->device); return_VALUE(link->irq.active); } @@ -709,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); } @@ -852,7 +848,7 @@ static struct sysdev_class irqrouter_sysdev_class = { set_kset_name("irqrouter"), - .resume = irqrouter_resume, + .suspend = irqrouter_suspend, }; diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c --- a/drivers/acpi/pci_root.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/pci_root.c 2005-03-20 16:31:54 -08:00 @@ -258,7 +258,7 @@ /* TBD: Locking */ list_add_tail(&root->node, &acpi_pci_roots); - printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n", + printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", acpi_device_name(device), acpi_device_bid(device), root->id.segment, root->id.bus); @@ -272,7 +272,7 @@ root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus); if (!root->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Bus %02x:%02x not present in PCI namespace\n", + "Bus %04x:%02x not present in PCI namespace\n", root->id.segment, root->id.bus)); result = -ENODEV; goto end; diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c --- a/drivers/acpi/power.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/power.c 2005-03-20 16:31:54 -08:00 @@ -58,8 +58,8 @@ #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -int acpi_power_add (struct acpi_device *device); -int acpi_power_remove (struct acpi_device *device, int type); +static int acpi_power_add (struct acpi_device *device); +static int acpi_power_remove (struct acpi_device *device, int type); static int acpi_power_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_power_driver = { @@ -479,7 +479,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_power_dir; +static struct proc_dir_entry *acpi_power_dir; static int acpi_power_seq_show(struct seq_file *seq, void *offset) { @@ -576,7 +576,7 @@ Driver Interface -------------------------------------------------------------------------- */ -int +static int acpi_power_add ( struct acpi_device *device) { @@ -642,7 +642,7 @@ } -int +static int acpi_power_remove ( struct acpi_device *device, int type) diff -Nru a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c --- a/drivers/acpi/processor_core.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/processor_core.c 2005-03-20 16:31:54 -08:00 @@ -105,7 +105,7 @@ #define UNINSTALL_NOTIFY_HANDLER 2 -struct file_operations acpi_processor_info_fops = { +static struct file_operations acpi_processor_info_fops = { .open = acpi_processor_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -121,7 +121,7 @@ Errata Handling -------------------------------------------------------------------------- */ -int +static int acpi_processor_errata_piix4 ( struct pci_dev *dev) { @@ -259,7 +259,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_processor_dir = NULL; +static struct proc_dir_entry *acpi_processor_dir = NULL; static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) { diff -Nru a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c --- a/drivers/acpi/processor_thermal.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/processor_thermal.c 2005-03-20 16:31:54 -08:00 @@ -345,7 +345,7 @@ return_VALUE(0); } -int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) +static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_processor_limit_seq_show, PDE(inode)->data); diff -Nru a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c --- a/drivers/acpi/processor_throttling.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/processor_throttling.c 2005-03-20 16:31:54 -08:00 @@ -308,7 +308,7 @@ return_VALUE(0); } -int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file) +static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_processor_throttling_seq_show, PDE(inode)->data); diff -Nru a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c --- a/drivers/acpi/resources/rsaddr.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/resources/rsaddr.c 2005-03-20 16:31:54 -08:00 @@ -110,13 +110,13 @@ buffer += 2; temp8 = *buffer; - /* Values 0-2 are valid */ + /* Values 0-2 and 0xC0-0xFF are valid */ - if (temp8 > 2) { + if ((temp8 > 2) && (temp8 < 0xC0)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } - output_struct->data.address16.resource_type = temp8 & 0x03; + output_struct->data.address16.resource_type = temp8; /* * Get the General Flags (Byte4) @@ -496,12 +496,13 @@ buffer += 2; temp8 = *buffer; - /* Values 0-2 are valid */ - if(temp8 > 2) { + /* Values 0-2 and 0xC0-0xFF are valid */ + + if ((temp8 > 2) && (temp8 < 0xC0)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } - output_struct->data.address32.resource_type = temp8 & 0x03; + output_struct->data.address32.resource_type = temp8; /* * Get the General Flags (Byte4) @@ -850,6 +851,7 @@ struct acpi_resource *output_struct = (void *) *output_buffer; u16 temp16; u8 temp8; + u8 resource_type; u8 *temp_ptr; acpi_size struct_size; u32 index; @@ -860,6 +862,7 @@ buffer = byte_stream_buffer; struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); + resource_type = *buffer; /* * Point past the Descriptor to get the number of bytes consumed @@ -882,13 +885,13 @@ buffer += 2; temp8 = *buffer; - /* Values 0-2 are valid */ + /* Values 0-2 and 0xC0-0xFF are valid */ - if(temp8 > 2) { + if ((temp8 > 2) && (temp8 < 0xC0)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } - output_struct->data.address64.resource_type = temp8 & 0x03; + output_struct->data.address64.resource_type = temp8; /* * Get the General Flags (Byte4) @@ -942,98 +945,113 @@ } } + if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { + /* Move past revision_id and Reserved byte */ + + buffer += 2; + } + /* - * Get Granularity (Bytes 6-13) + * Get Granularity (Bytes 6-13) or (Bytes 8-15) */ buffer += 1; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer); /* - * Get min_address_range (Bytes 14-21) + * Get min_address_range (Bytes 14-21) or (Bytes 16-23) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer); /* - * Get max_address_range (Bytes 22-29) + * Get max_address_range (Bytes 22-29) or (Bytes 24-31) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer); /* - * Get address_translation_offset (Bytes 30-37) + * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer); /* - * Get address_length (Bytes 38-45) + * Get address_length (Bytes 38-45) or (Bytes 40-47) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer); - /* - * Resource Source Index (if present) - */ - buffer += 8; + output_struct->data.address64.resource_source.index = 0x00; + output_struct->data.address64.resource_source.string_length = 0; + output_struct->data.address64.resource_source.string_ptr = NULL; - /* - * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the length. - */ - if (*bytes_consumed > (46 + 1)) { - /* Dereference the Index */ + if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { + /* Get type_specific_attribute (Bytes 48-55) */ - temp8 = *buffer; - output_struct->data.address64.resource_source.index = - (u32) temp8; + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer); + } + else { + output_struct->data.address64.type_specific_attributes = 0; - /* Point to the String */ + /* + * Resource Source Index (if present) + */ + buffer += 8; - buffer += 1; + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. + */ + if (*bytes_consumed > (46 + 1)) { + /* Dereference the Index */ - /* Point the String pointer to the end of this structure */ + temp8 = *buffer; + output_struct->data.address64.resource_source.index = + (u32) temp8; - output_struct->data.address64.resource_source.string_ptr = - (char *)((u8 *)output_struct + struct_size); + /* Point to the String */ - temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; + buffer += 1; - /* Copy the string into the buffer */ + /* Point the String pointer to the end of this structure */ - index = 0; - while (0x00 != *buffer) { - *temp_ptr = *buffer; + output_struct->data.address64.resource_source.string_ptr = + (char *)((u8 *)output_struct + struct_size); - temp_ptr += 1; - buffer += 1; - index += 1; - } + temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; - /* - * Add the terminating null - */ - *temp_ptr = 0x00; - output_struct->data.address64.resource_source.string_length = index + 1; + /* Copy the string into the buffer */ - /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. - */ - temp8 = (u8) (index + 1); - struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); - } - else { - output_struct->data.address64.resource_source.index = 0x00; - output_struct->data.address64.resource_source.string_length = 0; - output_struct->data.address64.resource_source.string_ptr = NULL; + index = 0; + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + output_struct->data.address64.resource_source.string_length = index + 1; + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); + } } /* diff -Nru a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c --- a/drivers/acpi/resources/rscalc.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/resources/rscalc.c 2005-03-20 16:31:54 -08:00 @@ -376,6 +376,20 @@ break; + case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); + break; + + case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: /* * 64-Bit Address Resource diff -Nru a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c --- a/drivers/acpi/resources/rsdump.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/resources/rsdump.c 2005-03-20 16:31:54 -08:00 @@ -571,7 +571,7 @@ break; } - acpi_os_printf (" Type Specific: %s Translation\n", + acpi_os_printf (" Type Specific: %s Translation\n", ACPI_SPARSE_TRANSLATION == address16_data->attribute.io.translation_attribute ? "Sparse" : "Dense"); @@ -584,8 +584,8 @@ default: - acpi_os_printf ("Invalid resource type. Exiting.\n"); - return; + acpi_os_printf ("0x%2.2X\n", address16_data->resource_type); + break; } acpi_os_printf (" Resource %s\n", @@ -718,7 +718,7 @@ break; } - acpi_os_printf (" Type Specific: %s Translation\n", + acpi_os_printf (" Type Specific: %s Translation\n", ACPI_SPARSE_TRANSLATION == address32_data->attribute.io.translation_attribute ? "Sparse" : "Dense"); @@ -731,8 +731,8 @@ default: - acpi_os_printf (" Invalid Resource Type..exiting.\n"); - return; + acpi_os_printf (" Resource Type: 0x%2.2X\n", address32_data->resource_type); + break; } acpi_os_printf (" Resource %s\n", @@ -865,7 +865,7 @@ break; } - acpi_os_printf (" Type Specific: %s Translation\n", + acpi_os_printf (" Type Specific: %s Translation\n", ACPI_SPARSE_TRANSLATION == address64_data->attribute.io.translation_attribute ? "Sparse" : "Dense"); @@ -878,8 +878,8 @@ default: - acpi_os_printf (" Invalid Resource Type..exiting.\n"); - return; + acpi_os_printf (" Resource Type: 0x%2.2X\n", address64_data->resource_type); + break; } acpi_os_printf (" Resource %s\n", @@ -913,7 +913,10 @@ acpi_os_printf (" Address Length: %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (address64_data->address_length)); - if(0xFF != address64_data->resource_source.index) { + acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes)); + + if (0xFF != address64_data->resource_source.index) { acpi_os_printf (" Resource Source Index: %X\n", address64_data->resource_source.index); acpi_os_printf (" Resource Source: %s\n", diff -Nru a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c --- a/drivers/acpi/resources/rslist.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/resources/rslist.c 2005-03-20 16:31:54 -08:00 @@ -178,6 +178,7 @@ case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: + case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: /* * 64-Bit Address Resource */ diff -Nru a/drivers/acpi/scan.c b/drivers/acpi/scan.c --- a/drivers/acpi/scan.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/scan.c 2005-03-20 16:31:54 -08:00 @@ -27,6 +27,10 @@ DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); +static int +acpi_bus_trim(struct acpi_device *start, + int rmdevice); + static void acpi_device_release(struct kobject * kobj) { struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj); @@ -81,12 +85,37 @@ .release = acpi_device_release, }; +static int namespace_hotplug(struct kset *kset, struct kobject *kobj, + char **envp, int num_envp, char *buffer, + int buffer_size) +{ + struct acpi_device *dev = to_acpi_device(kobj); + int i = 0; + int len = 0; + + if (!dev->driver) + return 0; + + if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, + "PHYSDEVDRIVER=%s", dev->driver->name)) + return -ENOMEM; + + envp[i] = NULL; + + return 0; +} + +static struct kset_hotplug_ops namespace_hotplug_ops = { + .hotplug = &namespace_hotplug, +}; + static struct kset acpi_namespace_kset = { .kobj = { .name = "namespace", }, .subsys = &acpi_subsys, .ktype = &ktype_acpi_ns, + .hotplug_ops = &namespace_hotplug_ops, }; @@ -358,7 +387,15 @@ struct acpi_device *dev, acpi_device_sysfs_files *func) { - if (dev->flags.ejectable == 1) + acpi_status status; + acpi_handle temp = NULL; + + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. + */ + status = acpi_get_handle(dev->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) (*(func))(&dev->kobj,&acpi_device_attr_eject.attr); } @@ -857,7 +894,7 @@ acpi_os_free(buffer.pointer); } -int acpi_device_set_context(struct acpi_device * device, int type) +static int acpi_device_set_context(struct acpi_device * device, int type) { acpi_status status = AE_OK; int result = 0; @@ -882,7 +919,7 @@ return result; } -void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type) +static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type) { #ifdef CONFIG_ACPI_DEBUG_OUTPUT char *type_string = NULL; @@ -925,7 +962,7 @@ } -int +static int acpi_bus_remove ( struct acpi_device *dev, int rmdevice) @@ -1223,7 +1260,7 @@ EXPORT_SYMBOL(acpi_bus_scan); -int +static int acpi_bus_trim(struct acpi_device *start, int rmdevice) { diff -Nru a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c --- a/drivers/acpi/sleep/main.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/sleep/main.c 2005-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 +++ b/drivers/acpi/sleep/poweroff.c 2005-03-20 16:31:54 -08: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/thermal.c b/drivers/acpi/thermal.c --- a/drivers/acpi/thermal.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/thermal.c 2005-03-20 16:31:54 -08:00 @@ -774,7 +774,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_thermal_dir; +static struct proc_dir_entry *acpi_thermal_dir; static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) { diff -Nru a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c --- a/drivers/acpi/toshiba_acpi.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/toshiba_acpi.c 2005-03-20 16:31:54 -08:00 @@ -481,7 +481,7 @@ #define PROC_TOSHIBA "toshiba" -ProcItem proc_items[] = +static ProcItem proc_items[] = { { "lcd" , read_lcd , write_lcd }, { "video" , read_video , write_video }, @@ -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/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c --- a/drivers/acpi/utilities/utcopy.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/utilities/utcopy.c 2005-03-20 16:31:54 -08:00 @@ -659,15 +659,17 @@ /* Create an actual buffer only if length > 0 */ if (source_desc->buffer.length) { - dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); + dest_desc->buffer.pointer = + ACPI_MEM_ALLOCATE (source_desc->buffer.length); if (!dest_desc->buffer.pointer) { return (AE_NO_MEMORY); } /* Copy the actual buffer data */ - ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, - source_desc->buffer.length); + ACPI_MEMCPY (dest_desc->buffer.pointer, + source_desc->buffer.pointer, + source_desc->buffer.length); } } break; @@ -682,7 +684,8 @@ */ if ((source_desc->string.pointer) && (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - dest_desc->string.pointer = ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1); + dest_desc->string.pointer = + ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1); if (!dest_desc->string.pointer) { return (AE_NO_MEMORY); } @@ -690,6 +693,14 @@ ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer, (acpi_size) source_desc->string.length + 1); } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * We copied the reference object, so we now must add a reference + * to the object pointed to by the reference + */ + acpi_ut_add_reference (source_desc->reference.object); break; default: diff -Nru a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c --- a/drivers/acpi/utilities/utdelete.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/utilities/utdelete.c 2005-03-20 16:31:54 -08:00 @@ -46,6 +46,7 @@ #include #include #include +#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utdelete") @@ -562,8 +563,23 @@ break; - case ACPI_TYPE_REGION: case ACPI_TYPE_LOCAL_REFERENCE: + + /* + * The target of an Index (a package, string, or buffer) must track + * changes to the ref count of the index. + */ + if (object->reference.opcode == AML_INDEX_OP) { + status = acpi_ut_create_update_state_and_push ( + object->reference.object, action, &state_list); + if (ACPI_FAILURE (status)) { + goto error_exit; + } + } + break; + + + case ACPI_TYPE_REGION: default: /* No subobjects */ diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/utilities/utglobal.c 2005-03-20 16:31:54 -08:00 @@ -194,6 +194,8 @@ */ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { + /* Operating System Vendor Strings */ + "Linux", "Windows 2000", "Windows 2001", @@ -202,7 +204,11 @@ "Windows 2001 SP1", "Windows 2001 SP2", "Windows 2001 SP3", - "Windows 2001 SP4" + "Windows 2001 SP4", + + /* Feature Group Strings */ + + "Extended Address Space Descriptor" }; @@ -355,6 +361,7 @@ /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS}, /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS}, /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS}, + /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS}, /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE}, /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, @@ -362,6 +369,7 @@ /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE}, /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0}, + /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE}, /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD}, diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c --- a/drivers/acpi/utilities/utmisc.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/utilities/utmisc.c 2005-03-20 16:31:54 -08:00 @@ -372,7 +372,7 @@ u32 base, acpi_integer *ret_integer) { - u32 this_digit; + u32 this_digit = 0; acpi_integer return_value = 0; acpi_integer quotient; @@ -380,6 +380,10 @@ ACPI_FUNCTION_TRACE ("ut_stroul64"); + if ((!string) || !(*string)) { + goto error_exit; + } + switch (base) { case ACPI_ANY_BASE: case 10: @@ -394,7 +398,7 @@ /* Skip over any white space in the buffer */ while (ACPI_IS_SPACE (*string) || *string == '\t') { - ++string; + string++; } /* @@ -403,9 +407,9 @@ */ if (base == 0) { if ((*string == '0') && - (ACPI_TOLOWER (*(++string)) == 'x')) { + (ACPI_TOLOWER (*(string + 1)) == 'x')) { base = 16; - ++string; + string += 2; } else { base = 10; @@ -416,10 +420,10 @@ * For hexadecimal base, skip over the leading * 0 or 0x, if they are present. */ - if (base == 16 && - *string == '0' && - ACPI_TOLOWER (*(++string)) == 'x') { - string++; + if ((base == 16) && + (*string == '0') && + (ACPI_TOLOWER (*(string + 1)) == 'x')) { + string += 2; } /* Any string left? */ @@ -437,23 +441,27 @@ this_digit = ((u8) *string) - '0'; } else { + if (base == 10) { + /* Digit is out of range */ + + goto error_exit; + } + this_digit = (u8) ACPI_TOUPPER (*string); - if (ACPI_IS_UPPER ((char) this_digit)) { + if (ACPI_IS_XDIGIT ((char) this_digit)) { /* Convert ASCII Hex char to value */ this_digit = this_digit - 'A' + 10; } else { - goto error_exit; + /* + * We allow non-hex chars, just stop now, same as end-of-string. + * See ACPI spec, string-to-integer conversion. + */ + break; } } - /* Check to see if digit is out of range */ - - if (this_digit >= base) { - goto error_exit; - } - /* Divide the digit into the correct position */ (void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit), @@ -464,8 +472,10 @@ return_value *= base; return_value += this_digit; - ++string; + string++; } + + /* All done, normal exit */ *ret_integer = return_value; return_ACPI_STATUS (AE_OK); diff -Nru a/drivers/acpi/video.c b/drivers/acpi/video.c --- a/drivers/acpi/video.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/acpi/video.c 2005-03-20 16:31:54 -08:00 @@ -683,7 +683,7 @@ FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_video_dir; +static struct proc_dir_entry *acpi_video_dir; /* video devices */ diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c --- a/drivers/base/sys.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/base/sys.c 2005-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 +++ b/drivers/net/b44.c 2005-03-20 16:31:54 -08:00 @@ -1921,6 +1921,7 @@ b44_free_rings(bp); spin_unlock_irq(&bp->lock); + pci_disable_device(pdev); return 0; } @@ -1930,6 +1931,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-03-20 16:31:54 -08:00 +++ b/drivers/net/e1000/e1000_main.c 2005-03-20 16:31:54 -08:00 @@ -3103,8 +3103,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-03-20 16:31:54 -08:00 +++ b/drivers/net/ne2k-pci.c 2005-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 +++ b/drivers/pci/pci-acpi.c 2005-03-20 16:31:54 -08:00 @@ -1,9 +1,10 @@ /* * File: pci-acpi.c - * Purpose: Provide PCI supports in ACPI + * Purpose: Provde 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,116 @@ 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) +{ + char dstate_str[] = "_S0D"; + acpi_status status; + unsigned long val; + struct device *dev = &pdev->dev; + + /* Fixme: the check is wrong after pm_message_t is a struct */ + if ((state >= PM_SUSPEND_MAX) || !DEVICE_ACPI_HANDLE(dev)) + return -EINVAL; + dstate_str[2] += state; /* _S1D, _S2D, _S3D, _S4D */ + status = acpi_evaluate_integer(DEVICE_ACPI_HANDLE(dev), dstate_str, + NULL, &val); + if (ACPI_SUCCESS(status)) + return val; + 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-03-20 16:31:54 -08:00 +++ b/drivers/pci/pci.c 2005-03-20 16:31:54 -08:00 @@ -240,7 +240,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) = NULL; int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { @@ -304,8 +304,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; } @@ -317,12 +324,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) = NULL; pci_power_t pci_choose_state(struct pci_dev *dev, u32 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 2: return PCI_D2; diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h --- a/drivers/pci/pci.h 2005-03-20 16:31:54 -08:00 +++ b/drivers/pci/pci.h 2005-03-20 16:31:54 -08: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/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/pcmcia/yenta_socket.c 2005-03-20 16:31:54 -08:00 @@ -1034,6 +1034,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 @@ -1057,6 +1058,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-03-20 16:31:54 -08:00 +++ b/drivers/pnp/pnpacpi/rsparser.c 2005-03-20 16:31:54 -08:00 @@ -219,9 +219,10 @@ res->data.address64.min_address_range, res->data.address64.address_length); break; + case ACPI_RSTYPE_VENDOR: + break; default: - pnp_warn("PnPACPI: Alloc type : %d not handle", - res->id); + pnp_warn("PnPACPI: unknown resource type %d", res->id); return AE_ERROR; } @@ -508,7 +509,7 @@ case ACPI_RSTYPE_END_DPF: return AE_CTRL_TERMINATE; default: - pnp_warn("PnPACPI:Option type: %d not handle", res->id); + pnp_warn("PnPACPI: unknown resource type %d", res->id); return AE_ERROR; } @@ -810,7 +811,7 @@ mem ++; break; default: /* other type */ - pnp_warn("Invalid type"); + pnp_warn("unknown resource type %d", resource->id); return -EINVAL; } resource ++; diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c 2005-03-20 16:31:54 -08:00 +++ b/drivers/usb/core/hcd-pci.c 2005-03-20 16:31:54 -08: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/acconfig.h b/include/acpi/acconfig.h --- a/include/acpi/acconfig.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acconfig.h 2005-03-20 16:31:54 -08:00 @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20050211 +#define ACPI_CA_VERSION 0x20050309 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -198,7 +198,7 @@ /* Number of strings associated with the _OSI reserved method */ -#define ACPI_NUM_OSI_STRINGS 9 +#define ACPI_NUM_OSI_STRINGS 10 /****************************************************************************** diff -Nru a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h --- a/include/acpi/acdisasm.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acdisasm.h 2005-03-20 16:31:54 -08:00 @@ -75,6 +75,11 @@ extern const char *acpi_gbl_TYPdecode[4]; extern const char *acpi_gbl_BMdecode[2]; extern const char *acpi_gbl_SIZdecode[4]; +extern const char *acpi_gbl_TTPdecode[2]; +extern const char *acpi_gbl_MTPdecode[4]; +extern const char *acpi_gbl_TRSdecode[2]; + + extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; diff -Nru a/include/acpi/acdispat.h b/include/acpi/acdispat.h --- a/include/acpi/acdispat.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acdispat.h 2005-03-20 16:31:54 -08:00 @@ -374,6 +374,16 @@ /* dsutils - Parser/Interpreter interface utility routines */ +void +acpi_ds_clear_implicit_return ( + struct acpi_walk_state *walk_state); + +u8 +acpi_ds_do_implicit_return ( + union acpi_operand_object *return_desc, + struct acpi_walk_state *walk_state, + u8 add_reference); + u8 acpi_ds_is_result_used ( union acpi_parse_object *op, diff -Nru a/include/acpi/acinterp.h b/include/acpi/acinterp.h --- a/include/acpi/acinterp.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acinterp.h 2005-03-20 16:31:54 -08:00 @@ -617,7 +617,6 @@ acpi_status acpi_ex_store_buffer_to_buffer ( - acpi_object_type original_src_type, union acpi_operand_object *source_desc, union acpi_operand_object *target_desc); diff -Nru a/include/acpi/aclocal.h b/include/acpi/aclocal.h --- a/include/acpi/aclocal.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/aclocal.h 2005-03-20 16:31:54 -08:00 @@ -774,6 +774,7 @@ #define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100 #define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200 #define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_WAKE_STATUS 0x8000 #define ACPI_BITMASK_ALL_FIXED_STATUS (ACPI_BITMASK_TIMER_STATUS | \ @@ -789,6 +790,7 @@ #define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100 #define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200 #define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_SCI_ENABLE 0x0001 #define ACPI_BITMASK_BUS_MASTER_RLD 0x0002 @@ -807,6 +809,7 @@ #define ACPI_BITPOSITION_POWER_BUTTON_STATUS 0x08 #define ACPI_BITPOSITION_SLEEP_BUTTON_STATUS 0x09 #define ACPI_BITPOSITION_RT_CLOCK_STATUS 0x0A +#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */ #define ACPI_BITPOSITION_WAKE_STATUS 0x0F #define ACPI_BITPOSITION_TIMER_ENABLE 0x00 @@ -814,6 +817,7 @@ #define ACPI_BITPOSITION_POWER_BUTTON_ENABLE 0x08 #define ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE 0x09 #define ACPI_BITPOSITION_RT_CLOCK_ENABLE 0x0A +#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */ #define ACPI_BITPOSITION_SCI_ENABLE 0x00 #define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01 diff -Nru a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h --- a/include/acpi/acpi_bus.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acpi_bus.h 2005-03-20 16:31:54 -08:00 @@ -328,7 +328,6 @@ int acpi_bus_register_driver (struct acpi_driver *driver); int acpi_bus_unregister_driver (struct acpi_driver *driver); int acpi_bus_scan (struct acpi_device *start); -int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); @@ -336,6 +335,27 @@ int acpi_match_ids (struct acpi_device *device, char *ids); 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*/ diff -Nru a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h --- a/include/acpi/acpi_drivers.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acpi_drivers.h 2005-03-20 16:31:54 -08:00 @@ -56,7 +56,8 @@ /* ACPI PCI Interrupt Link (pci_link.c) */ int acpi_irq_penalty_init (void); -int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low); +int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level, + int *active_high_low, char **name); /* ACPI PCI Interrupt Routing (pci_irq.c) */ @@ -107,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/acpi/acstruct.h b/include/acpi/acstruct.h --- a/include/acpi/acstruct.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/acstruct.h 2005-03-20 16:31:54 -08:00 @@ -94,6 +94,7 @@ union acpi_generic_state *control_state; /* List of control states (nested IFs) */ struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */ struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */ + union acpi_operand_object *implicit_return_obj; struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ struct acpi_namespace_node *method_call_node; /* Called method Node*/ union acpi_parse_object *method_call_op; /* method_call Op if running a method */ diff -Nru a/include/acpi/actbl.h b/include/acpi/actbl.h --- a/include/acpi/actbl.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/actbl.h 2005-03-20 16:31:54 -08:00 @@ -261,6 +261,8 @@ u8 local_sapic_eid; /* SAPIC EID */ u8 reserved [3]; /* Reserved - must be zero */ LOCAL_APIC_FLAGS + u32 processor_uID; /* Numeric UID - ACPI 3.0 */ + char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ }; struct madt_interrupt_source @@ -272,7 +274,7 @@ u8 processor_eid; /* Processor EID */ u8 io_sapic_vector; /* Vector value for PMI interrupts */ u32 interrupt; /* Global system interrupt */ - u32 reserved; /* Reserved - must be zero */ + u32 flags; /* Interrupt Source Flags */ }; diff -Nru a/include/acpi/actbl2.h b/include/acpi/actbl2.h --- a/include/acpi/actbl2.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/actbl2.h 2005-03-20 16:31:54 -08:00 @@ -108,7 +108,7 @@ /* - * ACPI 2.0 Generic Address Structure (GAS) + * ACPI 2.0+ Generic Address Structure (GAS) */ struct acpi_generic_address { @@ -159,7 +159,7 @@ u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ /* - * ACPI 2.0 Fixed ACPI Description Table (FADT) + * ACPI 2.0+ Fixed ACPI Description Table (FADT) */ struct fadt_descriptor_rev2 { @@ -174,17 +174,25 @@ u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ - u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits*/ + u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits */ u32 dock_cap : 1; /* Supports Docking */ - u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/ - u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */ - u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/ + u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG */ + u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed */ + u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices */ u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */ - /* Must be executed after writing the SLP_TYPx register. */ - u32 reserved6 : 18; /* Reserved - must be zero */ + /* must be executed after writing the SLP_TYPx register */ + /* ACPI 3.0 flag bits */ + + u32 pci_exp_wak : 1; /* System supports PCIEXP_WAKE (STS/EN) bits */ + u32 use_platform_clock : 1; /* OSPM should use platform-provided timer */ + u32 S4rtc_sts_valid : 1; /* Contents of RTC_STS valid after S4 wake */ + u32 remote_power_on_capable : 1; /* System is compatible with remote power on */ + u32 force_apic_cluster_model : 1; /* All local APICs must use cluster model */ + u32 force_apic_physical_destination_mode : 1; /* all local x_aPICs must use physical dest mode */ + u32 reserved6 : 12;/* Reserved - must be zero */ struct acpi_generic_address reset_register; /* Reset register address in GAS format */ - u8 reset_value; /* Value to write to the reset_register port to reset the system. */ + u8 reset_value; /* Value to write to the reset_register port to reset the system */ u8 reserved7[3]; /* These three bytes must be zero */ u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ u64 Xdsdt; /* 64-bit physical address of DSDT */ @@ -199,7 +207,7 @@ }; -/* "Downrevved" ACPI 2.0 FADT descriptor */ +/* "Down-revved" ACPI 2.0 FADT descriptor */ struct fadt_descriptor_rev2_minus { @@ -213,7 +221,7 @@ }; -/* Embedded Controller */ +/* ECDT - Embedded Controller Boot Resources Table */ struct ec_boot_resources { @@ -223,6 +231,55 @@ u32 uid; /* Unique ID - must be same as the EC _UID method */ u8 gpe_bit; /* The GPE for the EC */ u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */ +}; + + +/* SRAT - System Resource Affinity Table */ + +struct static_resource_alloc +{ + u8 type; + u8 length; + u8 proximity_domain_lo; + u8 apic_id; + u32 enabled :1; + u32 reserved3 :31; + u8 local_sapic_eid; + u8 proximity_domain_hi[3]; + u32 reserved4; +}; + +struct memory_affinity +{ + u8 type; + u8 length; + u32 proximity_domain; + u16 reserved3; + u64 base_address; + u64 address_length; + u32 reserved4; + u32 enabled :1; + u32 hot_pluggable :1; + u32 non_volatile :1; + u32 reserved5 :29; + u64 reserved6; +}; + +struct system_resource_affinity +{ + ACPI_TABLE_HEADER_DEF + u32 reserved1; /* Must be value '1' */ + u64 reserved2; +}; + + +/* SLIT - System Locality Distance Information Table */ + +struct system_locality_info +{ + ACPI_TABLE_HEADER_DEF + u64 locality_count; + u8 entry[1][1]; }; diff -Nru a/include/acpi/actypes.h b/include/acpi/actypes.h --- a/include/acpi/actypes.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/actypes.h 2005-03-20 16:31:54 -08:00 @@ -653,24 +653,26 @@ #define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04 #define ACPI_BITREG_RT_CLOCK_STATUS 0x05 #define ACPI_BITREG_WAKE_STATUS 0x06 +#define ACPI_BITREG_PCIEXP_WAKE_STATUS 0x07 -#define ACPI_BITREG_TIMER_ENABLE 0x07 -#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x08 -#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x09 -#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0A -#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0B -#define ACPI_BITREG_WAKE_ENABLE 0x0C - -#define ACPI_BITREG_SCI_ENABLE 0x0D -#define ACPI_BITREG_BUS_MASTER_RLD 0x0E -#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x0F -#define ACPI_BITREG_SLEEP_TYPE_A 0x10 -#define ACPI_BITREG_SLEEP_TYPE_B 0x11 -#define ACPI_BITREG_SLEEP_ENABLE 0x12 +#define ACPI_BITREG_TIMER_ENABLE 0x08 +#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x09 +#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x0A +#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0B +#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0C +#define ACPI_BITREG_WAKE_ENABLE 0x0D +#define ACPI_BITREG_PCIEXP_WAKE_DISABLE 0x0E + +#define ACPI_BITREG_SCI_ENABLE 0x0F +#define ACPI_BITREG_BUS_MASTER_RLD 0x10 +#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x11 +#define ACPI_BITREG_SLEEP_TYPE_A 0x12 +#define ACPI_BITREG_SLEEP_TYPE_B 0x13 +#define ACPI_BITREG_SLEEP_ENABLE 0x14 -#define ACPI_BITREG_ARB_DISABLE 0x13 +#define ACPI_BITREG_ARB_DISABLE 0x15 -#define ACPI_BITREG_MAX 0x13 +#define ACPI_BITREG_MAX 0x15 #define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 @@ -1206,6 +1208,7 @@ u64 max_address_range; u64 address_translation_offset; u64 address_length; + u64 type_specific_attributes; struct acpi_resource_source resource_source; }; diff -Nru a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h --- a/include/acpi/platform/acenv.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/platform/acenv.h 2005-03-20 16:31:54 -08:00 @@ -226,6 +226,7 @@ */ #define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) +#define ACPI_STRCHR(s1,c) strchr((s1), (c)) #ifdef ACPI_FUTURE_USAGE #define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) @@ -294,6 +295,7 @@ #define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2)) +#define ACPI_STRCHR(s1,c) acpi_ut_strchr ((s1), (c)) #ifdef ACPI_FUTURE_USAGE #define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) diff -Nru a/include/acpi/processor.h b/include/acpi/processor.h --- a/include/acpi/processor.h 2005-03-20 16:31:54 -08:00 +++ b/include/acpi/processor.h 2005-03-20 16:31:54 -08:00 @@ -201,7 +201,6 @@ /* in processor_throttling.c */ int acpi_processor_get_throttling_info (struct acpi_processor *pr); int acpi_processor_set_throttling (struct acpi_processor *pr, int state); -int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file); ssize_t acpi_processor_write_throttling ( struct file *file, const char __user *buffer, @@ -217,7 +216,6 @@ /* in processor_thermal.c */ int acpi_processor_get_limit_info (struct acpi_processor *pr); -int acpi_processor_limit_open_fs(struct inode *inode, struct file *file); ssize_t acpi_processor_write_limit ( struct file *file, const char __user *buffer, diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h --- a/include/linux/acpi.h 2005-03-20 16:31:54 -08:00 +++ b/include/linux/acpi.h 2005-03-20 16:31:54 -08:00 @@ -455,8 +455,6 @@ struct list_head entries; }; -extern struct acpi_prt_list acpi_prt; - struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev); diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h 2005-03-20 16:31:54 -08:00 +++ b/include/linux/device.h 2005-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 +++ b/include/linux/pm.h 2005-03-20 16:31:54 -08: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-03-20 16:31:54 -08:00 +++ b/kernel/power/main.c 2005-03-20 16:31:54 -08: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; @@ -186,7 +200,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; }