GIT 2c088b61bc5ad021f3594ef7ed68907b3e67c1bd git+ssh://master.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git#test 25e85376ecf5aa00d7849d655d2547a8bf6716a7 commit 25e85376ecf5aa00d7849d655d2547a8bf6716a7 Author: Venkatesh Pallipadi Date: Wed Apr 9 21:31:46 2008 -0400 2.6.25 regression: powertop says 120K wakeups/sec Patch to fix huge number of wakeups reported due to recent changes in processor_idle.c. The problem was that the entry_method determination was broken due to one of the recent commits (bc71bec91f987) causing C1 entry to not to go to halt. http://lkml.org/lkml/2008/3/22/124 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown commit 99bda83e8b3140b7e81572a5aabc7dedb455b272 Author: Ralf Baechle Date: Thu Mar 13 23:54:09 2008 +0100 MIPS Alchemy: Crapectomy after removal of pm_send_all calls. Signed-off-by: Ralf Baechle Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown commit 5373fd72577ffc4689ade0a2a1a885293c32c711 Author: Andrew Morton Date: Thu Mar 27 02:00:06 2008 -0400 PM: arch/x86/kernel/apm_32.c: fix build warning arch/x86/kernel/apm_32.c:1215: warning: label 'out' defined but not used Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 6afe1a1fe8ff83f6ac2726b04665e76ba7b14f3e Author: Pavel Machek Date: Thu Mar 13 23:52:49 2008 +0100 PM: Remove legacy PM AFAICT pm_send_all is a nop when noone uses pm_register... Hmm.. can we just force CONFIG_PM_LEGACY=n, and see what happens? Or maybe this is better idea? It may break build somewhere, but it should be easy to fix... (it builds here, i386 and x86-64). Signed-off-by: Pavel Machek Acked-by: Ralf Baechle Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown commit 24858c32288aab0e6ef7c48a4d867a764d700228 Author: Len Brown Date: Tue Apr 15 03:06:28 2008 -0400 ACPICA: fix build warning drivers/acpi/dispatcher/dsobject.c:499: warning: format ‘%X’ expects type ‘unsigned int’, but argument 4 has type ‘acpi_native_uint’ drivers/acpi/dispatcher/dsobject.c:507: warning: format ‘%X’ expects type ‘unsigned int’, but argument 7 has type ‘acpi_native_uint’ Signed-off-by: Len Brown commit 3d950a4f9bca08fe64614e4c7f9170b5a242776c Author: Bob Moore Date: Thu Apr 10 19:06:44 2008 +0400 ACPICA: Fix for some local named nodes not marked temporary and to disallow duplicates Fixed a problem with the CreateField, CreateXXXField (Bit, Byte, Word, Dword, Qword), Field, BankField, and IndexField operators when invoked from inside an executing control method. In this case, these operators created namespace nodes that were incorrectly left marked as permanent nodes instead of temporary nodes. This could cause a problem if there is race condition between an exiting control method and a running namespace walk. (Reported by Linn Crosetto). Fixed a problem where the CreateField and CreateXXXField operators would incorrectly allow duplicate names (the name of the field) with no exception generated. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 068940125997d74beb7bead36ed67d6f349bd9d3 Author: Bob Moore Date: Thu Apr 10 19:06:44 2008 +0400 ACPICA: Update version to 20080321 Update version to 20080321. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit ad1870a1516eb3e22995ac5df73a544f19bab2f7 Author: Zhang Rui Date: Thu Apr 10 19:06:44 2008 +0400 ACPICA: Update for new Notify values Implemented several changes for Notify handling: Added support for new Notify values (ACPI 2.0+) and improved the Notify debug output. Notify on PowerResource objects is no longer allowed, as per the ACPI specification. Signed-off-by: Zhang Rui Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 6f5a5a867dbd8b624a953de267d44ee59b391dab Author: Zhang Rui Date: Thu Apr 10 19:06:44 2008 +0400 ACPICA: Fix to disable unknown spurious GPEs Implemented another change to eliminate/suppress spurious or stray GPEs. The AcpiEvDisableGpe function will now disable GPEs that are neither enabled nor disabled -- meaning that the GPE is unknown to the system. This will prevent future interrupts from that GPE. http://bugzilla.kernel.org/show_bug.cgi?id=6217 Signed-off-by: Zhang Rui Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 9083243e779608d04b6f8527555f2ba03a989ae0 Author: Bob Moore Date: Thu Apr 10 19:06:44 2008 +0400 ACPICA: Fixes for size of StartDependent resource descriptor Fixed a couple of size calculation issues with the variable-length Start Dependent resource descriptor. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit ddcb30e2cc27bfdf74ecaa4ba3a7fb2be08df58e Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Updates for Debug object output Implemented several improvements for the output of the ASL "Debug" object to clarify and keep all data for a given object on one output line. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit fe20b478edfe7fcf7245b8042d4ff29c1ab59d9f Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Fixes for external Reference Objects All Reference Objects returned via the AcpiEvaluteObject interface are now marked as type "REFERENCE" instead of "ANY". The type ANY is now reservered for NULL objects - either NULL package elements or unresolved named references. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 4b393f84e0568749de794001a7a27518faf997d8 Author: Lin, Ming Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Fix to handle NULL package elements correctly Fixed problem where NULL package elements were not returned to the AcpiEvaluateObject interface correctly. Instead of returning a NULL ACPI_OBJECT package element, the element was simply ignored, potentially causing a buffer overflow and/or confusing the caller who expected a fixed number of elements. http://bugzilla.kernel.org/show_bug.cgi?id=10132 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 0d0bafeb11aeee59f13c9ad5ec964cfc7e7f0acb Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Fix for extraneous debug message for packages Fixed a problem where an extraneous debug message was produced for package objects (when debugging enabled). The message "Package List length larger than NumElements count" is now produced in the correct case, and is also an error message rather than a debug message. Added a debug message for the opposite case, where NumElements is larger than the Package List, and the package has been padded out with NULL elements. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit aa06a1c1fbb0ab115925ca515ba3ec9dcc6e774e Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Update ACPICA version to 20080213 Update ACPICA version to 20080213. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 96c4693f1f093634e61e234cb7d582f32c3e7868 Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Fix for possible error when packages/buffers are passed to methods externally Fixed a problem where buffer and package objects passed as arguments to a control method via the external AcpiEvaluateObject interface could cause an AE_AML_INTERNAL exception depending on the order and type of operators executed by the target control method. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 2e25ee7a7a5b241a5d360fa885df0195b66a2a4f Author: Lin, Ming Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Update behavior of CopyObject to match ACPI spec Fixed a problem where a CopyObject to RegionField, BankField, and IndexField objects did not perform an implicit conversion as it should. These types must retain their initial type permanently as per the ACPI specification. However, a CopyObject to all other object types should not perform an implicit conversion, as per the ACPI specification. http://www.acpica.org/bugzilla/show_bug.cgi?id=388 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 26262e84b3e97d6b99849c43cf24489060a9f3ec Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Fix for resource descriptor optimization issues for _CRS/_SRC Fixed a problem where resource descriptor size optimization could cause a problem when a _CRS resource template is passed to a _SRS method. The _SRS resource template must use the same descriptors (with the same size) as returned from _CRS. This change affects the following resource descriptors: IRQ/IRQNoFlags and StartDependendentFn/StartDependentFnNoPri. http://bugzilla.kernel.org/show_bug.cgi?id=9487 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 5ffef38684bb1cca0768fa1c0fba1d26a3cd55ad Author: Bob Moore Date: Thu Apr 10 19:06:43 2008 +0400 ACPICA: Disassembler support for new ACPI tables Implemented full disassembler support for the following new ACPI tables: BERT, EINJ, and ERST. Partial disassembler support for the complicated HEST table. These tables support the Windows Hardware Error Architecture (WHEA). Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 184f974086cccc662cb50151504514fb2c17a6a0 Author: Bob Moore Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Fix for ACPI_HIDWORD macro Fixed a regression introduced in version 20071114. The ACPI_HIDWORD macro was inadvertently changed to return a 16-bit value instead of a 32-bit value, truncating the upper Dword of a 64-bit value. This macro is only used to display debug output, so no incorrect calculations were made. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 7ae93e165173a71e2bd3f0a98daa8d9d5aff3299 Author: Bob Moore Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Added new error messages New messages for the 2 AE_SUPPORT cases. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 9d87f45b7527fbbb7da7ad67950d47d2d075152d Author: Bob Moore Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Add va_end statements as appropriate Added missing va_end statements that should correspond with each va_start statement. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit b259a68ceb6b34aac25d970664019cf9683a510e Author: Bob Moore Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Update version to 20080123 Update version to 20080123. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit d6deaf7a91ae64575b449eaa254451a503eecbc3 Author: Lin, Ming Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Fixes for Unload and DDBHandles Implemented support for the use of DDBHandles as an Indexed Reference, as per the ACPI spec. http://www.acpica.org/bugzilla/show_bug.cgi?id=486. Implemented support for UserTerm (Method invocation) for the Unload operator as per the ACPI spec. http://www.acpica.org/bugzilla/show_bug.cgi?id=580 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 67f9a3d0f3060abaa88994c7bc2cd67d3d1f0c09 Author: Bob Moore Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Bulletproof disassembler for bad ACPI tables Fixed a problem with the disassembler where invalid ACPI tables could cause faults or infinite loops. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit dd82a379e876f537b8335d9f9268ffcea2bc9648 Author: Bob Moore Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Include file support for new ACPI tables Implemented header file support for new ACPI tables - BERT, ERST, EINJ, HEST, IBFT, UEFI, WDAT. Disassembler support is forthcoming. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 4dfb5150f8ad3d4d81943e336dbacfcc0e54b9db Author: Lin, Ming Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Fix for LoadTable operator, input strings Fixed a problem with the LoadTable operator where the OemId and OemTableId input strings could cause unexpected failures if they were shorter than the maximum lengths allowed. http://www.acpica.org/bugzilla/show_bug.cgi?id=576 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit ac9463e32d8207804d47f6b7b794d7fc08a0d7f3 Author: Lin, Ming Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Fix for Load operator Fixed a problem with the Load operator where an exception was not returned in the case where the table is already loaded. http://www.acpica.org/bugzilla/show_bug.cgi?id=463 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 81431bb5deb421bc7ce6165e01b7469ba5f4b795 Author: Lin, Ming Date: Thu Apr 10 19:06:42 2008 +0400 ACPICA: Methods now implicitly return 0 in slack mode Implemented an enhancement to the interpreter "slack mode". In the absence of an explicit return or an implicitly returned object from the last executed opcode, a control method will now implicitly return an integer of value 0 for Microsoft compatibility. http://www.acpica.org/bugzilla/show_bug.cgi?id=392 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit dfb407eff0ca0eb01c1b221921eef0c719c964c9 Author: Lin, Ming Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Fix for SizeOf when used with Buffers and Packages Fixed a problem with the SizeOf operator when used with Package and Buffer objects. These objects have deferred execution for some arguments, and the execution is now completed before the SizeOf is executed. This problem caused unexpected AE_PACKAGE_LIMIT errors on some systems. http://bugzilla.kernel.org/show_bug.cgi?id=9558 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 93604a220436051fa4adf8b555e7b8918aa1b7d4 Author: Bob Moore Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Update version to 20071219 Update version to 20071219. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 9dd9b66c1c99f0082c4104ecfcfed56f905f7d7a Author: Lin, Ming Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Fixed a couple memory leaks associated with "implicit return" objects when the AML Interpreter slack mode is enabled http://www.acpica.org/bugzilla/show_bug.cgi?id=349 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 8a538626456fe7795d174e6eec34657b88e31733 Author: Lin, Ming Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Implemented full argument resolution support for the BankValue argument to BankField Previously, only constants were supported, now any TermArg may be used. http://www.acpica.org/bugzilla/show_bug.cgi?id=387 http://www.acpica.org/bugzilla/show_bug.cgi?id=393 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 49cbde18e0099e57e247286e7b63c5c75b645232 Author: Bob Moore Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Undo accidental checkin of not-fully-tested mutex changes Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit eab0682e65de0b8f52624cabfecb1d1d1a8edcd0 Author: Lin, Ming Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Implemented full support for deferred execution for the TermArg string arguments for DataTableRegion This enables forward references and full operand resolution for the three string arguments. Similar to OperationRegion deferred argument execution.) http://www.acpica.org/bugzilla/show_bug.cgi?id=430 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 73455df66090f33a4126ebc3499d230738dcef14 Author: Bob Moore Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Fixed a problem with Index Fields where the Index register was incorrectly limited to a maximum of 32 bits Now any size may be used. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit bc21822ba854fcabb67b75b4467f2660b39b19e9 Author: Bob Moore Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Fixed a problem with AcpiGetDevices where the search of a branch of the device tree could be terminated prematurely In accordance with the ACPI specification, the search is terminated if a device is both not present and not functional (instead of just not present.) Yakui Zhao. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 1179e8bcfa05652c5e7f33fd2e6a65b07e2aa743 Author: Bob Moore Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Update version to 20071114 Update version to 20071114. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit f8a45ae1ecd8b81570c6957759d0e71db76358de Author: Lin, Ming Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Fixed a problem with CopyObject used in conjunction with the Index operator The reference was incorrectly dereferenced before the copy. The reference is now correctly copied. http://bugzilla.kernel.org/show_bug.cgi?id=5391 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit e44076bc66552ad664bda6ec8e1c906be0b8f4dd Author: Lin, Ming Date: Thu Apr 10 19:06:41 2008 +0400 ACPICA: Fixed a problem with Index references passed as method arguments References passed as arguments to control methods were dereferenced immediately (before control was passed to the called method). The references are now correctly passed directly to the called method. http://bugzilla.kernel.org/show_bug.cgi?id=5389 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit ac3ebbeee66ed662a2e99a6150cc6f06fa1b54d9 Author: Bob Moore Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Fixed a problem with FromBCD and ToBCD with some compilers On some compilers, the ShortDivide function worked incorrectly, causing problems with the BCD functions with large input values. (Truncation from 64-bit to 32-bit occurred.) Internal http://www.acpica.org/bugzilla/show_bug.cgi?id=435 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit c0c8756509f624ae202becc36476e99dacef6e47 Author: Bob Moore Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Fixes a problem with control method references within packages Completes the package changes started with version 20071019. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 634c45928cfd4224d16c43b86883eeeda24aad3f Author: Bob Moore Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Cleanup of debug output Improved output of object dump routine. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 2ef51d55a97b8872031522509c35c9b636277a16 Author: Bob Moore Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Cosmetic changes only, no functional changes Lint changes, fix compiler warnings, etc. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit cc4910abd7b19e548aebc956101dd458f50b8ba8 Author: Bob Moore Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Cosmetic changes only, no functional changes Lint changes, fix compiler warnings, etc. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 3bc4dbadd723f756341385abaa5200df5ea04f89 Author: Bob Moore Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Update version to 20071019 Update version to 20071019. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit a4a8ddffc6f45f1e8240852c1784b7ef55afe742 Author: Lin, Ming Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Added additional parameter validation for LoadTable Implemented additional parameter validation for the LoadTable operator. The length of the input strings SignatureString, OemIdString, and OemTableId are now checked for maximum lengths. http://www.acpica.org/bugzilla/show_bug.cgi?id=582 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 33311576c25029729df8955a3b911716e18f601c Author: Lin, Ming Date: Thu Apr 10 19:06:40 2008 +0400 ACPICA: Fix for Increment/Decrement operator, incorrect type change Fixed a problem with the Increment and Decrement operators where the type of the target object could be unexpectedly and incorrectly changed. http://www.acpica.org/bugzilla/show_bug.cgi?id=353 Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit e6a204743b045764b6a7eec5ad7d83b0e9b2b2fe Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Fixed a memory leak when Device or Thermal objects referenced in packages Problem introduced in fix for Package references. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 521e7c692b24dd59558e997403b310c823801119 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Fix for Load/LoadTable to specify load location Fixed a problem with the Load and LoadTable operators where the table location within the namespace was ignored. Instead, the table was always loaded into the root or current scope. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 5073be4e0149225b88016febc4ee7ed77e554f14 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Add error checks to prevent faults Added additional error checking to prevent run-time faults. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 05fec335870cdb397f2e4c08e7f389c75eaa5769 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Add a table checksum verify for Load operator Added a table checksum verification for the Load operator, in the case where the load is from a buffer. http://www.acpica.org/bugzilla/show_bug.cgi?id=578 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 7c9e1853d0c39936f1b441be853b3cc0369f2ea2 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Fix for memory leak related to DdbHandle objects Fixed a memory leak where DdbHandle objects were not deleted automatically at control method exit. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 1eb7ef2f979a91cbf3a8e2c378027245cc966bf5 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Fix a fault when storing DdbHandle to Debug object Fixed a problem with the Debug object where a store of a DdbHandle reference object to the Debug object could cause a fault. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 3770a36c23c8e57e07ef45a295f203b321c2d304 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Fix for fault if Load() fails Fixed a problem with the Load operator when loading a table from a buffer object. The input buffer was prematurely zeroed and/or deleted. http://www.acpica.org/bugzilla/show_bug.cgi?id=577 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 99f0f7eacc40cb70f17379f4dfcb5388874bbd21 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: Fix for Alias operator to see target child objects Fixed a problem with the Alias operator when the target of the alias is a named ASL operator that opens a new scope -- Scope, Device, PowerResource, Processor, and ThermalZone. In these cases, any children of the original operator could not be accessed via the alias, potentially causing unexpected AE_NOT_FOUND exceptions. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit ea2ec76cfc0bbcaae00d775111cf689b41144554 Author: Bob Moore Date: Thu Apr 10 19:06:39 2008 +0400 ACPICA: update version number to 20070919 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 340983be58f93bcc2f3f5ff24638616eb983c54c Author: Lin, Ming Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Fix for namespace lookup problem Fixed a problem where objects of certain types (Device, ThermalZone, Processor, PowerResource) can be not found if they are declared and referenced from within the same control method http://www.acpica.org/bugzilla/show_bug.cgi?id=341. Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 78a2b53910b2f413498a1fa16db063d21217d295 Author: Lin, Ming Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: New interfaces for table event handlers Designed and implemented new external interfaces to install and remove handlers for ACPI table-related events. Current events that are defined are LOAD and UNLOAD. These interfaces allow the host to track ACPI tables as they are dynamically loaded and unloaded. See AcpiInstallTableHandler and AcpiRemoveTableHandler. Signed-off-by: Lin, Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 4fa5929b523692bd93fbc7e752288808632bbd6e Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Add minimal disassembly support for the SLIC table SLIC - Software Licensing Description Table. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit a41b96b9c3ae7f62b7488247331fa8162674dd17 Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Support for iASL - multiple files and wildcards Implemented support to allow multiple files to be compiled/disassembled in a single invocation. This includes command line wildcard support for both the Windows and Unix versions of the compiler. This feature simplifies the disassembly and compilation of multiple ACPI tables in a single directory. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 00f64b81de30e5413c83030917653013b0f2d216 Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Updated error message for dynamic method serialization Added more information to make the message clearer. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit f54eefef0262b43aa04421710e8c4fefc3b75fc9 Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Update version to 20070508 Update version to 20070508. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 2e2649c563a599ae653b5c2d8f0eb6233ee41062 Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Fix for update of the Global Lock Handle Fixed a problem where the global lock handle was not properly updated if a thread that acquired the global lock via executing AML code then attempted to acquire the lock via the AcpiAcquireGlobalLock interface. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit d212076a5ad2177b1dfec915c8e5cbb958497d17 Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Update version to 20070320 pdate version to 20070320 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 5bfb4b15f42fc39eb2a027ab5d2677f122893f87 Author: Bob Moore Date: Thu Apr 10 19:06:38 2008 +0400 ACPICA: Fix for package reference counts Prevents infinite loop of 'Large Reference Count' messages in aslts-bdemo-b286 test. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 8c4e2a9cd541e5891a051ed9bee930d4f81a9102 Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Increase maximum buffer size dumped to screen in buffer object dump Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 00c7f63bcc737305248c7ea01641c1046e9a58f9 Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Misc fixes for recent global lock code update Fixes as a result of running full validation test suite. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 12a7ad931614358ef95263116eccf148f3d2924c Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Removed obsolete ACPI_NO_INTEGER64_SUPPORT define Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 00562b922c9d5f500bd24a56384c01b76962d76a Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Removed extraneous code Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit f6985f70a9c63d20e6f1faa7111ecab4606d073a Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Update comments for acquire/release mutex interfaces pdate comments for acquire/release mutex interfaces Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit f06f263b347e69ec43b6a19225f910683f945262 Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Fixed a couple compiler warnings for extra extern statements Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 56fa458175b3f7fa2309a13fc15806e52a889be2 Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Avoid use of invalid pointers in returned object field During operand evaluation, ensure that the ReturnObj field is cleared on error and only valid pointers are stored there. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 3a92de47a20dd9865d951aacdb9d2311b4f3f028 Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: changed order of interpretation of operand objects The interpreter now evaluates operands in the order that they appear (both in the AML and ASL), instead of in reverse order. This previously caused subtle incompatibilities with the MS interpreter as well as being non-intuitive. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit cc181711ea0dfecf622f894c453fa257eb94cd9f Author: Bob Moore Date: Thu Apr 10 19:06:37 2008 +0400 ACPICA: Update for mutiple global lock acquisitions by same thread Allows AcpiAcquireGlobalLock external interface to be called multiple times by the same thread. Allows use of AML fields that require the global lock while the running AML is already holding the global lock. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit a7cec19c46606f82dc54e7101fb624cd622aff63 Author: Bob Moore Date: Thu Apr 10 19:06:36 2008 +0400 ACPICA: Removed unused code Handling of AML_NAME_OP as a Reference.Opcode is no longer needed. Kernel bugzilla 2874 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit a502beee7268d3edd0653249633fbd5ab4ab0864 Author: Bob Moore Date: Thu Apr 10 19:06:36 2008 +0400 ACPICA: Several fixes for internal method result stack fixes STACK_OVERFLOW exception on nested method calls. internal bugzilla 262 and 275. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit df44017037957f7d33e916b8864bde3d3daee772 Author: Adrian Bunk Date: Mon Mar 31 02:05:40 2008 +0300 #if 0 acpi/bay.c:eject_removable_drive() This patch #if 0's the unused eject_removable_drive(). Signed-off-by: Adrian Bunk Signed-off-by: Len Brown commit 729b2bdbfa19dd9be98dbd49caf2773b3271cc24 Author: Zhao Yakui Date: Wed Mar 19 13:26:54 2008 +0800 ACPI : Disable the device's ability to wake the sleeping system in the boot phase In some machines some GPE is shared by several ACPI devices, for example: sleep button, keyboard, mouse. At the same time one of them is non-wake(runtime) device and the other are wake devices. In such case OSPM should call the _PSW object to disable the device's ability to wake the sleeping system in the boot phase. Otherwise there will be ACPI interrupt flood triggered by the GPE input. The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. So it is necessary to call _DSW object first. Only when it is not present will the _PSW object used. http://bugzilla.kernel.org/show_bug.cgi?id=10224 Signed-off-by: Zhao Yakui Signed-off-by: Zhang Rui Signed-off-by: Len Brown commit ce52ddf58cbc2c40f5f08d37d2217945e4d5adf3 Author: Alexey Starikovskiy Date: Mon Mar 24 23:22:36 2008 +0300 ACPI: EC: Don't delete boot EC Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 6d9e11206371be370b153264934378a29b6afe9b Author: Alexey Starikovskiy Date: Mon Mar 24 23:22:29 2008 +0300 ACPI: EC: Use default setup handler Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit fa95ba04e6ba11d71e1b87becd054b38faf546c8 Author: Alexey Starikovskiy Date: Fri Mar 21 19:36:02 2008 +0300 ACPI: EC: Detect irq storm Problem seems to be that hw fails to clear GPE after we service it and write 1 into corresponding bit. Thus, as soon as we get interrupts enabled again, we receive a new one. Google gives too many results for "acer interrupt storm" for this being one-broken-machine case. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=9998 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 223883b7aafa02410ed2e571d6032c876d0b23b8 Author: Alexey Starikovskiy Date: Fri Mar 21 17:07:21 2008 +0300 ACPI: EC: Switch off GPE mode during suspend/resume Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit b77d81b2678950077088956da4638c26853389fc Author: Alexey Starikovskiy Date: Fri Mar 21 17:07:15 2008 +0300 ACPI: EC: Replace broken controller workarounds with poll mode. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit dc0e8490fe884a9378b8ee04a5b5f905f06f4633 Author: Alexey Starikovskiy Date: Fri Mar 21 17:07:09 2008 +0300 ACPI: EC: Improve debug output Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 845625cdcb17119d5f6c5c8dbe586f2f36e8008a Author: Alexey Starikovskiy Date: Fri Mar 21 17:07:03 2008 +0300 ACPI: EC: Add poll timer If we can not use interrupt mode of EC for some reason, start polling EC for events periodically. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit e6e82a3087e6dad619149246082c910623ea9c36 Author: Alexey Starikovskiy Date: Fri Mar 21 17:06:57 2008 +0300 ACPI: EC: Restore udelay in poll mode This fixes keyboard event handling on some systems. Note that this delay was thought unnecessary, and removed from linux-2.6.20 with 50c1e1138cb94f6aca0f8555777edbcefe0324e2 'ACPI: ec: Drop udelay() from poll mode. Loop by reading status field instead.' Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit ae255542057e67f3df0ff8504271c1284bfa95cd Author: Alexey Starikovskiy Date: Tue Mar 11 17:17:08 2008 -0400 ACPI: GPE enabling should happen after EC installation GPE could try to access EC region, so should not be enabled before EC is installed http://bugzilla.kernel.org/show_bug.cgi?id=9916 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown commit 1071695f17daf050638e0bc550db647f8237c3bb Author: David Brownell Date: Fri Feb 22 21:54:24 2008 -0800 ACPI: crosslink ACPI and "real" device nodes Add cross-links between ACPI device and "real" devices in sysfs, exposing otherwise-hidden interrelationships between the various device nodes for ACPI stuff. As a representative example, one hardware device is exposed as two logical devices (PNP and ACPI): .../pnp0/00:06/ .../LNXSYSTM:00/device:00/PNP0A03:00/device:15/PNP0B00:00/ The PNP device gets a "firmware_node" link pointing to the ACPI device, and is what a Linux device driver binds to. The ACPI device has instead a "physical_node" link pointing back to the PNP device. Other firmware frameworks, like OpenFirmware, could do the same thing to couple their firmware tables to the rest of the system. (Based on a patch from Zhang Rui. This version is modified to not depend on the patch makig ACPI initialize driver model wakeup flags.) Signed-off-by: David Brownell Cc: Zhang Rui Signed-off-by: Len Brown arch/frv/kernel/pm.c | 8 - arch/mips/au1000/common/power.c | 35 +--- arch/x86/kernel/apm_32.c | 16 - drivers/acpi/bay.c | 2 + drivers/acpi/dispatcher/dsfield.c | 171 +++++++----- drivers/acpi/dispatcher/dsmethod.c | 58 ++--- drivers/acpi/dispatcher/dsmthdat.c | 2 + drivers/acpi/dispatcher/dsobject.c | 99 +++++-- drivers/acpi/dispatcher/dsopcode.c | 258 ++++++++++++++++- drivers/acpi/dispatcher/dsutils.c | 165 ++++++++++-- drivers/acpi/dispatcher/dswexec.c | 76 +++--- drivers/acpi/dispatcher/dswload.c | 35 ++- drivers/acpi/dispatcher/dswstate.c | 515 +++++++-------------------------- drivers/acpi/ec.c | 240 ++++++++-------- drivers/acpi/events/evgpe.c | 9 +- drivers/acpi/events/evmisc.c | 90 +++--- drivers/acpi/events/evregion.c | 2 +- drivers/acpi/events/evxface.c | 21 +- drivers/acpi/executer/exconfig.c | 103 ++++++-- drivers/acpi/executer/excreate.c | 115 +------- drivers/acpi/executer/exdump.c | 67 +++-- drivers/acpi/executer/exfield.c | 61 +---- drivers/acpi/executer/exfldio.c | 44 +++- drivers/acpi/executer/exmutex.c | 235 +++++++++++----- drivers/acpi/executer/exoparg1.c | 23 ++- drivers/acpi/executer/exoparg2.c | 19 +- drivers/acpi/executer/exoparg3.c | 1 + drivers/acpi/executer/exoparg6.c | 8 +- drivers/acpi/executer/exprep.c | 15 + drivers/acpi/executer/exregion.c | 8 +- drivers/acpi/executer/exresnte.c | 10 +- drivers/acpi/executer/exresolv.c | 53 ++-- drivers/acpi/executer/exresop.c | 11 - drivers/acpi/executer/exstore.c | 117 ++++++-- drivers/acpi/executer/exsystem.c | 1 - drivers/acpi/executer/exutils.c | 65 +++-- drivers/acpi/glue.c | 20 ++ drivers/acpi/hardware/hwsleep.c | 14 +- drivers/acpi/namespace/nsaccess.c | 99 ++++--- drivers/acpi/namespace/nsdump.c | 9 +- drivers/acpi/namespace/nsinit.c | 10 + drivers/acpi/namespace/nsload.c | 4 +- drivers/acpi/namespace/nsnames.c | 6 + drivers/acpi/namespace/nsparse.c | 31 ++- drivers/acpi/namespace/nswalk.c | 4 +- drivers/acpi/namespace/nsxfeval.c | 13 +- drivers/acpi/parser/psargs.c | 61 +++-- drivers/acpi/parser/psloop.c | 59 +++- drivers/acpi/parser/psopcode.c | 36 ++- drivers/acpi/parser/psparse.c | 43 ++- drivers/acpi/parser/pstree.c | 2 + drivers/acpi/processor_idle.c | 4 + drivers/acpi/resources/rscalc.c | 24 ++- drivers/acpi/resources/rsdump.c | 8 +- drivers/acpi/resources/rsio.c | 39 +++- drivers/acpi/resources/rsirq.c | 43 +++- drivers/acpi/resources/rsmisc.c | 11 + drivers/acpi/resources/rsutils.c | 6 +- drivers/acpi/scan.c | 43 +++- drivers/acpi/tables/tbfind.c | 32 ++- drivers/acpi/tables/tbinstal.c | 22 +- drivers/acpi/tables/tbutils.c | 2 +- drivers/acpi/tables/tbxface.c | 89 ++++++ drivers/acpi/utilities/utalloc.c | 2 +- drivers/acpi/utilities/utcopy.c | 59 ++++- drivers/acpi/utilities/utdebug.c | 17 +- drivers/acpi/utilities/utdelete.c | 21 ++- drivers/acpi/utilities/utglobal.c | 47 +++- drivers/acpi/utilities/utinit.c | 3 + drivers/acpi/utilities/utmath.c | 2 +- drivers/acpi/utilities/utmisc.c | 4 + drivers/acpi/utilities/utobject.c | 6 +- drivers/acpi/utilities/utxface.c | 40 ++-- drivers/acpi/utils.c | 2 +- include/acpi/acconfig.h | 13 +- include/acpi/acdisasm.h | 36 ++- include/acpi/acdispat.h | 29 +- include/acpi/acglobal.h | 36 ++- include/acpi/acinterp.h | 13 +- include/acpi/aclocal.h | 8 +- include/acpi/acmacros.h | 69 +++--- include/acpi/acnamesp.h | 3 +- include/acpi/acobject.h | 3 +- include/acpi/acopcode.h | 4 +- include/acpi/acparser.h | 2 + include/acpi/acpixf.h | 5 + include/acpi/acresrc.h | 1 + include/acpi/acstruct.h | 3 + include/acpi/actbl1.h | 559 +++++++++++++++++++++++++++++++++++- include/acpi/actypes.h | 91 ++++--- include/acpi/acutils.h | 2 + kernel/power/Kconfig | 10 - kernel/power/Makefile | 1 - kernel/power/pm.c | 205 ------------- 94 files changed, 3040 insertions(+), 1748 deletions(-) diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index c57ce3f..73f3aee 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -163,14 +163,11 @@ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp, if ((mode != 1) && (mode != 5)) return -EINVAL; - retval = pm_send_all(PM_SUSPEND, (void *)3); - if (retval == 0) { if (mode == 5) retval = pm_do_bus_sleep(); else retval = pm_do_suspend(); - pm_send_all(PM_RESUME, (void *)0); } return retval; @@ -183,9 +180,6 @@ static int try_set_cmode(int new_cmode) if (!(clock_cmodes_permitted & (1< 0x100) - set_system_power_state(APM_STATE_REJECT); - err = -EBUSY; - ignore_sys_suspend = 0; - printk(KERN_WARNING "apm: suspend was vetoed.\n"); - goto out; - } - printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n"); - } - device_suspend(PMSG_SUSPEND); local_irq_disable(); device_power_down(PMSG_SUSPEND); @@ -1224,9 +1211,7 @@ static int suspend(int vetoable) device_power_up(); local_irq_enable(); device_resume(); - pm_send_all(PM_RESUME, (void *)0); queue_event(APM_NORMAL_RESUME, NULL); - out: spin_lock(&user_list_lock); for (as = user_list; as != NULL; as = as->next) { as->suspend_wait = 0; @@ -1337,7 +1322,6 @@ static void check_events(void) if ((event != APM_NORMAL_RESUME) || (ignore_normal_resume == 0)) { device_resume(); - pm_send_all(PM_RESUME, (void *)0); queue_event(event, NULL); } ignore_normal_resume = 0; diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 1fa8681..d2fc941 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -201,6 +201,7 @@ static int is_ejectable_bay(acpi_handle handle) return 0; } +#if 0 /** * eject_removable_drive - try to eject this drive * @dev : the device structure of the drive @@ -225,6 +226,7 @@ int eject_removable_drive(struct device *dev) return 0; } EXPORT_SYMBOL_GPL(eject_removable_drive); +#endif /* 0 */ static int acpi_bay_add_fs(struct bay *bay) { diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index f049639..0befcff 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ACPI_FUNCTION_TRACE(ds_create_buffer_field); - /* Get the name_string argument */ - + /* + * Get the name_string argument (name of the new buffer_field) + */ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + + /* For create_field, name is the 4th argument */ + arg = acpi_ps_get_arg(op, 3); } else { - /* Create Bit/Byte/Word/Dword field */ + /* For all other create_xXXField operators, name is the 3rd argument */ arg = acpi_ps_get_arg(op, 2); } @@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, node = walk_state->deferred_node; status = AE_OK; } else { - /* - * During the load phase, we want to enter the name of the field into - * the namespace. During the execute phase (when we evaluate the size - * operand), we want to lookup the name - */ - if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) { - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; - } else { - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND; + /* Execute flag should always be set when this function is entered */ + + if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { + return_ACPI_STATUS(AE_AML_INTERNAL); } - /* - * Enter the name_string into the namespace - */ + /* Creating new namespace node, should not already exist */ + + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* Mark node temporary if we are executing a method */ + + if (walk_state->method_node) { + flags |= ACPI_NS_TEMPORARY; + } + + /* Enter the name_string into the namespace */ + status = acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &(node)); + &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); @@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, /* * We could put the returned object (Node) on the object stack for later, * but for now, we will put it in the "op" object that the parser uses, - * so we can get it again at the end of this scope + * so we can get it again at the end of this scope. */ op->common.node = node; /* * If there is no object attached to the node, this node was just created - * and we need to create the field object. Otherwise, this was a lookup + * and we need to create the field object. Otherwise, this was a lookup * of an existing node and we don't want to create the field object again. */ obj_desc = acpi_ns_get_attached_object(node); @@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, } /* - * Remember location in AML stream of the field unit - * opcode and operands -- since the buffer and index - * operands must be evaluated. + * Remember location in AML stream of the field unit opcode and operands -- + * since the buffer and index operands must be evaluated. */ second_desc = obj_desc->common.next_object; second_desc->extra.aml_start = op->named.data; @@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, case AML_INT_NAMEDFIELD_OP: - /* Lookup the name */ + /* Lookup the name, it should already exist */ status = acpi_ns_lookup(walk_state->scope_info, (char *)&arg->named.name, @@ -272,20 +279,23 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, status); - if (status != AE_ALREADY_EXISTS) { - return_ACPI_STATUS(status); - } - - /* Already exists, ignore error */ + return_ACPI_STATUS(status); } else { arg->common.node = info->field_node; info->field_bit_length = arg->common.value.size; - /* Create and initialize an object for the new Field Node */ - - status = acpi_ex_prep_field_value(info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* + * If there is no object attached to the node, this node was + * just created and we need to create the field object. + * Otherwise, this was a lookup of an existing node and we + * don't want to create the field object again. + */ + if (!acpi_ns_get_attached_object + (info->field_node)) { + status = acpi_ex_prep_field_value(info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } } @@ -399,9 +409,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, union acpi_parse_object *arg = NULL; struct acpi_namespace_node *node; u8 type = 0; + u32 flags; ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); + /* Execute flag should always be set when this function is entered */ + + if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { + if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { + + /* bank_field Op is deferred, just return OK */ + + return_ACPI_STATUS(AE_OK); + } + + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* + * Get the field_list argument for this opcode. This is the start of the + * list of field elements. + */ switch (walk_state->opcode) { case AML_FIELD_OP: arg = acpi_ps_get_arg(op, 2); @@ -422,20 +450,33 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, return_ACPI_STATUS(AE_BAD_PARAMETER); } + if (!arg) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* Creating new namespace node(s), should not already exist */ + + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* Mark node(s) temporary if we are executing a method */ + + if (walk_state->method_node) { + flags |= ACPI_NS_TEMPORARY; + } + /* * Walk the list of entries in the field_list */ while (arg) { - - /* Ignore OFFSET and ACCESSAS terms here */ - + /* + * Ignore OFFSET and ACCESSAS terms here; we are only interested in the + * field names in order to enter them into the namespace. + */ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { status = acpi_ns_lookup(walk_state->scope_info, - (char *)&arg->named.name, - type, ACPI_IMODE_LOAD_PASS1, - ACPI_NS_NO_UPSEARCH | - ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND, + (char *)&arg->named.name, type, + ACPI_IMODE_LOAD_PASS1, flags, walk_state, &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, @@ -452,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, arg->common.node = node; } - /* Move to next field in the list */ + /* Get the next field element in the list */ arg = arg->common.next; } @@ -466,7 +507,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, * * PARAMETERS: Op - Op containing the Field definition and args * region_node - Object for the containing Operation Region - * ` walk_state - Current method state + * walk_state - Current method state * * RETURN: Status * @@ -513,36 +554,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, return_ACPI_STATUS(status); } - /* Third arg is the bank_value */ - - /* TBD: This arg is a term_arg, not a constant, and must be evaluated */ - + /* + * Third arg is the bank_value + * This arg is a term_arg, not a constant + * It will be evaluated later, by acpi_ds_eval_bank_field_operands + */ arg = arg->common.next; - /* Currently, only the following constants are supported */ - - switch (arg->common.aml_opcode) { - case AML_ZERO_OP: - info.bank_value = 0; - break; - - case AML_ONE_OP: - info.bank_value = 1; - break; - - case AML_BYTE_OP: - case AML_WORD_OP: - case AML_DWORD_OP: - case AML_QWORD_OP: - info.bank_value = (u32) arg->common.value.integer; - break; - - default: - info.bank_value = 0; - ACPI_ERROR((AE_INFO, - "Non-constant BankValue for BankField is not implemented")); - } - /* Fourth arg is the field flags */ arg = arg->common.next; @@ -553,8 +571,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); + /* + * Use Info.data_register_node to store bank_field Op + * It's safe because data_register_node will never be used when create bank field + * We store aml_start and aml_length in the bank_field Op for late evaluation + * Used in acpi_ex_prep_field_value(Info) + * + * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? + */ + info.data_register_node = (struct acpi_namespace_node *)op; + status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 1cbe619..9e24641 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -42,7 +42,6 @@ */ #include -#include #include #include #include @@ -102,8 +101,11 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) walk_state->opcode, walk_state->aml_offset, NULL); - (void)acpi_ex_enter_interpreter(); + acpi_ex_enter_interpreter(); } + + acpi_ds_clear_implicit_return(walk_state); + #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { @@ -232,9 +234,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * recursive call. */ if (!walk_state || - !obj_desc->method.mutex->mutex.owner_thread || - (walk_state->thread != - obj_desc->method.mutex->mutex.owner_thread)) { + !obj_desc->method.mutex->mutex.thread_id || + (walk_state->thread->thread_id != + obj_desc->method.mutex->mutex.thread_id)) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) @@ -254,8 +256,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, original_sync_level = walk_state->thread->current_sync_level; - obj_desc->method.mutex->mutex.owner_thread = - walk_state->thread; + obj_desc->method.mutex->mutex.thread_id = + walk_state->thread->thread_id; walk_state->thread->current_sync_level = obj_desc->method.sync_level; } else { @@ -535,8 +537,6 @@ void acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, struct acpi_walk_state *walk_state) { - struct acpi_namespace_node *method_node; - acpi_status status; ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); @@ -551,34 +551,26 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, /* Delete all arguments and locals */ acpi_ds_method_data_delete_all(walk_state); - } - /* - * If method is serialized, release the mutex and restore the - * current sync level for this thread - */ - if (method_desc->method.mutex) { + /* + * If method is serialized, release the mutex and restore the + * current sync level for this thread + */ + if (method_desc->method.mutex) { - /* Acquisition Depth handles recursive calls */ + /* Acquisition Depth handles recursive calls */ - method_desc->method.mutex->mutex.acquisition_depth--; - if (!method_desc->method.mutex->mutex.acquisition_depth) { - walk_state->thread->current_sync_level = - method_desc->method.mutex->mutex. - original_sync_level; + method_desc->method.mutex->mutex.acquisition_depth--; + if (!method_desc->method.mutex->mutex.acquisition_depth) { + walk_state->thread->current_sync_level = + method_desc->method.mutex->mutex. + original_sync_level; - acpi_os_release_mutex(method_desc->method.mutex->mutex. - os_mutex); - method_desc->method.mutex->mutex.owner_thread = NULL; + acpi_os_release_mutex(method_desc->method. + mutex->mutex.os_mutex); + method_desc->method.mutex->mutex.thread_id = 0; + } } - } - - if (walk_state) { - /* - * Delete any objects created by this method during execution. - * The method Node is stored in the walk state - */ - method_node = walk_state->method_node; /* * Delete any namespace objects created anywhere within @@ -620,7 +612,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, */ if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) && (!method_desc->method.mutex)) { - status = acpi_ds_create_method_mutex(method_desc); + (void)acpi_ds_create_method_mutex(method_desc); } /* No more threads, we can free the owner_id */ diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index ba4626e..38510d1 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -172,6 +172,8 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) } } + acpi_ds_clear_implicit_return(walk_state); + return_VOID; } diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 954ac8c..bdef2f0 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -157,7 +157,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, * will remain as named references. This behavior is not described * in the ACPI spec, but it appears to be an oversight. */ - obj_desc = (union acpi_operand_object *)op->common.node; + obj_desc = + ACPI_CAST_PTR(union acpi_operand_object, + op->common.node); status = acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR @@ -172,7 +174,19 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, switch (op->common.node->type) { /* * For these types, we need the actual node, not the subobject. - * However, the subobject got an extra reference count above. + * However, the subobject did not get an extra reference count above. + * + * TBD: should ex_resolve_node_to_value be changed to fix this? + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + acpi_ut_add_reference(op->common.node->object); + + /*lint -fallthrough */ + /* + * For these types, we need the actual node, not the subobject. + * The subobject got an extra reference count in ex_resolve_node_to_value. */ case ACPI_TYPE_MUTEX: case ACPI_TYPE_METHOD: @@ -180,25 +194,15 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - obj_desc = - (union acpi_operand_object *)op->common. - node; + /* We will create a reference object for these types below */ break; default: - break; - } - - /* - * If above resolved to an operand object, we are done. Otherwise, - * we have a NS node, we must create the package entry as a named - * reference. - */ - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != - ACPI_DESC_TYPE_NAMED) { + /* + * All other types - the node was resolved to an actual + * object, we are done. + */ goto exit; } } @@ -223,7 +227,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, exit: *obj_desc_ptr = obj_desc; - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -369,7 +373,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *parent; union acpi_operand_object *obj_desc = NULL; acpi_status status = AE_OK; - acpi_native_uint i; + u32 i; + u16 index; + u16 reference_count; ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); @@ -447,13 +453,60 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, package. elements[i]); } + + if (*obj_desc_ptr) { + + /* Existing package, get existing reference count */ + + reference_count = + (*obj_desc_ptr)->common.reference_count; + if (reference_count > 1) { + + /* Make new element ref count match original ref count */ + + for (index = 0; index < (reference_count - 1); + index++) { + acpi_ut_add_reference((obj_desc-> + package. + elements[i])); + } + } + } + arg = arg->common.next; } - if (!arg) { + /* Check for match between num_elements and actual length of package_list */ + + if (arg) { + /* + * num_elements was exhausted, but there are remaining elements in the + * package_list. + * + * Note: technically, this is an error, from ACPI spec: "It is an error + * for NumElements to be less than the number of elements in the + * PackageList". However, for now, we just print an error message and + * no exception is returned. + */ + while (arg) { + + /* Find out how many elements there really are */ + + i++; + arg = arg->common.next; + } + + ACPI_ERROR((AE_INFO, + "Package List length (%X) larger than NumElements count (%X), truncated\n", + i, element_count)); + } else if (i < element_count) { + /* + * Arg list (elements) was exhausted, but we did not reach num_elements count. + * Note: this is not an error, the package is padded out with NULLs. + */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Package List length larger than NumElements count (%X), truncated\n", - element_count)); + "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", + i, element_count)); } obj_desc->package.flags |= AOPOBJ_DATA_VALID; @@ -721,6 +774,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Node was saved in Op */ obj_desc->reference.node = op->common.node; + obj_desc->reference.object = + op->common.node->object; } obj_desc->reference.opcode = opcode; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index f501e08..35a7efd 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -49,6 +49,7 @@ #include #include #include +#include #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsopcode") @@ -219,6 +220,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) /******************************************************************************* * + * FUNCTION: acpi_ds_get_bank_field_arguments + * + * PARAMETERS: obj_desc - A valid bank_field object + * + * RETURN: Status. + * + * DESCRIPTION: Get bank_field bank_value. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) +{ + union acpi_operand_object *extra_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the AML pointer (method object) and bank_field node */ + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + node = obj_desc->bank_field.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", + acpi_ut_get_node_name(node))); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * * FUNCTION: acpi_ds_get_buffer_arguments * * PARAMETERS: obj_desc - A valid Buffer object @@ -770,7 +815,109 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, - ACPI_FORMAT_UINT64(obj_desc->region.address), + ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ + + obj_desc->region.flags |= AOPOBJ_DATA_VALID; + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_table_region_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from acpi_ds_exec_end_op during data_table_region parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object **operand; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + acpi_native_uint table_index; + struct acpi_table_header *table; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); + + /* + * This is where we evaluate the signature_string and oem_iDString + * and oem_table_iDString of the data_table_region declaration + */ + node = op->common.node; + + /* next_op points to signature_string op */ + + next_op = op->common.value.arg; + + /* + * Evaluate/create the signature_string and oem_iDString + * and oem_table_iDString operands + */ + status = acpi_ds_create_operands(walk_state, next_op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Resolve the signature_string and oem_iDString + * and oem_table_iDString operands + */ + status = acpi_ex_resolve_operands(op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + + operand = &walk_state->operands[0]; + + /* Find the ACPI table */ + + status = acpi_tb_find_table(operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer, &table_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_remove_reference(operand[0]); + acpi_ut_remove_reference(operand[1]); + acpi_ut_remove_reference(operand[2]); + + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + obj_desc->region.address = + (acpi_physical_address) ACPI_TO_INTEGER(table); + obj_desc->region.length = table->length; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, + ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), obj_desc->region.length)); /* Now the address and length are valid for this opregion */ @@ -808,6 +955,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, /* The first operand (for all of these data objects) is the length */ + /* + * Set proper index into operand stack for acpi_ds_obj_stack_push + * invoked inside acpi_ds_create_operand. + */ + walk_state->operand_index = walk_state->num_operands; + status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -878,6 +1031,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, /******************************************************************************* * + * FUNCTION: acpi_ds_eval_bank_field_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid bank_field Op object + * + * RETURN: Status + * + * DESCRIPTION: Get bank_field bank_value + * Called from acpi_ds_exec_end_op during bank_field parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object *operand_desc; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + union acpi_parse_object *arg; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); + + /* + * This is where we evaluate the bank_value field of the + * bank_field declaration + */ + + /* next_op points to the op that holds the Region */ + + next_op = op->common.value.arg; + + /* next_op points to the op that holds the Bank Register */ + + next_op = next_op->common.next; + + /* next_op points to the op that holds the Bank Value */ + + next_op = next_op->common.next; + + /* + * Set proper index into operand stack for acpi_ds_obj_stack_push + * invoked inside acpi_ds_create_operand. + * + * We use walk_state->Operands[0] to store the evaluated bank_value + */ + walk_state->operand_index = 0; + + status = acpi_ds_create_operand(walk_state, next_op, 0); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + + /* + * Get the bank_value operand and save it + * (at Top of stack) + */ + operand_desc = walk_state->operands[0]; + + /* Arg points to the start Bank Field */ + + arg = acpi_ps_get_arg(op, 4); + while (arg) { + + /* Ignore OFFSET and ACCESSAS terms here */ + + if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { + node = arg->common.node; + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + obj_desc->bank_field.value = + (u32) operand_desc->integer.value; + } + + /* Move to next field in the list */ + + arg = arg->common.next; + } + + acpi_ut_remove_reference(operand_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * * FUNCTION: acpi_ds_exec_begin_control_op * * PARAMETERS: walk_list - The list that owns the walk stack @@ -1070,8 +1323,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, * is set to anything other than zero! */ walk_state->return_desc = walk_state->operands[0]; - } else if ((walk_state->results) && - (walk_state->results->results.num_results > 0)) { + } else if (walk_state->result_count) { /* Since we have a real Return(), delete any implicit return */ diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 71503c0..f6c28d7 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, AML_VAR_PACKAGE_OP) || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || (op->common.parent->common.aml_opcode == - AML_INT_EVAL_SUBTREE_OP)) { + AML_INT_EVAL_SUBTREE_OP) + || (op->common.parent->common.aml_opcode == + AML_BANK_FIELD_OP)) { /* * These opcodes allow term_arg(s) as operands and therefore * the operands can be method calls. The result is used. @@ -472,7 +474,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* A valid name must be looked up in the namespace */ if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && - (arg->common.value.string)) { + (arg->common.value.string) && + !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg)); @@ -595,7 +598,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, } else { /* Check for null name case */ - if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { + if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && + !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { /* * If the name is null, this means that this is an * optional result parameter that was not specified @@ -617,7 +621,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_NOT_IMPLEMENTED); } - if (op_info->flags & AML_HAS_RETVAL) { + if ((op_info->flags & AML_HAS_RETVAL) + || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Argument previously created, already stacked\n")); @@ -630,9 +635,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * Use value that was already previously returned * by the evaluation of this argument */ - status = - acpi_ds_result_pop_from_bottom(&obj_desc, - walk_state); + status = acpi_ds_result_pop(&obj_desc, walk_state); if (ACPI_FAILURE(status)) { /* * Only error is underflow, and this indicates @@ -698,27 +701,52 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, { acpi_status status = AE_OK; union acpi_parse_object *arg; + union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; u32 arg_count = 0; + u32 index = walk_state->num_operands; + u32 i; ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); - /* For all arguments in the list... */ + /* Get all arguments in the list */ arg = first_arg; while (arg) { - status = acpi_ds_create_operand(walk_state, arg, arg_count); - if (ACPI_FAILURE(status)) { - goto cleanup; + if (index >= ACPI_OBJ_NUM_OPERANDS) { + return_ACPI_STATUS(AE_BAD_DATA); } - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Arg #%d (%p) done, Arg1=%p\n", arg_count, - arg, first_arg)); + arguments[index] = arg; + walk_state->operands[index] = NULL; /* Move on to next argument, if any */ arg = arg->common.next; arg_count++; + index++; + } + + index--; + + /* It is the appropriate order to get objects from the Result stack */ + + for (i = 0; i < arg_count; i++) { + arg = arguments[index]; + + /* Force the filling of the operand stack in inverse order */ + + walk_state->operand_index = (u8) index; + + status = acpi_ds_create_operand(walk_state, arg, index); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + index--; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Arg #%d (%p) done, Arg1=%p\n", index, arg, + first_arg)); } return_ACPI_STATUS(status); @@ -729,9 +757,112 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, * pop everything off of the operand stack and delete those * objects */ - (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); + acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); + + ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); + return_ACPI_STATUS(status); +} + +/***************************************************************************** + * + * FUNCTION: acpi_ds_evaluate_name_path + * + * PARAMETERS: walk_state - Current state of the parse tree walk, + * the opcode of current operation should be + * AML_INT_NAMEPATH_OP + * + * RETURN: Status + * + * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent + * interpreter object, convert it to value, if needed, duplicate + * it, if needed, and push it onto the current result stack. + * + ****************************************************************************/ + +acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op = walk_state->op; + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *new_obj_desc; + u8 type; + + ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); + + if (!op->common.parent) { + + /* This happens after certain exception processing */ + + goto exit; + } + + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { + + /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ + + goto exit; + } + + status = acpi_ds_create_operand(walk_state, op, 0); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (op->common.flags & ACPI_PARSEOP_TARGET) { + new_obj_desc = *operand; + goto push_result; + } + + type = ACPI_GET_OBJECT_TYPE(*operand); + + status = acpi_ex_resolve_to_value(operand, walk_state); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (type == ACPI_TYPE_INTEGER) { + + /* It was incremented by acpi_ex_resolve_to_value */ + + acpi_ut_remove_reference(*operand); + + status = + acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, + walk_state); + if (ACPI_FAILURE(status)) { + goto exit; + } + } else { + /* + * The object either was anew created or is + * a Namespace node - don't decrement it. + */ + new_obj_desc = *operand; + } + + /* Cleanup for name-path operand */ + + status = acpi_ds_obj_stack_pop(1, walk_state); + if (ACPI_FAILURE(status)) { + walk_state->result_obj = new_obj_desc; + goto exit; + } + + push_result: + + walk_state->result_obj = new_obj_desc; + + status = acpi_ds_result_push(walk_state->result_obj, walk_state); + if (ACPI_SUCCESS(status)) { + + /* Force to take it from stack */ + + op->common.flags |= ACPI_PARSEOP_IN_STACK; + } + + exit: - ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", - (arg_count + 1))); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 69693fa..bfe4450 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -285,11 +285,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, switch (opcode_class) { case AML_CLASS_CONTROL: - status = acpi_ds_result_stack_push(walk_state); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - status = acpi_ds_exec_begin_control_op(walk_state, op); break; @@ -305,20 +300,11 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, status = acpi_ds_load2_begin_op(walk_state, NULL); } - if (op->common.aml_opcode == AML_REGION_OP) { - status = acpi_ds_result_stack_push(walk_state); - } break; case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: - /* - * Most operators with arguments (except create_xxx_field operators) - * Start a new result/operand state - */ - if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) { - status = acpi_ds_result_stack_push(walk_state); - } + break; default: @@ -374,6 +360,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) /* Init the walk state */ walk_state->num_operands = 0; + walk_state->operand_index = 0; walk_state->return_desc = NULL; walk_state->result_obj = NULL; @@ -388,10 +375,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) /* Decode the Opcode Class */ switch (op_class) { - case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */ + case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ + + if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + status = acpi_ds_evaluate_name_path(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } break; - case AML_CLASS_EXECUTE: /* most operators with arguments */ + case AML_CLASS_EXECUTE: /* Most operators with arguments */ /* Build resolved operand stack */ @@ -400,13 +394,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) goto cleanup; } - /* Done with this result state (Now that operand stack is built) */ - - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - /* * All opcodes require operand resolution, with the only exceptions * being the object_type and size_of operators. @@ -487,16 +474,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) status = acpi_ds_exec_end_control_op(walk_state, op); - /* 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: @@ -516,7 +493,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) op->common.node = (struct acpi_namespace_node *)op->asl.value. - arg->asl.node->object; + arg->asl.node; acpi_ut_add_reference(op->asl.value.arg->asl. node->object); return_ACPI_STATUS(AE_OK); @@ -632,13 +609,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) break; } - /* Done with result state (Now that operand stack is built) */ - - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - /* * If a result object was returned from above, push it on the * current result stack @@ -671,8 +641,28 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { break; } + } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing DataTableRegion Strings Op=%p\n", + op)); + + status = + acpi_ds_eval_table_region_operands + (walk_state, op); + if (ACPI_FAILURE(status)) { + break; + } + } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing BankField Op=%p\n", + op)); - status = acpi_ds_result_stack_pop(walk_state); + status = + acpi_ds_eval_bank_field_operands(walk_state, + op); + if (ACPI_FAILURE(status)) { + break; + } } break; diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 8ab9d1b..775b183 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -443,6 +443,15 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + REGION_DATA_TABLE, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } } #endif @@ -767,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, acpi_ns_lookup(walk_state->scope_info, buffer_ptr, object_type, ACPI_IMODE_LOAD_PASS2, flags, walk_state, &node); + + if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "***New Node [%4.4s] %p is temporary\n", + acpi_ut_get_node_name(node), node)); + } break; } @@ -823,6 +838,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) struct acpi_namespace_node *new_node; #ifndef ACPI_NO_METHOD_EXECUTION u32 i; + u8 region_space; #endif ACPI_FUNCTION_TRACE(ds_load2_end_op); @@ -1003,11 +1019,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) status = acpi_ex_create_event(walk_state); break; - case AML_DATA_REGION_OP: - - status = acpi_ex_create_table_region(walk_state); - break; - case AML_ALIAS_OP: status = acpi_ex_create_alias(walk_state); @@ -1035,6 +1046,15 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) switch (op->common.aml_opcode) { #ifndef ACPI_NO_METHOD_EXECUTION case AML_REGION_OP: + case AML_DATA_REGION_OP: + + if (op->common.aml_opcode == AML_REGION_OP) { + region_space = (acpi_adr_space_type) + ((op->common.value.arg)->common.value. + integer); + } else { + region_space = REGION_DATA_TABLE; + } /* * If we are executing a method, initialize the region @@ -1043,10 +1063,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) status = acpi_ex_create_region(op->named.data, op->named.length, - (acpi_adr_space_type) - ((op->common.value. - arg)->common.value. - integer), + region_space, walk_state); if (ACPI_FAILURE(status)) { return (status); diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 5afcdd9..4c402be 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -49,85 +49,9 @@ #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dswstate") -/* Local prototypes */ -#ifdef ACPI_OBSOLETE_FUNCTIONS -acpi_status -acpi_ds_result_insert(void *object, - u32 index, struct acpi_walk_state *walk_state); - -acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state *walk_state); - -acpi_status -acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, - struct acpi_walk_state *walk_state); - -void *acpi_ds_obj_stack_get_value(u32 index, - struct acpi_walk_state *walk_state); -#endif - -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_remove - * - * PARAMETERS: Object - Where to return the popped object - * Index - Where to extract the object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In - * other words, this is a FIFO. - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_remove(union acpi_operand_object **object, - u32 index, struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_NAME(ds_result_remove); - - state = walk_state->results; - if (!state) { - ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", - walk_state)); - return (AE_NOT_EXIST); - } - - if (index >= ACPI_OBJ_MAX_OPERAND) { - ACPI_ERROR((AE_INFO, - "Index out of range: %X State=%p Num=%X", - index, walk_state, state->results.num_results)); - } - - /* Check for a valid result object */ - - if (!state->results.obj_desc[index]) { - ACPI_ERROR((AE_INFO, - "Null operand! State=%p #Ops=%X, Index=%X", - walk_state, state->results.num_results, index)); - return (AE_AML_NO_RETURN_VALUE); - } - - /* Remove the object */ - - state->results.num_results--; - - *object = state->results.obj_desc[index]; - state->results.obj_desc[index] = NULL; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] Index=%X State=%p Num=%X\n", - *object, - (*object) ? acpi_ut_get_object_type_name(*object) : - "NULL", index, walk_state, - state->results.num_results)); - - return (AE_OK); -} -#endif /* ACPI_FUTURE_USAGE */ + /* Local prototypes */ +static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); /******************************************************************************* * @@ -138,122 +62,67 @@ acpi_ds_result_remove(union acpi_operand_object **object, * * RETURN: Status * - * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In - * other words, this is a FIFO. + * DESCRIPTION: Pop an object off the top of this walk's result stack * ******************************************************************************/ acpi_status -acpi_ds_result_pop(union acpi_operand_object ** object, - struct acpi_walk_state * walk_state) +acpi_ds_result_pop(union acpi_operand_object **object, + struct acpi_walk_state *walk_state) { acpi_native_uint index; union acpi_generic_state *state; + acpi_status status; ACPI_FUNCTION_NAME(ds_result_pop); state = walk_state->results; - if (!state) { - return (AE_OK); - } - - if (!state->results.num_results) { - ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", - walk_state)); - return (AE_AML_NO_RETURN_VALUE); - } - /* Remove top element */ + /* Incorrect state of result stack */ - state->results.num_results--; - - for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { - - /* Check for a valid result object */ - - if (state->results.obj_desc[index - 1]) { - *object = state->results.obj_desc[index - 1]; - state->results.obj_desc[index - 1] = NULL; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] Index=%X State=%p Num=%X\n", - *object, - (*object) ? - acpi_ut_get_object_type_name(*object) - : "NULL", (u32) index - 1, walk_state, - state->results.num_results)); - - return (AE_OK); - } + if (state && !walk_state->result_count) { + ACPI_ERROR((AE_INFO, "No results on result stack")); + return (AE_AML_INTERNAL); } - ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state)); - return (AE_AML_NO_RETURN_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_pop_from_bottom - * - * PARAMETERS: Object - Where to return the popped object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In - * other words, this is a FIFO. - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, - struct acpi_walk_state * walk_state) -{ - acpi_native_uint index; - union acpi_generic_state *state; + if (!state && walk_state->result_count) { + ACPI_ERROR((AE_INFO, "No result state for result stack")); + return (AE_AML_INTERNAL); + } - ACPI_FUNCTION_NAME(ds_result_pop_from_bottom); + /* Empty result stack */ - state = walk_state->results; if (!state) { - ACPI_ERROR((AE_INFO, - "No result object pushed! State=%p", walk_state)); - return (AE_NOT_EXIST); - } - - if (!state->results.num_results) { - ACPI_ERROR((AE_INFO, "No result objects! State=%p", + ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } - /* Remove Bottom element */ - - *object = state->results.obj_desc[0]; - - /* Push entire stack down one element */ - - for (index = 0; index < state->results.num_results; index++) { - state->results.obj_desc[index] = - state->results.obj_desc[index + 1]; - } + /* Return object of the top element and clean that top element result stack */ - state->results.num_results--; - - /* Check for a valid result object */ + walk_state->result_count--; + index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; + *object = state->results.obj_desc[index]; if (!*object) { ACPI_ERROR((AE_INFO, - "Null operand! State=%p #Ops=%X Index=%X", - walk_state, state->results.num_results, - (u32) index)); + "No result objects on result stack, State=%p", + walk_state)); return (AE_AML_NO_RETURN_VALUE); } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n", - *object, - (*object) ? acpi_ut_get_object_type_name(*object) : - "NULL", state, walk_state)); + state->results.obj_desc[index] = NULL; + if (index == 0) { + status = acpi_ds_result_stack_pop(walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, + acpi_ut_get_object_type_name(*object), + (u32) index, walk_state, walk_state->result_count)); return (AE_OK); } @@ -276,39 +145,56 @@ acpi_ds_result_push(union acpi_operand_object * object, struct acpi_walk_state * walk_state) { union acpi_generic_state *state; + acpi_status status; + acpi_native_uint index; ACPI_FUNCTION_NAME(ds_result_push); + if (walk_state->result_count > walk_state->result_size) { + ACPI_ERROR((AE_INFO, "Result stack is full")); + return (AE_AML_INTERNAL); + } else if (walk_state->result_count == walk_state->result_size) { + + /* Extend the result stack */ + + status = acpi_ds_result_stack_push(walk_state); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Failed to extend the result stack")); + return (status); + } + } + + if (!(walk_state->result_count < walk_state->result_size)) { + ACPI_ERROR((AE_INFO, "No free elements in result stack")); + return (AE_AML_INTERNAL); + } + state = walk_state->results; if (!state) { ACPI_ERROR((AE_INFO, "No result stack frame during push")); return (AE_AML_INTERNAL); } - if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) { - ACPI_ERROR((AE_INFO, - "Result stack overflow: Obj=%p State=%p Num=%X", - object, walk_state, state->results.num_results)); - return (AE_STACK_OVERFLOW); - } - if (!object) { ACPI_ERROR((AE_INFO, "Null Object! Obj=%p State=%p Num=%X", - object, walk_state, state->results.num_results)); + object, walk_state, walk_state->result_count)); return (AE_BAD_PARAMETER); } - state->results.obj_desc[state->results.num_results] = object; - state->results.num_results++; + /* Assign the address of object to the top free element of result stack */ + + index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; + state->results.obj_desc[index] = object; + walk_state->result_count++; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", object, - object ? acpi_ut_get_object_type_name((union acpi_operand_object *) - object) : "NULL", - walk_state, state->results.num_results, + object), walk_state, + walk_state->result_count, walk_state->current_result)); return (AE_OK); @@ -322,16 +208,25 @@ acpi_ds_result_push(union acpi_operand_object * object, * * RETURN: Status * - * DESCRIPTION: Push an object onto the walk_state result stack. + * DESCRIPTION: Push an object onto the walk_state result stack * ******************************************************************************/ -acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) +static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_stack_push); + /* Check for stack overflow */ + + if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > + ACPI_RESULTS_OBJ_NUM_MAX) { + ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", + walk_state, walk_state->result_size)); + return (AE_STACK_OVERFLOW); + } + state = acpi_ut_create_generic_state(); if (!state) { return (AE_NO_MEMORY); @@ -340,6 +235,10 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; acpi_ut_push_generic_state(&walk_state->results, state); + /* Increase the length of the result stack by the length of frame */ + + walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", state, walk_state)); @@ -354,11 +253,11 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) * * RETURN: Status * - * DESCRIPTION: Pop an object off of the walk_state result stack. + * DESCRIPTION: Pop an object off of the walk_state result stack * ******************************************************************************/ -acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; @@ -367,18 +266,27 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) /* Check for stack underflow */ if (walk_state->results == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Result stack underflow - State=%p\n", walk_state)); return (AE_AML_NO_OPERAND); } + if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { + ACPI_ERROR((AE_INFO, "Insufficient result stack size")); + return (AE_AML_INTERNAL); + } + state = acpi_ut_pop_generic_state(&walk_state->results); + acpi_ut_delete_generic_state(state); + + /* Decrease the length of result stack by the length of frame */ + + walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Result=%p RemainingResults=%X State=%p\n", - state, state->results.num_results, walk_state)); - - acpi_ut_delete_generic_state(state); + state, walk_state->result_count, walk_state)); return (AE_OK); } @@ -412,9 +320,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) /* Put the object onto the stack */ - walk_state->operands[walk_state->num_operands] = object; + walk_state->operands[walk_state->operand_index] = object; walk_state->num_operands++; + /* For the usual order of filling the operand stack */ + + walk_state->operand_index++; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", object, acpi_ut_get_object_type_name((union @@ -484,43 +396,36 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) * ******************************************************************************/ -acpi_status +void acpi_ds_obj_stack_pop_and_delete(u32 pop_count, - struct acpi_walk_state * walk_state) + struct acpi_walk_state *walk_state) { - u32 i; + acpi_native_int i; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); - for (i = 0; i < pop_count; i++) { - - /* Check for stack underflow */ + if (pop_count == 0) { + return; + } + for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) { if (walk_state->num_operands == 0) { - ACPI_ERROR((AE_INFO, - "Object stack underflow! Count=%X State=%p #Ops=%X", - pop_count, walk_state, - walk_state->num_operands)); - return (AE_STACK_UNDERFLOW); + return; } /* Pop the stack and delete an object if present in this stack entry */ walk_state->num_operands--; - obj_desc = walk_state->operands[walk_state->num_operands]; + obj_desc = walk_state->operands[i]; if (obj_desc) { - acpi_ut_remove_reference(walk_state-> - operands[walk_state-> - num_operands]); - walk_state->operands[walk_state->num_operands] = NULL; + acpi_ut_remove_reference(walk_state->operands[i]); + walk_state->operands[i] = NULL; } } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", pop_count, walk_state, walk_state->num_operands)); - - return (AE_OK); } /******************************************************************************* @@ -560,7 +465,7 @@ struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state * * RETURN: None * - * DESCRIPTION: Place the Thread state at the head of the state list. + * DESCRIPTION: Place the Thread state at the head of the state list * ******************************************************************************/ @@ -636,7 +541,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union *thread) { struct acpi_walk_state *walk_state; - acpi_status status; ACPI_FUNCTION_TRACE(ds_create_walk_state); @@ -659,14 +563,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_ds_method_data_init(walk_state); #endif - /* Create an initial result stack entry */ - - status = acpi_ds_result_stack_push(walk_state); - if (ACPI_FAILURE(status)) { - ACPI_FREE(walk_state); - return_PTR(NULL); - } - /* Put the new state at the head of the walk list */ if (thread) { @@ -860,190 +756,3 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) ACPI_FREE(walk_state); return_VOID; } - -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_insert - * - * PARAMETERS: Object - Object to push - * Index - Where to insert the object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Insert an object onto this walk's result stack - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_insert(void *object, - u32 index, struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_NAME(ds_result_insert); - - state = walk_state->results; - if (!state) { - ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", - walk_state)); - return (AE_NOT_EXIST); - } - - if (index >= ACPI_OBJ_NUM_OPERANDS) { - ACPI_ERROR((AE_INFO, - "Index out of range: %X Obj=%p State=%p Num=%X", - index, object, walk_state, - state->results.num_results)); - return (AE_BAD_PARAMETER); - } - - if (!object) { - ACPI_ERROR((AE_INFO, - "Null Object! Index=%X Obj=%p State=%p Num=%X", - index, object, walk_state, - state->results.num_results)); - return (AE_BAD_PARAMETER); - } - - state->results.obj_desc[index] = object; - state->results.num_results++; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] State=%p Num=%X Cur=%X\n", - object, - object ? - acpi_ut_get_object_type_name((union - acpi_operand_object *) - object) : "NULL", - walk_state, state->results.num_results, - walk_state->current_result)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_delete_all - * - * PARAMETERS: walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Clear the object stack by deleting all objects that are on it. - * Should be used with great care, if at all! - * - ******************************************************************************/ - -acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state) -{ - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state); - - /* The stack size is configurable, but fixed */ - - for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) { - if (walk_state->operands[i]) { - acpi_ut_remove_reference(walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_pop_object - * - * PARAMETERS: Object - Where to return the popped object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT - * deleted by this routine. - * - ******************************************************************************/ - -acpi_status -acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, - struct acpi_walk_state *walk_state) -{ - ACPI_FUNCTION_NAME(ds_obj_stack_pop_object); - - /* Check for stack underflow */ - - if (walk_state->num_operands == 0) { - ACPI_ERROR((AE_INFO, - "Missing operand/stack empty! State=%p #Ops=%X", - walk_state, walk_state->num_operands)); - *object = NULL; - return (AE_AML_NO_OPERAND); - } - - /* Pop the stack */ - - walk_state->num_operands--; - - /* Check for a valid operand */ - - if (!walk_state->operands[walk_state->num_operands]) { - ACPI_ERROR((AE_INFO, - "Null operand! State=%p #Ops=%X", - walk_state, walk_state->num_operands)); - *object = NULL; - return (AE_AML_NO_OPERAND); - } - - /* Get operand and set stack entry to null */ - - *object = walk_state->operands[walk_state->num_operands]; - walk_state->operands[walk_state->num_operands] = NULL; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", - *object, acpi_ut_get_object_type_name(*object), - walk_state, walk_state->num_operands)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_get_value - * - * PARAMETERS: Index - Stack index whose value is desired. Based - * on the top of the stack (index=0 == top) - * walk_state - Current Walk state - * - * RETURN: Pointer to the requested operand - * - * DESCRIPTION: Retrieve an object from this walk's operand stack. Index must - * be within the range of the current stack pointer. - * - ******************************************************************************/ - -void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state); - - /* Can't do it if the stack is empty */ - - if (walk_state->num_operands == 0) { - return_PTR(NULL); - } - - /* or if the index is past the top of the stack */ - - if (index > (walk_state->num_operands - (u32) 1)) { - return_PTR(NULL); - } - - return_PTR(walk_state-> - operands[(acpi_native_uint) (walk_state->num_operands - 1) - - index]); -} -#endif diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7222a18..3d93621 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -73,38 +73,14 @@ enum ec_event { #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ enum { EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ - EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ - EC_FLAGS_ADDRESS, /* Address is being written */ - EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ - EC_FLAGS_WDATA, /* Data is being written */ - EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ -}; - -static int acpi_ec_remove(struct acpi_device *device, int type); -static int acpi_ec_start(struct acpi_device *device); -static int acpi_ec_stop(struct acpi_device *device, int type); -static int acpi_ec_add(struct acpi_device *device); - -static const struct acpi_device_id ec_device_ids[] = { - {"PNP0C09", 0}, - {"", 0}, -}; - -static struct acpi_driver acpi_ec_driver = { - .name = "ec", - .class = ACPI_EC_CLASS, - .ids = ec_device_ids, - .ops = { - .add = acpi_ec_add, - .remove = acpi_ec_remove, - .start = acpi_ec_start, - .stop = acpi_ec_stop, - }, + EC_FLAGS_NO_GPE, /* Don't use GPE mode */ + EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -129,6 +105,8 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; + struct delayed_work work; + atomic_t irq_count; u8 handlers_installed; } *boot_ec, *first_ec; @@ -177,65 +155,52 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +static void ec_schedule_ec_poll(struct acpi_ec *ec) { - int ret = 0; + if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) + schedule_delayed_work(&ec->work, + msecs_to_jiffies(ACPI_EC_DELAY)); +} - if (unlikely(event == ACPI_EC_EVENT_OBF_1 && - test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) - force_poll = 1; - if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && - test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) - force_poll = 1; - if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && - test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) - force_poll = 1; +static void ec_switch_to_poll_mode(struct acpi_ec *ec) +{ + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); +} + +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +{ + atomic_set(&ec->irq_count, 0); if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && likely(!force_poll)) { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), msecs_to_jiffies(ACPI_EC_DELAY))) - goto end; + return 0; clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (acpi_ec_check_status(ec, event)) { - if (event == ACPI_EC_EVENT_OBF_1) { - /* miss OBF_1 GPE, don't expect it */ - pr_info(PREFIX "missing OBF confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); - } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { - /* miss address GPE, don't expect it anymore */ - pr_info(PREFIX "missing address confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); - } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { - /* miss write data GPE, don't expect it */ - pr_info(PREFIX "missing write data confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); - } else { - /* missing GPEs, switch back to poll mode */ - if (printk_ratelimit()) - pr_info(PREFIX "missing confirmations, " + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " "switch off interrupt mode.\n"); - clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - } - goto end; + ec_switch_to_poll_mode(ec); + ec_schedule_ec_poll(ec); + return 0; } } else { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) - goto end; + return 0; + udelay(ACPI_EC_UDELAY); } } - pr_err(PREFIX "acpi_ec_wait timeout," - " status = %d, expect_event = %d\n", - acpi_ec_read_status(ec), event); - ret = -ETIME; - end: - clear_bit(EC_FLAGS_ADDRESS, &ec->flags); - return ret; + pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", + acpi_ec_read_status(ec), + (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); + return -ETIME; } static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, @@ -245,8 +210,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, { int result = 0; set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - acpi_ec_write_cmd(ec, command); pr_debug(PREFIX "transaction start\n"); + acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { @@ -254,15 +219,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, "write_cmd timeout, command = %d\n", command); goto end; } - /* mark the address byte written to EC */ - if (rdata_len + wdata_len > 1) - set_bit(EC_FLAGS_ADDRESS, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { - set_bit(EC_FLAGS_WDATA, &ec->flags); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { pr_err(PREFIX @@ -527,47 +488,51 @@ static u32 acpi_ec_gpe_handler(void *data) { acpi_status status = AE_OK; struct acpi_ec *ec = data; + u8 state = acpi_ec_read_status(ec); pr_debug(PREFIX "~~~> interrupt\n"); + atomic_inc(&ec->irq_count); + if (atomic_read(&ec->irq_count) > 5) { + pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); + ec_switch_to_poll_mode(ec); + goto end; + } clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) { + if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); - } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { + } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && + in_interrupt()) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) pr_info(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); + clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } - +end: + ec_schedule_ec_poll(ec); return ACPI_SUCCESS(status) ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } +static void do_ec_poll(struct work_struct *work) +{ + struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); + atomic_set(&ec->irq_count, 0); + (void)acpi_ec_gpe_handler(ec); +} + /* -------------------------------------------------------------------------- Address Space Management -------------------------------------------------------------------------- */ static acpi_status -acpi_ec_space_setup(acpi_handle region_handle, - u32 function, void *handler_context, void **return_context) -{ - /* - * The EC object is in the handler context and is needed - * when calling the acpi_ec_space_handler. - */ - *return_context = (function != ACPI_REGION_DEACTIVATE) ? - handler_context : NULL; - - return AE_OK; -} - -static acpi_status acpi_ec_space_handler(u32 function, acpi_physical_address address, u32 bits, acpi_integer *value, void *handler_context, void *region_context) @@ -709,6 +674,8 @@ static struct acpi_ec *make_acpi_ec(void) mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); + INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); + atomic_set(&ec->irq_count, 0); return ec; } @@ -741,17 +708,21 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); if (ACPI_FAILURE(status)) return status; - /* Find and register all query methods */ - acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, - acpi_ec_register_query_methods, ec, NULL); /* Use the global lock for all EC transactions? */ acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); ec->handle = handle; return AE_CTRL_TERMINATE; } +static void ec_poll_stop(struct acpi_ec *ec) +{ + clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + cancel_delayed_work(&ec->work); +} + static void ec_remove_handlers(struct acpi_ec *ec) { + ec_poll_stop(ec); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) pr_err(PREFIX "failed to remove space handler\n"); @@ -771,31 +742,28 @@ static int acpi_ec_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_EC_CLASS); /* Check for boot EC */ - if (boot_ec) { - if (boot_ec->handle == device->handle) { - /* Pre-loaded EC from DSDT, just move pointer */ - ec = boot_ec; - boot_ec = NULL; - goto end; - } else if (boot_ec->handle == ACPI_ROOT_OBJECT) { - /* ECDT-based EC, time to shut it down */ - ec_remove_handlers(boot_ec); - kfree(boot_ec); - first_ec = boot_ec = NULL; + if (boot_ec && + (boot_ec->handle == device->handle || + boot_ec->handle == ACPI_ROOT_OBJECT)) { + ec = boot_ec; + boot_ec = NULL; + } else { + ec = make_acpi_ec(); + if (!ec) + return -ENOMEM; + if (ec_parse_device(device->handle, 0, ec, NULL) != + AE_CTRL_TERMINATE) { + kfree(ec); + return -EINVAL; } } - ec = make_acpi_ec(); - if (!ec) - return -ENOMEM; - - if (ec_parse_device(device->handle, 0, ec, NULL) != - AE_CTRL_TERMINATE) { - kfree(ec); - return -EINVAL; - } ec->handle = device->handle; - end: + + /* Find and register all query methods */ + acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, + acpi_ec_register_query_methods, ec, NULL); + if (!first_ec) first_ec = ec; acpi_driver_data(device) = ec; @@ -870,7 +838,7 @@ static int ec_install_handlers(struct acpi_ec *ec) status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, - &acpi_ec_space_setup, ec); + NULL, ec); if (ACPI_FAILURE(status)) { acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); return -ENODEV; @@ -897,6 +865,7 @@ static int acpi_ec_start(struct acpi_device *device) /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + ec_schedule_ec_poll(ec); return ret; } @@ -924,6 +893,11 @@ int __init acpi_boot_ec_enable(void) return -EFAULT; } +static const struct acpi_device_id ec_device_ids[] = { + {"PNP0C09", 0}, + {"", 0}, +}; + int __init acpi_ec_ecdt_probe(void) { int ret; @@ -944,6 +918,7 @@ int __init acpi_ec_ecdt_probe(void) boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; + acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); } else { /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ @@ -973,6 +948,39 @@ int __init acpi_ec_ecdt_probe(void) return -ENODEV; } +static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) +{ + struct acpi_ec *ec = acpi_driver_data(device); + /* Stop using GPE */ + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + return 0; +} + +static int acpi_ec_resume(struct acpi_device *device) +{ + struct acpi_ec *ec = acpi_driver_data(device); + /* Enable use of GPE back */ + clear_bit(EC_FLAGS_NO_GPE, &ec->flags); + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + return 0; +} + +static struct acpi_driver acpi_ec_driver = { + .name = "ec", + .class = ACPI_EC_CLASS, + .ids = ec_device_ids, + .ops = { + .add = acpi_ec_add, + .remove = acpi_ec_remove, + .start = acpi_ec_start, + .stop = acpi_ec_stop, + .suspend = acpi_ec_suspend, + .resume = acpi_ec_resume, + }, +}; + static int __init acpi_ec_init(void) { int result = 0; diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 0dadd2a..904db24 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -248,7 +248,14 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) ACPI_FUNCTION_TRACE(ev_disable_gpe); - if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { + /* + * Ignore this if the GPE is valid and not enabled. + * + * Flags is only zero if GPE is neither enabled or disabled -- it may + * be a spurious or stray GPE -- disable it in the default case below. + */ + if (gpe_event_info->flags && + (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK))) { return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 21cb749..16cf270 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -49,22 +49,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evmisc") -/* Names for Notify() values, used for debug output */ -#ifdef ACPI_DEBUG_OUTPUT -static const char *acpi_notify_value_names[] = { - "Bus Check", - "Device Check", - "Device Wake", - "Eject Request", - "Device Check Light", - "Frequency Mismatch", - "Bus Mode Mismatch", - "Power Fault" -}; -#endif - /* Pointer to FACS needed for the Global Lock */ - static struct acpi_table_facs *facs = NULL; /* Local prototypes */ @@ -94,7 +79,6 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) switch (node->type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: /* * These are the ONLY objects that can receive ACPI notifications @@ -139,17 +123,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Dispatching Notify(%X) on node %p\n", notify_value, - node)); - - if (notify_value <= 7) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n", - acpi_notify_value_names[notify_value])); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Notify value: 0x%2.2X **Device Specific**\n", - notify_value)); - } + "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", + acpi_ut_get_node_name(node), node, notify_value, + acpi_ut_get_notify_name(notify_value))); /* Get the notify object attached to the NS Node */ @@ -159,10 +135,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, /* We have the notify object, Get the right handler */ switch (node->type) { + + /* Notify allowed only on these types */ + case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { handler_obj = @@ -179,8 +157,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, } } - /* If there is any handler to run, schedule the dispatcher */ - + /* + * If there is any handler to run, schedule the dispatcher. + * Check for: + * 1) Global system notify handler + * 2) Global device notify handler + * 3) Per-device notify handler + */ if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || (acpi_gbl_device_notify.handler @@ -190,6 +173,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, return (AE_NO_MEMORY); } + if (!handler_obj) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Executing system notify handler for Notify (%4.4s, %X) node %p\n", + acpi_ut_get_node_name(node), + notify_value, node)); + } + notify_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; @@ -202,15 +192,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(notify_info); } - } - - if (!handler_obj) { + } else { /* - * There is no per-device notify handler for this device. - * This may or may not be a problem. + * There is no notify handler (per-device or system) for this device. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No notify handler for Notify(%4.4s, %X) node %p\n", + "No notify handler for Notify (%4.4s, %X) node %p\n", acpi_ut_get_node_name(node), notify_value, node)); } @@ -349,9 +336,10 @@ acpi_status acpi_ev_init_global_lock_handler(void) ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -439,7 +427,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) * Only one thread can acquire the GL at a time, the global_lock_mutex * enforces this. This interface releases the interpreter if we must wait. */ - status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); + status = acpi_ex_system_wait_mutex( + acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); if (status == AE_TIME) { if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { acpi_ev_global_lock_acquired++; @@ -448,9 +437,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) } if (ACPI_FAILURE(status)) { - status = - acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, - timeout); + status = acpi_ex_system_wait_mutex( + acpi_gbl_global_lock_mutex->mutex.os_mutex, + timeout); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -460,6 +449,19 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) acpi_ev_global_lock_acquired++; /* + * Update the global lock handle and check for wraparound. The handle is + * only used for the external global lock interfaces, but it is updated + * here to properly handle the case where a single thread may acquire the + * lock via both the AML and the acpi_acquire_global_lock interfaces. The + * handle is therefore updated on the first acquire from a given thread + * regardless of where the acquisition request originated. + */ + acpi_gbl_global_lock_handle++; + if (acpi_gbl_global_lock_handle == 0) { + acpi_gbl_global_lock_handle = 1; + } + + /* * Make sure that a global lock actually exists. If not, just treat * the lock as a standard mutex. */ @@ -555,7 +557,7 @@ acpi_status acpi_ev_release_global_lock(void) /* Release the local GL mutex */ acpi_ev_global_lock_thread_id = NULL; acpi_ev_global_lock_acquired = 0; - acpi_os_release_mutex(acpi_gbl_global_lock_mutex); + acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 58ad097..03624e9 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -394,7 +394,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", ®ion_obj->region.handler->address_space, handler, - ACPI_FORMAT_UINT64(address), + ACPI_FORMAT_NATIVE_UINT(address), acpi_ut_get_region_name(region_obj->region. space_id))); diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 6d866a0..412cae6 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -758,6 +758,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) * * DESCRIPTION: Acquire the ACPI Global Lock * + * Note: Allows callers with the same thread ID to acquire the global lock + * multiple times. In other words, externally, the behavior of the global lock + * is identical to an AML mutex. On the first acquire, a new handle is + * returned. On any subsequent calls to acquire by the same thread, the same + * handle is returned. + * ******************************************************************************/ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) { @@ -770,14 +776,19 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) /* Must lock interpreter to prevent race conditions */ acpi_ex_enter_interpreter(); - status = acpi_ev_acquire_global_lock(timeout); - acpi_ex_exit_interpreter(); + + status = acpi_ex_acquire_mutex_object(timeout, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); if (ACPI_SUCCESS(status)) { - acpi_gbl_global_lock_handle++; + + /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ + *handle = acpi_gbl_global_lock_handle; } + acpi_ex_exit_interpreter(); return (status); } @@ -798,11 +809,11 @@ acpi_status acpi_release_global_lock(u32 handle) { acpi_status status; - if (handle != acpi_gbl_global_lock_handle) { + if (!handle || (handle != acpi_gbl_global_lock_handle)) { return (AE_NOT_ACQUIRED); } - status = acpi_ev_release_global_lock(); + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); return (status); } diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 25802f3..ed92fb5 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); + /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + + if ((operand[0]->string.length > ACPI_NAME_SIZE) || + (operand[1]->string.length > ACPI_OEM_ID_SIZE) || + (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + /* Find the ACPI table in the RSDT/XSDT */ status = acpi_tb_find_table(operand[0]->string.pointer, @@ -229,11 +236,18 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, status = acpi_get_table_by_index(table_index, &table); if (ACPI_SUCCESS(status)) { ACPI_INFO((AE_INFO, - "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", + "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", table->signature, table->oem_id, table->oem_table_id)); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, + acpi_gbl_table_handler_context); + } + *return_desc = ddb_handle; return_ACPI_STATUS(status); } @@ -268,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_table_desc table_desc; acpi_native_uint table_index; acpi_status status; + u32 length; ACPI_FUNCTION_TRACE(ex_load_op); @@ -278,16 +293,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", + obj_desc, + acpi_ut_get_object_type_name(obj_desc))); + /* Region must be system_memory (from ACPI spec) */ if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", - obj_desc, - acpi_ut_get_object_type_name(obj_desc))); - /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. @@ -299,6 +314,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } } + /* + * We will simply map the memory region for the table. However, the + * memory region is technically not guaranteed to remain stable and + * we may eventually have to copy the table to a local buffer. + */ table_desc.address = obj_desc->region.address; table_desc.length = obj_desc->region.length; table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; @@ -306,18 +326,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ - /* Simply extract the buffer from the buffer object */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Buffer or Field %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); - table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, - obj_desc->buffer.pointer); - table_desc.length = table_desc.pointer->length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + length = obj_desc->buffer.length; + + /* Must have at least an ACPI table header */ + + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* Validate checksum here. It won't get validated in tb_add_table */ - obj_desc->buffer.pointer = NULL; + status = + acpi_tb_verify_checksum(ACPI_CAST_PTR + (struct acpi_table_header, + obj_desc->buffer.pointer), length); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * We need to copy the buffer since the original buffer could be + * changed or deleted in the future + */ + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, + length); + table_desc.length = length; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; break; default: @@ -333,7 +376,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } status = - acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); + acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, + &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ @@ -349,11 +393,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* table_ptr was deallocated above */ + acpi_ut_remove_reference(ddb_handle); return_ACPI_STATUS(status); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, + table_desc.pointer, + acpi_gbl_table_handler_context); + } + cleanup: if (ACPI_FAILURE(status)) { + + /* Delete allocated buffer or mapping */ + acpi_tb_delete_table(&table_desc); } return_ACPI_STATUS(status); @@ -376,6 +432,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; acpi_native_uint table_index; + struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_unload_table); @@ -395,17 +452,25 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) table_index = (acpi_native_uint) table_desc->reference.object; + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_SUCCESS(status)) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, + table, + acpi_gbl_table_handler_context); + } + } + /* * Delete the entire namespace under this table Node * (Offset contains the table_id) */ acpi_tb_delete_namespace_by_owner(table_index); - acpi_tb_release_owner_id(table_index); + (void)acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); - /* Delete the table descriptor (ddb_handle) */ - - acpi_ut_remove_reference(table_desc); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 6e9a23e..0396bd4 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -96,6 +96,9 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) * to the original Node. */ switch (target_node->type) { + + /* For these types, the sub-object can change dynamically via a Store */ + case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -103,9 +106,18 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_BUFFER_FIELD: /* + * These types open a new scope, so we need the NS node in order to access + * any children. + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + /* * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. This is because for these - * types, the object can change dynamically via a Store. + * NS node, not the object itself. */ alias_node->type = ACPI_TYPE_LOCAL_ALIAS; alias_node->object = @@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_METHOD: /* - * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. This is because for these - * types, the object can change dynamically via a Store. + * Control method aliases need to be differentiated */ alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; alias_node->object = @@ -342,101 +352,6 @@ acpi_ex_create_region(u8 * aml_start, /******************************************************************************* * - * FUNCTION: acpi_ex_create_table_region - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new data_table_region object - * - ******************************************************************************/ - -acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - union acpi_operand_object *region_obj2; - acpi_native_uint table_index; - struct acpi_table_header *table; - - ACPI_FUNCTION_TRACE(ex_create_table_region); - - /* Get the Node from the object stack */ - - node = walk_state->op->common.node; - - /* - * If the region object is already attached to this node, - * just return - */ - if (acpi_ns_get_attached_object(node)) { - return_ACPI_STATUS(AE_OK); - } - - /* Find the ACPI table */ - - status = acpi_tb_find_table(operand[1]->string.pointer, - operand[2]->string.pointer, - operand[3]->string.pointer, &table_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Create the region descriptor */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - region_obj2 = obj_desc->common.next_object; - region_obj2->extra.region_context = NULL; - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Init the region from the operands */ - - obj_desc->region.space_id = REGION_DATA_TABLE; - obj_desc->region.address = - (acpi_physical_address) ACPI_TO_INTEGER(table); - obj_desc->region.length = table->length; - obj_desc->region.node = node; - obj_desc->region.flags = AOPOBJ_DATA_VALID; - - /* Install the new region object in the parent Node */ - - status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = acpi_ev_initialize_region(obj_desc, FALSE); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_EXIST) { - status = AE_OK; - } else { - goto cleanup; - } - } - - obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; - - cleanup: - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ex_create_processor * * PARAMETERS: walk_state - Current state diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 51c9c29..ed560e6 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -500,25 +500,28 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("Reference: Debug\n"); break; - case AML_NAME_OP: + case AML_INDEX_OP: - ACPI_DUMP_PATHNAME(obj_desc->reference.object, - "Reference: Name: ", ACPI_LV_INFO, - _COMPONENT); - ACPI_DUMP_ENTRY(obj_desc->reference.object, - ACPI_LV_INFO); + acpi_os_printf("Reference: Index %p\n", + obj_desc->reference.object); break; - case AML_INDEX_OP: + case AML_LOAD_OP: - acpi_os_printf("Reference: Index %p\n", + acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n", obj_desc->reference.object); break; case AML_REF_OF_OP: - acpi_os_printf("Reference: (RefOf) %p\n", - obj_desc->reference.object); + acpi_os_printf("Reference: (RefOf) %p [%s]\n", + obj_desc->reference.object, + acpi_ut_get_type_name(((union + acpi_operand_object + *)obj_desc-> + reference. + object)->common. + type)); break; case AML_ARG_OP: @@ -559,8 +562,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_INT_NAMEPATH_OP: - acpi_os_printf("Reference.Node->Name %X\n", - obj_desc->reference.node->name.integer); + acpi_os_printf("Reference: Namepath %X [%4.4s]\n", + obj_desc->reference.node->name.integer, + obj_desc->reference.node->name.ascii); break; default: @@ -640,8 +644,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); } else { acpi_os_printf(" base %8.8X%8.8X Length %X\n", - ACPI_FORMAT_UINT64(obj_desc->region. - address), + ACPI_FORMAT_NATIVE_UINT(obj_desc->region. + address), obj_desc->region.length); } break; @@ -877,20 +881,43 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { - acpi_os_printf("Named Object %p ", obj_desc->reference.node); + acpi_os_printf(" Named Object %p ", obj_desc->reference.node); status = acpi_ns_handle_to_pathname(obj_desc->reference.node, &ret_buf); if (ACPI_FAILURE(status)) { - acpi_os_printf("Could not convert name to pathname\n"); + acpi_os_printf(" Could not convert name to pathname\n"); } else { acpi_os_printf("%s\n", (char *)ret_buf.pointer); ACPI_FREE(ret_buf.pointer); } } else if (obj_desc->reference.object) { - acpi_os_printf("\nReferenced Object: %p\n", - obj_desc->reference.object); + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == + ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf(" Target: %p", + obj_desc->reference.object); + if (obj_desc->reference.opcode == AML_LOAD_OP) { + /* + * For DDBHandle reference, + * obj_desc->Reference.Object is the table index + */ + acpi_os_printf(" [DDBHandle]\n"); + } else { + acpi_os_printf(" [%s]\n", + acpi_ut_get_type_name(((union + acpi_operand_object + *) + obj_desc-> + reference. + object)-> + common. + type)); + } + } else { + acpi_os_printf(" Target: %p\n", + obj_desc->reference.object); + } } } @@ -976,7 +1003,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_LOCAL_REFERENCE: - acpi_os_printf("[Object Reference] "); + acpi_os_printf("[Object Reference] %s", + (acpi_ps_get_opcode_info + (obj_desc->reference.opcode))->name); acpi_ex_dump_reference_obj(obj_desc); break; diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 2d88a3d..aef8db8 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, union acpi_operand_object *buffer_desc; acpi_size length; void *buffer; - u8 locked; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the read. @@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, buffer.pointer), ACPI_READ | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); goto exit; } @@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Read from the field */ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); exit: if (ACPI_FAILURE(status)) { @@ -214,10 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, { acpi_status status; u32 length; - u32 required_length; void *buffer; - void *new_buffer; - u8 locked; union acpi_operand_object *buffer_desc; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -278,9 +271,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the write (returns status and perhaps data in the @@ -291,7 +282,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, (acpi_integer *) buffer, ACPI_WRITE | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; return_ACPI_STATUS(status); @@ -319,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* - * We must have a buffer that is at least as long as the field - * we are writing to. This is because individual fields are - * indivisible and partial writes are not supported -- as per - * the ACPI specification. - */ - new_buffer = NULL; - required_length = - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); - - if (length < required_length) { - - /* We need to create a new buffer */ - - new_buffer = ACPI_ALLOCATE_ZEROED(required_length); - if (!new_buffer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the original data to the new buffer, starting - * at Byte zero. All unused (upper) bytes of the - * buffer will be 0. - */ - ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length); - buffer = new_buffer; - length = required_length; - } - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, @@ -366,19 +328,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); - acpi_ex_release_global_lock(locked); - - /* Free temporary buffer if we used one */ - - if (new_buffer) { - ACPI_FREE(new_buffer); - } + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 65a48b6..ae40294 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, rgn_desc->region.space_id, obj_desc->common_field.access_byte_width, obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, (void *)address)); + field_datum_byte_offset, ACPI_CAST_PTR(void, + address))); /* Invoke the appropriate address_space/op_region handler */ @@ -805,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, u32 datum_count; u32 field_datum_count; u32 i; + u32 required_length; + void *new_buffer; ACPI_FUNCTION_TRACE(ex_insert_into_field); /* Validate input buffer */ - if (buffer_length < - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_ERROR((AE_INFO, - "Field size %X (bits) is too large for buffer (%X)", - obj_desc->common_field.bit_length, buffer_length)); + new_buffer = NULL; + required_length = + ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); + /* + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. + */ + if (buffer_length < required_length) { - return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + /* We need to create a new buffer */ + + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); + if (!new_buffer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); + buffer = new_buffer; + buffer_length = required_length; } /* @@ -866,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, merged_datum, field_offset); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto exit; } field_offset += obj_desc->common_field.access_byte_width; @@ -924,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); + exit: + /* Free temporary buffer if we used one */ + + if (new_buffer) { + ACPI_FREE(new_buffer); + } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 6748e3e..b8d035c 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -126,6 +126,79 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, /******************************************************************************* * + * FUNCTION: acpi_ex_acquire_mutex_object + * + * PARAMETERS: time_desc - Timeout in milliseconds + * obj_desc - Mutex object + * Thread - Current thread state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common + * path that supports multiple acquires by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator + * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_acquire_global_lock + * + ******************************************************************************/ + +acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Support for multiple acquires by the owning thread */ + + if (obj_desc->mutex.thread_id == thread_id) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); + } + + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_acquire_global_lock(timeout); + } else { + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + timeout); + } + + if (ACPI_FAILURE(status)) { + + /* Includes failure from a timeout on time_desc */ + + return_ACPI_STATUS(status); + } + + /* Acquired the mutex: update mutex object */ + + obj_desc->mutex.thread_id = thread_id; + obj_desc->mutex.acquisition_depth = 1; + obj_desc->mutex.original_sync_level = 0; + obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * * FUNCTION: acpi_ex_acquire_mutex * * PARAMETERS: time_desc - Timeout integer @@ -151,7 +224,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Sanity check: we must have a valid thread ID */ + /* Must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -161,7 +234,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, } /* - * Current Sync must be less than or equal to the sync level of the + * Current sync level must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { @@ -172,51 +245,89 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Support for multiple acquires by the owning thread */ + status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, + obj_desc, + walk_state->thread->thread_id); + if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { - if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } + /* Save Thread object, original/current sync levels */ + + obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.original_sync_level = + walk_state->thread->current_sync_level; + walk_state->thread->current_sync_level = + obj_desc->mutex.sync_level; + + /* Link the mutex to the current thread for force-unlock at method exit */ + + acpi_ex_link_mutex(obj_desc, walk_state->thread); } - /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + return_ACPI_STATUS(status); +} - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = - acpi_ev_acquire_global_lock((u16) time_desc->integer.value); - } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - (u16) time_desc->integer. - value); +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_mutex_object + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * Provides a common path that supports multiple releases (after + * previous multiple acquires) by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_release_mutex, via an AML Acquire() operator + * 2) From acpi_ex_release_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_release_global_lock + * + ******************************************************************************/ + +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_release_mutex_object); + + if (obj_desc->mutex.acquisition_depth == 0) { + return (AE_NOT_ACQUIRED); } - if (ACPI_FAILURE(status)) { + /* Match multiple Acquires with multiple Releases */ - /* Includes failure from a timeout on time_desc */ + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { - return_ACPI_STATUS(status); + /* Just decrement the depth and return */ + + return_ACPI_STATUS(AE_OK); } - /* Have the mutex: update mutex and walk info and save the sync_level */ + if (obj_desc->mutex.owner_thread) { - obj_desc->mutex.owner_thread = walk_state->thread; - obj_desc->mutex.acquisition_depth = 1; - obj_desc->mutex.original_sync_level = - walk_state->thread->current_sync_level; + /* Unlink the mutex from the owner's list */ - walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; + acpi_ex_unlink_mutex(obj_desc); + obj_desc->mutex.owner_thread = NULL; + } - /* Link the mutex to the current thread for force-unlock at method exit */ + /* Release the mutex, special case for Global Lock */ - acpi_ex_link_mutex(obj_desc, walk_state->thread); - return_ACPI_STATUS(AE_OK); + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } + + /* Clear mutex info */ + + obj_desc->mutex.thread_id = 0; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -253,22 +364,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Sanity check: we must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) - && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { + && (obj_desc != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, @@ -278,45 +380,37 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } + /* Must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + /* * The sync level of the mutex must be less than or equal to the current * sync level */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], incorrect SyncLevel", - acpi_ut_get_node_name(obj_desc->mutex.node))); + "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d", + acpi_ut_get_node_name(obj_desc->mutex.node), + obj_desc->mutex.sync_level, + walk_state->thread->current_sync_level)); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Match multiple Acquires with multiple Releases */ - - obj_desc->mutex.acquisition_depth--; - if (obj_desc->mutex.acquisition_depth != 0) { - - /* Just decrement the depth and return */ - - return_ACPI_STATUS(AE_OK); - } - - /* Unlink the mutex from the owner's list */ + status = acpi_ex_release_mutex_object(obj_desc); - acpi_ex_unlink_mutex(obj_desc); + if (obj_desc->mutex.acquisition_depth == 0) { - /* Release the mutex, special case for Global Lock */ + /* Restore the original sync_level */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); + walk_state->thread->current_sync_level = + obj_desc->mutex.original_sync_level; } - - /* Update the mutex and restore sync_level */ - - obj_desc->mutex.owner_thread = NULL; - walk_state->thread->current_sync_level = - obj_desc->mutex.original_sync_level; - return_ACPI_STATUS(status); } @@ -357,7 +451,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Release the mutex, special case for Global Lock */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + if (obj_desc == acpi_gbl_global_lock_mutex) { /* Ignore errors */ @@ -369,6 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.thread_id = 0; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 252f10a..313803b 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -121,6 +121,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) if ((ACPI_FAILURE(status)) || walk_state->result_obj) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } else { /* Save the return value */ @@ -739,26 +740,38 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) value = acpi_gbl_integer_byte_width; break; - case ACPI_TYPE_BUFFER: - value = temp_desc->buffer.length; - break; - case ACPI_TYPE_STRING: value = temp_desc->string.length; break; + case ACPI_TYPE_BUFFER: + + /* Buffer arguments may not be evaluated at this point */ + + status = acpi_ds_get_buffer_arguments(temp_desc); + value = temp_desc->buffer.length; + break; + case ACPI_TYPE_PACKAGE: + + /* Package arguments may not be evaluated at this point */ + + status = acpi_ds_get_package_arguments(temp_desc); value = temp_desc->package.count; break; default: ACPI_ERROR((AE_INFO, - "Operand is not Buf/Int/Str/Pkg - found type %s", + "Operand must be Buffer/Integer/String/Package - found type %s", acpi_ut_get_type_name(type))); status = AE_AML_OPERAND_TYPE; goto cleanup; } + if (ACPI_FAILURE(status)) { + goto cleanup; + } + /* * Now that we have the size of the object, create a result * object to hold the value diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 17e652e..81c02b1 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -241,10 +241,6 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - /* Return the remainder */ - - walk_state->result_obj = return_desc1; - cleanup: /* * Since the remainder is not returned indirectly, remove a reference to @@ -259,6 +255,12 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc1); } + /* Save return object (the remainder) on success */ + + else { + walk_state->result_obj = return_desc1; + } + return_ACPI_STATUS(status); } @@ -490,6 +492,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } return_ACPI_STATUS(status); @@ -583,8 +586,6 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = ACPI_INTEGER_MAX; } - walk_state->result_obj = return_desc; - cleanup: /* Delete return object on error */ @@ -593,5 +594,11 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 7fe67cf..a573f5d 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -260,6 +260,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status) || walk_state->result_obj) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } /* Set the return object and exit */ diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index bd80a9c..163b2b3 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -322,8 +322,6 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) goto cleanup; } - walk_state->result_obj = return_desc; - cleanup: /* Delete return object on error */ @@ -332,5 +330,11 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index efe5d4b..6eb45bf 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) { union acpi_operand_object *obj_desc; + union acpi_operand_object *second_desc = NULL; u32 type; acpi_status status; @@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj, obj_desc->bank_field.bank_obj)); + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the bank_value + * operands must be evaluated. + */ + second_desc = obj_desc->common.next_object; + second_desc->extra.aml_start = + ((union acpi_parse_object *)(info->data_register_node))-> + named.data; + second_desc->extra.aml_length = + ((union acpi_parse_object *)(info->data_register_node))-> + named.length; + break; case ACPI_TYPE_LOCAL_INDEX_FIELD: diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 3f51b7e..cbc6788 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -160,7 +160,7 @@ acpi_ex_system_memory_space_handler(u32 function, if (!mem_info->mapped_logical_address) { ACPI_ERROR((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", - ACPI_FORMAT_UINT64(address), + ACPI_FORMAT_NATIVE_UINT(address), (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS(AE_NO_MEMORY); @@ -182,7 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, ACPI_FORMAT_UINT64(address))); + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); /* * Perform the memory read or write @@ -284,7 +285,8 @@ acpi_ex_system_io_space_handler(u32 function, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, ACPI_FORMAT_UINT64(address))); + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); /* Decode the function parameter */ diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 2b3a01c..42c8a0f 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -116,9 +116,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, * Several object types require no further processing: * 1) Device/Thermal objects don't have a "real" subobject, return the Node * 2) Method locals and arguments have a pseudo-Node + * 3) 10/2007: Added method type to assist with Package construction. */ if ((entry_type == ACPI_TYPE_DEVICE) || (entry_type == ACPI_TYPE_THERMAL) || + (entry_type == ACPI_TYPE_METHOD) || (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { return_ACPI_STATUS(AE_OK); } @@ -214,7 +216,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* For these objects, just return the object attached to the Node */ case ACPI_TYPE_MUTEX: - case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: @@ -238,13 +239,12 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_LOCAL_REFERENCE: switch (source_desc->reference.opcode) { - case AML_LOAD_OP: + case AML_LOAD_OP: /* This is a ddb_handle */ + case AML_REF_OF_OP: + case AML_INDEX_OP: - /* This is a ddb_handle */ /* Return an additional reference to the object */ - case AML_REF_OF_OP: - obj_desc = source_desc; acpi_ut_add_reference(obj_desc); break; diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 6c64e55..5b5b2ff 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -140,7 +140,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, { acpi_status status = AE_OK; union acpi_operand_object *stack_desc; - void *temp_node; union acpi_operand_object *obj_desc = NULL; u16 opcode; @@ -156,23 +155,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, opcode = stack_desc->reference.opcode; switch (opcode) { - case AML_NAME_OP: - - /* - * Convert name reference to a namespace node - * Then, acpi_ex_resolve_node_to_value can be used to get the value - */ - temp_node = stack_desc->reference.object; - - /* Delete the Reference Object */ - - acpi_ut_remove_reference(stack_desc); - - /* Return the namespace node */ - - (*stack_ptr) = temp_node; - break; - case AML_LOCAL_OP: case AML_ARG_OP: @@ -207,15 +189,25 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (stack_desc->reference.target_type) { case ACPI_TYPE_BUFFER_FIELD: - /* Just return - leave the Reference on the stack */ + /* Just return - do not dereference */ break; case ACPI_TYPE_PACKAGE: + /* If method call or copy_object - do not dereference */ + + if ((walk_state->opcode == + AML_INT_METHODCALL_OP) + || (walk_state->opcode == AML_COPY_OP)) { + break; + } + + /* Otherwise, dereference the package_index to a package element */ + obj_desc = *stack_desc->reference.where; if (obj_desc) { /* - * Valid obj descriptor, copy pointer to return value + * Valid object descriptor, copy pointer to return value * (i.e., dereference the package index) * Delete the ref object, increment the returned object */ @@ -224,11 +216,11 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, *stack_ptr = obj_desc; } else { /* - * A NULL object descriptor means an unitialized element of + * A NULL object descriptor means an uninitialized element of * the package, can't dereference it */ ACPI_ERROR((AE_INFO, - "Attempt to deref an Index to NULL pkg element Idx=%p", + "Attempt to dereference an Index to NULL package element Idx=%p", stack_desc)); status = AE_AML_UNINITIALIZED_ELEMENT; } @@ -239,7 +231,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* Invalid reference object */ ACPI_ERROR((AE_INFO, - "Unknown TargetType %X in Index/Reference obj %p", + "Unknown TargetType %X in Index/Reference object %p", stack_desc->reference.target_type, stack_desc)); status = AE_AML_INTERNAL; @@ -251,7 +243,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, case AML_DEBUG_OP: case AML_LOAD_OP: - /* Just leave the object as-is */ + /* Just leave the object as-is, do not dereference */ break; @@ -390,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } /* - * For reference objects created via the ref_of or Index operators, - * we need to get to the base object (as per the ACPI specification - * of the object_type and size_of operators). This means traversing - * the list of possibly many nested references. + * For reference objects created via the ref_of, Index, or Load/load_table + * operators, we need to get to the base object (as per the ACPI + * specification of the object_type and size_of operators). This means + * traversing the list of possibly many nested references. */ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.opcode) { @@ -463,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; + case AML_LOAD_OP: + + type = ACPI_TYPE_DDB_HANDLE; + goto exit; + case AML_LOCAL_OP: case AML_ARG_OP: diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 09d897b..259047a 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -137,7 +137,6 @@ acpi_ex_resolve_operands(u16 opcode, union acpi_operand_object *obj_desc; acpi_status status = AE_OK; u8 object_type; - void *temp_node; u32 arg_types; const struct acpi_opcode_info *op_info; u32 this_arg_type; @@ -239,7 +238,6 @@ acpi_ex_resolve_operands(u16 opcode, /*lint -fallthrough */ - case AML_NAME_OP: case AML_INDEX_OP: case AML_REF_OF_OP: case AML_ARG_OP: @@ -332,15 +330,6 @@ acpi_ex_resolve_operands(u16 opcode, if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - - if (obj_desc->reference.opcode == AML_NAME_OP) { - - /* Convert a named reference to the actual named object */ - - temp_node = obj_desc->reference.object; - acpi_ut_remove_reference(obj_desc); - (*stack_ptr) = temp_node; - } goto next_operand; case ARGI_DATAREFOBJ: /* Store operator only */ diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index f4b69a6..dbc5e18 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -84,8 +84,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", - level, " ")); + /* Print line header as long as we are not in the middle of an object display */ + + if (!((level > 0) && index == 0)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", + level, " ")); + } /* Display index for package output only */ @@ -95,12 +99,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, } if (!source_desc) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "\n")); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ", + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", acpi_ut_get_object_type_name (source_desc))); @@ -123,6 +127,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, return_VOID; } + /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ + switch (ACPI_GET_OBJECT_TYPE(source_desc)) { case ACPI_TYPE_INTEGER: @@ -147,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER(source_desc->buffer.pointer, (source_desc->buffer.length < - 32) ? source_desc->buffer.length : 32); + 256) ? source_desc->buffer.length : 256); break; case ACPI_TYPE_STRING: @@ -160,7 +166,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_PACKAGE: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "[0x%.2X Elements]\n", + "[Contains 0x%.2X Elements]\n", source_desc->package.count)); /* Output the entire contents of the package */ @@ -180,12 +186,59 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (source_desc->reference.opcode), source_desc->reference.offset)); } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n", + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", acpi_ps_get_opcode_name (source_desc->reference.opcode))); } - if (source_desc->reference.object) { + if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " Table OwnerId %p\n", + source_desc->reference.object)); + break; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); + + /* Check for valid node first, then valid object */ + + if (source_desc->reference.node) { + if (ACPI_GET_DESCRIPTOR_TYPE + (source_desc->reference.node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " %p - Not a valid namespace node\n", + source_desc->reference. + node)); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "Node %p [%4.4s] ", + source_desc->reference. + node, + (source_desc->reference. + node)->name.ascii)); + + switch ((source_desc->reference.node)->type) { + + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + acpi_os_printf("Device\n"); + break; + + case ACPI_TYPE_THERMAL: + acpi_os_printf("Thermal Zone\n"); + break; + + default: + acpi_ex_do_debug_object((source_desc-> + reference. + node)->object, + level + 4, 0); + break; + } + } + } else if (source_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) == ACPI_DESC_TYPE_NAMED) { @@ -198,18 +251,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, acpi_ex_do_debug_object(source_desc->reference. object, level + 4, 0); } - } else if (source_desc->reference.node) { - acpi_ex_do_debug_object((source_desc->reference.node)-> - object, level + 4, 0); } break; default: - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n", - source_desc, - acpi_ut_get_object_type_name - (source_desc))); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", + source_desc)); break; } @@ -313,7 +361,6 @@ acpi_ex_store(union acpi_operand_object *source_desc, * 4) Store to the debug object */ switch (ref_desc->reference.opcode) { - case AML_NAME_OP: case AML_REF_OF_OP: /* Storing an object into a Name "container" */ @@ -415,11 +462,24 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, */ obj_desc = *(index_desc->reference.where); - status = - acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (ACPI_GET_OBJECT_TYPE(source_desc) == + ACPI_TYPE_LOCAL_REFERENCE + && source_desc->reference.opcode == AML_LOAD_OP) { + + /* This is a DDBHandle, just add a reference to it */ + + acpi_ut_add_reference(source_desc); + new_desc = source_desc; + } else { + /* Normal object, copy it */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, + &new_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } if (obj_desc) { @@ -571,10 +631,17 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* If no implicit conversion, drop into the default case below */ - if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { - - /* Force execution of default (no implicit conversion) */ - + if ((!implicit_conversion) || + ((walk_state->opcode == AML_COPY_OP) && + (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && + (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && + (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { + /* + * Force execution of default (no implicit conversion). Note: + * copy_object does not perform an implicit conversion, as per the ACPI + * spec -- except in case of region/bank/index fields -- because these + * objects must retain their original type permanently. + */ target_type = ACPI_TYPE_ANY; } diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 9460baf..a20a974 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -44,7 +44,6 @@ #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exsystem") diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aecc..1b93f4d 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -61,7 +61,6 @@ #include #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exutils") @@ -217,9 +216,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) /* * Object must be a valid number and we must be executing - * a control method + * a control method. NS node could be there for AML_INT_NAMEPATH_OP. */ if ((!obj_desc) || + (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { return; } @@ -240,72 +240,73 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) * PARAMETERS: field_flags - Flags with Lock rule: * always_lock or never_lock * - * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * RETURN: None * - * DESCRIPTION: Obtain the global lock and keep track of this fact via two - * methods. A global variable keeps the state of the lock, and - * the state is returned to the caller. + * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field + * flags specifiy that it is to be obtained before field access. * ******************************************************************************/ -u8 acpi_ex_acquire_global_lock(u32 field_flags) +void acpi_ex_acquire_global_lock(u32 field_flags) { - u8 locked = FALSE; acpi_status status; ACPI_FUNCTION_TRACE(ex_acquire_global_lock); - /* Only attempt lock if the always_lock bit is set */ + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } - if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* Attempt to get the global lock, wait forever */ - /* We should attempt to get the lock, wait forever */ + status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); - status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); - if (ACPI_SUCCESS(status)) { - locked = TRUE; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Could not acquire Global Lock")); - } + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire Global Lock")); } - return_UINT8(locked); + return_VOID; } /******************************************************************************* * * FUNCTION: acpi_ex_release_global_lock * - * PARAMETERS: locked_by_me - Return value from corresponding call to - * acquire_global_lock. + * PARAMETERS: field_flags - Flags with Lock rule: + * always_lock or never_lock * * RETURN: None * - * DESCRIPTION: Release the global lock if it is locked. + * DESCRIPTION: Release the ACPI hardware Global Lock * ******************************************************************************/ -void acpi_ex_release_global_lock(u8 locked_by_me) +void acpi_ex_release_global_lock(u32 field_flags) { acpi_status status; ACPI_FUNCTION_TRACE(ex_release_global_lock); - /* Only attempt unlock if the caller locked it */ + /* Only use the lock if the always_lock bit is set */ - if (locked_by_me) { + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } - /* OK, now release the lock */ + /* Release the global lock */ - status = acpi_ev_release_global_lock(); - if (ACPI_FAILURE(status)) { + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); + if (ACPI_FAILURE(status)) { - /* Report the error, but there isn't much else we can do */ + /* Report the error, but there isn't much else we can do */ - ACPI_EXCEPTION((AE_INFO, status, - "Could not release ACPI Global Lock")); - } + ACPI_EXCEPTION((AE_INFO, status, + "Could not release Global Lock")); } return_VOID; diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index eda0978..06f8634 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device); static int acpi_bind_one(struct device *dev, acpi_handle handle) { + struct acpi_device *acpi_dev; acpi_status status; if (dev->archdata.acpi_handle) { @@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) } dev->archdata.acpi_handle = handle; + status = acpi_bus_get_device(handle, &acpi_dev); + if (!ACPI_FAILURE(status)) { + int ret; + + ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, + "firmware_node"); + ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, + "physical_node"); + } + return 0; } @@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev) if (!dev->archdata.acpi_handle) return 0; if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { + struct acpi_device *acpi_dev; + /* acpi_get_physical_device increase refcnt by one */ put_device(dev); + + if (!acpi_bus_get_device(dev->archdata.acpi_handle, + &acpi_dev)) { + sysfs_remove_link(&dev->kobj, "firmware_node"); + sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); + } + acpi_detach_data(dev->archdata.acpi_handle, acpi_glue_data_handler); dev->archdata.acpi_handle = NULL; diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 4290e01..202f11a 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -70,9 +70,10 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) /* Get the FACS */ - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -124,9 +125,10 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) /* Get the FACS */ - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 57faf59..54852fb 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -208,8 +208,7 @@ acpi_status acpi_ns_root_initialize(void) /* Special case for ACPI Global Lock */ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { - acpi_gbl_global_lock_mutex = - obj_desc->mutex.os_mutex; + acpi_gbl_global_lock_mutex = obj_desc; /* Create additional counting semaphore for global lock */ @@ -582,44 +581,68 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(status); } - /* - * Sanity typecheck of the target object: - * - * If 1) This is the last segment (num_segments == 0) - * 2) And we are looking for a specific type - * (Not checking for TYPE_ANY) - * 3) Which is not an alias - * 4) Which is not a local type (TYPE_SCOPE) - * 5) And the type of target object is known (not TYPE_ANY) - * 6) And target object does not match what we are looking for - * - * Then we have a type mismatch. Just warn and ignore it. - */ - if ((num_segments == 0) && - (type_to_check_for != ACPI_TYPE_ANY) && - (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && - (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && - (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && - (this_node->type != ACPI_TYPE_ANY) && - (this_node->type != type_to_check_for)) { - - /* Complain about a type mismatch */ - - ACPI_WARNING((AE_INFO, - "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", - ACPI_CAST_PTR(char, &simple_name), - acpi_ut_get_type_name(this_node->type), - acpi_ut_get_type_name - (type_to_check_for))); + /* More segments to follow? */ + + if (num_segments > 0) { + /* + * If we have an alias to an object that opens a scope (such as a + * device or processor), we need to dereference the alias here so that + * we can access any children of the original node (via the remaining + * segments). + */ + if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { + if (acpi_ns_opens_scope + (((struct acpi_namespace_node *)this_node-> + object)->type)) { + this_node = + (struct acpi_namespace_node *) + this_node->object; + } + } } - /* - * If this is the last name segment and we are not looking for a - * specific type, but the type of found object is known, use that type - * to see if it opens a scope. - */ - if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) { - type = this_node->type; + /* Special handling for the last segment (num_segments == 0) */ + + else { + /* + * Sanity typecheck of the target object: + * + * If 1) This is the last segment (num_segments == 0) + * 2) And we are looking for a specific type + * (Not checking for TYPE_ANY) + * 3) Which is not an alias + * 4) Which is not a local type (TYPE_SCOPE) + * 5) And the type of target object is known (not TYPE_ANY) + * 6) And target object does not match what we are looking for + * + * Then we have a type mismatch. Just warn and ignore it. + */ + if ((type_to_check_for != ACPI_TYPE_ANY) && + (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && + (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) + && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) + && (this_node->type != ACPI_TYPE_ANY) + && (this_node->type != type_to_check_for)) { + + /* Complain about a type mismatch */ + + ACPI_WARNING((AE_INFO, + "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", + ACPI_CAST_PTR(char, &simple_name), + acpi_ut_get_type_name(this_node-> + type), + acpi_ut_get_type_name + (type_to_check_for))); + } + + /* + * If this is the last name segment and we are not looking for a + * specific type, but the type of found object is known, use that type + * to (later) see if it opens a scope. + */ + if (type == ACPI_TYPE_ANY) { + type = this_node->type; + } } /* Point to next name segment and make this node current */ diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 1fc4f86..3068e20 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -249,7 +249,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, acpi_os_printf("ID %X Len %.4X Addr %p\n", obj_desc->processor.proc_id, obj_desc->processor.length, - (char *)obj_desc->processor.address); + ACPI_CAST_PTR(void, + obj_desc->processor. + address)); break; case ACPI_TYPE_DEVICE: @@ -320,9 +322,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, space_id)); if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", - ACPI_FORMAT_UINT64(obj_desc-> - region. - address), + ACPI_FORMAT_NATIVE_UINT + (obj_desc->region.address), obj_desc->region.length); } else { acpi_os_printf diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 33db224..72b3245 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -244,6 +244,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, info->field_count++; break; + case ACPI_TYPE_LOCAL_BANK_FIELD: + info->field_count++; + break; + case ACPI_TYPE_BUFFER: info->buffer_count++; break; @@ -287,6 +291,12 @@ acpi_ns_init_one_object(acpi_handle obj_handle, status = acpi_ds_get_buffer_field_arguments(obj_desc); break; + case ACPI_TYPE_LOCAL_BANK_FIELD: + + info->field_init++; + status = acpi_ds_get_bank_field_arguments(obj_desc); + break; + case ACPI_TYPE_BUFFER: info->buffer_init++; diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index d4f9654..1bfcb6f 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -107,11 +107,11 @@ acpi_ns_load_table(acpi_native_uint table_index, goto unlock; } - status = acpi_ns_parse_table(table_index, node->child); + status = acpi_ns_parse_table(table_index, node); if (ACPI_SUCCESS(status)) { acpi_tb_set_table_loaded_flag(table_index, TRUE); } else { - acpi_tb_release_owner_id(table_index); + (void)acpi_tb_release_owner_id(table_index); } unlock: diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index cbd94af..ba1a4f0 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -180,6 +180,12 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) next_node = node; while (next_node && (next_node != acpi_gbl_root_node)) { + if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { + ACPI_ERROR((AE_INFO, + "Invalid NS Node (%p) while traversing path", + next_node)); + return 0; + } size += ACPI_PATH_SEGMENT_LENGTH; next_node = acpi_ns_get_parent_node(next_node); } diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index e696aa8..f260b69 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -64,7 +64,8 @@ ACPI_MODULE_NAME("nsparse") ******************************************************************************/ acpi_status acpi_ns_one_complete_parse(acpi_native_uint pass_number, - acpi_native_uint table_index) + acpi_native_uint table_index, + struct acpi_namespace_node * start_node) { union acpi_parse_object *parse_root; acpi_status status; @@ -111,14 +112,25 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, aml_start = (u8 *) table + sizeof(struct acpi_table_header); aml_length = table->length - sizeof(struct acpi_table_header); status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, - aml_start, aml_length, NULL, - (u8) pass_number); + aml_start, (u32) aml_length, + NULL, (u8) pass_number); } if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); - acpi_ps_delete_parse_tree(parse_root); - return_ACPI_STATUS(status); + goto cleanup; + } + + /* start_node is the default location to load the table */ + + if (start_node && start_node != acpi_gbl_root_node) { + status = + acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, + walk_state); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } } /* Parse the AML */ @@ -127,6 +139,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, (unsigned)pass_number)); status = acpi_ps_parse_aml(walk_state); + cleanup: acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); } @@ -163,7 +176,9 @@ acpi_ns_parse_table(acpi_native_uint table_index, * performs another complete parse of the AML. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); - status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index); + status = + acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, + start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -178,7 +193,9 @@ acpi_ns_parse_table(acpi_native_uint table_index, * parse objects are all cached. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); - status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index); + status = + acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, + start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index 280b835..c7b5409 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -77,9 +77,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct /* It's really the parent's _scope_ that we want */ - if (parent_node->child) { - next_node = parent_node->child; - } + next_node = parent_node->child; } else { diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index b92133f..cd97c80 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -467,10 +467,13 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (AE_CTRL_DEPTH); } - if (!(flags & ACPI_STA_DEVICE_PRESENT)) { - - /* Don't examine children of the device if not present */ - + if (!(flags & ACPI_STA_DEVICE_PRESENT) && + !(flags & ACPI_STA_DEVICE_FUNCTIONING)) { + /* + * Don't examine the children of the device only when the + * device is neither present nor functional. See ACPI spec, + * description of _STA for more information. + */ return (AE_CTRL_DEPTH); } @@ -539,7 +542,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, * value is returned to the caller. * * This is a wrapper for walk_namespace, but the callback performs - * additional filtering. Please see acpi_get_device_callback. + * additional filtering. Please see acpi_ns_get_device_callback. * ******************************************************************************/ diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index c2b9835..2a3a948 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -230,12 +230,12 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, struct acpi_parse_state *parser_state, union acpi_parse_object *arg, u8 possible_method_call) { + acpi_status status; char *path; union acpi_parse_object *name_op; - acpi_status status; union acpi_operand_object *method_desc; struct acpi_namespace_node *node; - union acpi_generic_state scope_info; + u8 *start = parser_state->aml; ACPI_FUNCTION_TRACE(ps_get_next_namepath); @@ -249,25 +249,18 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_OK); } - /* Setup search scope info */ - - scope_info.scope.node = NULL; - node = parser_state->start_node; - if (node) { - scope_info.scope.node = node; - } - /* - * Lookup the name in the internal namespace. We don't want to add - * anything new to the namespace here, however, so we use MODE_EXECUTE. + * Lookup the name in the internal namespace, starting with the current + * scope. We don't want to add anything new to the namespace here, + * however, so we use MODE_EXECUTE. * Allow searching of the parent tree, but don't open a new scope - * we just want to lookup the object (must be mode EXECUTE to perform * the upsearch) */ - status = - acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, - NULL, &node); + status = acpi_ns_lookup(walk_state->scope_info, path, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &node); /* * If this name is a control method invocation, we must @@ -275,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { + if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + /* + * acpi_ps_get_next_namestring has increased the AML pointer, + * so we need to restore the saved AML pointer for method call. + */ + walk_state->parser_state.aml = start; + walk_state->arg_count = 1; + acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); + return_ACPI_STATUS(AE_OK); + } /* This name is actually a control method invocation */ @@ -686,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_NO_MEMORY); } - status = - acpi_ps_get_next_namepath(walk_state, parser_state, - arg, 0); + /* To support super_name arg of Unload */ + + if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + status = + acpi_ps_get_next_namepath(walk_state, + parser_state, arg, + 1); + + /* + * If the super_name arg of Unload is a method call, + * we have restored the AML pointer, just free this Arg + */ + if (arg->common.aml_opcode == + AML_INT_METHODCALL_OP) { + acpi_ps_free_op(arg); + arg = NULL; + } + } else { + status = + acpi_ps_get_next_namepath(walk_state, + parser_state, arg, + 0); + } } else { /* Single complex argument, nothing returned */ diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 773aee8..a7c7688 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -182,6 +182,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); unnamed_op->common.value.arg = NULL; + unnamed_op->common.arg_list_length = 0; unnamed_op->common.aml_opcode = walk_state->opcode; /* @@ -241,7 +242,8 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, acpi_ps_append_arg(*op, unnamed_op->common.value.arg); acpi_gbl_depth++; - if ((*op)->common.aml_opcode == AML_REGION_OP) { + if ((*op)->common.aml_opcode == AML_REGION_OP || + (*op)->common.aml_opcode == AML_DATA_REGION_OP) { /* * Defer final parsing of an operation_region body, because we don't * have enough info in the first pass to parse it correctly (i.e., @@ -280,6 +282,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, acpi_status status = AE_OK; union acpi_parse_object *op; union acpi_parse_object *named_op = NULL; + union acpi_parse_object *parent_scope; + u8 argument_count; + const struct acpi_opcode_info *op_info; ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); @@ -320,8 +325,32 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, op->named.length = 0; } - acpi_ps_append_arg(acpi_ps_get_parent_scope - (&(walk_state->parser_state)), op); + if (walk_state->opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); + acpi_ps_append_arg(parent_scope, op); + + if (parent_scope) { + op_info = + acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); + if (op_info->flags & AML_HAS_TARGET) { + argument_count = + acpi_ps_get_argument_count(op_info->type); + if (parent_scope->common.arg_list_length > + argument_count) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } if (walk_state->descending_callback != NULL) { /* @@ -603,13 +632,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); - - if ((*op)->common.aml_opcode != AML_WHILE_OP) { - status2 = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } } /* Close this iteration of the While loop */ @@ -640,10 +662,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } - status2 = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state @@ -1005,7 +1023,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) acpi_gbl_depth--; } - if (op->common.aml_opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP || + op->common.aml_opcode == AML_DATA_REGION_OP) { /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass @@ -1030,6 +1049,16 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) (u32) (parser_state->aml - op->named.data); } + if (op->common.aml_opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * + * body_length is unknown until we parse the body + */ + op->named.length = + (u32) (parser_state->aml - op->named.data); + } + /* This op complete, notify the dispatcher */ if (walk_state->ascending_callback != NULL) { diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 9296e86..18ed59d 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -49,6 +49,9 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopcode") +static const u8 acpi_gbl_argument_count[] = + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; + /******************************************************************************* * * NAME: acpi_gbl_aml_op_info @@ -59,6 +62,7 @@ ACPI_MODULE_NAME("psopcode") * the operand type. * ******************************************************************************/ + /* * Summary of opcode types/flags * @@ -176,6 +180,7 @@ ACPI_MODULE_NAME("psopcode") AML_CREATE_QWORD_FIELD_OP ******************************************************************************/ + /* * Master Opcode information table. A summary of everything we know about each * opcode, all in one place. @@ -515,9 +520,10 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | + AML_DEFER), /* Internal opcodes that map to invalid AML opcodes */ @@ -619,9 +625,9 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + AML_NSNODE | AML_NAMED | AML_DEFER), /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, @@ -779,3 +785,25 @@ char *acpi_ps_get_opcode_name(u16 opcode) #endif } + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_argument_count + * + * PARAMETERS: op_type - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +u8 acpi_ps_get_argument_count(u32 op_type) +{ + + if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { + return (acpi_gbl_argument_count[op_type]); + } + + return (0); +} diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 5d63f48..a4c4020 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -205,6 +205,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || (op->common.parent->common.aml_opcode == + AML_BANK_FIELD_OP) + || (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); @@ -349,19 +351,13 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, parser_state->aml = walk_state->aml_last_while; walk_state->control_state->common.value = FALSE; - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_BREAK; - } + status = AE_CTRL_BREAK; break; case AE_CTRL_CONTINUE: parser_state->aml = walk_state->aml_last_while; - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_CONTINUE; - } + status = AE_CTRL_CONTINUE; break; case AE_CTRL_PENDING: @@ -383,10 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, * Just close out this package */ parser_state->aml = acpi_ps_get_next_package_end(parser_state); - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_PENDING; - } + status = AE_CTRL_PENDING; break; case AE_CTRL_FALSE: @@ -541,7 +534,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) if ((status == AE_ALREADY_EXISTS) && (!walk_state->method_desc->method.mutex)) { ACPI_INFO((AE_INFO, - "Marking method %4.4s as Serialized", + "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", walk_state->method_node->name. ascii)); @@ -601,6 +594,30 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) * The object is deleted */ if (!previous_walk_state->return_desc) { + /* + * In slack mode execution, if there is no return value + * we should implicitly return zero (0) as a default value. + */ + if (acpi_gbl_enable_interpreter_slack && + !previous_walk_state-> + implicit_return_obj) { + previous_walk_state-> + implicit_return_obj = + acpi_ut_create_internal_object + (ACPI_TYPE_INTEGER); + if (!previous_walk_state-> + implicit_return_obj) { + return_ACPI_STATUS + (AE_NO_MEMORY); + } + + previous_walk_state-> + implicit_return_obj-> + integer.value = 0; + } + + /* Restart the calling control method */ + status = acpi_ds_restart_control_method (walk_state, diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index 966e7ea..0e1a322 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -171,6 +171,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) while (arg) { arg->common.parent = op; arg = arg->common.next; + + op->common.arg_list_length++; } } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 788da97..836362b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -848,6 +848,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) /* all processors need to support C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; + pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; @@ -960,6 +961,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address); } + if (cx.type == ACPI_STATE_C1) { + cx.valid = 1; + } obj = &(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 0dd2ce8..d801823 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -73,7 +73,7 @@ acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); static u8 acpi_rs_count_set_bits(u16 bit_field) { - u8 bits_set; + acpi_native_uint bits_set; ACPI_FUNCTION_ENTRY(); @@ -81,10 +81,10 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) /* Zero the least significant bit that is set */ - bit_field &= (bit_field - 1); + bit_field &= (u16) (bit_field - 1); } - return (bits_set); + return ((u8) bits_set); } /******************************************************************************* @@ -211,6 +211,24 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) * variable-length fields */ switch (resource->type) { + case ACPI_RESOURCE_TYPE_IRQ: + + /* Length can be 3 or 2 */ + + if (resource->data.irq.descriptor_length == 2) { + total_size--; + } + break; + + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + + /* Length can be 1 or 0 */ + + if (resource->data.irq.descriptor_length == 0) { + total_size--; + } + break; + case ACPI_RESOURCE_TYPE_VENDOR: /* * Vendor Defined Resource: diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index 46da116..ed6447d 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -87,8 +87,10 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); * ******************************************************************************/ -struct acpi_rsdump_info acpi_rs_dump_irq[6] = { +struct acpi_rsdump_info acpi_rs_dump_irq[7] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), + "Descriptor Length", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", acpi_gbl_he_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", @@ -115,9 +117,11 @@ struct acpi_rsdump_info acpi_rs_dump_dma[6] = { NULL} }; -struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = { +struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), "Start-Dependent-Functions", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), + "Descriptor Length", NULL}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), "Compatibility Priority", acpi_gbl_config_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index b297bc3..610d7c2 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c @@ -185,7 +185,7 @@ struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { +struct acpi_rsconvert_info acpi_rs_get_start_dpf[6] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, ACPI_RS_SIZE(struct acpi_resource_start_dependent), ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, @@ -196,6 +196,12 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { ACPI_ACCEPTABLE_CONFIGURATION, 2}, + /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + AML_OFFSET(start_dpf.descriptor_type), + 0}, + /* All done if there is no flag byte present in the descriptor */ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, @@ -219,7 +225,9 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { +struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = { + /* Start with a default descriptor of length 1 */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, sizeof(struct aml_resource_start_dependent), ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, @@ -236,6 +244,33 @@ struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { AML_OFFSET(start_dpf.flags), 2}, /* + * All done if the output descriptor length is required to be 1 + * (i.e., optimization to 0 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + 1}, + + /* Set length to 0 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, + sizeof(struct aml_resource_start_dependent_noprio)}, + + /* + * All done if the output descriptor length is required to be 0. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 0-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + 0}, + + /* Reset length to 1 byte (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_start_dependent)}, + + /* * All done if flags byte is necessary -- if either priority value * is not ACPI_ACCEPTABLE_CONFIGURATION */ diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 5657f7b..382a77b 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c @@ -52,7 +52,7 @@ ACPI_MODULE_NAME("rsirq") * acpi_rs_get_irq * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_irq[7] = { +struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, ACPI_RS_SIZE(struct acpi_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, @@ -69,6 +69,12 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = { ACPI_EDGE_SENSITIVE, 1}, + /* Get the descriptor length (2 or 3 for IRQ descriptor) */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.irq.descriptor_length), + AML_OFFSET(irq.descriptor_type), + 0}, + /* All done if no flag byte present in descriptor */ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, @@ -94,7 +100,9 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_irq[9] = { +struct acpi_rsconvert_info acpi_rs_set_irq[13] = { + /* Start with a default descriptor of length 3 */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, sizeof(struct aml_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, @@ -105,7 +113,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { AML_OFFSET(irq.irq_mask), ACPI_RS_OFFSET(data.irq.interrupt_count)}, - /* Set the flags byte by default */ + /* Set the flags byte */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -118,6 +126,33 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), AML_OFFSET(irq.flags), 4}, + + /* + * All done if the output descriptor length is required to be 3 + * (i.e., optimization to 2 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.descriptor_length), + 3}, + + /* Set length to 2 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}, + + /* + * All done if the output descriptor length is required to be 2. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 2-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.descriptor_length), + 2}, + + /* Reset length to 3 bytes (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, + /* * Check if the flags byte is necessary. Not needed if the flags are: * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE @@ -134,7 +169,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { ACPI_RS_OFFSET(data.irq.sharable), ACPI_EXCLUSIVE}, - /* irq_no_flags() descriptor can be used */ + /* We can optimize to a 2-byte irq_no_flags() descriptor */ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} }; diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index c7081af..3e69eff 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -497,6 +497,17 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, } break; + case ACPI_RSC_EXIT_EQ: + /* + * Control - Exit conversion if equal + */ + if (*ACPI_ADD_PTR(u8, resource, + COMPARE_TARGET(info)) == + COMPARE_VALUE(info)) { + goto exit; + } + break; + default: ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 11c0bd7..935a482 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -97,17 +97,17 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) u16 acpi_rs_encode_bitmask(u8 * list, u8 count) { acpi_native_uint i; - u16 mask; + acpi_native_uint mask; ACPI_FUNCTION_ENTRY(); /* Encode the list into a single bitmask */ for (i = 0, mask = 0; i < count; i++) { - mask |= (0x0001 << list[i]); + mask |= (0x1 << list[i]); } - return (mask); + return ((u16) mask); } /******************************************************************************* diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e6ce262..bd32351 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -692,6 +692,9 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *package = NULL; + union acpi_object in_arg[3]; + struct acpi_object_list arg_list = { 3, in_arg }; + acpi_status psw_status = AE_OK; struct acpi_device_id button_device_ids[] = { {"PNP0C0D", 0}, @@ -700,7 +703,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) {"", 0}, }; - /* _PRW */ status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -718,6 +720,45 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) kfree(buffer.pointer); device->wakeup.flags.valid = 1; + /* Call _PSW/_DSW object to disable its ability to wake the sleeping + * system for the ACPI device with the _PRW object. + * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. + * So it is necessary to call _DSW object first. Only when it is not + * present will the _PSW object used. + */ + /* + * Three agruments are needed for the _DSW object. + * Argument 0: enable/disable the wake capabilities + * When _DSW object is called to disable the wake capabilities, maybe + * the first argument is filled. The value of the other two agruments + * is meaningless. + */ + in_arg[0].type = ACPI_TYPE_INTEGER; + in_arg[0].integer.value = 0; + in_arg[1].type = ACPI_TYPE_INTEGER; + in_arg[1].integer.value = 0; + in_arg[2].type = ACPI_TYPE_INTEGER; + in_arg[2].integer.value = 0; + psw_status = acpi_evaluate_object(device->handle, "_DSW", + &arg_list, NULL); + if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n")); + /* + * When the _DSW object is not present, OSPM will call _PSW object. + */ + if (psw_status == AE_NOT_FOUND) { + /* + * Only one agruments is required for the _PSW object. + * agrument 0: enable/disable the wake capabilities + */ + arg_list.count = 1; + in_arg[0].integer.value = 0; + psw_status = acpi_evaluate_object(device->handle, "_PSW", + &arg_list, NULL); + if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in " + "evaluate _PSW\n")); + } /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c index 058c064..772ca41 100644 --- a/drivers/acpi/tables/tbfind.c +++ b/drivers/acpi/tables/tbfind.c @@ -70,12 +70,22 @@ acpi_tb_find_table(char *signature, { acpi_native_uint i; acpi_status status; + struct acpi_table_header header; ACPI_FUNCTION_TRACE(tb_find_table); + /* Normalize the input strings */ + + ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); + ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); + ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); + ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + + /* Search for the table */ + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), - signature, ACPI_NAME_SIZE)) { + header.signature, ACPI_NAME_SIZE)) { /* Not the requested table */ @@ -104,20 +114,24 @@ acpi_tb_find_table(char *signature, if (!ACPI_MEMCMP (acpi_gbl_root_table_list.tables[i].pointer->signature, - signature, ACPI_NAME_SIZE) && (!oem_id[0] - || - !ACPI_MEMCMP - (acpi_gbl_root_table_list. - tables[i].pointer->oem_id, - oem_id, ACPI_OEM_ID_SIZE)) + header.signature, ACPI_NAME_SIZE) && (!oem_id[0] + || + !ACPI_MEMCMP + (acpi_gbl_root_table_list. + tables[i].pointer-> + oem_id, + header.oem_id, + ACPI_OEM_ID_SIZE)) && (!oem_table_id[0] || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. - pointer->oem_table_id, oem_table_id, + pointer->oem_table_id, + header.oem_table_id, ACPI_OEM_TABLE_ID_SIZE))) { *table_index = i; ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Found table [%4.4s]\n", signature)); + "Found table [%4.4s]\n", + header.signature)); return_ACPI_STATUS(AE_OK); } } diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 3bc0c67..c4a9abb 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -125,13 +125,20 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, /* The table must be either an SSDT or a PSDT or an OEMx */ - if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) - && - (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) - && (strncmp(table_desc->pointer->signature, "OEM", 3))) { - ACPI_ERROR((AE_INFO, - "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx", - table_desc->pointer->signature)); + if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&& + !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&& + strncmp(table_desc->pointer->signature, "OEM", 3)) { + /* Check for a printable name */ + if (acpi_ut_valid_acpi_name( + *(u32 *) table_desc->pointer->signature)) { + ACPI_ERROR((AE_INFO, "Table has invalid signature " + "[%4.4s], must be SSDT or PSDT", + table_desc->pointer->signature)); + } else { + ACPI_ERROR((AE_INFO, "Table has invalid signature " + "(0x%8.8X), must be SSDT or PSDT", + *(u32 *) table_desc->pointer->signature)); + } return_ACPI_STATUS(AE_BAD_SIGNATURE); } @@ -162,6 +169,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, acpi_tb_delete_table(table_desc); *table_index = i; + status = AE_ALREADY_EXISTS; goto release; } diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 010f196..d04442f 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -212,7 +212,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) if (checksum) { ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", + "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", table->signature, table->checksum, (u8) (table->checksum - checksum))); diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index a9e3331..5f22715 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -635,6 +635,95 @@ acpi_status acpi_load_tables(void) ACPI_EXPORT_SYMBOL(acpi_load_tables) +/******************************************************************************* + * + * FUNCTION: acpi_install_table_handler + * + * PARAMETERS: Handler - Table event handler + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Install table event handler + * + ******************************************************************************/ +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_table_handler); + + if (!handler) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow more than one handler */ + + if (acpi_gbl_table_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_table_handler = handler; + acpi_gbl_table_handler_context = context; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_table_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_table_handler + * + * PARAMETERS: Handler - Table event handler that was installed + * previously. + * + * RETURN: Status + * + * DESCRIPTION: Remove table event handler + * + ******************************************************************************/ +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_table_handler); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Make sure that the installed handler is the same */ + + if (!handler || handler != acpi_gbl_table_handler) { + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_table_handler = NULL; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) + + static int __init acpi_no_auto_ssdt_setup(char *s) { printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 6e56d5f..181e669 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -147,7 +147,7 @@ acpi_status acpi_ut_delete_caches(void) if (acpi_gbl_display_final_mem_stats) { ACPI_STRCPY(buffer, "MEMORY"); - acpi_db_display_statistics(buffer); + (void)acpi_db_display_statistics(buffer); } #endif diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 879eaa1..2a57c2c 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -43,6 +43,8 @@ #include #include +#include + #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utcopy") @@ -172,22 +174,21 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, case ACPI_TYPE_LOCAL_REFERENCE: - /* - * This is an object reference. Attempt to dereference it. - */ + /* This is an object reference. */ + switch (internal_object->reference.opcode) { case AML_INT_NAMEPATH_OP: /* For namepath, return the object handle ("reference") */ default: - /* - * Use the object type of "Any" to indicate a reference - * to object containing a handle to an ACPI named object. - */ - external_object->type = ACPI_TYPE_ANY; + + /* We are referring to the namespace node */ + external_object->reference.handle = internal_object->reference.node; + external_object->reference.actual_type = + acpi_ns_get_type(internal_object->reference.node); break; } break; @@ -215,6 +216,11 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, /* * There is no corresponding external object type */ + ACPI_ERROR((AE_INFO, + "Unsupported object type, cannot convert to external object: %s", + acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE + (internal_object)))); + return_ACPI_STATUS(AE_SUPPORT); } @@ -455,6 +461,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_INTEGER: + case ACPI_TYPE_LOCAL_REFERENCE: internal_object = acpi_ut_create_internal_object((u8) external_object-> @@ -464,9 +471,18 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, } break; + case ACPI_TYPE_ANY: /* This is the case for a NULL object */ + + *ret_internal_object = NULL; + return_ACPI_STATUS(AE_OK); + default: /* All other types are not supported */ + ACPI_ERROR((AE_INFO, + "Unsupported object type, cannot convert to internal object: %s", + acpi_ut_get_type_name(external_object->type))); + return_ACPI_STATUS(AE_SUPPORT); } @@ -502,6 +518,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, external_object->buffer.length); internal_object->buffer.length = external_object->buffer.length; + + /* Mark buffer data valid */ + + internal_object->buffer.flags |= AOPOBJ_DATA_VALID; break; case ACPI_TYPE_INTEGER: @@ -509,6 +529,15 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, internal_object->integer.value = external_object->integer.value; break; + case ACPI_TYPE_LOCAL_REFERENCE: + + /* TBD: should validate incoming handle */ + + internal_object->reference.opcode = AML_INT_NAMEPATH_OP; + internal_object->reference.node = + external_object->reference.handle; + break; + default: /* Other types can't get here */ break; @@ -570,13 +599,17 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, /* Truncate package and delete it */ - package_object->package.count = i; + package_object->package.count = (u32) i; package_elements[i] = NULL; acpi_ut_remove_reference(package_object); return_ACPI_STATUS(status); } } + /* Mark package data valid */ + + package_object->package.flags |= AOPOBJ_DATA_VALID; + *internal_object = package_object; return_ACPI_STATUS(status); } @@ -709,7 +742,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, /* * We copied the reference object, so we now must add a reference * to the object pointed to by the reference + * + * DDBHandle reference (from Load/load_table is a special reference, + * it's Reference.Object is the table index, so does not need to + * increase the reference count */ + if (source_desc->reference.opcode == AML_LOAD_OP) { + break; + } + acpi_ut_add_reference(source_desc->reference.object); break; diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 7361204..8014442 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -68,9 +68,9 @@ static const char *acpi_ut_trim_function_name(const char *function_name); void acpi_ut_init_stack_ptr_trace(void) { - u32 current_sp; + acpi_size current_sp; - acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF(¤t_sp, NULL); + acpi_gbl_entry_stack_pointer = ¤t_sp; } /******************************************************************************* @@ -89,10 +89,8 @@ void acpi_ut_track_stack_ptr(void) { acpi_size current_sp; - current_sp = ACPI_PTR_DIFF(¤t_sp, NULL); - - if (current_sp < acpi_gbl_lowest_stack_pointer) { - acpi_gbl_lowest_stack_pointer = current_sp; + if (¤t_sp < acpi_gbl_lowest_stack_pointer) { + acpi_gbl_lowest_stack_pointer = ¤t_sp; } if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { @@ -203,6 +201,7 @@ acpi_ut_debug_print(u32 requested_debug_level, va_start(args, format); acpi_os_vprintf(format, args); + va_end(args); } ACPI_EXPORT_SYMBOL(acpi_ut_debug_print) @@ -240,6 +239,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level, va_start(args, format); acpi_os_vprintf(format, args); + va_end(args); } ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) @@ -524,6 +524,11 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) u32 temp32; u8 buf_char; + if (!buffer) { + acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + if ((count < 4) || (count & 0x01)) { display = DB_BYTE_DISPLAY; } diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index f777ceb..f5b2f6a 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -158,7 +158,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) "***** Mutex %p, OS Mutex %p\n", object, object->mutex.os_mutex)); - if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + if (object == acpi_gbl_global_lock_mutex) { /* Global Lock has extra semaphore */ @@ -252,6 +252,17 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) } break; + case ACPI_TYPE_LOCAL_BANK_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Bank Field %p\n", object)); + + second_desc = acpi_ns_get_secondary_object(object); + if (second_desc) { + acpi_ut_delete_object_desc(second_desc); + } + break; + default: break; } @@ -524,10 +535,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) 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. + * The target of an Index (a package, string, or buffer) or a named + * reference must track changes to the ref count of the index or + * target object. */ - if (object->reference.opcode == AML_INDEX_OP) { + if ((object->reference.opcode == AML_INDEX_OP) || + (object->reference.opcode == AML_INT_NAMEPATH_OP)) { next_object = object->reference.object; } break; diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 630c9a2..d0226fe 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -602,6 +602,48 @@ char *acpi_ut_get_mutex_name(u32 mutex_id) return (acpi_gbl_mutex_names[mutex_id]); } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_notify_name + * + * PARAMETERS: notify_value - Value from the Notify() request + * + * RETURN: String corresponding to the Notify Value. + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +static const char *acpi_gbl_notify_value_names[] = { + "Bus Check", + "Device Check", + "Device Wake", + "Eject Request", + "Device Check Light", + "Frequency Mismatch", + "Bus Mode Mismatch", + "Power Fault", + "Capabilities Check", + "Device PLD Check", + "Reserved", + "System Locality Update" +}; + +const char *acpi_ut_get_notify_name(u32 notify_value) +{ + + if (notify_value <= ACPI_NOTIFY_MAX) { + return (acpi_gbl_notify_value_names[notify_value]); + } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + return ("Reserved"); + } else { /* Greater or equal to 0x80 */ + + return ("**Device Specific**"); + } +} #endif /******************************************************************************* @@ -675,12 +717,13 @@ void acpi_ut_init_globals(void) acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; - /* Global notify handlers */ + /* Global handlers */ acpi_gbl_system_notify.handler = NULL; acpi_gbl_device_notify.handler = NULL; acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; + acpi_gbl_table_handler = NULL; /* Global Lock support */ @@ -722,7 +765,7 @@ void acpi_ut_init_globals(void) acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; #ifdef ACPI_DEBUG_OUTPUT - acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX; + acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); #endif #ifdef ACPI_DBG_TRACK_ALLOCATIONS diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index ad3c0d0..de44477 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -125,9 +125,12 @@ void acpi_ut_subsystem_shutdown(void) acpi_gbl_startup_flags = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); +#ifndef ACPI_ASL_COMPILER + /* Close the acpi_event Handling */ acpi_ev_terminate(); +#endif /* Close the Namespace */ diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 0c56a0d..16dbf66 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -276,7 +276,7 @@ acpi_ut_short_divide(acpi_integer in_dividend, *out_quotient = in_dividend / divisor; } if (out_remainder) { - *out_remainder = (u32) in_dividend % divisor; + *out_remainder = (u32) (in_dividend % divisor); } return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 2d19f71..2f48fd6 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -1033,6 +1033,7 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); } void ACPI_INTERNAL_VAR_XFACE @@ -1061,6 +1062,8 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); + va_end(args); } void ACPI_INTERNAL_VAR_XFACE @@ -1077,4 +1080,5 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf("\n"); + va_end(args); } diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index e08b3fa..cdb8ff5 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -107,6 +107,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, switch (type) { case ACPI_TYPE_REGION: case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: /* These types require a secondary object */ @@ -469,9 +470,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: - /* - * No extra data for these types - */ + /* No extra data for these types */ + break; case ACPI_TYPE_LOCAL_REFERENCE: diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 2d49691..4b336c8 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -49,6 +49,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxface") +#ifndef ACPI_ASL_COMPILER /******************************************************************************* * * FUNCTION: acpi_initialize_subsystem @@ -192,24 +193,6 @@ acpi_status acpi_enable_subsystem(u32 flags) } } - /* - * Complete the GPE initialization for the GPE blocks defined in the FADT - * (GPE block 0 and 1). - * - * Note1: This is where the _PRW methods are executed for the GPEs. These - * methods can only be executed after the SCI and Global Lock handlers are - * installed and initialized. - * - * Note2: Currently, there seems to be no need to run the _REG methods - * before execution of the _PRW methods and enabling of the GPEs. - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - status = acpi_ev_install_fadt_gpes(); - if (ACPI_FAILURE(status)) { - return (status); - } - } - return_ACPI_STATUS(status); } @@ -280,6 +263,24 @@ acpi_status acpi_initialize_objects(u32 flags) } /* + * Complete the GPE initialization for the GPE blocks defined in the FADT + * (GPE block 0 and 1). + * + * Note1: This is where the _PRW methods are executed for the GPEs. These + * methods can only be executed after the SCI and Global Lock handlers are + * installed and initialized. + * + * Note2: Currently, there seems to be no need to run the _REG methods + * before execution of the _PRW methods and enabling of the GPEs. + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_install_fadt_gpes(); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* * Empty the caches (delete the cached objects) on the assumption that * the table load filled them up more than they will be at runtime -- * thus wasting non-paged memory. @@ -292,6 +293,7 @@ acpi_status acpi_initialize_objects(u32 flags) ACPI_EXPORT_SYMBOL(acpi_initialize_objects) +#endif /******************************************************************************* * * FUNCTION: acpi_terminate @@ -335,6 +337,7 @@ acpi_status acpi_terminate(void) } ACPI_EXPORT_SYMBOL(acpi_terminate) +#ifndef ACPI_ASL_COMPILER #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -490,3 +493,4 @@ acpi_status acpi_purge_cached_objects(void) } ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) +#endif diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 44ea60c..1009261 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -398,7 +398,7 @@ acpi_evaluate_reference(acpi_handle handle, element = &(package->package.elements[i]); - if (element->type != ACPI_TYPE_ANY) { + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { status = AE_BAD_DATA; printk(KERN_ERR PREFIX "Expecting a [Reference] package element, found type %X\n", diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 422f29c..b4668b1 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070126 +#define ACPI_CA_VERSION 0x20080321 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -150,6 +150,17 @@ #define ACPI_OBJ_NUM_OPERANDS 8 #define ACPI_OBJ_MAX_OPERAND 7 +/* Number of elements in the Result Stack frame, can be an arbitrary value */ + +#define ACPI_RESULTS_FRAME_OBJ_NUM 8 + +/* + * Maximal number of elements the Result Stack can contain, + * it may be an arbitray value not exceeding the types of + * result_size and result_count (now u8). + */ +#define ACPI_RESULTS_OBJ_NUM_MAX 255 + /* Names within the namespace are 4 bytes long */ #define ACPI_NAME_SIZE 4 diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 389d772..73d86eb 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -97,19 +97,23 @@ typedef const struct acpi_dmtable_info { #define ACPI_DMT_CHKSUM 20 #define ACPI_DMT_SPACEID 21 #define ACPI_DMT_GAS 22 -#define ACPI_DMT_DMAR 23 -#define ACPI_DMT_MADT 24 -#define ACPI_DMT_SRAT 25 -#define ACPI_DMT_EXIT 26 -#define ACPI_DMT_SIG 27 +#define ACPI_DMT_ASF 23 +#define ACPI_DMT_DMAR 24 +#define ACPI_DMT_HEST 25 +#define ACPI_DMT_HESTNTFY 26 +#define ACPI_DMT_HESTNTYP 27 +#define ACPI_DMT_MADT 28 +#define ACPI_DMT_SRAT 29 +#define ACPI_DMT_EXIT 30 +#define ACPI_DMT_SIG 31 typedef -void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table); +void (*acpi_dmtable_handler) (struct acpi_table_header * table); struct acpi_dmtable_data { char *signature; struct acpi_dmtable_info *table_info; - ACPI_TABLE_HANDLER table_handler; + acpi_dmtable_handler table_handler; char *name; }; @@ -149,6 +153,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_asf3[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf4[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[]; extern struct acpi_dmtable_info acpi_dm_table_info_boot[]; +extern struct acpi_dmtable_info acpi_dm_table_info_bert[]; extern struct acpi_dmtable_info acpi_dm_table_info_cpep[]; extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[]; extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[]; @@ -158,11 +163,17 @@ extern struct acpi_dmtable_info acpi_dm_table_info_dmar_scope[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar1[]; extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[]; +extern struct acpi_dmtable_info acpi_dm_table_info_einj[]; +extern struct acpi_dmtable_info acpi_dm_table_info_einj0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_erst[]; extern struct acpi_dmtable_info acpi_dm_table_info_facs[]; extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[]; extern struct acpi_dmtable_info acpi_dm_table_info_fadt2[]; extern struct acpi_dmtable_info acpi_dm_table_info_gas[]; extern struct acpi_dmtable_info acpi_dm_table_info_header[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hest[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hest9[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hest_notify[]; extern struct acpi_dmtable_info acpi_dm_table_info_hpet[]; extern struct acpi_dmtable_info acpi_dm_table_info_madt[]; extern struct acpi_dmtable_info acpi_dm_table_info_madt0[]; @@ -180,6 +191,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[]; extern struct acpi_dmtable_info acpi_dm_table_info_rsdp1[]; extern struct acpi_dmtable_info acpi_dm_table_info_rsdp2[]; extern struct acpi_dmtable_info acpi_dm_table_info_sbst[]; +extern struct acpi_dmtable_info acpi_dm_table_info_slic[]; extern struct acpi_dmtable_info acpi_dm_table_info_slit[]; extern struct acpi_dmtable_info acpi_dm_table_info_spcr[]; extern struct acpi_dmtable_info acpi_dm_table_info_spmi[]; @@ -194,7 +206,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[]; */ void acpi_dm_dump_data_table(struct acpi_table_header *table); -void +acpi_status acpi_dm_dump_table(u32 table_length, u32 table_offset, void *table, @@ -213,9 +225,13 @@ void acpi_dm_dump_cpep(struct acpi_table_header *table); void acpi_dm_dump_dmar(struct acpi_table_header *table); +void acpi_dm_dump_einj(struct acpi_table_header *table); + +void acpi_dm_dump_erst(struct acpi_table_header *table); + void acpi_dm_dump_fadt(struct acpi_table_header *table); -void acpi_dm_dump_srat(struct acpi_table_header *table); +void acpi_dm_dump_hest(struct acpi_table_header *table); void acpi_dm_dump_mcfg(struct acpi_table_header *table); @@ -227,6 +243,8 @@ void acpi_dm_dump_rsdt(struct acpi_table_header *table); void acpi_dm_dump_slit(struct acpi_table_header *table); +void acpi_dm_dump_srat(struct acpi_table_header *table); + void acpi_dm_dump_xsdt(struct acpi_table_header *table); /* diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index 7f690bb..a5b97f0 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -53,6 +53,9 @@ acpi_status acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc); +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc); + acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *rgn_desc); acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc); @@ -68,10 +71,18 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *op); acpi_status +acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + +acpi_status acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *op, union acpi_operand_object *obj_desc); +acpi_status +acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + acpi_status acpi_ds_initialize_region(acpi_handle obj_handle); /* @@ -269,6 +280,8 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state); void acpi_ds_clear_operands(struct acpi_walk_state *walk_state); +acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state); + /* * dswscope - Scope Stack manipulation */ @@ -303,7 +316,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, u32 aml_length, struct acpi_evaluate_info *info, u8 pass_number); -acpi_status +void acpi_ds_obj_stack_pop_and_delete(u32 pop_count, struct acpi_walk_state *walk_state); @@ -316,21 +329,11 @@ void acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, struct acpi_thread_state *thread); -acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state); - -acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state); - acpi_status acpi_ds_result_stack_clear(struct acpi_walk_state *walk_state); struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state *thread); -#ifdef ACPI_FUTURE_USAGE -acpi_status -acpi_ds_result_remove(union acpi_operand_object **object, - u32 index, struct acpi_walk_state *walk_state); -#endif - acpi_status acpi_ds_result_pop(union acpi_operand_object **object, struct acpi_walk_state *walk_state); @@ -339,8 +342,4 @@ acpi_status acpi_ds_result_push(union acpi_operand_object *object, struct acpi_walk_state *walk_state); -acpi_status -acpi_ds_result_pop_from_bottom(union acpi_operand_object **object, - struct acpi_walk_state *walk_state); - #endif /* _ACDISPAT_H_ */ diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 47a1fd8..86cff21 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -170,10 +170,14 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; /* - * Global lock semaphore works in conjunction with the actual HW global lock + * Global lock mutex is an actual AML mutex object + * Global lock semaphore works in conjunction with the HW global lock */ -ACPI_EXTERN acpi_mutex acpi_gbl_global_lock_mutex; +ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; +ACPI_EXTERN u16 acpi_gbl_global_lock_handle; +ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; +ACPI_EXTERN u8 acpi_gbl_global_lock_present; /* * Spinlocks are used for interfaces that can be possibly called at @@ -213,27 +217,33 @@ ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; +ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; +ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; +/* Owner ID support */ + +ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; +ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; +ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; + /* Misc */ ACPI_EXTERN u32 acpi_gbl_original_mode; ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; ACPI_EXTERN u32 acpi_gbl_ps_find_count; -ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; -ACPI_EXTERN u16 acpi_gbl_global_lock_handle; -ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; -ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; ACPI_EXTERN u8 acpi_gbl_debugger_configuration; -ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; ACPI_EXTERN u8 acpi_gbl_step_to_next_call; ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; -ACPI_EXTERN u8 acpi_gbl_global_lock_present; ACPI_EXTERN u8 acpi_gbl_events_initialized; ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; +#ifndef DEFINE_ACPI_GLOBALS + +/* Other miscellaneous */ + extern u8 acpi_gbl_shutdown; extern u32 acpi_gbl_startup_flags; extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; @@ -241,6 +251,8 @@ extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; +#endif + /* Exception codes */ extern char const *acpi_gbl_exception_names_env[]; @@ -255,8 +267,6 @@ extern char const *acpi_gbl_exception_names_ctrl[]; * ****************************************************************************/ -#define NUM_NS_TYPES ACPI_TYPE_INVALID+1 - #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #define NUM_PREDEFINED_NAMES 10 #else @@ -267,7 +277,7 @@ ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; -extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; +extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; extern const struct acpi_predefined_names acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES]; @@ -275,8 +285,8 @@ extern const struct acpi_predefined_names ACPI_EXTERN u32 acpi_gbl_current_node_count; ACPI_EXTERN u32 acpi_gbl_current_node_size; ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count; -ACPI_EXTERN acpi_size acpi_gbl_entry_stack_pointer; -ACPI_EXTERN acpi_size acpi_gbl_lowest_stack_pointer; +ACPI_EXTERN acpi_size *acpi_gbl_entry_stack_pointer; +ACPI_EXTERN acpi_size *acpi_gbl_lowest_stack_pointer; ACPI_EXTERN u32 acpi_gbl_deepest_nesting; #endif diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index ce7c9d6..f4dd98f 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -215,8 +215,6 @@ acpi_ex_create_region(u8 * aml_start, u32 aml_length, u8 region_space, struct acpi_walk_state *walk_state); -acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state); - acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state); acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state); @@ -248,9 +246,16 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, struct acpi_walk_state *walk_state); acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id); + +acpi_status acpi_ex_release_mutex(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state); +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc); + void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread); void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc); @@ -455,9 +460,9 @@ void acpi_ex_relinquish_interpreter(void); void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); -u8 acpi_ex_acquire_global_lock(u32 rule); +void acpi_ex_acquire_global_lock(u32 rule); -void acpi_ex_release_global_lock(u8 locked); +void acpi_ex_release_global_lock(u32 rule); void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 202cd42..946da60 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -522,9 +522,8 @@ struct acpi_thread_state { * AML arguments */ struct acpi_result_values { - ACPI_STATE_COMMON u8 num_results; - u8 last_insert; - union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS]; + ACPI_STATE_COMMON + union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM]; }; typedef @@ -604,6 +603,7 @@ union acpi_parse_value { union acpi_parse_object *next; /* Next op */\ struct acpi_namespace_node *node; /* For use by interpreter */\ union acpi_parse_value value; /* Value or args associated with the opcode */\ + u8 arg_list_length; /* Number of elements in the arg list */\ ACPI_DISASM_ONLY_MEMBERS (\ u8 disasm_flags; /* Used during AML disassembly */\ u8 disasm_opcode; /* Subtype used for disassembly */\ @@ -696,6 +696,8 @@ struct acpi_parse_state { #define ACPI_PARSEOP_NAMED 0x02 #define ACPI_PARSEOP_DEFERRED 0x04 #define ACPI_PARSEOP_BYTELIST 0x08 +#define ACPI_PARSEOP_IN_STACK 0x10 +#define ACPI_PARSEOP_TARGET 0x20 #define ACPI_PARSEOP_IN_CACHE 0x80 /* Parse object disasm_flags */ diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 99d171c..1f0fdbf 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -61,30 +61,6 @@ #define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) -#ifdef ACPI_NO_INTEGER64_SUPPORT -/* - * acpi_integer is 32-bits, no 64-bit support on this platform - */ -#define ACPI_LODWORD(l) ((u32)(l)) -#define ACPI_HIDWORD(l) ((u32)(0)) - -#else - -/* - * Full 64-bit address/integer on both 32-bit and 64-bit platforms - */ -#define ACPI_LODWORD(l) ((u32)(u64)(l)) -#define ACPI_HIDWORD(l) ((u32)(((*(struct uint64_struct *)(void *)(&l))).hi)) -#endif - -/* - * printf() format helpers - */ - -/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */ - -#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) - /* * Extract data using a pointer. Any more than a byte and we * get into potential aligment issues -- see the STORE macros below. @@ -122,6 +98,31 @@ #endif /* + * Full 64-bit integer must be available on both 32-bit and 64-bit platforms + */ +struct acpi_integer_overlay { + u32 lo_dword; + u32 hi_dword; +}; + +#define ACPI_LODWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->lo_dword) +#define ACPI_HIDWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->hi_dword) + +/* + * printf() format helpers + */ + +/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */ + +#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +#else +#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +#endif + +/* * Macros for moving data around to/from buffers that are possibly unaligned. * If the hardware supports the transfer of unaligned data, just do the store. * Otherwise, we have to move one byte at a time. @@ -137,29 +138,29 @@ /* These macros reverse the bytes during the move, converting little-endian to big endian */ - /* Big Endian <== Little Endian */ - /* Hi...Lo Lo...Hi */ + /* Big Endian <== Little Endian */ + /* Hi...Lo Lo...Hi */ /* 16-bit source, 16/32/64 destination */ #define ACPI_MOVE_16_TO_16(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_32(d,s) {(*(u32 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} /* 32-bit source, 16/32/64 destination */ #define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */ #define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ - (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ + (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_32_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\ ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\ diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index 5ef38a6..1cad10b 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -113,7 +113,8 @@ acpi_ns_parse_table(acpi_native_uint table_index, acpi_status acpi_ns_one_complete_parse(acpi_native_uint pass_number, - acpi_native_uint table_index); + acpi_native_uint table_index, + struct acpi_namespace_node *start_node); /* * nsaccess - Top-level namespace access diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index 7e1211a..2461bb9 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -155,8 +155,9 @@ struct acpi_object_event { struct acpi_object_mutex { ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ u16 acquisition_depth; /* Allow multiple Acquires, same thread */ - struct acpi_thread_state *owner_thread; /* Current owner of the mutex */ acpi_mutex os_mutex; /* Actual OS synchronization object */ + acpi_thread_id thread_id; /* Current owner of the mutex */ + struct acpi_thread_state *owner_thread; /* Current owner of the mutex */ union acpi_operand_object *prev; /* Link for list of acquired mutexes */ union acpi_operand_object *next; /* Link for list of acquired mutexes */ struct acpi_namespace_node *node; /* Containing namespace node */ diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h index e6f76a2..ab54349 100644 --- a/include/acpi/acopcode.h +++ b/include/acpi/acopcode.h @@ -233,7 +233,7 @@ #define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING) #define ARGI_DEBUG_OP ARG_NONE -#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) +#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_TARGETREF) #define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING) #define ARGI_DEVICE_OP ARGI_INVALID_OPCODE #define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF) @@ -246,7 +246,7 @@ #define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET) #define ARGI_IF_OP ARGI_INVALID_OPCODE -#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) +#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_TARGETREF) #define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE #define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index 85c358e..a3ae76b 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -109,6 +109,8 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); char *acpi_ps_get_opcode_name(u16 opcode); +u8 acpi_ps_get_argument_count(u32 op_type); + /* * psparse - top level parsing routines */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index d970f7f..c92acda 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -119,6 +119,11 @@ acpi_status acpi_get_table_by_index(acpi_native_uint table_index, struct acpi_table_header **out_table); +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context); + +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler); + /* * Namespace and name interfaces */ diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h index 9486ab2..33e9f38 100644 --- a/include/acpi/acresrc.h +++ b/include/acpi/acresrc.h @@ -94,6 +94,7 @@ typedef const struct acpi_rsconvert_info { #define ACPI_RSC_BITMASK16 18 #define ACPI_RSC_EXIT_NE 19 #define ACPI_RSC_EXIT_LE 20 +#define ACPI_RSC_EXIT_EQ 21 /* Resource Conversion sub-opcodes */ diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index 8848265..19b838d 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -80,12 +80,15 @@ struct acpi_walk_state { u16 opcode; /* Current AML opcode */ u8 next_op_info; /* Info about next_op */ u8 num_operands; /* Stack pointer for Operands[] array */ + u8 operand_index; /* Index into operand stack, to be used by acpi_ds_obj_stack_push */ acpi_owner_id owner_id; /* Owner of objects created during the walk */ u8 last_predicate; /* Result of last predicate */ u8 current_result; u8 return_used; u8 scope_depth; u8 pass_number; /* Parse pass during table load */ + u8 result_size; /* Total elements for the result stack */ + u8 result_count; /* Current number of occupied elements of result stack */ u32 aml_offset; u32 arg_types; u32 method_breakpoint; /* For single stepping */ diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index a1b1b2e..604dfb3 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -58,20 +58,28 @@ * it more difficult to inadvertently type in the wrong signature. */ #define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ +#define ACPI_SIG_BERT "BERT" /* Boot Error Record Table */ #define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ #define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */ #define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ #define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ #define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */ +#define ACPI_SIG_EINJ "EINJ" /* Error Injection table */ +#define ACPI_SIG_ERST "ERST" /* Error Record Serialization Table */ +#define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */ #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ +#define ACPI_SIG_IBFT "IBFT" /* i_sCSI Boot Firmware Table */ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ #define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ +#define ACPI_SIG_SLIC "SLIC" /* Software Licensing Description Table */ #define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */ #define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ #define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ +#define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */ +#define ACPI_SIG_WDAT "WDAT" /* Watchdog Action Table */ #define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */ /* @@ -86,13 +94,25 @@ * portable, so do not use any other bitfield types. */ -/* Common Sub-table header (used in MADT, SRAT, etc.) */ +/* Common Subtable header (used in MADT, SRAT, etc.) */ struct acpi_subtable_header { u8 type; u8 length; }; +/* Common Subtable header for WHEA tables (EINJ, ERST, WDAT) */ + +struct acpi_whea_header { + u8 action; + u8 instruction; + u8 flags; + u8 reserved; + struct acpi_generic_address register_region; + u64 value; /* Value used with Read/Write register */ + u64 mask; /* Bitmask required for this register instruction */ +}; + /******************************************************************************* * * ASF - Alert Standard Format table (Signature "ASF!") @@ -204,6 +224,35 @@ struct acpi_asf_address { /******************************************************************************* * + * BERT - Boot Error Record Table + * + ******************************************************************************/ + +struct acpi_table_bert { + struct acpi_table_header header; /* Common ACPI table header */ + u32 region_length; /* Length of the boot error region */ + u64 address; /* Physical addresss of the error region */ +}; + +/* Boot Error Region */ + +struct acpi_bert_region { + u32 block_status; + u32 raw_data_offset; + u32 raw_data_length; + u32 data_length; + u32 error_severity; +}; + +/* block_status Flags */ + +#define ACPI_BERT_UNCORRECTABLE (1) +#define ACPI_BERT_CORRECTABLE (2) +#define ACPI_BERT_MULTIPLE_UNCORRECTABLE (4) +#define ACPI_BERT_MULTIPLE_CORRECTABLE (8) + +/******************************************************************************* + * * BOOT - Simple Boot Flag Table * ******************************************************************************/ @@ -350,6 +399,352 @@ struct acpi_table_ecdt { /******************************************************************************* * + * EINJ - Error Injection Table + * + ******************************************************************************/ + +struct acpi_table_einj { + struct acpi_table_header header; /* Common ACPI table header */ + u32 header_length; + u32 reserved; + u32 entries; +}; + +/* EINJ Injection Instruction Entries (actions) */ + +struct acpi_einj_entry { + struct acpi_whea_header whea_header; /* Common header for WHEA tables */ +}; + +/* Values for Action field above */ + +enum acpi_einj_actions { + ACPI_EINJ_BEGIN_OPERATION = 0, + ACPI_EINJ_GET_TRIGGER_TABLE = 1, + ACPI_EINJ_SET_ERROR_TYPE = 2, + ACPI_EINJ_GET_ERROR_TYPE = 3, + ACPI_EINJ_END_OPERATION = 4, + ACPI_EINJ_EXECUTE_OPERATION = 5, + ACPI_EINJ_CHECK_BUSY_STATUS = 6, + ACPI_EINJ_GET_COMMAND_STATUS = 7, + ACPI_EINJ_ACTION_RESERVED = 8, /* 8 and greater are reserved */ + ACPI_EINJ_TRIGGER_ERROR = 0xFF /* Except for this value */ +}; + +/* Values for Instruction field above */ + +enum acpi_einj_instructions { + ACPI_EINJ_READ_REGISTER = 0, + ACPI_EINJ_READ_REGISTER_VALUE = 1, + ACPI_EINJ_WRITE_REGISTER = 2, + ACPI_EINJ_WRITE_REGISTER_VALUE = 3, + ACPI_EINJ_NOOP = 4, + ACPI_EINJ_INSTRUCTION_RESERVED = 5 /* 5 and greater are reserved */ +}; + +/* EINJ Trigger Error Action Table */ + +struct acpi_einj_trigger { + u32 header_size; + u32 revision; + u32 table_size; + u32 entry_count; +}; + +/******************************************************************************* + * + * ERST - Error Record Serialization Table + * + ******************************************************************************/ + +struct acpi_table_erst { + struct acpi_table_header header; /* Common ACPI table header */ + u32 header_length; + u32 reserved; + u32 entries; +}; + +/* ERST Serialization Entries (actions) */ + +struct acpi_erst_entry { + struct acpi_whea_header whea_header; /* Common header for WHEA tables */ +}; + +/* Values for Action field above */ + +enum acpi_erst_actions { + ACPI_ERST_BEGIN_WRITE_OPERATION = 0, + ACPI_ERST_BEGIN_READ_OPERATION = 1, + ACPI_ERST_BETGIN_CLEAR_OPERATION = 2, + ACPI_ERST_END_OPERATION = 3, + ACPI_ERST_SET_RECORD_OFFSET = 4, + ACPI_ERST_EXECUTE_OPERATION = 5, + ACPI_ERST_CHECK_BUSY_STATUS = 6, + ACPI_ERST_GET_COMMAND_STATUS = 7, + ACPI_ERST_GET_RECORD_IDENTIFIER = 8, + ACPI_ERST_SET_RECORD_IDENTIFIER = 9, + ACPI_ERST_GET_RECORD_COUNT = 10, + ACPI_ERST_BEGIN_DUMMY_WRIITE = 11, + ACPI_ERST_NOT_USED = 12, + ACPI_ERST_GET_ERROR_RANGE = 13, + ACPI_ERST_GET_ERROR_LENGTH = 14, + ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, + ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ +}; + +/* Values for Instruction field above */ + +enum acpi_erst_instructions { + ACPI_ERST_READ_REGISTER = 0, + ACPI_ERST_READ_REGISTER_VALUE = 1, + ACPI_ERST_WRITE_REGISTER = 2, + ACPI_ERST_WRITE_REGISTER_VALUE = 3, + ACPI_ERST_NOOP = 4, + ACPI_ERST_LOAD_VAR1 = 5, + ACPI_ERST_LOAD_VAR2 = 6, + ACPI_ERST_STORE_VAR1 = 7, + ACPI_ERST_ADD = 8, + ACPI_ERST_SUBTRACT = 9, + ACPI_ERST_ADD_VALUE = 10, + ACPI_ERST_SUBTRACT_VALUE = 11, + ACPI_ERST_STALL = 12, + ACPI_ERST_STALL_WHILE_TRUE = 13, + ACPI_ERST_SKIP_NEXT_IF_TRUE = 14, + ACPI_ERST_GOTO = 15, + ACPI_ERST_SET_SRC_ADDRESS_BASE = 16, + ACPI_ERST_SET_DST_ADDRESS_BASE = 17, + ACPI_ERST_MOVE_DATA = 18, + ACPI_ERST_INSTRUCTION_RESERVED = 19 /* 19 and greater are reserved */ +}; + +/******************************************************************************* + * + * HEST - Hardware Error Source Table + * + ******************************************************************************/ + +struct acpi_table_hest { + struct acpi_table_header header; /* Common ACPI table header */ + u32 error_source_count; +}; + +/* HEST subtable header */ + +struct acpi_hest_header { + u16 type; +}; + +/* Values for Type field above for subtables */ + +enum acpi_hest_types { + ACPI_HEST_TYPE_XPF_MACHINE_CHECK = 0, + ACPI_HEST_TYPE_XPF_CORRECTED_MACHINE_CHECK = 1, + ACPI_HEST_TYPE_XPF_UNUSED = 2, + ACPI_HEST_TYPE_XPF_NON_MASKABLE_INTERRUPT = 3, + ACPI_HEST_TYPE_IPF_CORRECTED_MACHINE_CHECK = 4, + ACPI_HEST_TYPE_IPF_CORRECTED_PLATFORM_ERROR = 5, + ACPI_HEST_TYPE_AER_ROOT_PORT = 6, + ACPI_HEST_TYPE_AER_ENDPOINT = 7, + ACPI_HEST_TYPE_AER_BRIDGE = 8, + ACPI_HEST_TYPE_GENERIC_HARDWARE_ERROR_SOURCE = 9, + ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ +}; + +/* + * HEST Sub-subtables + */ + +/* XPF Machine Check Error Bank */ + +struct acpi_hest_xpf_error_bank { + u8 bank_number; + u8 clear_status_on_init; + u8 status_format; + u8 config_write_enable; + u32 control_register; + u64 control_init_data; + u32 status_register; + u32 address_register; + u32 misc_register; +}; + +/* Generic Error Status */ + +struct acpi_hest_generic_status { + u32 block_status; + u32 raw_data_offset; + u32 raw_data_length; + u32 data_length; + u32 error_severity; +}; + +/* Generic Error Data */ + +struct acpi_hest_generic_data { + u8 section_type[16]; + u32 error_severity; + u16 revision; + u8 validation_bits; + u8 flags; + u32 error_data_length; + u8 fru_id[16]; + u8 fru_text[20]; +}; + +/* Common HEST structure for PCI/AER types below (6,7,8) */ + +struct acpi_hest_aer_common { + u16 source_id; + u16 config_write_enable; + u8 flags; + u8 enabled; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u32 bus; + u16 device; + u16 function; + u16 device_control; + u16 reserved; + u32 uncorrectable_error_mask; + u32 uncorrectable_error_severity; + u32 correctable_error_mask; + u32 advanced_error_cababilities; +}; + +/* Hardware Error Notification */ + +struct acpi_hest_notify { + u8 type; + u8 length; + u16 config_write_enable; + u32 poll_interval; + u32 vector; + u32 polling_threshold_value; + u32 polling_threshold_window; + u32 error_threshold_value; + u32 error_threshold_window; +}; + +/* Values for Notify Type field above */ + +enum acpi_hest_notify_types { + ACPI_HEST_NOTIFY_POLLED = 0, + ACPI_HEST_NOTIFY_EXTERNAL = 1, + ACPI_HEST_NOTIFY_LOCAL = 2, + ACPI_HEST_NOTIFY_SCI = 3, + ACPI_HEST_NOTIFY_NMI = 4, + ACPI_HEST_NOTIFY_RESERVED = 5 /* 5 and greater are reserved */ +}; + +/* + * HEST subtables + * + * From WHEA Design Document, 16 May 2007. + * Note: There is no subtable type 2 in this version of the document, + * and there are two different subtable type 3s. + */ + + /* 0: XPF Machine Check Exception */ + +struct acpi_hest_xpf_machine_check { + struct acpi_hest_header header; + u16 source_id; + u16 config_write_enable; + u8 flags; + u8 reserved1; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u64 global_capability_data; + u64 global_control_data; + u8 num_hardware_banks; + u8 reserved2[7]; +}; + +/* 1: XPF Corrected Machine Check */ + +struct acpi_table_hest_xpf_corrected { + struct acpi_hest_header header; + u16 source_id; + u16 config_write_enable; + u8 flags; + u8 enabled; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + struct acpi_hest_notify notify; + u8 num_hardware_banks; + u8 reserved[3]; +}; + +/* 3: XPF Non-Maskable Interrupt */ + +struct acpi_hest_xpf_nmi { + struct acpi_hest_header header; + u16 source_id; + u32 reserved; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u32 max_raw_data_length; +}; + +/* 4: IPF Corrected Machine Check */ + +struct acpi_hest_ipf_corrected { + struct acpi_hest_header header; + u8 enabled; + u8 reserved; +}; + +/* 5: IPF Corrected Platform Error */ + +struct acpi_hest_ipf_corrected_platform { + struct acpi_hest_header header; + u8 enabled; + u8 reserved; +}; + +/* 6: PCI Express Root Port AER */ + +struct acpi_hest_aer_root { + struct acpi_hest_header header; + struct acpi_hest_aer_common aer; + u32 root_error_command; +}; + +/* 7: PCI Express AER (AER Endpoint) */ + +struct acpi_hest_aer { + struct acpi_hest_header header; + struct acpi_hest_aer_common aer; +}; + +/* 8: PCI Express/PCI-X Bridge AER */ + +struct acpi_hest_aer_bridge { + struct acpi_hest_header header; + struct acpi_hest_aer_common aer; + u32 secondary_uncorrectable_error_mask; + u32 secondary_uncorrectable_error_severity; + u32 secondary_advanced_capabilities; +}; + +/* 9: Generic Hardware Error Source */ + +struct acpi_hest_generic { + struct acpi_hest_header header; + u16 source_id; + u16 related_source_id; + u8 config_write_enable; + u8 enabled; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u32 max_raw_data_length; + struct acpi_generic_address error_status_address; + struct acpi_hest_notify notify; + u32 error_status_block_length; +}; + +/******************************************************************************* + * * HPET - High Precision Event Timer table * ******************************************************************************/ @@ -373,6 +768,96 @@ struct acpi_table_hpet { /******************************************************************************* * + * IBFT - Boot Firmware Table + * + ******************************************************************************/ + +struct acpi_table_ibft { + struct acpi_table_header header; /* Common ACPI table header */ + u8 reserved[12]; +}; + +/* IBFT common subtable header */ + +struct acpi_ibft_header { + u8 type; + u8 version; + u16 length; + u8 index; + u8 flags; +}; + +/* Values for Type field above */ + +enum acpi_ibft_type { + ACPI_IBFT_TYPE_NOT_USED = 0, + ACPI_IBFT_TYPE_CONTROL = 1, + ACPI_IBFT_TYPE_INITIATOR = 2, + ACPI_IBFT_TYPE_NIC = 3, + ACPI_IBFT_TYPE_TARGET = 4, + ACPI_IBFT_TYPE_EXTENSIONS = 5, + ACPI_IBFT_TYPE_RESERVED = 6 /* 6 and greater are reserved */ +}; + +/* IBFT subtables */ + +struct acpi_ibft_control { + struct acpi_ibft_header header; + u16 extensions; + u16 initiator_offset; + u16 nic0_offset; + u16 target0_offset; + u16 nic1_offset; + u16 target1_offset; +}; + +struct acpi_ibft_initiator { + struct acpi_ibft_header header; + u8 sns_server[16]; + u8 slp_server[16]; + u8 primary_server[16]; + u8 secondary_server[16]; + u16 name_length; + u16 name_offset; +}; + +struct acpi_ibft_nic { + struct acpi_ibft_header header; + u8 ip_address[16]; + u8 subnet_mask_prefix; + u8 origin; + u8 gateway[16]; + u8 primary_dns[16]; + u8 secondary_dns[16]; + u8 dhcp[16]; + u16 vlan; + u8 mac_address[6]; + u16 pci_address; + u16 name_length; + u16 name_offset; +}; + +struct acpi_ibft_target { + struct acpi_ibft_header header; + u8 target_ip_address[16]; + u16 target_ip_socket; + u8 target_boot_lun[8]; + u8 chap_type; + u8 nic_association; + u16 target_name_length; + u16 target_name_offset; + u16 chap_name_length; + u16 chap_name_offset; + u16 chap_secret_length; + u16 chap_secret_offset; + u16 reverse_chap_name_length; + u16 reverse_chap_name_offset; + u16 reverse_chap_secret_length; + u16 reverse_chap_secret_offset; +}; + +/******************************************************************************* + * * MADT - Multiple APIC Description Table * ******************************************************************************/ @@ -697,6 +1182,78 @@ struct acpi_table_tcpa { /******************************************************************************* * + * UEFI - UEFI Boot optimization Table + * + ******************************************************************************/ + +struct acpi_table_uefi { + struct acpi_table_header header; /* Common ACPI table header */ + u8 identifier[16]; /* UUID identifier */ + u16 data_offset; /* Offset of remaining data in table */ + u8 data; +}; + +/******************************************************************************* + * + * WDAT - Watchdog Action Table + * + ******************************************************************************/ + +struct acpi_table_wdat { + struct acpi_table_header header; /* Common ACPI table header */ + u32 header_length; /* Watchdog Header Length */ + u16 pci_segment; /* PCI Segment number */ + u8 pci_bus; /* PCI Bus number */ + u8 pci_device; /* PCI Device number */ + u8 pci_function; /* PCI Function number */ + u8 reserved[3]; + u32 timer_period; /* Period of one timer count (msec) */ + u32 max_count; /* Maximum counter value supported */ + u32 min_count; /* Minimum counter value */ + u8 flags; + u8 reserved2[3]; + u32 entries; /* Number of watchdog entries that follow */ +}; + +/* WDAT Instruction Entries (actions) */ + +struct acpi_wdat_entry { + struct acpi_whea_header whea_header; /* Common header for WHEA tables */ +}; + +/* Values for Action field above */ + +enum acpi_wdat_actions { + ACPI_WDAT_RESET = 1, + ACPI_WDAT_GET_CURRENT_COUNTDOWN = 4, + ACPI_WDAT_GET_COUNTDOWN = 5, + ACPI_WDAT_SET_COUNTDOWN = 6, + ACPI_WDAT_GET_RUNNING_STATE = 8, + ACPI_WDAT_SET_RUNNING_STATE = 9, + ACPI_WDAT_GET_STOPPED_STATE = 10, + ACPI_WDAT_SET_STOPPED_STATE = 11, + ACPI_WDAT_GET_REBOOT = 16, + ACPI_WDAT_SET_REBOOT = 17, + ACPI_WDAT_GET_SHUTDOWN = 18, + ACPI_WDAT_SET_SHUTDOWN = 19, + ACPI_WDAT_GET_STATUS = 32, + ACPI_WDAT_SET_STATUS = 33, + ACPI_WDAT_ACTION_RESERVED = 34 /* 34 and greater are reserved */ +}; + +/* Values for Instruction field above */ + +enum acpi_wdat_instructions { + ACPI_WDAT_READ_VALUE = 0, + ACPI_WDAT_READ_COUNTDOWN = 1, + ACPI_WDAT_WRITE_VALUE = 2, + ACPI_WDAT_WRITE_COUNTDOWN = 3, + ACPI_WDAT_INSTRUCTION_RESERVED = 4, /* 4 and greater are reserved */ + ACPI_WDAT_PRESERVE_REGISTER = 0x80 /* Except for this value */ +}; + +/******************************************************************************* + * * WDRT - Watchdog Resource Table * ******************************************************************************/ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index e73a389..cc24cef 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -323,27 +323,11 @@ struct uint32_struct { #define acpi_semaphore void * /* - * Acpi integer width. In ACPI version 1, integers are - * 32 bits. In ACPI version 2, integers are 64 bits. - * Note that this pertains to the ACPI integer type only, not - * other integers used in the implementation of the ACPI CA + * Acpi integer width. In ACPI version 1, integers are 32 bits. In ACPI + * version 2, integers are 64 bits. Note that this pertains to the ACPI integer + * type only, not other integers used in the implementation of the ACPI CA * subsystem. */ -#ifdef ACPI_NO_INTEGER64_SUPPORT - -/* 32-bit integers only, no 64-bit support */ - -typedef u32 acpi_integer; -#define ACPI_INTEGER_MAX ACPI_UINT32_MAX -#define ACPI_INTEGER_BIT_SIZE 32 -#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */ - -#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */ - -#else - -/* 64-bit integers */ - typedef unsigned long long acpi_integer; #define ACPI_INTEGER_MAX ACPI_UINT64_MAX #define ACPI_INTEGER_BIT_SIZE 64 @@ -352,7 +336,6 @@ typedef unsigned long long acpi_integer; #if ACPI_MACHINE_WIDTH == 64 #define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */ #endif -#endif #define ACPI_MAX64_DECIMAL_DIGITS 20 #define ACPI_MAX32_DECIMAL_DIGITS 10 @@ -419,14 +402,20 @@ typedef unsigned long long acpi_integer; /* * Standard notify values */ -#define ACPI_NOTIFY_BUS_CHECK (u8) 0 -#define ACPI_NOTIFY_DEVICE_CHECK (u8) 1 -#define ACPI_NOTIFY_DEVICE_WAKE (u8) 2 -#define ACPI_NOTIFY_EJECT_REQUEST (u8) 3 -#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 4 -#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 5 -#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 -#define ACPI_NOTIFY_POWER_FAULT (u8) 7 +#define ACPI_NOTIFY_BUS_CHECK (u8) 0x00 +#define ACPI_NOTIFY_DEVICE_CHECK (u8) 0x01 +#define ACPI_NOTIFY_DEVICE_WAKE (u8) 0x02 +#define ACPI_NOTIFY_EJECT_REQUEST (u8) 0x03 +#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 0x04 +#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 0x05 +#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 0x06 +#define ACPI_NOTIFY_POWER_FAULT (u8) 0x07 +#define ACPI_NOTIFY_CAPABILITIES_CHECK (u8) 0x08 +#define ACPI_NOTIFY_DEVICE_PLD_CHECK (u8) 0x09 +#define ACPI_NOTIFY_RESERVED (u8) 0x0A +#define ACPI_NOTIFY_LOCALITY_UPDATE (u8) 0x0B + +#define ACPI_NOTIFY_MAX 0x0B /* * Types associated with ACPI names and objects. The first group of @@ -494,6 +483,8 @@ typedef u32 acpi_object_type; #define ACPI_TYPE_INVALID 0x1E #define ACPI_TYPE_NOT_FOUND 0xFF +#define ACPI_NUM_NS_TYPES (ACPI_TYPE_INVALID + 1) + /* * All I/O */ @@ -599,7 +590,7 @@ typedef u32 acpi_event_status; #define ACPI_SYSTEM_NOTIFY 0x1 #define ACPI_DEVICE_NOTIFY 0x2 -#define ACPI_ALL_NOTIFY 0x3 +#define ACPI_ALL_NOTIFY (ACPI_SYSTEM_NOTIFY | ACPI_DEVICE_NOTIFY) #define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3 #define ACPI_MAX_SYS_NOTIFY 0x7f @@ -654,46 +645,51 @@ typedef u8 acpi_adr_space_type; /* * External ACPI object definition */ + +/* + * Note: Type == ACPI_TYPE_ANY (0) is used to indicate a NULL package element + * or an unresolved named reference. + */ union acpi_object { acpi_object_type type; /* See definition of acpi_ns_type for values */ struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_INTEGER */ acpi_integer value; /* The actual number */ } integer; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_STRING */ u32 length; /* # of bytes in string, excluding trailing null */ char *pointer; /* points to the string value */ } string; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_BUFFER */ u32 length; /* # of bytes in buffer */ u8 *pointer; /* points to the buffer */ } buffer; struct { - acpi_object_type type; - u32 fill1; - acpi_handle handle; /* object reference */ - } reference; - - struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_PACKAGE */ u32 count; /* # of elements in package */ union acpi_object *elements; /* Pointer to an array of ACPI_OBJECTs */ } package; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_LOCAL_REFERENCE */ + acpi_object_type actual_type; /* Type associated with the Handle */ + acpi_handle handle; /* object reference */ + } reference; + + struct { + acpi_object_type type; /* ACPI_TYPE_PROCESSOR */ u32 proc_id; acpi_io_address pblk_address; u32 pblk_length; } processor; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_POWER */ u32 system_level; u32 resource_order; } power_resource; @@ -747,6 +743,12 @@ struct acpi_system_info { u32 debug_layer; }; +/* Table Event Types */ + +#define ACPI_TABLE_EVENT_LOAD 0x0 +#define ACPI_TABLE_EVENT_UNLOAD 0x1 +#define ACPI_NUM_TABLE_EVENTS 2 + /* * Types specific to the OS service interfaces */ @@ -776,6 +778,11 @@ acpi_status(*acpi_exception_handler) (acpi_status aml_status, u16 opcode, u32 aml_offset, void *context); +/* Table Event handler (Load, load_table etc) and types */ + +typedef +acpi_status(*acpi_tbl_handler) (u32 event, void *table, void *context); + /* Address Spaces (For Operation Regions) */ typedef @@ -990,6 +997,7 @@ struct acpi_vendor_uuid { * Structures used to describe device resources */ struct acpi_resource_irq { + u8 descriptor_length; u8 triggering; u8 polarity; u8 sharable; @@ -1006,6 +1014,7 @@ struct acpi_resource_dma { }; struct acpi_resource_start_dependent { + u8 descriptor_length; u8 compatibility_priority; u8 performance_robustness; }; diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index a291854..26115da 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -116,6 +116,8 @@ void acpi_ut_init_globals(void); char *acpi_ut_get_mutex_name(u32 mutex_id); +const char *acpi_ut_get_notify_name(u32 notify_value); + #endif char *acpi_ut_get_type_name(acpi_object_type type); diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 6233f3b..b45da40 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -19,16 +19,6 @@ config PM will issue the hlt instruction if nothing is to be done, thereby sending the processor to sleep and saving power. -config PM_LEGACY - bool "Legacy Power Management API (DEPRECATED)" - depends on PM - default n - ---help--- - Support for pm_register() and friends. This old API is obsoleted - by the driver model. - - If unsure, say N. - config PM_DEBUG bool "Power Management Debug Support" depends on PM diff --git a/kernel/power/Makefile b/kernel/power/Makefile index f7dfff2..597823b 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -4,7 +4,6 @@ EXTRA_CFLAGS += -DDEBUG endif obj-y := main.o -obj-$(CONFIG_PM_LEGACY) += pm.o obj-$(CONFIG_PM_SLEEP) += process.o console.o obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o diff --git a/kernel/power/pm.c b/kernel/power/pm.c deleted file mode 100644 index 60c73fa..0000000 --- a/kernel/power/pm.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * pm.c - Power management interface - * - * Copyright (C) 2000 Andrew Henroid - * - * 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 - -/* - * Locking notes: - * pm_devs_lock can be a semaphore providing pm ops are not called - * from an interrupt handler (already a bad idea so no change here). Each - * change must be protected so that an unlink of an entry doesn't clash - * with a pm send - which is permitted to sleep in the current architecture - * - * Module unloads clashing with pm events now work out safely, the module - * unload path will block until the event has been sent. It may well block - * until a resume but that will be fine. - */ - -static DEFINE_MUTEX(pm_devs_lock); -static LIST_HEAD(pm_devs); - -/** - * pm_register - register a device with power management - * @type: device type - * @id: device ID - * @callback: callback function - * - * Add a device to the list of devices that wish to be notified about - * power management events. A &pm_dev structure is returned on success, - * on failure the return is %NULL. - * - * The callback function will be called in process context and - * it may sleep. - */ - -struct pm_dev *pm_register(pm_dev_t type, - unsigned long id, - pm_callback callback) -{ - struct pm_dev *dev = kzalloc(sizeof(struct pm_dev), GFP_KERNEL); - if (dev) { - dev->type = type; - dev->id = id; - dev->callback = callback; - - mutex_lock(&pm_devs_lock); - list_add(&dev->entry, &pm_devs); - mutex_unlock(&pm_devs_lock); - } - return dev; -} - -/** - * pm_send - send request to a single device - * @dev: device to send to - * @rqst: power management request - * @data: data for the callback - * - * Issue a power management request to a given device. The - * %PM_SUSPEND and %PM_RESUME events are handled specially. The - * data field must hold the intended next state. No call is made - * if the state matches. - * - * BUGS: what stops two power management requests occurring in parallel - * and conflicting. - * - * WARNING: Calling pm_send directly is not generally recommended, in - * particular there is no locking against the pm_dev going away. The - * caller must maintain all needed locking or have 'inside knowledge' - * on the safety. Also remember that this function is not locked against - * pm_unregister. This means that you must handle SMP races on callback - * execution and unload yourself. - */ - -static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - int status = 0; - unsigned long prev_state, next_state; - - if (in_interrupt()) - BUG(); - - switch (rqst) { - case PM_SUSPEND: - case PM_RESUME: - prev_state = dev->state; - next_state = (unsigned long) data; - if (prev_state != next_state) { - if (dev->callback) - status = (*dev->callback)(dev, rqst, data); - if (!status) { - dev->state = next_state; - dev->prev_state = prev_state; - } - } - else { - dev->prev_state = prev_state; - } - break; - default: - if (dev->callback) - status = (*dev->callback)(dev, rqst, data); - break; - } - return status; -} - -/* - * Undo incomplete request - */ -static void pm_undo_all(struct pm_dev *last) -{ - struct list_head *entry = last->entry.prev; - while (entry != &pm_devs) { - struct pm_dev *dev = list_entry(entry, struct pm_dev, entry); - if (dev->state != dev->prev_state) { - /* previous state was zero (running) resume or - * previous state was non-zero (suspended) suspend - */ - pm_request_t undo = (dev->prev_state - ? PM_SUSPEND:PM_RESUME); - pm_send(dev, undo, (void*) dev->prev_state); - } - entry = entry->prev; - } -} - -/** - * pm_send_all - send request to all managed devices - * @rqst: power management request - * @data: data for the callback - * - * Issue a power management request to a all devices. The - * %PM_SUSPEND events are handled specially. Any device is - * permitted to fail a suspend by returning a non zero (error) - * value from its callback function. If any device vetoes a - * suspend request then all other devices that have suspended - * during the processing of this request are restored to their - * previous state. - * - * WARNING: This function takes the pm_devs_lock. The lock is not dropped until - * the callbacks have completed. This prevents races against pm locking - * functions, races against module unload pm_unregister code. It does - * mean however that you must not issue pm_ functions within the callback - * or you will deadlock and users will hate you. - * - * Zero is returned on success. If a suspend fails then the status - * from the device that vetoes the suspend is returned. - * - * BUGS: what stops two power management requests occurring in parallel - * and conflicting. - */ - -int pm_send_all(pm_request_t rqst, void *data) -{ - struct list_head *entry; - - mutex_lock(&pm_devs_lock); - entry = pm_devs.next; - while (entry != &pm_devs) { - struct pm_dev *dev = list_entry(entry, struct pm_dev, entry); - if (dev->callback) { - int status = pm_send(dev, rqst, data); - if (status) { - /* return devices to previous state on - * failed suspend request - */ - if (rqst == PM_SUSPEND) - pm_undo_all(dev); - mutex_unlock(&pm_devs_lock); - return status; - } - } - entry = entry->next; - } - mutex_unlock(&pm_devs_lock); - return 0; -} - -EXPORT_SYMBOL(pm_register); -EXPORT_SYMBOL(pm_send_all); -