mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
Power management and ACPI material for v4.3-rc1
- ACPICA update to upstream revision 20150818 including method tracing extensions to allow more in-depth AML debugging in the kernel and a number of assorted fixes and cleanups (Bob Moore, Lv Zheng, Markus Elfring). - ACPI sysfs code updates and a documentation update related to AML method tracing (Lv Zheng). - ACPI EC driver fix related to serialized evaluations of _Qxx methods and ACPI tools updates allowing the EC userspace tool to be built from the kernel source (Lv Zheng). - ACPI processor driver updates preparing it for future introduction of CPPC support and ACPI PCC mailbox driver updates (Ashwin Chaugule). - ACPI interrupts enumeration fix for a regression related to the handling of IRQ attribute conflicts between MADT and the ACPI namespace (Jiang Liu). - Fixes related to ACPI device PM (Mika Westerberg, Srinidhi Kasagar). - ACPI device registration code reorganization to separate the sysfs-related code and bus type operations from the rest (Rafael J Wysocki). - Assorted cleanups in the ACPI core (Jarkko Nikula, Mathias Krause, Andy Shevchenko, Rafael J Wysocki, Nicolas Iooss). - ACPI cpufreq driver and ia64 cpufreq driver fixes and cleanups (Pan Xinhui, Rafael J Wysocki). - cpufreq core cleanups on top of the previous changes allowing it to preseve its sysfs directories over system suspend/resume (Viresh Kumar, Rafael J Wysocki, Sebastian Andrzej Siewior). - cpufreq fixes and cleanups related to governors (Viresh Kumar). - cpufreq updates (core and the cpufreq-dt driver) related to the turbo/boost mode support (Viresh Kumar, Bartlomiej Zolnierkiewicz). - New DT bindings for Operating Performance Points (OPP), support for them in the OPP framework and in the cpufreq-dt driver plus related OPP framework fixes and cleanups (Viresh Kumar). - cpufreq powernv driver updates (Shilpasri G Bhat). - New cpufreq driver for Mediatek MT8173 (Pi-Cheng Chen). - Assorted cpufreq driver (speedstep-lib, sfi, integrator) cleanups and fixes (Abhilash Jindal, Andrzej Hajda, Cristian Ardelean). - intel_pstate driver updates including Skylake-S support, support for enabling HW P-states per CPU and an additional vendor bypass list entry (Kristen Carlson Accardi, Chen Yu, Ethan Zhao). - cpuidle core fixes related to the handling of coupled idle states (Xunlei Pang). - intel_idle driver updates including Skylake Client support and support for freeze-mode-specific idle states (Len Brown). - Driver core updates related to power management (Andy Shevchenko, Rafael J Wysocki). - Generic power domains framework fixes and cleanups (Jon Hunter, Geert Uytterhoeven, Rajendra Nayak, Ulf Hansson). - Device PM QoS framework update to allow the latency tolerance setting to be exposed to user space via sysfs (Mika Westerberg). - devfreq support for PPMUv2 in Exynos5433 and a fix for an incorrect exynos-ppmu DT binding (Chanwoo Choi, Javier Martinez Canillas). - System sleep support updates (Alan Stern, Len Brown, SungEun Kim). - rockchip-io AVS support updates (Heiko Stuebner). - PM core clocks support fixup (Colin Ian King). - Power capping RAPL driver update including support for Skylake H/S and Broadwell-H (Radivoje Jovanovic, Seiichi Ikarashi). - Generic device properties framework fixes related to the handling of static (driver-provided) property sets (Andy Shevchenko). - turbostat and cpupower updates (Len Brown, Shilpasri G Bhat, Shreyas B Prabhu). / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJV5hhGAAoJEILEb/54YlRxs+EQAK51iFk48+IbpHYaZZ50Yo4m ZZc2zBcbwRcBlU9vKERrhG+jieSl8J/JJNxT8vBjKqyvNw038mCjewQh02ol0HuC R7nlDiVJkmZ50sLO4xwE/1UBZr/XqbddwCUnYzvFMkMTA0ePzFtf8BrJ1FXpT8S/ fkwSXQty6hvJDwxkfrbMSaA730wMju9lahx8D6MlmUAedWYZOJDMQKB4WKa/St5X 9uckBPHUBB2KiKlXxdbFPwKLNxHvLROq5SpDLc6cM/7XZB+QfNFy85CUjCUtYo1O 1W8k0qnztvZ6UEv27qz5dejGyAGOarMWGGNsmL9evoeGeHRpQL+dom7HcTnbAfUZ walyhYSm/zKkdy7Vl3xWUUQkMG48+PviMI6K0YhHXb3Rm5wlR/yBNZTwNIty9SX/ fKCHEa8QynWwLxgm53c3xRkiitJxMsHNK03moLD9zQMjshTyTNvpNbZoahyKQzk6 H+9M1DBRHhkkREDWSwGutukxfEMtWe2vcZcyERrFiY7l5k1j58DwDBMPqjPhRv6q P/1NlCzr0XYf83Y86J18LbDuPGDhTjjIEn6CqbtI2mmWqTg3+rF7zvS2ux+FzMnA gisv8l6GT9JiWhxKFqqL/rrVpwtyHebWLYE/RpNUW6fEzLziRNj1qyYO9dqI/GGi I3rfxlXoc/5xJWCgNB8f =fTgI -----END PGP SIGNATURE----- Merge tag 'pm+acpi-4.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull power management and ACPI updates from Rafael Wysocki: "From the number of commits perspective, the biggest items are ACPICA and cpufreq changes with the latter taking the lead (over 50 commits). On the cpufreq front, there are many cleanups and minor fixes in the core and governors, driver updates etc. We also have a new cpufreq driver for Mediatek MT8173 chips. ACPICA mostly updates its debug infrastructure and adds a number of fixes and cleanups for a good measure. The Operating Performance Points (OPP) framework is updated with new DT bindings and support for them among other things. We have a few updates of the generic power domains framework and a reorganization of the ACPI device enumeration code and bus type operations. And a lot of fixes and cleanups all over. Included is one branch from the MFD tree as it contains some PM-related driver core and ACPI PM changes a few other commits are based on. Specifics: - ACPICA update to upstream revision 20150818 including method tracing extensions to allow more in-depth AML debugging in the kernel and a number of assorted fixes and cleanups (Bob Moore, Lv Zheng, Markus Elfring). - ACPI sysfs code updates and a documentation update related to AML method tracing (Lv Zheng). - ACPI EC driver fix related to serialized evaluations of _Qxx methods and ACPI tools updates allowing the EC userspace tool to be built from the kernel source (Lv Zheng). - ACPI processor driver updates preparing it for future introduction of CPPC support and ACPI PCC mailbox driver updates (Ashwin Chaugule). - ACPI interrupts enumeration fix for a regression related to the handling of IRQ attribute conflicts between MADT and the ACPI namespace (Jiang Liu). - Fixes related to ACPI device PM (Mika Westerberg, Srinidhi Kasagar). - ACPI device registration code reorganization to separate the sysfs-related code and bus type operations from the rest (Rafael J Wysocki). - Assorted cleanups in the ACPI core (Jarkko Nikula, Mathias Krause, Andy Shevchenko, Rafael J Wysocki, Nicolas Iooss). - ACPI cpufreq driver and ia64 cpufreq driver fixes and cleanups (Pan Xinhui, Rafael J Wysocki). - cpufreq core cleanups on top of the previous changes allowing it to preseve its sysfs directories over system suspend/resume (Viresh Kumar, Rafael J Wysocki, Sebastian Andrzej Siewior). - cpufreq fixes and cleanups related to governors (Viresh Kumar). - cpufreq updates (core and the cpufreq-dt driver) related to the turbo/boost mode support (Viresh Kumar, Bartlomiej Zolnierkiewicz). - New DT bindings for Operating Performance Points (OPP), support for them in the OPP framework and in the cpufreq-dt driver plus related OPP framework fixes and cleanups (Viresh Kumar). - cpufreq powernv driver updates (Shilpasri G Bhat). - New cpufreq driver for Mediatek MT8173 (Pi-Cheng Chen). - Assorted cpufreq driver (speedstep-lib, sfi, integrator) cleanups and fixes (Abhilash Jindal, Andrzej Hajda, Cristian Ardelean). - intel_pstate driver updates including Skylake-S support, support for enabling HW P-states per CPU and an additional vendor bypass list entry (Kristen Carlson Accardi, Chen Yu, Ethan Zhao). - cpuidle core fixes related to the handling of coupled idle states (Xunlei Pang). - intel_idle driver updates including Skylake Client support and support for freeze-mode-specific idle states (Len Brown). - Driver core updates related to power management (Andy Shevchenko, Rafael J Wysocki). - Generic power domains framework fixes and cleanups (Jon Hunter, Geert Uytterhoeven, Rajendra Nayak, Ulf Hansson). - Device PM QoS framework update to allow the latency tolerance setting to be exposed to user space via sysfs (Mika Westerberg). - devfreq support for PPMUv2 in Exynos5433 and a fix for an incorrect exynos-ppmu DT binding (Chanwoo Choi, Javier Martinez Canillas). - System sleep support updates (Alan Stern, Len Brown, SungEun Kim). - rockchip-io AVS support updates (Heiko Stuebner). - PM core clocks support fixup (Colin Ian King). - Power capping RAPL driver update including support for Skylake H/S and Broadwell-H (Radivoje Jovanovic, Seiichi Ikarashi). - Generic device properties framework fixes related to the handling of static (driver-provided) property sets (Andy Shevchenko). - turbostat and cpupower updates (Len Brown, Shilpasri G Bhat, Shreyas B Prabhu)" * tag 'pm+acpi-4.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (180 commits) cpufreq: speedstep-lib: Use monotonic clock cpufreq: powernv: Increase the verbosity of OCC console messages cpufreq: sfi: use kmemdup rather than duplicating its implementation cpufreq: drop !cpufreq_driver check from cpufreq_parse_governor() cpufreq: rename cpufreq_real_policy as cpufreq_user_policy cpufreq: remove redundant 'policy' field from user_policy cpufreq: remove redundant 'governor' field from user_policy cpufreq: update user_policy.* on success cpufreq: use memcpy() to copy policy cpufreq: remove redundant CPUFREQ_INCOMPATIBLE notifier event cpufreq: mediatek: Add MT8173 cpufreq driver dt-bindings: mediatek: Add MT8173 CPU DVFS clock bindings PM / Domains: Fix typo in description of genpd_dev_pm_detach() PM / Domains: Remove unusable governor dummies PM / Domains: Make pm_genpd_init() available to modules PM / domains: Align column headers and data in pm_genpd_summary output powercap / RAPL: disable the 2nd power limit properly tools: cpupower: Fix error when running cpupower monitor PM / OPP: Drop unlikely before IS_ERR(_OR_NULL) PM / OPP: Fix static checker warning (broken 64bit big endian systems) ...
This commit is contained in:
commit
ae98207309
@ -1,26 +1,192 @@
|
||||
/sys/module/acpi/parameters/:
|
||||
ACPICA Trace Facility
|
||||
|
||||
trace_method_name
|
||||
The AML method name that the user wants to trace
|
||||
Copyright (C) 2015, Intel Corporation
|
||||
Author: Lv Zheng <lv.zheng@intel.com>
|
||||
|
||||
trace_debug_layer
|
||||
The temporary debug_layer used when tracing the method.
|
||||
Using 0xffffffff by default if it is 0.
|
||||
|
||||
trace_debug_level
|
||||
The temporary debug_level used when tracing the method.
|
||||
Using 0x00ffffff by default if it is 0.
|
||||
Abstract:
|
||||
|
||||
trace_state
|
||||
This document describes the functions and the interfaces of the method
|
||||
tracing facility.
|
||||
|
||||
1. Functionalities and usage examples:
|
||||
|
||||
ACPICA provides method tracing capability. And two functions are
|
||||
currently implemented using this capability.
|
||||
|
||||
A. Log reducer
|
||||
ACPICA subsystem provides debugging outputs when CONFIG_ACPI_DEBUG is
|
||||
enabled. The debugging messages which are deployed via
|
||||
ACPI_DEBUG_PRINT() macro can be reduced at 2 levels - per-component
|
||||
level (known as debug layer, configured via
|
||||
/sys/module/acpi/parameters/debug_layer) and per-type level (known as
|
||||
debug level, configured via /sys/module/acpi/parameters/debug_level).
|
||||
|
||||
But when the particular layer/level is applied to the control method
|
||||
evaluations, the quantity of the debugging outputs may still be too
|
||||
large to be put into the kernel log buffer. The idea thus is worked out
|
||||
to only enable the particular debug layer/level (normally more detailed)
|
||||
logs when the control method evaluation is started, and disable the
|
||||
detailed logging when the control method evaluation is stopped.
|
||||
|
||||
The following command examples illustrate the usage of the "log reducer"
|
||||
functionality:
|
||||
a. Filter out the debug layer/level matched logs when control methods
|
||||
are being evaluated:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0xXXXXXXXX" > trace_debug_layer
|
||||
# echo "0xYYYYYYYY" > trace_debug_level
|
||||
# echo "enable" > trace_state
|
||||
b. Filter out the debug layer/level matched logs when the specified
|
||||
control method is being evaluated:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0xXXXXXXXX" > trace_debug_layer
|
||||
# echo "0xYYYYYYYY" > trace_debug_level
|
||||
# echo "\PPPP.AAAA.TTTT.HHHH" > trace_method_name
|
||||
# echo "method" > /sys/module/acpi/parameters/trace_state
|
||||
c. Filter out the debug layer/level matched logs when the specified
|
||||
control method is being evaluated for the first time:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0xXXXXXXXX" > trace_debug_layer
|
||||
# echo "0xYYYYYYYY" > trace_debug_level
|
||||
# echo "\PPPP.AAAA.TTTT.HHHH" > trace_method_name
|
||||
# echo "method-once" > /sys/module/acpi/parameters/trace_state
|
||||
Where:
|
||||
0xXXXXXXXX/0xYYYYYYYY: Refer to Documentation/acpi/debug.txt for
|
||||
possible debug layer/level masking values.
|
||||
\PPPP.AAAA.TTTT.HHHH: Full path of a control method that can be found
|
||||
in the ACPI namespace. It needn't be an entry
|
||||
of a control method evaluation.
|
||||
|
||||
B. AML tracer
|
||||
|
||||
There are special log entries added by the method tracing facility at
|
||||
the "trace points" the AML interpreter starts/stops to execute a control
|
||||
method, or an AML opcode. Note that the format of the log entries are
|
||||
subject to change:
|
||||
[ 0.186427] exdebug-0398 ex_trace_point : Method Begin [0xf58394d8:\_SB.PCI0.LPCB.ECOK] execution.
|
||||
[ 0.186630] exdebug-0398 ex_trace_point : Opcode Begin [0xf5905c88:If] execution.
|
||||
[ 0.186820] exdebug-0398 ex_trace_point : Opcode Begin [0xf5905cc0:LEqual] execution.
|
||||
[ 0.187010] exdebug-0398 ex_trace_point : Opcode Begin [0xf5905a20:-NamePath-] execution.
|
||||
[ 0.187214] exdebug-0398 ex_trace_point : Opcode End [0xf5905a20:-NamePath-] execution.
|
||||
[ 0.187407] exdebug-0398 ex_trace_point : Opcode Begin [0xf5905f60:One] execution.
|
||||
[ 0.187594] exdebug-0398 ex_trace_point : Opcode End [0xf5905f60:One] execution.
|
||||
[ 0.187789] exdebug-0398 ex_trace_point : Opcode End [0xf5905cc0:LEqual] execution.
|
||||
[ 0.187980] exdebug-0398 ex_trace_point : Opcode Begin [0xf5905cc0:Return] execution.
|
||||
[ 0.188146] exdebug-0398 ex_trace_point : Opcode Begin [0xf5905f60:One] execution.
|
||||
[ 0.188334] exdebug-0398 ex_trace_point : Opcode End [0xf5905f60:One] execution.
|
||||
[ 0.188524] exdebug-0398 ex_trace_point : Opcode End [0xf5905cc0:Return] execution.
|
||||
[ 0.188712] exdebug-0398 ex_trace_point : Opcode End [0xf5905c88:If] execution.
|
||||
[ 0.188903] exdebug-0398 ex_trace_point : Method End [0xf58394d8:\_SB.PCI0.LPCB.ECOK] execution.
|
||||
|
||||
Developers can utilize these special log entries to track the AML
|
||||
interpretion, thus can aid issue debugging and performance tuning. Note
|
||||
that, as the "AML tracer" logs are implemented via ACPI_DEBUG_PRINT()
|
||||
macro, CONFIG_ACPI_DEBUG is also required to be enabled for enabling
|
||||
"AML tracer" logs.
|
||||
|
||||
The following command examples illustrate the usage of the "AML tracer"
|
||||
functionality:
|
||||
a. Filter out the method start/stop "AML tracer" logs when control
|
||||
methods are being evaluated:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0x80" > trace_debug_layer
|
||||
# echo "0x10" > trace_debug_level
|
||||
# echo "enable" > trace_state
|
||||
b. Filter out the method start/stop "AML tracer" when the specified
|
||||
control method is being evaluated:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0x80" > trace_debug_layer
|
||||
# echo "0x10" > trace_debug_level
|
||||
# echo "\PPPP.AAAA.TTTT.HHHH" > trace_method_name
|
||||
# echo "method" > trace_state
|
||||
c. Filter out the method start/stop "AML tracer" logs when the specified
|
||||
control method is being evaluated for the first time:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0x80" > trace_debug_layer
|
||||
# echo "0x10" > trace_debug_level
|
||||
# echo "\PPPP.AAAA.TTTT.HHHH" > trace_method_name
|
||||
# echo "method-once" > trace_state
|
||||
d. Filter out the method/opcode start/stop "AML tracer" when the
|
||||
specified control method is being evaluated:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0x80" > trace_debug_layer
|
||||
# echo "0x10" > trace_debug_level
|
||||
# echo "\PPPP.AAAA.TTTT.HHHH" > trace_method_name
|
||||
# echo "opcode" > trace_state
|
||||
e. Filter out the method/opcode start/stop "AML tracer" when the
|
||||
specified control method is being evaluated for the first time:
|
||||
# cd /sys/module/acpi/parameters
|
||||
# echo "0x80" > trace_debug_layer
|
||||
# echo "0x10" > trace_debug_level
|
||||
# echo "\PPPP.AAAA.TTTT.HHHH" > trace_method_name
|
||||
# echo "opcode-opcode" > trace_state
|
||||
|
||||
Note that all above method tracing facility related module parameters can
|
||||
be used as the boot parameters, for example:
|
||||
acpi.trace_debug_layer=0x80 acpi.trace_debug_level=0x10 \
|
||||
acpi.trace_method_name=\_SB.LID0._LID acpi.trace_state=opcode-once
|
||||
|
||||
2. Interface descriptions:
|
||||
|
||||
All method tracing functions can be configured via ACPI module
|
||||
parameters that are accessible at /sys/module/acpi/parameters/:
|
||||
|
||||
trace_method_name
|
||||
The full path of the AML method that the user wants to trace.
|
||||
Note that the full path shouldn't contain the trailing "_"s in its
|
||||
name segments but may contain "\" to form an absolute path.
|
||||
|
||||
trace_debug_layer
|
||||
The temporary debug_layer used when the tracing feature is enabled.
|
||||
Using ACPI_EXECUTER (0x80) by default, which is the debug_layer
|
||||
used to match all "AML tracer" logs.
|
||||
|
||||
trace_debug_level
|
||||
The temporary debug_level used when the tracing feature is enabled.
|
||||
Using ACPI_LV_TRACE_POINT (0x10) by default, which is the
|
||||
debug_level used to match all "AML tracer" logs.
|
||||
|
||||
trace_state
|
||||
The status of the tracing feature.
|
||||
|
||||
"enabled" means this feature is enabled
|
||||
and the AML method is traced every time it's executed.
|
||||
|
||||
"1" means this feature is enabled and the AML method
|
||||
will only be traced during the next execution.
|
||||
|
||||
"disabled" means this feature is disabled.
|
||||
Users can enable/disable this debug tracing feature by
|
||||
"echo string > /sys/module/acpi/parameters/trace_state".
|
||||
"string" should be one of "enable", "disable" and "1".
|
||||
Users can enable/disable this debug tracing feature by executing
|
||||
the following command:
|
||||
# echo string > /sys/module/acpi/parameters/trace_state
|
||||
Where "string" should be one of the followings:
|
||||
"disable"
|
||||
Disable the method tracing feature.
|
||||
"enable"
|
||||
Enable the method tracing feature.
|
||||
ACPICA debugging messages matching
|
||||
"trace_debug_layer/trace_debug_level" during any method
|
||||
execution will be logged.
|
||||
"method"
|
||||
Enable the method tracing feature.
|
||||
ACPICA debugging messages matching
|
||||
"trace_debug_layer/trace_debug_level" during method execution
|
||||
of "trace_method_name" will be logged.
|
||||
"method-once"
|
||||
Enable the method tracing feature.
|
||||
ACPICA debugging messages matching
|
||||
"trace_debug_layer/trace_debug_level" during method execution
|
||||
of "trace_method_name" will be logged only once.
|
||||
"opcode"
|
||||
Enable the method tracing feature.
|
||||
ACPICA debugging messages matching
|
||||
"trace_debug_layer/trace_debug_level" during method/opcode
|
||||
execution of "trace_method_name" will be logged.
|
||||
"opcode-once"
|
||||
Enable the method tracing feature.
|
||||
ACPICA debugging messages matching
|
||||
"trace_debug_layer/trace_debug_level" during method/opcode
|
||||
execution of "trace_method_name" will be logged only once.
|
||||
Note that, the difference between the "enable" and other feature
|
||||
enabling options are:
|
||||
1. When "enable" is specified, since
|
||||
"trace_debug_layer/trace_debug_level" shall apply to all control
|
||||
method evaluations, after configuring "trace_state" to "enable",
|
||||
"trace_method_name" will be reset to NULL.
|
||||
2. When "method/opcode" is specified, if
|
||||
"trace_method_name" is NULL when "trace_state" is configured to
|
||||
these options, the "trace_debug_layer/trace_debug_level" will
|
||||
apply to all control method evaluations.
|
||||
|
@ -55,16 +55,13 @@ transition notifiers.
|
||||
----------------------------
|
||||
|
||||
These are notified when a new policy is intended to be set. Each
|
||||
CPUFreq policy notifier is called three times for a policy transition:
|
||||
CPUFreq policy notifier is called twice for a policy transition:
|
||||
|
||||
1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if
|
||||
they see a need for this - may it be thermal considerations or
|
||||
hardware limitations.
|
||||
|
||||
2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid
|
||||
hardware failure.
|
||||
|
||||
3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy
|
||||
2.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy
|
||||
- if two hardware drivers failed to agree on a new policy before this
|
||||
stage, the incompatible hardware shall be shut down, and the user
|
||||
informed of this.
|
||||
|
83
Documentation/devicetree/bindings/clock/mt8173-cpu-dvfs.txt
Normal file
83
Documentation/devicetree/bindings/clock/mt8173-cpu-dvfs.txt
Normal file
@ -0,0 +1,83 @@
|
||||
Device Tree Clock bindins for CPU DVFS of Mediatek MT8173 SoC
|
||||
|
||||
Required properties:
|
||||
- clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock names.
|
||||
- clock-names: Should contain the following:
|
||||
"cpu" - The multiplexer for clock input of CPU cluster.
|
||||
"intermediate" - A parent of "cpu" clock which is used as "intermediate" clock
|
||||
source (usually MAINPLL) when the original CPU PLL is under
|
||||
transition and not stable yet.
|
||||
Please refer to Documentation/devicetree/bindings/clk/clock-bindings.txt for
|
||||
generic clock consumer properties.
|
||||
- proc-supply: Regulator for Vproc of CPU cluster.
|
||||
|
||||
Optional properties:
|
||||
- sram-supply: Regulator for Vsram of CPU cluster. When present, the cpufreq driver
|
||||
needs to do "voltage tracking" to step by step scale up/down Vproc and
|
||||
Vsram to fit SoC specific needs. When absent, the voltage scaling
|
||||
flow is handled by hardware, hence no software "voltage tracking" is
|
||||
needed.
|
||||
|
||||
Example:
|
||||
--------
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
reg = <0x000>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
clocks = <&infracfg CLK_INFRA_CA53SEL>,
|
||||
<&apmixedsys CLK_APMIXED_MAINPLL>;
|
||||
clock-names = "cpu", "intermediate";
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
reg = <0x001>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
clocks = <&infracfg CLK_INFRA_CA53SEL>,
|
||||
<&apmixedsys CLK_APMIXED_MAINPLL>;
|
||||
clock-names = "cpu", "intermediate";
|
||||
};
|
||||
|
||||
cpu2: cpu@100 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a57";
|
||||
reg = <0x100>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
clocks = <&infracfg CLK_INFRA_CA57SEL>,
|
||||
<&apmixedsys CLK_APMIXED_MAINPLL>;
|
||||
clock-names = "cpu", "intermediate";
|
||||
};
|
||||
|
||||
cpu3: cpu@101 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a57";
|
||||
reg = <0x101>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
clocks = <&infracfg CLK_INFRA_CA57SEL>,
|
||||
<&apmixedsys CLK_APMIXED_MAINPLL>;
|
||||
clock-names = "cpu", "intermediate";
|
||||
};
|
||||
|
||||
&cpu0 {
|
||||
proc-supply = <&mt6397_vpca15_reg>;
|
||||
};
|
||||
|
||||
&cpu1 {
|
||||
proc-supply = <&mt6397_vpca15_reg>;
|
||||
};
|
||||
|
||||
&cpu2 {
|
||||
proc-supply = <&da9211_vcpu_reg>;
|
||||
sram-supply = <&mt6397_vsramca7_reg>;
|
||||
};
|
||||
|
||||
&cpu3 {
|
||||
proc-supply = <&da9211_vcpu_reg>;
|
||||
sram-supply = <&mt6397_vsramca7_reg>;
|
||||
};
|
@ -11,15 +11,14 @@ to various devfreq devices. The devfreq devices would use the event data when
|
||||
derterming the current state of each IP.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "samsung,exynos-ppmu".
|
||||
- compatible: Should be "samsung,exynos-ppmu" or "samsung,exynos-ppmu-v2.
|
||||
- reg: physical base address of each PPMU and length of memory mapped region.
|
||||
|
||||
Optional properties:
|
||||
- clock-names : the name of clock used by the PPMU, "ppmu"
|
||||
- clocks : phandles for clock specified in "clock-names" property
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
Example1 : PPMU nodes in exynos3250.dtsi are listed below.
|
||||
Example1 : PPMUv1 nodes in exynos3250.dtsi are listed below.
|
||||
|
||||
ppmu_dmc0: ppmu_dmc0@106a0000 {
|
||||
compatible = "samsung,exynos-ppmu";
|
||||
@ -108,3 +107,41 @@ Example2 : Events of each PPMU node in exynos3250-rinato.dts are listed below.
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example3 : PPMUv2 nodes in exynos5433.dtsi are listed below.
|
||||
|
||||
ppmu_d0_cpu: ppmu_d0_cpu@10480000 {
|
||||
compatible = "samsung,exynos-ppmu-v2";
|
||||
reg = <0x10480000 0x2000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ppmu_d0_general: ppmu_d0_general@10490000 {
|
||||
compatible = "samsung,exynos-ppmu-v2";
|
||||
reg = <0x10490000 0x2000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ppmu_d0_rt: ppmu_d0_rt@104a0000 {
|
||||
compatible = "samsung,exynos-ppmu-v2";
|
||||
reg = <0x104a0000 0x2000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ppmu_d1_cpu: ppmu_d1_cpu@104b0000 {
|
||||
compatible = "samsung,exynos-ppmu-v2";
|
||||
reg = <0x104b0000 0x2000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ppmu_d1_general: ppmu_d1_general@104c0000 {
|
||||
compatible = "samsung,exynos-ppmu-v2";
|
||||
reg = <0x104c0000 0x2000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ppmu_d1_rt: ppmu_d1_rt@104d0000 {
|
||||
compatible = "samsung,exynos-ppmu-v2";
|
||||
reg = <0x104d0000 0x2000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
|
||||
properties.
|
||||
|
||||
Required properties:
|
||||
- opp-hz: Frequency in Hz
|
||||
- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
|
||||
|
||||
Optional properties:
|
||||
- opp-microvolt: voltage in micro Volts.
|
||||
@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <980000 1000000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = <1200000000>;
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
clock-latency-ns = <290000>;
|
||||
turbo-mode;
|
||||
@ -237,20 +237,20 @@ independently.
|
||||
*/
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <980000 1000000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = <1200000000>;
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
opp-microamp = <90000;
|
||||
lock-latency-ns = <290000>;
|
||||
@ -313,20 +313,20 @@ DVFS state together.
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <980000 1000000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = <1200000000>;
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
opp-microamp = <90000>;
|
||||
clock-latency-ns = <290000>;
|
||||
@ -339,20 +339,20 @@ DVFS state together.
|
||||
opp-shared;
|
||||
|
||||
opp10 {
|
||||
opp-hz = <1300000000>;
|
||||
opp-hz = /bits/ 64 <1300000000>;
|
||||
opp-microvolt = <1045000 1050000 1055000>;
|
||||
opp-microamp = <95000>;
|
||||
clock-latency-ns = <400000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp11 {
|
||||
opp-hz = <1400000000>;
|
||||
opp-hz = /bits/ 64 <1400000000>;
|
||||
opp-microvolt = <1075000>;
|
||||
opp-microamp = <100000>;
|
||||
clock-latency-ns = <400000>;
|
||||
};
|
||||
opp12 {
|
||||
opp-hz = <1500000000>;
|
||||
opp-hz = /bits/ 64 <1500000000>;
|
||||
opp-microvolt = <1010000 1100000 1110000>;
|
||||
opp-microamp = <95000>;
|
||||
clock-latency-ns = <400000>;
|
||||
@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000>, /* Supply 0 */
|
||||
<960000>, /* Supply 1 */
|
||||
<960000>; /* Supply 2 */
|
||||
@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
|
||||
/* OR */
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>, /* Supply 0 */
|
||||
<960000 965000 975000>, /* Supply 1 */
|
||||
<960000 965000 975000>; /* Supply 2 */
|
||||
@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
|
||||
/* OR */
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>, /* Supply 0 */
|
||||
<960000 965000 975000>, /* Supply 1 */
|
||||
<960000 965000 975000>; /* Supply 2 */
|
||||
@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <600000000>;
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
...
|
||||
};
|
||||
|
||||
opp01 {
|
||||
opp-hz = <800000000>;
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
...
|
||||
};
|
||||
};
|
||||
@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
|
||||
opp-shared;
|
||||
|
||||
opp10 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
...
|
||||
};
|
||||
|
||||
opp11 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
...
|
||||
};
|
||||
};
|
@ -48,7 +48,7 @@ Example 2:
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
child: power-controller@12340000 {
|
||||
child: power-controller@12341000 {
|
||||
compatible = "foo,power-controller";
|
||||
reg = <0x12341000 0x1000>;
|
||||
power-domains = <&parent 0>;
|
||||
|
@ -33,6 +33,8 @@ Required properties:
|
||||
- compatible: should be one of:
|
||||
- "rockchip,rk3188-io-voltage-domain" for rk3188
|
||||
- "rockchip,rk3288-io-voltage-domain" for rk3288
|
||||
- "rockchip,rk3368-io-voltage-domain" for rk3368
|
||||
- "rockchip,rk3368-pmu-io-voltage-domain" for rk3368 pmu-domains
|
||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
||||
|
||||
|
||||
@ -64,6 +66,18 @@ Possible supplies for rk3288:
|
||||
- sdcard-supply: The supply connected to SDMMC0_VDD.
|
||||
- wifi-supply: The supply connected to APIO3_VDD. Also known as SDIO0.
|
||||
|
||||
Possible supplies for rk3368:
|
||||
- audio-supply: The supply connected to APIO3_VDD.
|
||||
- dvp-supply: The supply connected to DVPIO_VDD.
|
||||
- flash0-supply: The supply connected to FLASH0_VDD. Typically for eMMC
|
||||
- gpio30-supply: The supply connected to APIO1_VDD.
|
||||
- gpio1830 The supply connected to APIO4_VDD.
|
||||
- sdcard-supply: The supply connected to SDMMC0_VDD.
|
||||
- wifi-supply: The supply connected to APIO2_VDD. Also known as SDIO0.
|
||||
|
||||
Possible supplies for rk3368 pmu-domains:
|
||||
- pmu-supply: The supply connected to PMUIO_VDD.
|
||||
- vop-supply: The supply connected to LCDC_VDD.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -341,6 +341,13 @@ the phases are:
|
||||
and is entirely responsible for bringing the device back to the
|
||||
functional state as appropriate.
|
||||
|
||||
Note that this direct-complete procedure applies even if the device is
|
||||
disabled for runtime PM; only the runtime-PM status matters. It follows
|
||||
that if a device has system-sleep callbacks but does not support runtime
|
||||
PM, then its prepare callback must never return a positive value. This
|
||||
is because all devices are initially set to runtime-suspended with
|
||||
runtime PM disabled.
|
||||
|
||||
2. The suspend methods should quiesce the device to stop it from performing
|
||||
I/O. They also may save the device registers and put it into the
|
||||
appropriate low-power state, depending on the bus type the device is on,
|
||||
|
@ -445,10 +445,6 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
|
||||
bool pm_runtime_status_suspended(struct device *dev);
|
||||
- return true if the device's runtime PM status is 'suspended'
|
||||
|
||||
bool pm_runtime_suspended_if_enabled(struct device *dev);
|
||||
- return true if the device's runtime PM status is 'suspended' and its
|
||||
'power.disable_depth' field is equal to 1
|
||||
|
||||
void pm_runtime_allow(struct device *dev);
|
||||
- set the power.runtime_auto flag for the device and decrease its usage
|
||||
counter (used by the /sys/devices/.../power/control interface to
|
||||
|
@ -361,6 +361,7 @@ enum opal_msg_type {
|
||||
OPAL_MSG_HMI_EVT,
|
||||
OPAL_MSG_DPO,
|
||||
OPAL_MSG_PRD,
|
||||
OPAL_MSG_OCC,
|
||||
OPAL_MSG_TYPE_MAX,
|
||||
};
|
||||
|
||||
@ -700,6 +701,17 @@ struct opal_prd_msg_header {
|
||||
|
||||
struct opal_prd_msg;
|
||||
|
||||
#define OCC_RESET 0
|
||||
#define OCC_LOAD 1
|
||||
#define OCC_THROTTLE 2
|
||||
#define OCC_MAX_THROTTLE_STATUS 5
|
||||
|
||||
struct opal_occ_msg {
|
||||
__be64 type;
|
||||
__be64 chip;
|
||||
__be64 throttle_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* SG entries
|
||||
*
|
||||
|
@ -184,6 +184,12 @@
|
||||
#define MSR_PP1_ENERGY_STATUS 0x00000641
|
||||
#define MSR_PP1_POLICY 0x00000642
|
||||
|
||||
#define MSR_CONFIG_TDP_NOMINAL 0x00000648
|
||||
#define MSR_CONFIG_TDP_LEVEL_1 0x00000649
|
||||
#define MSR_CONFIG_TDP_LEVEL_2 0x0000064A
|
||||
#define MSR_CONFIG_TDP_CONTROL 0x0000064B
|
||||
#define MSR_TURBO_ACTIVATION_RATIO 0x0000064C
|
||||
|
||||
#define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658
|
||||
#define MSR_PKG_ANY_CORE_C0_RES 0x00000659
|
||||
#define MSR_PKG_ANY_GFXE_C0_RES 0x0000065A
|
||||
|
@ -445,6 +445,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
|
||||
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
||||
|
||||
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||
acpi_penalize_sci_irq(bus_irq, trigger, polarity);
|
||||
|
||||
/*
|
||||
* stash over-ride to indicate we've been here
|
||||
|
@ -189,17 +189,24 @@ config ACPI_DOCK
|
||||
This driver supports ACPI-controlled docking stations and removable
|
||||
drive bays such as the IBM Ultrabay and the Dell Module Bay.
|
||||
|
||||
config ACPI_CPU_FREQ_PSS
|
||||
bool
|
||||
select THERMAL
|
||||
|
||||
config ACPI_PROCESSOR_IDLE
|
||||
bool
|
||||
select CPU_IDLE
|
||||
|
||||
config ACPI_PROCESSOR
|
||||
tristate "Processor"
|
||||
select THERMAL
|
||||
select CPU_IDLE
|
||||
depends on X86 || IA64
|
||||
select ACPI_PROCESSOR_IDLE
|
||||
select ACPI_CPU_FREQ_PSS
|
||||
default y
|
||||
help
|
||||
This driver installs ACPI as the idle handler for Linux and uses
|
||||
ACPI C2 and C3 processor states to save power on systems that
|
||||
support it. It is required by several flavors of cpufreq
|
||||
performance-state drivers.
|
||||
This driver adds support for the ACPI Processor package. It is required
|
||||
by several flavors of cpufreq performance-state, thermal, throttling and
|
||||
idle drivers.
|
||||
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called processor.
|
||||
|
@ -24,7 +24,7 @@ acpi-y += nvs.o
|
||||
# Power management related files
|
||||
acpi-y += wakeup.o
|
||||
acpi-$(CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT) += sleep.o
|
||||
acpi-y += device_pm.o
|
||||
acpi-y += device_sysfs.o device_pm.o
|
||||
acpi-$(CONFIG_ACPI_SLEEP) += proc.o
|
||||
|
||||
|
||||
@ -80,8 +80,10 @@ obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
|
||||
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
|
||||
|
||||
# processor has its own "processor." module_param namespace
|
||||
processor-y := processor_driver.o processor_throttling.o
|
||||
processor-y += processor_idle.o processor_thermal.o
|
||||
processor-y := processor_driver.o
|
||||
processor-$(CONFIG_ACPI_PROCESSOR_IDLE) += processor_idle.o
|
||||
processor-$(CONFIG_ACPI_CPU_FREQ_PSS) += processor_throttling.o \
|
||||
processor_thermal.o
|
||||
processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
|
||||
|
||||
obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
|
||||
|
@ -16,10 +16,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -17,10 +17,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -59,6 +59,7 @@ ACPI_MODULE_NAME("acpi_lpss");
|
||||
#define LPSS_CLK_DIVIDER BIT(2)
|
||||
#define LPSS_LTR BIT(3)
|
||||
#define LPSS_SAVE_CTX BIT(4)
|
||||
#define LPSS_NO_D3_DELAY BIT(5)
|
||||
|
||||
struct lpss_private_data;
|
||||
|
||||
@ -155,6 +156,10 @@ static const struct lpss_device_desc byt_pwm_dev_desc = {
|
||||
.flags = LPSS_SAVE_CTX,
|
||||
};
|
||||
|
||||
static const struct lpss_device_desc bsw_pwm_dev_desc = {
|
||||
.flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
|
||||
};
|
||||
|
||||
static const struct lpss_device_desc byt_uart_dev_desc = {
|
||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
||||
.clk_con_id = "baudclk",
|
||||
@ -162,6 +167,14 @@ static const struct lpss_device_desc byt_uart_dev_desc = {
|
||||
.setup = lpss_uart_setup,
|
||||
};
|
||||
|
||||
static const struct lpss_device_desc bsw_uart_dev_desc = {
|
||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX
|
||||
| LPSS_NO_D3_DELAY,
|
||||
.clk_con_id = "baudclk",
|
||||
.prv_offset = 0x800,
|
||||
.setup = lpss_uart_setup,
|
||||
};
|
||||
|
||||
static const struct lpss_device_desc byt_spi_dev_desc = {
|
||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
||||
.prv_offset = 0x400,
|
||||
@ -177,8 +190,15 @@ static const struct lpss_device_desc byt_i2c_dev_desc = {
|
||||
.setup = byt_i2c_setup,
|
||||
};
|
||||
|
||||
static const struct lpss_device_desc bsw_i2c_dev_desc = {
|
||||
.flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
|
||||
.prv_offset = 0x800,
|
||||
.setup = byt_i2c_setup,
|
||||
};
|
||||
|
||||
static struct lpss_device_desc bsw_spi_dev_desc = {
|
||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX
|
||||
| LPSS_NO_D3_DELAY,
|
||||
.prv_offset = 0x400,
|
||||
.setup = lpss_deassert_reset,
|
||||
};
|
||||
@ -213,11 +233,12 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
||||
{ "INT33FC", },
|
||||
|
||||
/* Braswell LPSS devices */
|
||||
{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
|
||||
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
|
||||
{ "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
|
||||
{ "8086228A", LPSS_ADDR(bsw_uart_dev_desc) },
|
||||
{ "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
|
||||
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
|
||||
{ "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) },
|
||||
|
||||
/* Broadwell LPSS devices */
|
||||
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
|
||||
{ "INT3431", LPSS_ADDR(lpt_dev_desc) },
|
||||
{ "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
|
||||
@ -557,9 +578,14 @@ static void acpi_lpss_restore_ctx(struct device *dev,
|
||||
* The following delay is needed or the subsequent write operations may
|
||||
* fail. The LPSS devices are actually PCI devices and the PCI spec
|
||||
* expects 10ms delay before the device can be accessed after D3 to D0
|
||||
* transition.
|
||||
* transition. However some platforms like BSW does not need this delay.
|
||||
*/
|
||||
msleep(10);
|
||||
unsigned int delay = 10; /* default 10ms delay */
|
||||
|
||||
if (pdata->dev_desc->flags & LPSS_NO_D3_DELAY)
|
||||
delay = 0;
|
||||
|
||||
msleep(delay);
|
||||
|
||||
for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
|
||||
unsigned long offset = i * sizeof(u32);
|
||||
|
@ -16,11 +16,6 @@
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* ACPI based HotPlug driver that supports Memory Hotplug
|
||||
* This driver fields notifications from firmware for memory add
|
||||
* and remove operations and alerts the VM of the affected memory
|
||||
|
@ -12,10 +12,6 @@
|
||||
* 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.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -485,7 +485,7 @@ static const struct acpi_device_id processor_device_ids[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct acpi_scan_handler __refdata processor_handler = {
|
||||
static struct acpi_scan_handler processor_handler = {
|
||||
.ids = processor_device_ids,
|
||||
.attach = acpi_processor_add,
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
|
@ -17,10 +17,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -11,6 +11,7 @@ obj-y += acpi.o
|
||||
acpi-y := \
|
||||
dsargs.o \
|
||||
dscontrol.o \
|
||||
dsdebug.o \
|
||||
dsfield.o \
|
||||
dsinit.o \
|
||||
dsmethod.o \
|
||||
@ -164,6 +165,7 @@ acpi-y += \
|
||||
utmath.o \
|
||||
utmisc.o \
|
||||
utmutex.o \
|
||||
utnonansi.o \
|
||||
utobject.o \
|
||||
utosi.o \
|
||||
utownerid.o \
|
||||
|
@ -67,9 +67,6 @@ struct acpi_db_execute_walk {
|
||||
};
|
||||
|
||||
#define PARAM_LIST(pl) pl
|
||||
#define DBTEST_OUTPUT_LEVEL(lvl) if (acpi_gbl_db_opt_verbose)
|
||||
#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\
|
||||
acpi_os_printf PARAM_LIST(fp);}
|
||||
|
||||
#define EX_NO_SINGLE_STEP 1
|
||||
#define EX_SINGLE_STEP 2
|
||||
@ -77,10 +74,6 @@ struct acpi_db_execute_walk {
|
||||
/*
|
||||
* dbxface - external debugger interfaces
|
||||
*/
|
||||
acpi_status acpi_db_initialize(void);
|
||||
|
||||
void acpi_db_terminate(void);
|
||||
|
||||
acpi_status
|
||||
acpi_db_single_step(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op, u32 op_type);
|
||||
@ -102,6 +95,8 @@ void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
|
||||
|
||||
acpi_status acpi_db_sleep(char *object_arg);
|
||||
|
||||
void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg);
|
||||
|
||||
void acpi_db_display_locks(void);
|
||||
|
||||
void acpi_db_display_resources(char *object_arg);
|
||||
@ -261,6 +256,23 @@ acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
|
||||
char *acpi_db_get_next_token(char *string,
|
||||
char **next, acpi_object_type * return_type);
|
||||
|
||||
/*
|
||||
* dbobject
|
||||
*/
|
||||
void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc);
|
||||
|
||||
void
|
||||
acpi_db_display_internal_object(union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
void acpi_db_decode_arguments(struct acpi_walk_state *walk_state);
|
||||
|
||||
void acpi_db_decode_locals(struct acpi_walk_state *walk_state);
|
||||
|
||||
void
|
||||
acpi_db_dump_method_info(acpi_status status,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
/*
|
||||
* dbstats - Generation and display of ACPI table statistics
|
||||
*/
|
||||
|
@ -354,4 +354,12 @@ acpi_status
|
||||
acpi_ds_result_push(union acpi_operand_object *object,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
/*
|
||||
* dsdebug - parser debugging routines
|
||||
*/
|
||||
void
|
||||
acpi_ds_dump_method_stack(acpi_status status,
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op);
|
||||
|
||||
#endif /* _ACDISPAT_H_ */
|
||||
|
@ -58,11 +58,12 @@ ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list);
|
||||
|
||||
ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT);
|
||||
ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header);
|
||||
ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX);
|
||||
ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX);
|
||||
ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX);
|
||||
|
||||
#if (!ACPI_REDUCED_HARDWARE)
|
||||
ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS);
|
||||
ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_facs32);
|
||||
ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_facs64);
|
||||
|
||||
#endif /* !ACPI_REDUCED_HARDWARE */
|
||||
|
||||
@ -235,6 +236,10 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_level, 0);
|
||||
|
||||
ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list);
|
||||
|
||||
/* Maximum number of While() loop iterations before forced abort */
|
||||
|
||||
ACPI_GLOBAL(u16, acpi_gbl_max_loop_iterations);
|
||||
|
||||
/* Control method single step flag */
|
||||
|
||||
ACPI_GLOBAL(u8, acpi_gbl_cm_single_step);
|
||||
@ -290,8 +295,6 @@ ACPI_GLOBAL(u32, acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]);
|
||||
|
||||
ACPI_GLOBAL(u32, acpi_gbl_original_dbg_level);
|
||||
ACPI_GLOBAL(u32, acpi_gbl_original_dbg_layer);
|
||||
ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_level);
|
||||
ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer);
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
@ -309,9 +312,10 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_no_resource_disassembly, FALSE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_ignore_noop_operator, FALSE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_cstyle_disassembly, TRUE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_force_aml_disassembly, FALSE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_opt_verbose, TRUE);
|
||||
|
||||
ACPI_GLOBAL(u8, acpi_gbl_db_opt_disasm);
|
||||
ACPI_GLOBAL(u8, acpi_gbl_db_opt_verbose);
|
||||
ACPI_GLOBAL(u8, acpi_gbl_dm_opt_disasm);
|
||||
ACPI_GLOBAL(u8, acpi_gbl_dm_opt_listing);
|
||||
ACPI_GLOBAL(u8, acpi_gbl_num_external_methods);
|
||||
ACPI_GLOBAL(u32, acpi_gbl_resolved_external_methods);
|
||||
ACPI_GLOBAL(struct acpi_external_list *, acpi_gbl_external_list);
|
||||
@ -346,8 +350,8 @@ ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]);
|
||||
/*
|
||||
* Statistic globals
|
||||
*/
|
||||
ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1]);
|
||||
ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1]);
|
||||
ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TOTAL_TYPES]);
|
||||
ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TOTAL_TYPES]);
|
||||
ACPI_GLOBAL(u16, acpi_gbl_obj_type_count_misc);
|
||||
ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc);
|
||||
ACPI_GLOBAL(u32, acpi_gbl_num_nodes);
|
||||
|
@ -131,6 +131,28 @@ void
|
||||
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
|
||||
u32 level, u32 index);
|
||||
|
||||
void
|
||||
acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
void
|
||||
acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
void
|
||||
acpi_ex_start_trace_opcode(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
void
|
||||
acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
void
|
||||
acpi_ex_trace_point(acpi_trace_event_type type,
|
||||
u8 begin, u8 *aml, char *pathname);
|
||||
|
||||
/*
|
||||
* exfield - ACPI AML (p-code) execution - field manipulation
|
||||
*/
|
||||
|
@ -174,8 +174,12 @@ struct acpi_namespace_node {
|
||||
*/
|
||||
#ifdef ACPI_LARGE_NAMESPACE_NODE
|
||||
union acpi_parse_object *op;
|
||||
void *method_locals;
|
||||
void *method_args;
|
||||
u32 value;
|
||||
u32 length;
|
||||
u8 arg_count;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -209,11 +213,9 @@ struct acpi_table_list {
|
||||
#define ACPI_ROOT_ORIGIN_ALLOCATED (1)
|
||||
#define ACPI_ROOT_ALLOW_RESIZE (2)
|
||||
|
||||
/* Predefined (fixed) table indexes */
|
||||
/* Predefined table indexes */
|
||||
|
||||
#define ACPI_TABLE_INDEX_DSDT (0)
|
||||
#define ACPI_TABLE_INDEX_FACS (1)
|
||||
#define ACPI_TABLE_INDEX_X_FACS (2)
|
||||
#define ACPI_INVALID_TABLE_INDEX (0xFFFFFFFF)
|
||||
|
||||
struct acpi_find_context {
|
||||
char *search_for;
|
||||
@ -404,6 +406,13 @@ struct acpi_simple_repair_info {
|
||||
|
||||
#define ACPI_NUM_RTYPES 5 /* Number of actual object types */
|
||||
|
||||
/* Info for running the _REG methods */
|
||||
|
||||
struct acpi_reg_walk_info {
|
||||
acpi_adr_space_type space_id;
|
||||
u32 reg_run_count;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Event typedefs and structs
|
||||
@ -715,7 +724,7 @@ union acpi_parse_value {
|
||||
union acpi_parse_object *arg; /* arguments and contained ops */
|
||||
};
|
||||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG_OUTPUT)
|
||||
#define ACPI_DISASM_ONLY_MEMBERS(a) a;
|
||||
#else
|
||||
#define ACPI_DISASM_ONLY_MEMBERS(a)
|
||||
@ -726,7 +735,7 @@ union acpi_parse_value {
|
||||
u8 descriptor_type; /* To differentiate various internal objs */\
|
||||
u8 flags; /* Type of Op */\
|
||||
u16 aml_opcode; /* AML opcode */\
|
||||
u32 aml_offset; /* Offset of declaration in AML */\
|
||||
u8 *aml; /* Address of declaration in AML */\
|
||||
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 */\
|
||||
@ -1103,6 +1112,9 @@ struct acpi_db_method_info {
|
||||
* Index of current thread inside all them created.
|
||||
*/
|
||||
char init_args;
|
||||
#ifdef ACPI_DEBUGGER
|
||||
acpi_object_type arg_types[4];
|
||||
#endif
|
||||
char *arguments[4];
|
||||
char num_threads_str[11];
|
||||
char id_of_thread_str[11];
|
||||
@ -1119,6 +1131,10 @@ struct acpi_integrity_info {
|
||||
#define ACPI_DB_CONSOLE_OUTPUT 0x02
|
||||
#define ACPI_DB_DUPLICATE_OUTPUT 0x03
|
||||
|
||||
struct acpi_object_info {
|
||||
u32 types[ACPI_TOTAL_TYPES];
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Debug
|
||||
|
@ -220,6 +220,15 @@
|
||||
#define ACPI_MUL_32(a) _ACPI_MUL(a, 5)
|
||||
#define ACPI_MOD_32(a) _ACPI_MOD(a, 32)
|
||||
|
||||
/* Test for ASCII character */
|
||||
|
||||
#define ACPI_IS_ASCII(c) ((c) < 0x80)
|
||||
|
||||
/* Signed integers */
|
||||
|
||||
#define ACPI_SIGN_POSITIVE 0
|
||||
#define ACPI_SIGN_NEGATIVE 1
|
||||
|
||||
/*
|
||||
* Rounding macros (Power of two boundaries only)
|
||||
*/
|
||||
|
@ -272,17 +272,20 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
*/
|
||||
u32 acpi_ns_opens_scope(acpi_object_type type);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_build_external_path(struct acpi_namespace_node *node,
|
||||
acpi_size size, char *name_buffer);
|
||||
|
||||
char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node);
|
||||
|
||||
u32
|
||||
acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
|
||||
char *full_path, u32 path_size, u8 no_trailing);
|
||||
|
||||
char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
|
||||
u8 no_trailing);
|
||||
|
||||
char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_handle_to_pathname(acpi_handle target_handle,
|
||||
struct acpi_buffer *buffer);
|
||||
struct acpi_buffer *buffer, u8 no_trailing);
|
||||
|
||||
u8
|
||||
acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for);
|
||||
|
@ -176,6 +176,7 @@ struct acpi_object_method {
|
||||
u8 param_count;
|
||||
u8 sync_level;
|
||||
union acpi_operand_object *mutex;
|
||||
union acpi_operand_object *node;
|
||||
u8 *aml_start;
|
||||
union {
|
||||
acpi_internal_method implementation;
|
||||
|
@ -225,11 +225,11 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *root);
|
||||
/*
|
||||
* psutils - parser utilities
|
||||
*/
|
||||
union acpi_parse_object *acpi_ps_create_scope_op(void);
|
||||
union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml);
|
||||
|
||||
void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode);
|
||||
|
||||
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode);
|
||||
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml);
|
||||
|
||||
void acpi_ps_free_op(union acpi_parse_object *op);
|
||||
|
||||
|
@ -85,7 +85,7 @@ struct acpi_walk_state {
|
||||
u8 namespace_override; /* Override existing objects */
|
||||
u8 result_size; /* Total elements for the result stack */
|
||||
u8 result_count; /* Current number of occupied elements of result stack */
|
||||
u32 aml_offset;
|
||||
u8 *aml;
|
||||
u32 arg_types;
|
||||
u32 method_breakpoint; /* For single stepping */
|
||||
u32 user_breakpoint; /* User AML breakpoint */
|
||||
|
@ -154,14 +154,20 @@ void acpi_tb_check_dsdt_header(void);
|
||||
struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index);
|
||||
|
||||
void
|
||||
acpi_tb_install_table_with_override(u32 table_index,
|
||||
struct acpi_table_desc *new_table_desc,
|
||||
u8 override);
|
||||
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
|
||||
u8 override, u32 *table_index);
|
||||
|
||||
acpi_status
|
||||
acpi_tb_install_fixed_table(acpi_physical_address address,
|
||||
char *signature, u32 table_index);
|
||||
char *signature, u32 *table_index);
|
||||
|
||||
acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
|
||||
|
||||
u8 acpi_is_valid_signature(char *signature);
|
||||
|
||||
/*
|
||||
* tbxfload
|
||||
*/
|
||||
acpi_status acpi_tb_load_namespace(void);
|
||||
|
||||
#endif /* __ACTABLES_H__ */
|
||||
|
@ -166,6 +166,17 @@ struct acpi_pkg_info {
|
||||
#define DB_DWORD_DISPLAY 4
|
||||
#define DB_QWORD_DISPLAY 8
|
||||
|
||||
/*
|
||||
* utnonansi - Non-ANSI C library functions
|
||||
*/
|
||||
void acpi_ut_strupr(char *src_string);
|
||||
|
||||
void acpi_ut_strlwr(char *src_string);
|
||||
|
||||
int acpi_ut_stricmp(char *string1, char *string2);
|
||||
|
||||
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
|
||||
|
||||
/*
|
||||
* utglobal - Global data structures and procedures
|
||||
*/
|
||||
@ -205,8 +216,6 @@ acpi_status acpi_ut_hardware_initialize(void);
|
||||
|
||||
void acpi_ut_subsystem_shutdown(void);
|
||||
|
||||
#define ACPI_IS_ASCII(c) ((c) < 0x80)
|
||||
|
||||
/*
|
||||
* utcopy - Object construction and conversion interfaces
|
||||
*/
|
||||
@ -508,7 +517,7 @@ const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status
|
||||
|
||||
u8 acpi_ut_is_pci_root_bridge(char *id);
|
||||
|
||||
#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP)
|
||||
#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
|
||||
u8 acpi_ut_is_aml_table(struct acpi_table_header *table);
|
||||
#endif
|
||||
|
||||
@ -567,16 +576,6 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag);
|
||||
/*
|
||||
* utstring - String and character utilities
|
||||
*/
|
||||
void acpi_ut_strupr(char *src_string);
|
||||
|
||||
#ifdef ACPI_ASL_COMPILER
|
||||
void acpi_ut_strlwr(char *src_string);
|
||||
|
||||
int acpi_ut_stricmp(char *string1, char *string2);
|
||||
#endif
|
||||
|
||||
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
|
||||
|
||||
void acpi_ut_print_string(char *string, u16 max_length);
|
||||
|
||||
#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
|
||||
|
@ -86,7 +86,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node,
|
||||
|
||||
/* Allocate a new parser op to be the root of the parsed tree */
|
||||
|
||||
op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
|
||||
op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@ -129,7 +129,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node,
|
||||
|
||||
/* Evaluate the deferred arguments */
|
||||
|
||||
op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
|
||||
op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
|
||||
*/
|
||||
control_state->control.loop_count++;
|
||||
if (control_state->control.loop_count >
|
||||
ACPI_MAX_LOOP_ITERATIONS) {
|
||||
acpi_gbl_max_loop_iterations) {
|
||||
status = AE_AML_INFINITE_LOOP;
|
||||
break;
|
||||
}
|
||||
|
231
drivers/acpi/acpica/dsdebug.c
Normal file
231
drivers/acpi/acpica/dsdebug.c
Normal file
@ -0,0 +1,231 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: dsdebug - Parser/Interpreter interface - debugging
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2015, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acdispat.h"
|
||||
#include "acnamesp.h"
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
#include "acdisasm.h"
|
||||
#endif
|
||||
#include "acinterp.h"
|
||||
|
||||
#define _COMPONENT ACPI_DISPATCHER
|
||||
ACPI_MODULE_NAME("dsdebug")
|
||||
|
||||
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
|
||||
/* Local prototypes */
|
||||
static void
|
||||
acpi_ds_print_node_pathname(struct acpi_namespace_node *node,
|
||||
const char *message);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_print_node_pathname
|
||||
*
|
||||
* PARAMETERS: node - Object
|
||||
* message - Prefix message
|
||||
*
|
||||
* DESCRIPTION: Print an object's full namespace pathname
|
||||
* Manages allocation/freeing of a pathname buffer
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
acpi_ds_print_node_pathname(struct acpi_namespace_node *node,
|
||||
const char *message)
|
||||
{
|
||||
struct acpi_buffer buffer;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_print_node_pathname);
|
||||
|
||||
if (!node) {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[NULL NAME]"));
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/* Convert handle to full pathname and print it (with supplied message) */
|
||||
|
||||
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
|
||||
|
||||
status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (message) {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "%s ",
|
||||
message));
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[%s] (Node %p)",
|
||||
(char *)buffer.pointer, node));
|
||||
ACPI_FREE(buffer.pointer);
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_dump_method_stack
|
||||
*
|
||||
* PARAMETERS: status - Method execution status
|
||||
* walk_state - Current state of the parse tree walk
|
||||
* op - Executing parse op
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Called when a method has been aborted because of an error.
|
||||
* Dumps the method execution stack.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ds_dump_method_stack(acpi_status status,
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op)
|
||||
{
|
||||
union acpi_parse_object *next;
|
||||
struct acpi_thread_state *thread;
|
||||
struct acpi_walk_state *next_walk_state;
|
||||
struct acpi_namespace_node *previous_method = NULL;
|
||||
union acpi_operand_object *method_desc;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_dump_method_stack);
|
||||
|
||||
/* Ignore control codes, they are not errors */
|
||||
|
||||
if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/* We may be executing a deferred opcode */
|
||||
|
||||
if (walk_state->deferred_node) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"Executing subtree for Buffer/Package/Region\n"));
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no Thread, we are not actually executing a method.
|
||||
* This can happen when the iASL compiler calls the interpreter
|
||||
* to perform constant folding.
|
||||
*/
|
||||
thread = walk_state->thread;
|
||||
if (!thread) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/* Display exception and method name */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"\n**** Exception %s during execution of method ",
|
||||
acpi_format_exception(status)));
|
||||
acpi_ds_print_node_pathname(walk_state->method_node, NULL);
|
||||
|
||||
/* Display stack of executing methods */
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
|
||||
"\n\nMethod Execution Stack:\n"));
|
||||
next_walk_state = thread->walk_state_list;
|
||||
|
||||
/* Walk list of linked walk states */
|
||||
|
||||
while (next_walk_state) {
|
||||
method_desc = next_walk_state->method_desc;
|
||||
if (method_desc) {
|
||||
acpi_ex_stop_trace_method((struct acpi_namespace_node *)
|
||||
method_desc->method.node,
|
||||
method_desc, walk_state);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
" Method [%4.4s] executing: ",
|
||||
acpi_ut_get_node_name(next_walk_state->
|
||||
method_node)));
|
||||
|
||||
/* First method is the currently executing method */
|
||||
|
||||
if (next_walk_state == walk_state) {
|
||||
if (op) {
|
||||
|
||||
/* Display currently executing ASL statement */
|
||||
|
||||
next = op->common.next;
|
||||
op->common.next = NULL;
|
||||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
acpi_dm_disassemble(next_walk_state, op,
|
||||
ACPI_UINT32_MAX);
|
||||
#endif
|
||||
op->common.next = next;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This method has called another method
|
||||
* NOTE: the method call parse subtree is already deleted at this
|
||||
* point, so we cannot disassemble the method invocation.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
|
||||
"Call to method "));
|
||||
acpi_ds_print_node_pathname(previous_method, NULL);
|
||||
}
|
||||
|
||||
previous_method = next_walk_state->method_node;
|
||||
next_walk_state = next_walk_state->next;
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "\n"));
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
#else
|
||||
void
|
||||
acpi_ds_dump_method_stack(acpi_status status,
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
@ -237,12 +237,22 @@ acpi_ds_initialize_objects(u32 table_index,
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* DSDT is always the first AML table */
|
||||
|
||||
if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT)) {
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
|
||||
"\nInitializing Namespace objects:\n"));
|
||||
}
|
||||
|
||||
/* Summary of objects initialized */
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
|
||||
"Table [%4.4s] (id %4.4X) - %4u Objects with %3u Devices, "
|
||||
"%3u Regions, %3u Methods (%u/%u/%u Serial/Non/Cvt)\n",
|
||||
table->signature, owner_id, info.object_count,
|
||||
info.device_count, info.op_region_count,
|
||||
info.method_count, info.serial_method_count,
|
||||
"Table [%4.4s:%8.8s] (id %.2X) - %4u Objects with %3u Devices, "
|
||||
"%3u Regions, %4u Methods (%u/%u/%u Serial/Non/Cvt)\n",
|
||||
table->signature, table->oem_table_id, owner_id,
|
||||
info.object_count, info.device_count,
|
||||
info.op_region_count, info.method_count,
|
||||
info.serial_method_count,
|
||||
info.non_serial_method_count,
|
||||
info.serialized_method_count));
|
||||
|
||||
|
@ -46,11 +46,9 @@
|
||||
#include "acdispat.h"
|
||||
#include "acinterp.h"
|
||||
#include "acnamesp.h"
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
#include "acdisasm.h"
|
||||
#endif
|
||||
#include "acparser.h"
|
||||
#include "amlcode.h"
|
||||
#include "acdebug.h"
|
||||
|
||||
#define _COMPONENT ACPI_DISPATCHER
|
||||
ACPI_MODULE_NAME("dsmethod")
|
||||
@ -103,7 +101,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
|
||||
|
||||
/* Create/Init a root op for the method parse tree */
|
||||
|
||||
op = acpi_ps_alloc_op(AML_METHOD_OP);
|
||||
op = acpi_ps_alloc_op(AML_METHOD_OP, obj_desc->method.aml_start);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@ -205,7 +203,7 @@ acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Called on method error. Invoke the global exception handler if
|
||||
* present, dump the method data if the disassembler is configured
|
||||
* present, dump the method data if the debugger is configured
|
||||
*
|
||||
* Note: Allows the exception handler to change the status code
|
||||
*
|
||||
@ -214,6 +212,8 @@ acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
|
||||
acpi_status
|
||||
acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state)
|
||||
{
|
||||
u32 aml_offset;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
/* Ignore AE_OK and control exception codes */
|
||||
@ -234,26 +234,30 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state)
|
||||
* Handler can map the exception code to anything it wants, including
|
||||
* AE_OK, in which case the executing method will not be aborted.
|
||||
*/
|
||||
aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml,
|
||||
walk_state->parser_state.
|
||||
aml_start);
|
||||
|
||||
status = acpi_gbl_exception_handler(status,
|
||||
walk_state->method_node ?
|
||||
walk_state->method_node->
|
||||
name.integer : 0,
|
||||
walk_state->opcode,
|
||||
walk_state->aml_offset,
|
||||
NULL);
|
||||
aml_offset, NULL);
|
||||
acpi_ex_enter_interpreter();
|
||||
}
|
||||
|
||||
acpi_ds_clear_implicit_return(walk_state);
|
||||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_ds_dump_method_stack(status, walk_state, walk_state->op);
|
||||
|
||||
/* Display method locals/args if disassembler is present */
|
||||
/* Display method locals/args if debugger is present */
|
||||
|
||||
acpi_dm_dump_method_info(status, walk_state, walk_state->op);
|
||||
}
|
||||
#ifdef ACPI_DEBUGGER
|
||||
acpi_db_dump_method_info(status, walk_state);
|
||||
#endif
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
@ -328,6 +332,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
|
||||
return_ACPI_STATUS(AE_NULL_ENTRY);
|
||||
}
|
||||
|
||||
acpi_ex_start_trace_method(method_node, obj_desc, walk_state);
|
||||
|
||||
/* Prevent wraparound of thread count */
|
||||
|
||||
if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
|
||||
@ -574,9 +580,7 @@ cleanup:
|
||||
/* On error, we must terminate the method properly */
|
||||
|
||||
acpi_ds_terminate_control_method(obj_desc, next_walk_state);
|
||||
if (next_walk_state) {
|
||||
acpi_ds_delete_walk_state(next_walk_state);
|
||||
}
|
||||
acpi_ds_delete_walk_state(next_walk_state);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
@ -826,5 +830,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
|
||||
}
|
||||
}
|
||||
|
||||
acpi_ex_stop_trace_method((struct acpi_namespace_node *)method_desc->
|
||||
method.node, method_desc, walk_state);
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
@ -480,8 +480,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object **operand;
|
||||
struct acpi_namespace_node *node;
|
||||
union acpi_parse_object *next_op;
|
||||
u32 table_index;
|
||||
struct acpi_table_header *table;
|
||||
u32 table_index;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
|
||||
|
||||
@ -504,6 +504,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
operand = &walk_state->operands[0];
|
||||
|
||||
/*
|
||||
* Resolve the Signature string, oem_id string,
|
||||
* and oem_table_id string operands
|
||||
@ -511,32 +513,34 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
status = acpi_ex_resolve_operands(op->common.aml_opcode,
|
||||
ACPI_WALK_OPERANDS, walk_state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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);
|
||||
if (status == AE_NOT_FOUND) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
|
||||
operand[0]->string.pointer,
|
||||
operand[1]->string.pointer,
|
||||
operand[2]->string.pointer));
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||
status = AE_NOT_EXIST;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
|
||||
@ -551,6 +555,11 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
|
||||
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
|
||||
|
||||
cleanup:
|
||||
acpi_ut_remove_reference(operand[0]);
|
||||
acpi_ut_remove_reference(operand[1]);
|
||||
acpi_ut_remove_reference(operand[2]);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
|
||||
|
||||
/* Create a new op */
|
||||
|
||||
op = acpi_ps_alloc_op(walk_state->opcode);
|
||||
op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* Create a new op */
|
||||
|
||||
op = acpi_ps_alloc_op(walk_state->opcode);
|
||||
op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
@ -626,9 +626,17 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
|
||||
acpi_adr_space_type space_id)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_reg_walk_info info;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
|
||||
|
||||
info.space_id = space_id;
|
||||
info.reg_run_count = 0;
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
|
||||
" Running _REG methods for SpaceId %s\n",
|
||||
acpi_ut_get_region_name(info.space_id)));
|
||||
|
||||
/*
|
||||
* Run all _REG methods for all Operation Regions for this space ID. This
|
||||
* is a separate walk in order to handle any interdependencies between
|
||||
@ -637,7 +645,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
|
||||
*/
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
|
||||
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
|
||||
NULL, &space_id, NULL);
|
||||
NULL, &info, NULL);
|
||||
|
||||
/* Special case for EC: handle "orphan" _REG methods with no region */
|
||||
|
||||
@ -645,6 +653,11 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
|
||||
acpi_ev_orphan_ec_reg_method(node);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
|
||||
" Executed %u _REG methods for SpaceId %s\n",
|
||||
info.reg_run_count,
|
||||
acpi_ut_get_region_name(info.space_id)));
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
@ -664,10 +677,10 @@ acpi_ev_reg_run(acpi_handle obj_handle,
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
struct acpi_namespace_node *node;
|
||||
acpi_adr_space_type space_id;
|
||||
acpi_status status;
|
||||
struct acpi_reg_walk_info *info;
|
||||
|
||||
space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context);
|
||||
info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);
|
||||
|
||||
/* Convert and validate the device handle */
|
||||
|
||||
@ -696,13 +709,14 @@ acpi_ev_reg_run(acpi_handle obj_handle,
|
||||
|
||||
/* Object is a Region */
|
||||
|
||||
if (obj_desc->region.space_id != space_id) {
|
||||
if (obj_desc->region.space_id != info->space_id) {
|
||||
|
||||
/* This region is for a different address space, just ignore it */
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
info->reg_run_count++;
|
||||
status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
|
||||
return (status);
|
||||
}
|
||||
|
@ -162,14 +162,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
ACPI_FUNCTION_TRACE(ex_load_table_op);
|
||||
|
||||
/* Validate lengths for the Signature, oem_id, and oem_table_id strings */
|
||||
|
||||
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_AML_STRING_LIMIT);
|
||||
}
|
||||
|
||||
/* Find the ACPI table in the RSDT/XSDT */
|
||||
|
||||
status = acpi_tb_find_table(operand[0]->string.pointer,
|
||||
|
@ -486,6 +486,7 @@ acpi_ex_create_method(u8 * aml_start,
|
||||
|
||||
obj_desc->method.aml_start = aml_start;
|
||||
obj_desc->method.aml_length = aml_length;
|
||||
obj_desc->method.node = operand[0];
|
||||
|
||||
/*
|
||||
* Disassemble the method flags. Split off the arg_count, Serialized
|
||||
|
@ -43,11 +43,21 @@
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
#include "acparser.h"
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exdebug")
|
||||
|
||||
static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
#ifdef ACPI_DEBUG_OUTPUT
|
||||
static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
|
||||
#endif
|
||||
|
||||
#ifndef ACPI_NO_ERROR_MESSAGES
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -70,6 +80,7 @@ ACPI_MODULE_NAME("exdebug")
|
||||
* enabled if necessary.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
|
||||
u32 level, u32 index)
|
||||
@ -308,3 +319,316 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
|
||||
return_VOID;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_interpreter_trace_enabled
|
||||
*
|
||||
* PARAMETERS: name - Whether method name should be matched,
|
||||
* this should be checked before starting
|
||||
* the tracer
|
||||
*
|
||||
* RETURN: TRUE if interpreter trace is enabled.
|
||||
*
|
||||
* DESCRIPTION: Check whether interpreter trace is enabled
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u8 acpi_ex_interpreter_trace_enabled(char *name)
|
||||
{
|
||||
|
||||
/* Check if tracing is enabled */
|
||||
|
||||
if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if tracing is filtered:
|
||||
*
|
||||
* 1. If the tracer is started, acpi_gbl_trace_method_object should have
|
||||
* been filled by the trace starter
|
||||
* 2. If the tracer is not started, acpi_gbl_trace_method_name should be
|
||||
* matched if it is specified
|
||||
* 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
|
||||
* not be cleared by the trace stopper during the first match
|
||||
*/
|
||||
if (acpi_gbl_trace_method_object) {
|
||||
return (TRUE);
|
||||
}
|
||||
if (name &&
|
||||
(acpi_gbl_trace_method_name &&
|
||||
strcmp(acpi_gbl_trace_method_name, name))) {
|
||||
return (FALSE);
|
||||
}
|
||||
if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
|
||||
!acpi_gbl_trace_method_name) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_get_trace_event_name
|
||||
*
|
||||
* PARAMETERS: type - Trace event type
|
||||
*
|
||||
* RETURN: Trace event name.
|
||||
*
|
||||
* DESCRIPTION: Used to obtain the full trace event name.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef ACPI_DEBUG_OUTPUT
|
||||
|
||||
static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case ACPI_TRACE_AML_METHOD:
|
||||
|
||||
return "Method";
|
||||
|
||||
case ACPI_TRACE_AML_OPCODE:
|
||||
|
||||
return "Opcode";
|
||||
|
||||
case ACPI_TRACE_AML_REGION:
|
||||
|
||||
return "Region";
|
||||
|
||||
default:
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_trace_point
|
||||
*
|
||||
* PARAMETERS: type - Trace event type
|
||||
* begin - TRUE if before execution
|
||||
* aml - Executed AML address
|
||||
* pathname - Object path
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Internal interpreter execution trace.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_trace_point(acpi_trace_event_type type,
|
||||
u8 begin, u8 *aml, char *pathname)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_trace_point);
|
||||
|
||||
if (pathname) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"%s %s [0x%p:%s] execution.\n",
|
||||
acpi_ex_get_trace_event_name(type),
|
||||
begin ? "Begin" : "End", aml, pathname));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"%s %s [0x%p] execution.\n",
|
||||
acpi_ex_get_trace_event_name(type),
|
||||
begin ? "Begin" : "End", aml));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_start_trace_method
|
||||
*
|
||||
* PARAMETERS: method_node - Node of the method
|
||||
* obj_desc - The method object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Start control method execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
char *pathname = NULL;
|
||||
u8 enabled = FALSE;
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_start_trace_method);
|
||||
|
||||
if (method_node) {
|
||||
pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
|
||||
}
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
enabled = acpi_ex_interpreter_trace_enabled(pathname);
|
||||
if (enabled && !acpi_gbl_trace_method_object) {
|
||||
acpi_gbl_trace_method_object = obj_desc;
|
||||
acpi_gbl_original_dbg_level = acpi_dbg_level;
|
||||
acpi_gbl_original_dbg_layer = acpi_dbg_layer;
|
||||
acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
|
||||
acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
|
||||
|
||||
if (acpi_gbl_trace_dbg_level) {
|
||||
acpi_dbg_level = acpi_gbl_trace_dbg_level;
|
||||
}
|
||||
if (acpi_gbl_trace_dbg_layer) {
|
||||
acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
|
||||
}
|
||||
}
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
exit:
|
||||
if (enabled) {
|
||||
ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE,
|
||||
obj_desc ? obj_desc->method.aml_start : NULL,
|
||||
pathname);
|
||||
}
|
||||
if (pathname) {
|
||||
ACPI_FREE(pathname);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_stop_trace_method
|
||||
*
|
||||
* PARAMETERS: method_node - Node of the method
|
||||
* obj_desc - The method object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Stop control method execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
char *pathname = NULL;
|
||||
u8 enabled;
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_stop_trace_method);
|
||||
|
||||
if (method_node) {
|
||||
pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
|
||||
}
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit_path;
|
||||
}
|
||||
|
||||
enabled = acpi_ex_interpreter_trace_enabled(NULL);
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
if (enabled) {
|
||||
ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE,
|
||||
obj_desc ? obj_desc->method.aml_start : NULL,
|
||||
pathname);
|
||||
}
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit_path;
|
||||
}
|
||||
|
||||
/* Check whether the tracer should be stopped */
|
||||
|
||||
if (acpi_gbl_trace_method_object == obj_desc) {
|
||||
|
||||
/* Disable further tracing if type is one-shot */
|
||||
|
||||
if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
|
||||
acpi_gbl_trace_method_name = NULL;
|
||||
}
|
||||
|
||||
acpi_dbg_level = acpi_gbl_original_dbg_level;
|
||||
acpi_dbg_layer = acpi_gbl_original_dbg_layer;
|
||||
acpi_gbl_trace_method_object = NULL;
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
exit_path:
|
||||
if (pathname) {
|
||||
ACPI_FREE(pathname);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_start_trace_opcode
|
||||
*
|
||||
* PARAMETERS: op - The parser opcode object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Start opcode execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_start_trace_opcode(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_start_trace_opcode);
|
||||
|
||||
if (acpi_ex_interpreter_trace_enabled(NULL) &&
|
||||
(acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
|
||||
ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE,
|
||||
op->common.aml, op->common.aml_op_name);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_stop_trace_opcode
|
||||
*
|
||||
* PARAMETERS: op - The parser opcode object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Stop opcode execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
|
||||
|
||||
if (acpi_ex_interpreter_trace_enabled(NULL) &&
|
||||
(acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
|
||||
ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE,
|
||||
op->common.aml, op->common.aml_op_name);
|
||||
}
|
||||
}
|
||||
|
@ -995,9 +995,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
|
||||
if (obj_desc->reference.class == ACPI_REFCLASS_NAME) {
|
||||
acpi_os_printf(" %p ", obj_desc->reference.node);
|
||||
|
||||
status =
|
||||
acpi_ns_handle_to_pathname(obj_desc->reference.node,
|
||||
&ret_buf);
|
||||
status = acpi_ns_handle_to_pathname(obj_desc->reference.node,
|
||||
&ret_buf, TRUE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_os_printf(" Could not convert name to pathname\n");
|
||||
} else {
|
||||
|
@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
|
||||
if (!source_desc) {
|
||||
ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
|
||||
node->name.ascii, node));
|
||||
return_ACPI_STATUS(AE_AML_NO_OPERAND);
|
||||
return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -337,8 +337,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
||||
acpi_object_type * return_type,
|
||||
union acpi_operand_object **return_desc)
|
||||
{
|
||||
union acpi_operand_object *obj_desc = (void *)operand;
|
||||
struct acpi_namespace_node *node;
|
||||
union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
|
||||
struct acpi_namespace_node *node =
|
||||
ACPI_CAST_PTR(struct acpi_namespace_node, operand);
|
||||
acpi_object_type type;
|
||||
acpi_status status;
|
||||
|
||||
@ -355,9 +356,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
||||
case ACPI_DESC_TYPE_NAMED:
|
||||
|
||||
type = ((struct acpi_namespace_node *)obj_desc)->type;
|
||||
obj_desc =
|
||||
acpi_ns_get_attached_object((struct acpi_namespace_node *)
|
||||
obj_desc);
|
||||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
|
||||
/* If we had an Alias node, use the attached object for type info */
|
||||
|
||||
@ -368,6 +367,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
|
||||
acpi_namespace_node *)
|
||||
obj_desc);
|
||||
}
|
||||
|
||||
if (!obj_desc) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"[%4.4s] Node is unresolved or uninitialized",
|
||||
acpi_ut_get_node_name(node)));
|
||||
return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -160,19 +160,8 @@ acpi_set_firmware_waking_vectors(acpi_physical_address physical_address,
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vectors);
|
||||
|
||||
/* If Hardware Reduced flag is set, there is no FACS */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
if (acpi_gbl_facs32) {
|
||||
(void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_facs32,
|
||||
physical_address,
|
||||
physical_address64);
|
||||
}
|
||||
if (acpi_gbl_facs64) {
|
||||
(void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_facs64,
|
||||
if (acpi_gbl_FACS) {
|
||||
(void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_FACS,
|
||||
physical_address,
|
||||
physical_address64);
|
||||
}
|
||||
|
@ -274,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
|
||||
acpi_ex_exit_interpreter();
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
info->return_object = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -464,7 +465,8 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
|
||||
|
||||
status = acpi_ns_evaluate(info);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INIT_NAMES,
|
||||
"Executed module-level code at %p\n",
|
||||
method_obj->method.aml_start));
|
||||
|
||||
/* Delete a possible implicit return value (in slack mode) */
|
||||
|
@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
acpi_tb_set_table_loaded_flag(table_index, TRUE);
|
||||
} else {
|
||||
(void)acpi_tb_release_owner_id(table_index);
|
||||
/*
|
||||
* On error, delete any namespace objects created by this table.
|
||||
* We cannot initialize these objects, so delete them. There are
|
||||
* a couple of expecially bad cases:
|
||||
* AE_ALREADY_EXISTS - namespace collision.
|
||||
* AE_NOT_FOUND - the target of a Scope operator does not
|
||||
* exist. This target of Scope must already exist in the
|
||||
* namespace, as per the ACPI specification.
|
||||
*/
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
|
||||
tables[table_index].owner_id);
|
||||
acpi_tb_release_owner_id(table_index);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
@ -49,73 +49,6 @@
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsnames")
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_build_external_path
|
||||
*
|
||||
* PARAMETERS: node - NS node whose pathname is needed
|
||||
* size - Size of the pathname
|
||||
* *name_buffer - Where to return the pathname
|
||||
*
|
||||
* RETURN: Status
|
||||
* Places the pathname into the name_buffer, in external format
|
||||
* (name segments separated by path separators)
|
||||
*
|
||||
* DESCRIPTION: Generate a full pathaname
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_ns_build_external_path(struct acpi_namespace_node *node,
|
||||
acpi_size size, char *name_buffer)
|
||||
{
|
||||
acpi_size index;
|
||||
struct acpi_namespace_node *parent_node;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
/* Special case for root */
|
||||
|
||||
index = size - 1;
|
||||
if (index < ACPI_NAME_SIZE) {
|
||||
name_buffer[0] = AML_ROOT_PREFIX;
|
||||
name_buffer[1] = 0;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/* Store terminator byte, then build name backwards */
|
||||
|
||||
parent_node = node;
|
||||
name_buffer[index] = 0;
|
||||
|
||||
while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) {
|
||||
index -= ACPI_NAME_SIZE;
|
||||
|
||||
/* Put the name into the buffer */
|
||||
|
||||
ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name);
|
||||
parent_node = parent_node->parent;
|
||||
|
||||
/* Prefix name with the path separator */
|
||||
|
||||
index--;
|
||||
name_buffer[index] = ACPI_PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
/* Overwrite final separator with the root prefix character */
|
||||
|
||||
name_buffer[index] = AML_ROOT_PREFIX;
|
||||
|
||||
if (index != 0) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not construct external pathname; index=%u, size=%u, Path=%s",
|
||||
(u32) index, (u32) size, &name_buffer[size]));
|
||||
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_get_external_pathname
|
||||
@ -130,37 +63,13 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
|
||||
* for error and debug statements.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
|
||||
{
|
||||
acpi_status status;
|
||||
char *name_buffer;
|
||||
acpi_size size;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
|
||||
|
||||
/* Calculate required buffer size based on depth below root */
|
||||
|
||||
size = acpi_ns_get_pathname_length(node);
|
||||
if (!size) {
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
/* Allocate a buffer to be returned to caller */
|
||||
|
||||
name_buffer = ACPI_ALLOCATE_ZEROED(size);
|
||||
if (!name_buffer) {
|
||||
ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
/* Build the path in the allocated buffer */
|
||||
|
||||
status = acpi_ns_build_external_path(node, size, name_buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_FREE(name_buffer);
|
||||
return_PTR(NULL);
|
||||
}
|
||||
name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);
|
||||
|
||||
return_PTR(name_buffer);
|
||||
}
|
||||
@ -180,33 +89,12 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
|
||||
acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
|
||||
{
|
||||
acpi_size size;
|
||||
struct acpi_namespace_node *next_node;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
/*
|
||||
* Compute length of pathname as 5 * number of name segments.
|
||||
* Go back up the parent tree to the root
|
||||
*/
|
||||
size = 0;
|
||||
next_node = node;
|
||||
size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
|
||||
|
||||
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 Namespace Node (%p) while traversing namespace",
|
||||
next_node));
|
||||
return (0);
|
||||
}
|
||||
size += ACPI_PATH_SEGMENT_LENGTH;
|
||||
next_node = next_node->parent;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
size = 1; /* Root node case */
|
||||
}
|
||||
|
||||
return (size + 1); /* +1 for null string terminator */
|
||||
return (size);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -216,6 +104,8 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
|
||||
* PARAMETERS: target_handle - Handle of named object whose name is
|
||||
* to be found
|
||||
* buffer - Where the pathname is returned
|
||||
* no_trailing - Remove trailing '_' for each name
|
||||
* segment
|
||||
*
|
||||
* RETURN: Status, Buffer is filled with pathname if status is AE_OK
|
||||
*
|
||||
@ -225,7 +115,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
|
||||
|
||||
acpi_status
|
||||
acpi_ns_handle_to_pathname(acpi_handle target_handle,
|
||||
struct acpi_buffer * buffer)
|
||||
struct acpi_buffer * buffer, u8 no_trailing)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_namespace_node *node;
|
||||
@ -240,7 +130,8 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
|
||||
|
||||
/* Determine size required for the caller buffer */
|
||||
|
||||
required_size = acpi_ns_get_pathname_length(node);
|
||||
required_size =
|
||||
acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
|
||||
if (!required_size) {
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
@ -254,8 +145,8 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
|
||||
|
||||
/* Build the path in the caller buffer */
|
||||
|
||||
status =
|
||||
acpi_ns_build_external_path(node, required_size, buffer->pointer);
|
||||
(void)acpi_ns_build_normalized_path(node, buffer->pointer,
|
||||
required_size, no_trailing);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
@ -264,3 +155,149 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
|
||||
(char *)buffer->pointer, (u32) required_size));
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_build_normalized_path
|
||||
*
|
||||
* PARAMETERS: node - Namespace node
|
||||
* full_path - Where the path name is returned
|
||||
* path_size - Size of returned path name buffer
|
||||
* no_trailing - Remove trailing '_' from each name segment
|
||||
*
|
||||
* RETURN: Return 1 if the AML path is empty, otherwise returning (length
|
||||
* of pathname + 1) which means the 'FullPath' contains a trailing
|
||||
* null.
|
||||
*
|
||||
* DESCRIPTION: Build and return a full namespace pathname.
|
||||
* Note that if the size of 'FullPath' isn't large enough to
|
||||
* contain the namespace node's path name, the actual required
|
||||
* buffer length is returned, and it should be greater than
|
||||
* 'PathSize'. So callers are able to check the returning value
|
||||
* to determine the buffer size of 'FullPath'.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u32
|
||||
acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
|
||||
char *full_path, u32 path_size, u8 no_trailing)
|
||||
{
|
||||
u32 length = 0, i;
|
||||
char name[ACPI_NAME_SIZE];
|
||||
u8 do_no_trailing;
|
||||
char c, *left, *right;
|
||||
struct acpi_namespace_node *next_node;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node);
|
||||
|
||||
#define ACPI_PATH_PUT8(path, size, byte, length) \
|
||||
do { \
|
||||
if ((length) < (size)) \
|
||||
{ \
|
||||
(path)[(length)] = (byte); \
|
||||
} \
|
||||
(length)++; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Make sure the path_size is correct, so that we don't need to
|
||||
* validate both full_path and path_size.
|
||||
*/
|
||||
if (!full_path) {
|
||||
path_size = 0;
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
goto build_trailing_null;
|
||||
}
|
||||
|
||||
next_node = node;
|
||||
while (next_node && next_node != acpi_gbl_root_node) {
|
||||
if (next_node != node) {
|
||||
ACPI_PATH_PUT8(full_path, path_size,
|
||||
AML_DUAL_NAME_PREFIX, length);
|
||||
}
|
||||
ACPI_MOVE_32_TO_32(name, &next_node->name);
|
||||
do_no_trailing = no_trailing;
|
||||
for (i = 0; i < 4; i++) {
|
||||
c = name[4 - i - 1];
|
||||
if (do_no_trailing && c != '_') {
|
||||
do_no_trailing = FALSE;
|
||||
}
|
||||
if (!do_no_trailing) {
|
||||
ACPI_PATH_PUT8(full_path, path_size, c, length);
|
||||
}
|
||||
}
|
||||
next_node = next_node->parent;
|
||||
}
|
||||
ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);
|
||||
|
||||
/* Reverse the path string */
|
||||
|
||||
if (length <= path_size) {
|
||||
left = full_path;
|
||||
right = full_path + length - 1;
|
||||
while (left < right) {
|
||||
c = *left;
|
||||
*left++ = *right;
|
||||
*right-- = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append the trailing null */
|
||||
|
||||
build_trailing_null:
|
||||
ACPI_PATH_PUT8(full_path, path_size, '\0', length);
|
||||
|
||||
#undef ACPI_PATH_PUT8
|
||||
|
||||
return_UINT32(length);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_get_normalized_pathname
|
||||
*
|
||||
* PARAMETERS: node - Namespace node whose pathname is needed
|
||||
* no_trailing - Remove trailing '_' from each name segment
|
||||
*
|
||||
* RETURN: Pointer to storage containing the fully qualified name of
|
||||
* the node, In external format (name segments separated by path
|
||||
* separators.)
|
||||
*
|
||||
* DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
|
||||
* for error and debug statements. All trailing '_' will be
|
||||
* removed from the full pathname if 'NoTrailing' is specified..
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
|
||||
u8 no_trailing)
|
||||
{
|
||||
char *name_buffer;
|
||||
acpi_size size;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node);
|
||||
|
||||
/* Calculate required buffer size based on depth below root */
|
||||
|
||||
size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
|
||||
if (!size) {
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
/* Allocate a buffer to be returned to caller */
|
||||
|
||||
name_buffer = ACPI_ALLOCATE_ZEROED(size);
|
||||
if (!name_buffer) {
|
||||
ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
/* Build the path in the allocated buffer */
|
||||
|
||||
(void)acpi_ns_build_normalized_path(node, name_buffer, size,
|
||||
no_trailing);
|
||||
|
||||
return_PTR(name_buffer);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ acpi_ns_one_complete_parse(u32 pass_number,
|
||||
{
|
||||
union acpi_parse_object *parse_root;
|
||||
acpi_status status;
|
||||
u32 aml_length;
|
||||
u32 aml_length;
|
||||
u8 *aml_start;
|
||||
struct acpi_walk_state *walk_state;
|
||||
struct acpi_table_header *table;
|
||||
@ -78,6 +78,20 @@ acpi_ns_one_complete_parse(u32 pass_number,
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_one_complete_parse);
|
||||
|
||||
status = acpi_get_table_by_index(table_index, &table);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Table must consist of at least a complete header */
|
||||
|
||||
if (table->length < sizeof(struct acpi_table_header)) {
|
||||
return_ACPI_STATUS(AE_BAD_HEADER);
|
||||
}
|
||||
|
||||
aml_start = (u8 *)table + sizeof(struct acpi_table_header);
|
||||
aml_length = table->length - sizeof(struct acpi_table_header);
|
||||
|
||||
status = acpi_tb_get_owner_id(table_index, &owner_id);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
@ -85,7 +99,7 @@ acpi_ns_one_complete_parse(u32 pass_number,
|
||||
|
||||
/* Create and init a Root Node */
|
||||
|
||||
parse_root = acpi_ps_create_scope_op();
|
||||
parse_root = acpi_ps_create_scope_op(aml_start);
|
||||
if (!parse_root) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@ -98,23 +112,12 @@ acpi_ns_one_complete_parse(u32 pass_number,
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = acpi_get_table_by_index(table_index, &table);
|
||||
status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
|
||||
aml_start, aml_length, NULL,
|
||||
(u8)pass_number);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_ds_delete_walk_state(walk_state);
|
||||
acpi_ps_free_op(parse_root);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Table must consist of at least a complete header */
|
||||
|
||||
if (table->length < sizeof(struct acpi_table_header)) {
|
||||
status = AE_BAD_HEADER;
|
||||
} else {
|
||||
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);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Found OSDT table, enable the namespace override feature */
|
||||
@ -124,11 +127,6 @@ acpi_ns_one_complete_parse(u32 pass_number,
|
||||
walk_state->namespace_override = TRUE;
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_ds_delete_walk_state(walk_state);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* start_node is the default location to load the table */
|
||||
|
||||
if (start_node && start_node != acpi_gbl_root_node) {
|
||||
|
@ -83,7 +83,7 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
|
||||
|
||||
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
|
||||
|
||||
status = acpi_ns_handle_to_pathname(node, &buffer);
|
||||
status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (message) {
|
||||
acpi_os_printf("%s ", message);
|
||||
@ -596,6 +596,23 @@ void acpi_ns_terminate(void)
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_terminate);
|
||||
|
||||
#ifdef ACPI_EXEC_APP
|
||||
{
|
||||
union acpi_operand_object *prev;
|
||||
union acpi_operand_object *next;
|
||||
|
||||
/* Delete any module-level code blocks */
|
||||
|
||||
next = acpi_gbl_module_code_list;
|
||||
while (next) {
|
||||
prev = next;
|
||||
next = next->method.mutex;
|
||||
prev->method.mutex = NULL; /* Clear the Mutex (cheated) field */
|
||||
acpi_ut_remove_reference(prev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Free the entire namespace -- all nodes and all objects
|
||||
* attached to the nodes
|
||||
|
@ -172,11 +172,15 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
|
||||
return (status);
|
||||
}
|
||||
|
||||
if (name_type == ACPI_FULL_PATHNAME) {
|
||||
if (name_type == ACPI_FULL_PATHNAME ||
|
||||
name_type == ACPI_FULL_PATHNAME_NO_TRAILING) {
|
||||
|
||||
/* Get the full pathname (From the namespace root) */
|
||||
|
||||
status = acpi_ns_handle_to_pathname(handle, buffer);
|
||||
status = acpi_ns_handle_to_pathname(handle, buffer,
|
||||
name_type ==
|
||||
ACPI_FULL_PATHNAME ? FALSE :
|
||||
TRUE);
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
|
||||
"Control Method - %p Desc %p Path=%p\n", node,
|
||||
method_desc, path));
|
||||
|
||||
name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
|
||||
name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, start);
|
||||
if (!name_op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@ -484,7 +484,7 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
|
||||
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
|
||||
*parser_state)
|
||||
{
|
||||
u32 aml_offset;
|
||||
u8 *aml;
|
||||
union acpi_parse_object *field;
|
||||
union acpi_parse_object *arg = NULL;
|
||||
u16 opcode;
|
||||
@ -498,8 +498,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
|
||||
|
||||
ACPI_FUNCTION_TRACE(ps_get_next_field);
|
||||
|
||||
aml_offset =
|
||||
(u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start);
|
||||
aml = parser_state->aml;
|
||||
|
||||
/* Determine field type */
|
||||
|
||||
@ -536,13 +535,11 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
|
||||
|
||||
/* Allocate a new field op */
|
||||
|
||||
field = acpi_ps_alloc_op(opcode);
|
||||
field = acpi_ps_alloc_op(opcode, aml);
|
||||
if (!field) {
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
field->common.aml_offset = aml_offset;
|
||||
|
||||
/* Decode the field type */
|
||||
|
||||
switch (opcode) {
|
||||
@ -604,6 +601,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
|
||||
* Argument for Connection operator can be either a Buffer
|
||||
* (resource descriptor), or a name_string.
|
||||
*/
|
||||
aml = parser_state->aml;
|
||||
if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) {
|
||||
parser_state->aml++;
|
||||
|
||||
@ -616,7 +614,8 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
|
||||
|
||||
/* Non-empty list */
|
||||
|
||||
arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
|
||||
arg =
|
||||
acpi_ps_alloc_op(AML_INT_BYTELIST_OP, aml);
|
||||
if (!arg) {
|
||||
acpi_ps_free_op(field);
|
||||
return_PTR(NULL);
|
||||
@ -665,7 +664,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
|
||||
|
||||
parser_state->aml = pkg_end;
|
||||
} else {
|
||||
arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
|
||||
arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, aml);
|
||||
if (!arg) {
|
||||
acpi_ps_free_op(field);
|
||||
return_PTR(NULL);
|
||||
@ -730,7 +729,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* Constants, strings, and namestrings are all the same size */
|
||||
|
||||
arg = acpi_ps_alloc_op(AML_BYTE_OP);
|
||||
arg = acpi_ps_alloc_op(AML_BYTE_OP, parser_state->aml);
|
||||
if (!arg) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@ -777,7 +776,8 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* Non-empty list */
|
||||
|
||||
arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
|
||||
arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP,
|
||||
parser_state->aml);
|
||||
if (!arg) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@ -807,7 +807,9 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* null_name or name_string */
|
||||
|
||||
arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
|
||||
arg =
|
||||
acpi_ps_alloc_op(AML_INT_NAMEPATH_OP,
|
||||
parser_state->aml);
|
||||
if (!arg) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acinterp.h"
|
||||
#include "acparser.h"
|
||||
#include "acdispat.h"
|
||||
#include "amlcode.h"
|
||||
@ -125,10 +126,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
*/
|
||||
while (GET_CURRENT_ARG_TYPE(walk_state->arg_types)
|
||||
&& !walk_state->arg_count) {
|
||||
walk_state->aml_offset =
|
||||
(u32) ACPI_PTR_DIFF(walk_state->parser_state.aml,
|
||||
walk_state->parser_state.
|
||||
aml_start);
|
||||
walk_state->aml = walk_state->parser_state.aml;
|
||||
|
||||
status =
|
||||
acpi_ps_get_next_arg(walk_state,
|
||||
@ -140,7 +138,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
}
|
||||
|
||||
if (arg) {
|
||||
arg->common.aml_offset = walk_state->aml_offset;
|
||||
acpi_ps_append_arg(op, arg);
|
||||
}
|
||||
|
||||
@ -324,6 +321,8 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op,
|
||||
union acpi_operand_object *method_obj;
|
||||
struct acpi_namespace_node *parent_node;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ps_link_module_code);
|
||||
|
||||
/* Get the tail of the list */
|
||||
|
||||
prev = next = acpi_gbl_module_code_list;
|
||||
@ -343,9 +342,13 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op,
|
||||
|
||||
method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
|
||||
if (!method_obj) {
|
||||
return;
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Create/Link new code block: %p\n",
|
||||
method_obj));
|
||||
|
||||
if (parent_op->common.node) {
|
||||
parent_node = parent_op->common.node;
|
||||
} else {
|
||||
@ -370,8 +373,14 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op,
|
||||
prev->method.mutex = method_obj;
|
||||
}
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Appending to existing code block: %p\n",
|
||||
prev));
|
||||
|
||||
prev->method.aml_length += aml_length;
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -494,16 +503,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
|
||||
continue;
|
||||
}
|
||||
|
||||
op->common.aml_offset = walk_state->aml_offset;
|
||||
|
||||
if (walk_state->op_info) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
|
||||
(u32) op->common.aml_opcode,
|
||||
walk_state->op_info->name, op,
|
||||
parser_state->aml,
|
||||
op->common.aml_offset));
|
||||
}
|
||||
acpi_ex_start_trace_opcode(op, walk_state);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -66,12 +66,11 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state);
|
||||
|
||||
static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
|
||||
{
|
||||
u32 aml_offset;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state);
|
||||
|
||||
walk_state->aml_offset =
|
||||
(u32)ACPI_PTR_DIFF(walk_state->parser_state.aml,
|
||||
walk_state->parser_state.aml_start);
|
||||
walk_state->aml = walk_state->parser_state.aml;
|
||||
walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state));
|
||||
|
||||
/*
|
||||
@ -98,10 +97,14 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
|
||||
/* The opcode is unrecognized. Complain and skip unknown opcodes */
|
||||
|
||||
if (walk_state->pass_number == 2) {
|
||||
aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml,
|
||||
walk_state->
|
||||
parser_state.aml_start);
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
|
||||
walk_state->opcode,
|
||||
(u32)(walk_state->aml_offset +
|
||||
(u32)(aml_offset +
|
||||
sizeof(struct acpi_table_header))));
|
||||
|
||||
ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16),
|
||||
@ -115,14 +118,14 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
|
||||
acpi_os_printf
|
||||
("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
|
||||
walk_state->opcode,
|
||||
(u32)(walk_state->aml_offset +
|
||||
(u32)(aml_offset +
|
||||
sizeof(struct acpi_table_header)));
|
||||
|
||||
/* Dump the context surrounding the invalid opcode */
|
||||
|
||||
acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
|
||||
aml - 16), 48, DB_BYTE_DISPLAY,
|
||||
(walk_state->aml_offset +
|
||||
(aml_offset +
|
||||
sizeof(struct acpi_table_header) -
|
||||
16));
|
||||
acpi_os_printf(" */\n");
|
||||
@ -294,7 +297,7 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
|
||||
/* Create Op structure and append to parent's argument list */
|
||||
|
||||
walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
|
||||
op = acpi_ps_alloc_op(walk_state->opcode);
|
||||
op = acpi_ps_alloc_op(walk_state->opcode, aml_op_start);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
@ -147,6 +147,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
||||
return_ACPI_STATUS(AE_OK); /* OK for now */
|
||||
}
|
||||
|
||||
acpi_ex_stop_trace_opcode(op, walk_state);
|
||||
|
||||
/* Delete this op and the subtree below it if asked to */
|
||||
|
||||
if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) !=
|
||||
@ -185,7 +187,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
||||
* op must be replaced by a placeholder return op
|
||||
*/
|
||||
replacement_op =
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP,
|
||||
op->common.aml);
|
||||
if (!replacement_op) {
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
@ -209,7 +212,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
||||
|| (op->common.parent->common.aml_opcode ==
|
||||
AML_VAR_PACKAGE_OP)) {
|
||||
replacement_op =
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP,
|
||||
op->common.aml);
|
||||
if (!replacement_op) {
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
@ -224,7 +228,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
||||
AML_VAR_PACKAGE_OP)) {
|
||||
replacement_op =
|
||||
acpi_ps_alloc_op(op->common.
|
||||
aml_opcode);
|
||||
aml_opcode,
|
||||
op->common.aml);
|
||||
if (!replacement_op) {
|
||||
status = AE_NO_MEMORY;
|
||||
} else {
|
||||
@ -240,7 +245,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
|
||||
default:
|
||||
|
||||
replacement_op =
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
|
||||
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP,
|
||||
op->common.aml);
|
||||
if (!replacement_op) {
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
|
@ -60,11 +60,11 @@ ACPI_MODULE_NAME("psutils")
|
||||
* DESCRIPTION: Create a Scope and associated namepath op with the root name
|
||||
*
|
||||
******************************************************************************/
|
||||
union acpi_parse_object *acpi_ps_create_scope_op(void)
|
||||
union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml)
|
||||
{
|
||||
union acpi_parse_object *scope_op;
|
||||
|
||||
scope_op = acpi_ps_alloc_op(AML_SCOPE_OP);
|
||||
scope_op = acpi_ps_alloc_op(AML_SCOPE_OP, aml);
|
||||
if (!scope_op) {
|
||||
return (NULL);
|
||||
}
|
||||
@ -103,6 +103,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
|
||||
* FUNCTION: acpi_ps_alloc_op
|
||||
*
|
||||
* PARAMETERS: opcode - Opcode that will be stored in the new Op
|
||||
* aml - Address of the opcode
|
||||
*
|
||||
* RETURN: Pointer to the new Op, null on failure
|
||||
*
|
||||
@ -112,7 +113,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
|
||||
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml)
|
||||
{
|
||||
union acpi_parse_object *op;
|
||||
const struct acpi_opcode_info *op_info;
|
||||
@ -149,6 +150,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
|
||||
|
||||
if (op) {
|
||||
acpi_ps_init_op(op, opcode);
|
||||
op->common.aml = aml;
|
||||
op->common.flags = flags;
|
||||
}
|
||||
|
||||
|
@ -47,15 +47,12 @@
|
||||
#include "acdispat.h"
|
||||
#include "acinterp.h"
|
||||
#include "actables.h"
|
||||
#include "acnamesp.h"
|
||||
|
||||
#define _COMPONENT ACPI_PARSER
|
||||
ACPI_MODULE_NAME("psxface")
|
||||
|
||||
/* Local Prototypes */
|
||||
static void acpi_ps_start_trace(struct acpi_evaluate_info *info);
|
||||
|
||||
static void acpi_ps_stop_trace(struct acpi_evaluate_info *info);
|
||||
|
||||
static void
|
||||
acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
|
||||
|
||||
@ -76,7 +73,7 @@ acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
|
||||
acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
@ -85,108 +82,14 @@ acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* TBDs: Validate name, allow full path or just nameseg */
|
||||
|
||||
acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name);
|
||||
acpi_gbl_trace_method_name = name;
|
||||
acpi_gbl_trace_flags = flags;
|
||||
|
||||
if (debug_level) {
|
||||
acpi_gbl_trace_dbg_level = debug_level;
|
||||
}
|
||||
if (debug_layer) {
|
||||
acpi_gbl_trace_dbg_layer = debug_layer;
|
||||
}
|
||||
acpi_gbl_trace_dbg_level = debug_level;
|
||||
acpi_gbl_trace_dbg_layer = debug_layer;
|
||||
status = AE_OK;
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ps_start_trace
|
||||
*
|
||||
* PARAMETERS: info - Method info struct
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Start control method execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void acpi_ps_start_trace(struct acpi_evaluate_info *info)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!acpi_gbl_trace_method_name) ||
|
||||
(acpi_gbl_trace_method_name != info->node->name.integer)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
acpi_gbl_original_dbg_level = acpi_dbg_level;
|
||||
acpi_gbl_original_dbg_layer = acpi_dbg_layer;
|
||||
|
||||
acpi_dbg_level = 0x00FFFFFF;
|
||||
acpi_dbg_layer = ACPI_UINT32_MAX;
|
||||
|
||||
if (acpi_gbl_trace_dbg_level) {
|
||||
acpi_dbg_level = acpi_gbl_trace_dbg_level;
|
||||
}
|
||||
if (acpi_gbl_trace_dbg_layer) {
|
||||
acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
|
||||
}
|
||||
|
||||
exit:
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ps_stop_trace
|
||||
*
|
||||
* PARAMETERS: info - Method info struct
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Stop control method execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!acpi_gbl_trace_method_name) ||
|
||||
(acpi_gbl_trace_method_name != info->node->name.integer)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Disable further tracing if type is one-shot */
|
||||
|
||||
if (acpi_gbl_trace_flags & 1) {
|
||||
acpi_gbl_trace_method_name = 0;
|
||||
acpi_gbl_trace_dbg_level = 0;
|
||||
acpi_gbl_trace_dbg_layer = 0;
|
||||
}
|
||||
|
||||
acpi_dbg_level = acpi_gbl_original_dbg_level;
|
||||
acpi_dbg_layer = acpi_gbl_original_dbg_layer;
|
||||
|
||||
exit:
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -212,7 +115,7 @@ exit:
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
|
||||
acpi_status acpi_ps_execute_method(struct acpi_evaluate_info * info)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_parse_object *op;
|
||||
@ -243,10 +146,6 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
|
||||
*/
|
||||
acpi_ps_update_parameter_list(info, REF_INCREMENT);
|
||||
|
||||
/* Begin tracing if requested */
|
||||
|
||||
acpi_ps_start_trace(info);
|
||||
|
||||
/*
|
||||
* Execute the method. Performs parse simultaneously
|
||||
*/
|
||||
@ -256,7 +155,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
|
||||
|
||||
/* Create and init a Root Node */
|
||||
|
||||
op = acpi_ps_create_scope_op();
|
||||
op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
|
||||
if (!op) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
@ -326,10 +225,6 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
|
||||
cleanup:
|
||||
acpi_ps_delete_parse_tree(op);
|
||||
|
||||
/* End optional tracing */
|
||||
|
||||
acpi_ps_stop_trace(info);
|
||||
|
||||
/* Take away the extra reference that we gave the parameters above */
|
||||
|
||||
acpi_ps_update_parameter_list(info, REF_DECREMENT);
|
||||
|
@ -348,7 +348,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
status =
|
||||
acpi_ns_handle_to_pathname((acpi_handle)
|
||||
node,
|
||||
&path_buffer);
|
||||
&path_buffer,
|
||||
FALSE);
|
||||
|
||||
/* +1 to include null terminator */
|
||||
|
||||
|
@ -345,7 +345,7 @@ void acpi_tb_parse_fadt(u32 table_index)
|
||||
/* Obtain the DSDT and FACS tables via their addresses within the FADT */
|
||||
|
||||
acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
|
||||
ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
|
||||
ACPI_SIG_DSDT, &acpi_gbl_dsdt_index);
|
||||
|
||||
/* If Hardware Reduced flag is set, there is no FACS */
|
||||
|
||||
@ -354,13 +354,13 @@ void acpi_tb_parse_fadt(u32 table_index)
|
||||
acpi_tb_install_fixed_table((acpi_physical_address)
|
||||
acpi_gbl_FADT.facs,
|
||||
ACPI_SIG_FACS,
|
||||
ACPI_TABLE_INDEX_FACS);
|
||||
&acpi_gbl_facs_index);
|
||||
}
|
||||
if (acpi_gbl_FADT.Xfacs) {
|
||||
acpi_tb_install_fixed_table((acpi_physical_address)
|
||||
acpi_gbl_FADT.Xfacs,
|
||||
ACPI_SIG_FACS,
|
||||
ACPI_TABLE_INDEX_X_FACS);
|
||||
&acpi_gbl_xfacs_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,12 +68,25 @@ acpi_status
|
||||
acpi_tb_find_table(char *signature,
|
||||
char *oem_id, char *oem_table_id, u32 *table_index)
|
||||
{
|
||||
u32 i;
|
||||
acpi_status status;
|
||||
struct acpi_table_header header;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_find_table);
|
||||
|
||||
/* Validate the input table signature */
|
||||
|
||||
if (!acpi_is_valid_signature(signature)) {
|
||||
return_ACPI_STATUS(AE_BAD_SIGNATURE);
|
||||
}
|
||||
|
||||
/* Don't allow the OEM strings to be too long */
|
||||
|
||||
if ((strlen(oem_id) > ACPI_OEM_ID_SIZE) ||
|
||||
(strlen(oem_table_id) > ACPI_OEM_TABLE_ID_SIZE)) {
|
||||
return_ACPI_STATUS(AE_AML_STRING_LIMIT);
|
||||
}
|
||||
|
||||
/* Normalize the input strings */
|
||||
|
||||
memset(&header, 0, sizeof(struct acpi_table_header));
|
||||
|
@ -100,9 +100,9 @@ acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
|
||||
*
|
||||
* FUNCTION: acpi_tb_install_table_with_override
|
||||
*
|
||||
* PARAMETERS: table_index - Index into root table array
|
||||
* new_table_desc - New table descriptor to install
|
||||
* PARAMETERS: new_table_desc - New table descriptor to install
|
||||
* override - Whether override should be performed
|
||||
* table_index - Where the table index is returned
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
@ -114,12 +114,14 @@ acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_tb_install_table_with_override(u32 table_index,
|
||||
struct acpi_table_desc *new_table_desc,
|
||||
u8 override)
|
||||
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
|
||||
u8 override, u32 *table_index)
|
||||
{
|
||||
u32 i;
|
||||
acpi_status status;
|
||||
|
||||
if (table_index >= acpi_gbl_root_table_list.current_table_count) {
|
||||
status = acpi_tb_get_next_table_descriptor(&i, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -134,8 +136,7 @@ acpi_tb_install_table_with_override(u32 table_index,
|
||||
acpi_tb_override_table(new_table_desc);
|
||||
}
|
||||
|
||||
acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
|
||||
tables[table_index],
|
||||
acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i],
|
||||
new_table_desc->address,
|
||||
new_table_desc->flags,
|
||||
new_table_desc->pointer);
|
||||
@ -143,9 +144,13 @@ acpi_tb_install_table_with_override(u32 table_index,
|
||||
acpi_tb_print_table_header(new_table_desc->address,
|
||||
new_table_desc->pointer);
|
||||
|
||||
/* This synchronizes acpi_gbl_dsdt_index */
|
||||
|
||||
*table_index = i;
|
||||
|
||||
/* Set the global integer width (based upon revision of the DSDT) */
|
||||
|
||||
if (table_index == ACPI_TABLE_INDEX_DSDT) {
|
||||
if (i == acpi_gbl_dsdt_index) {
|
||||
acpi_ut_set_integer_width(new_table_desc->pointer->revision);
|
||||
}
|
||||
}
|
||||
@ -157,7 +162,7 @@ acpi_tb_install_table_with_override(u32 table_index,
|
||||
* PARAMETERS: address - Physical address of DSDT or FACS
|
||||
* signature - Table signature, NULL if no need to
|
||||
* match
|
||||
* table_index - Index into root table array
|
||||
* table_index - Where the table index is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
@ -168,7 +173,7 @@ acpi_tb_install_table_with_override(u32 table_index,
|
||||
|
||||
acpi_status
|
||||
acpi_tb_install_fixed_table(acpi_physical_address address,
|
||||
char *signature, u32 table_index)
|
||||
char *signature, u32 *table_index)
|
||||
{
|
||||
struct acpi_table_desc new_table_desc;
|
||||
acpi_status status;
|
||||
@ -200,7 +205,9 @@ acpi_tb_install_fixed_table(acpi_physical_address address,
|
||||
goto release_and_exit;
|
||||
}
|
||||
|
||||
acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE);
|
||||
/* Add the table to the global root table list */
|
||||
|
||||
acpi_tb_install_table_with_override(&new_table_desc, TRUE, table_index);
|
||||
|
||||
release_and_exit:
|
||||
|
||||
@ -355,13 +362,8 @@ acpi_tb_install_standard_table(acpi_physical_address address,
|
||||
|
||||
/* Add the table to the global root table list */
|
||||
|
||||
status = acpi_tb_get_next_table_descriptor(&i, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto release_and_exit;
|
||||
}
|
||||
|
||||
*table_index = i;
|
||||
acpi_tb_install_table_with_override(i, &new_table_desc, override);
|
||||
acpi_tb_install_table_with_override(&new_table_desc, override,
|
||||
table_index);
|
||||
|
||||
release_and_exit:
|
||||
|
||||
|
@ -68,28 +68,27 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
|
||||
|
||||
acpi_status acpi_tb_initialize_facs(void)
|
||||
{
|
||||
struct acpi_table_facs *facs;
|
||||
|
||||
/* If Hardware Reduced flag is set, there is no FACS */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
acpi_gbl_FACS = NULL;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
(void)acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
|
||||
ACPI_CAST_INDIRECT_PTR(struct
|
||||
acpi_table_header,
|
||||
&acpi_gbl_facs32));
|
||||
(void)acpi_get_table_by_index(ACPI_TABLE_INDEX_X_FACS,
|
||||
ACPI_CAST_INDIRECT_PTR(struct
|
||||
acpi_table_header,
|
||||
&acpi_gbl_facs64));
|
||||
|
||||
if (acpi_gbl_facs64
|
||||
&& (!acpi_gbl_facs32 || !acpi_gbl_use32_bit_facs_addresses)) {
|
||||
acpi_gbl_FACS = acpi_gbl_facs64;
|
||||
} else if (acpi_gbl_facs32) {
|
||||
acpi_gbl_FACS = acpi_gbl_facs32;
|
||||
} else if (acpi_gbl_FADT.Xfacs &&
|
||||
(!acpi_gbl_FADT.facs
|
||||
|| !acpi_gbl_use32_bit_facs_addresses)) {
|
||||
(void)acpi_get_table_by_index(acpi_gbl_xfacs_index,
|
||||
ACPI_CAST_INDIRECT_PTR(struct
|
||||
acpi_table_header,
|
||||
&facs));
|
||||
acpi_gbl_FACS = facs;
|
||||
} else if (acpi_gbl_FADT.facs) {
|
||||
(void)acpi_get_table_by_index(acpi_gbl_facs_index,
|
||||
ACPI_CAST_INDIRECT_PTR(struct
|
||||
acpi_table_header,
|
||||
&facs));
|
||||
acpi_gbl_FACS = facs;
|
||||
}
|
||||
|
||||
/* If there is no FACS, just continue. There was already an error msg */
|
||||
@ -192,7 +191,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
|
||||
acpi_tb_uninstall_table(table_desc);
|
||||
|
||||
acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT],
|
||||
tables[acpi_gbl_dsdt_index],
|
||||
ACPI_PTR_TO_PHYSADDR(new_table),
|
||||
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
|
||||
new_table);
|
||||
@ -369,13 +368,6 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
|
||||
table_entry_size);
|
||||
table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
|
||||
|
||||
/*
|
||||
* First three entries in the table array are reserved for the DSDT
|
||||
* and 32bit/64bit FACS, which are not actually present in the
|
||||
* RSDT/XSDT - they come from the FADT
|
||||
*/
|
||||
acpi_gbl_root_table_list.current_table_count = 3;
|
||||
|
||||
/* Initialize the root table array from the RSDT/XSDT */
|
||||
|
||||
for (i = 0; i < table_count; i++) {
|
||||
@ -412,3 +404,36 @@ next_table:
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_is_valid_signature
|
||||
*
|
||||
* PARAMETERS: signature - Sig string to be validated
|
||||
*
|
||||
* RETURN: TRUE if signature is correct length and has valid characters
|
||||
*
|
||||
* DESCRIPTION: Validate an ACPI table signature.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_is_valid_signature(char *signature)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
/* Validate the signature length */
|
||||
|
||||
if (strlen(signature) != ACPI_NAME_SIZE) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* Validate each character in the signature */
|
||||
|
||||
for (i = 0; i < ACPI_NAME_SIZE; i++) {
|
||||
if (!acpi_ut_valid_acpi_char(signature[i], i)) {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
@ -51,9 +51,6 @@
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbxfload")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status acpi_tb_load_namespace(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_load_tables
|
||||
@ -65,7 +62,6 @@ static acpi_status acpi_tb_load_namespace(void);
|
||||
* DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status __init acpi_load_tables(void)
|
||||
{
|
||||
acpi_status status;
|
||||
@ -75,6 +71,13 @@ acpi_status __init acpi_load_tables(void)
|
||||
/* Load the namespace from the tables */
|
||||
|
||||
status = acpi_tb_load_namespace();
|
||||
|
||||
/* Don't let single failures abort the load */
|
||||
|
||||
if (status == AE_CTRL_TERMINATE) {
|
||||
status = AE_OK;
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"While loading namespace from ACPI tables"));
|
||||
@ -97,11 +100,14 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)
|
||||
* the RSDT/XSDT.
|
||||
*
|
||||
******************************************************************************/
|
||||
static acpi_status acpi_tb_load_namespace(void)
|
||||
acpi_status acpi_tb_load_namespace(void)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
struct acpi_table_header *new_dsdt;
|
||||
struct acpi_table_desc *table;
|
||||
u32 tables_loaded = 0;
|
||||
u32 tables_failed = 0;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_load_namespace);
|
||||
|
||||
@ -111,15 +117,11 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||
* Load the namespace. The DSDT is required, but any SSDT and
|
||||
* PSDT tables are optional. Verify the DSDT.
|
||||
*/
|
||||
table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index];
|
||||
|
||||
if (!acpi_gbl_root_table_list.current_table_count ||
|
||||
!ACPI_COMPARE_NAME(&
|
||||
(acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT].signature),
|
||||
ACPI_SIG_DSDT)
|
||||
||
|
||||
ACPI_FAILURE(acpi_tb_validate_table
|
||||
(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT]))) {
|
||||
!ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_DSDT) ||
|
||||
ACPI_FAILURE(acpi_tb_validate_table(table))) {
|
||||
status = AE_NO_ACPI_TABLES;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
@ -130,8 +132,7 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||
* array can change dynamically as tables are loaded at run-time. Note:
|
||||
* .Pointer field is not validated until after call to acpi_tb_validate_table.
|
||||
*/
|
||||
acpi_gbl_DSDT =
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer;
|
||||
acpi_gbl_DSDT = table->pointer;
|
||||
|
||||
/*
|
||||
* Optionally copy the entire DSDT to local memory (instead of simply
|
||||
@ -140,7 +141,7 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||
* the DSDT.
|
||||
*/
|
||||
if (acpi_gbl_copy_dsdt_locally) {
|
||||
new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT);
|
||||
new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index);
|
||||
if (new_dsdt) {
|
||||
acpi_gbl_DSDT = new_dsdt;
|
||||
}
|
||||
@ -157,41 +158,65 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||
|
||||
/* Load and parse tables */
|
||||
|
||||
status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
|
||||
status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed"));
|
||||
tables_failed++;
|
||||
} else {
|
||||
tables_loaded++;
|
||||
}
|
||||
|
||||
/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
|
||||
table = &acpi_gbl_root_table_list.tables[i];
|
||||
|
||||
if (!acpi_gbl_root_table_list.tables[i].address ||
|
||||
(!ACPI_COMPARE_NAME
|
||||
(&(acpi_gbl_root_table_list.tables[i].signature),
|
||||
ACPI_SIG_SSDT)
|
||||
&&
|
||||
!ACPI_COMPARE_NAME(&
|
||||
(acpi_gbl_root_table_list.tables[i].
|
||||
signature), ACPI_SIG_PSDT)
|
||||
&&
|
||||
!ACPI_COMPARE_NAME(&
|
||||
(acpi_gbl_root_table_list.tables[i].
|
||||
signature), ACPI_SIG_OSDT))
|
||||
||
|
||||
ACPI_FAILURE(acpi_tb_validate_table
|
||||
(&acpi_gbl_root_table_list.tables[i]))) {
|
||||
(!ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_SSDT)
|
||||
&& !ACPI_COMPARE_NAME(table->signature.ascii,
|
||||
ACPI_SIG_PSDT)
|
||||
&& !ACPI_COMPARE_NAME(table->signature.ascii,
|
||||
ACPI_SIG_OSDT))
|
||||
|| ACPI_FAILURE(acpi_tb_validate_table(table))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore errors while loading tables, get as many as possible */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
(void)acpi_ns_load_table(i, acpi_gbl_root_node);
|
||||
status = acpi_ns_load_table(i, acpi_gbl_root_node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"(%4.4s:%8.8s) while loading table",
|
||||
table->signature.ascii,
|
||||
table->pointer->oem_table_id));
|
||||
tables_failed++;
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
|
||||
"Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n",
|
||||
table->signature.ascii,
|
||||
table->pointer->oem_table_id));
|
||||
} else {
|
||||
tables_loaded++;
|
||||
}
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
}
|
||||
|
||||
ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired"));
|
||||
if (!tables_failed) {
|
||||
ACPI_INFO((AE_INFO,
|
||||
"%u ACPI AML tables successfully acquired and loaded",
|
||||
tables_loaded));
|
||||
} else {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"%u table load failures, %u successful",
|
||||
tables_failed, tables_loaded));
|
||||
|
||||
/* Indicate at least one failure */
|
||||
|
||||
status = AE_CTRL_TERMINATE;
|
||||
}
|
||||
|
||||
unlock_and_exit:
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acinterp.h"
|
||||
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utdebug")
|
||||
@ -560,8 +561,37 @@ acpi_ut_ptr_exit(u32 line_number,
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_trace_point
|
||||
*
|
||||
* PARAMETERS: type - Trace event type
|
||||
* begin - TRUE if before execution
|
||||
* aml - Executed AML address
|
||||
* pathname - Object path
|
||||
* pointer - Pointer to the related object
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Interpreter execution trace.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_trace_point(acpi_trace_event_type type, u8 begin, u8 *aml, char *pathname)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
acpi_ex_trace_point(type, begin, aml, pathname);
|
||||
|
||||
#ifdef ACPI_USE_SYSTEM_TRACER
|
||||
acpi_os_trace_point(type, begin, aml, pathname);
|
||||
#endif
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_trace_point)
|
||||
#endif
|
||||
#ifdef ACPI_APPLICATION
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -575,7 +605,6 @@ acpi_ut_ptr_exit(u32 line_number,
|
||||
* DESCRIPTION: Print error message to the console, used by applications.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
@ -209,6 +209,9 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
|
||||
acpi_ut_delete_object_desc(object->method.mutex);
|
||||
object->method.mutex = NULL;
|
||||
}
|
||||
if (object->method.node) {
|
||||
object->method.node = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_REGION:
|
||||
|
@ -312,7 +312,7 @@ acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
|
||||
/* Get the entire file */
|
||||
|
||||
fprintf(stderr,
|
||||
"Reading ACPI table from file %10s - Length %.8u (0x%06X)\n",
|
||||
"Reading ACPI table from file %12s - Length %.8u (0x%06X)\n",
|
||||
filename, file_size, file_size);
|
||||
|
||||
status = acpi_ut_read_table(file, table, &table_length);
|
||||
|
@ -204,11 +204,10 @@ acpi_status acpi_ut_init_globals(void)
|
||||
acpi_gbl_acpi_hardware_present = TRUE;
|
||||
acpi_gbl_last_owner_id_index = 0;
|
||||
acpi_gbl_next_owner_id_offset = 0;
|
||||
acpi_gbl_trace_dbg_level = 0;
|
||||
acpi_gbl_trace_dbg_layer = 0;
|
||||
acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
|
||||
acpi_gbl_osi_mutex = NULL;
|
||||
acpi_gbl_reg_methods_executed = FALSE;
|
||||
acpi_gbl_max_loop_iterations = 0xFFFF;
|
||||
|
||||
/* Hardware oriented */
|
||||
|
||||
|
@ -75,7 +75,7 @@ u8 acpi_ut_is_pci_root_bridge(char *id)
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP)
|
||||
#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_is_aml_table
|
||||
@ -376,7 +376,7 @@ acpi_ut_display_init_pathname(u8 type,
|
||||
/* Get the full pathname to the node */
|
||||
|
||||
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
|
||||
status = acpi_ns_handle_to_pathname(obj_handle, &buffer);
|
||||
status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
380
drivers/acpi/acpica/utnonansi.c
Normal file
380
drivers/acpi/acpica/utnonansi.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Module Name: utnonansi - Non-ansi C library functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2015, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utnonansi")
|
||||
|
||||
/*
|
||||
* Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit
|
||||
* version of strtoul.
|
||||
*/
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_strlwr (strlwr)
|
||||
*
|
||||
* PARAMETERS: src_string - The source string to convert
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Convert a string to lowercase
|
||||
*
|
||||
******************************************************************************/
|
||||
void acpi_ut_strlwr(char *src_string)
|
||||
{
|
||||
char *string;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
if (!src_string) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Walk entire string, lowercasing the letters */
|
||||
|
||||
for (string = src_string; *string; string++) {
|
||||
*string = (char)tolower((int)*string);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_strupr (strupr)
|
||||
*
|
||||
* PARAMETERS: src_string - The source string to convert
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Convert a string to uppercase
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ut_strupr(char *src_string)
|
||||
{
|
||||
char *string;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
if (!src_string) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Walk entire string, uppercasing the letters */
|
||||
|
||||
for (string = src_string; *string; string++) {
|
||||
*string = (char)toupper((int)*string);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_stricmp (stricmp)
|
||||
*
|
||||
* PARAMETERS: string1 - first string to compare
|
||||
* string2 - second string to compare
|
||||
*
|
||||
* RETURN: int that signifies string relationship. Zero means strings
|
||||
* are equal.
|
||||
*
|
||||
* DESCRIPTION: Case-insensitive string compare. Implementation of the
|
||||
* non-ANSI stricmp function.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int acpi_ut_stricmp(char *string1, char *string2)
|
||||
{
|
||||
int c1;
|
||||
int c2;
|
||||
|
||||
do {
|
||||
c1 = tolower((int)*string1);
|
||||
c2 = tolower((int)*string2);
|
||||
|
||||
string1++;
|
||||
string2++;
|
||||
}
|
||||
while ((c1 == c2) && (c1));
|
||||
|
||||
return (c1 - c2);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_strtoul64
|
||||
*
|
||||
* PARAMETERS: string - Null terminated string
|
||||
* base - Radix of the string: 16 or ACPI_ANY_BASE;
|
||||
* ACPI_ANY_BASE means 'in behalf of to_integer'
|
||||
* ret_integer - Where the converted integer is returned
|
||||
*
|
||||
* RETURN: Status and Converted value
|
||||
*
|
||||
* DESCRIPTION: Convert a string into an unsigned value. Performs either a
|
||||
* 32-bit or 64-bit conversion, depending on the current mode
|
||||
* of the interpreter.
|
||||
*
|
||||
* NOTE: Does not support Octal strings, not needed.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
|
||||
{
|
||||
u32 this_digit = 0;
|
||||
u64 return_value = 0;
|
||||
u64 quotient;
|
||||
u64 dividend;
|
||||
u32 to_integer_op = (base == ACPI_ANY_BASE);
|
||||
u32 mode32 = (acpi_gbl_integer_byte_width == 4);
|
||||
u8 valid_digits = 0;
|
||||
u8 sign_of0x = 0;
|
||||
u8 term = 0;
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR(ut_stroul64, string);
|
||||
|
||||
switch (base) {
|
||||
case ACPI_ANY_BASE:
|
||||
case 16:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Invalid Base */
|
||||
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
if (!string) {
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Skip over any white space in the buffer */
|
||||
|
||||
while ((*string) && (isspace((int)*string) || *string == '\t')) {
|
||||
string++;
|
||||
}
|
||||
|
||||
if (to_integer_op) {
|
||||
/*
|
||||
* Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
|
||||
* We need to determine if it is decimal or hexadecimal.
|
||||
*/
|
||||
if ((*string == '0') && (tolower((int)*(string + 1)) == 'x')) {
|
||||
sign_of0x = 1;
|
||||
base = 16;
|
||||
|
||||
/* Skip over the leading '0x' */
|
||||
string += 2;
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any string left? Check that '0x' is not followed by white space. */
|
||||
|
||||
if (!(*string) || isspace((int)*string) || *string == '\t') {
|
||||
if (to_integer_op) {
|
||||
goto error_exit;
|
||||
} else {
|
||||
goto all_done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a 32-bit or 64-bit conversion, depending upon the current
|
||||
* execution mode of the interpreter
|
||||
*/
|
||||
dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
|
||||
|
||||
/* Main loop: convert the string to a 32- or 64-bit integer */
|
||||
|
||||
while (*string) {
|
||||
if (isdigit((int)*string)) {
|
||||
|
||||
/* Convert ASCII 0-9 to Decimal value */
|
||||
|
||||
this_digit = ((u8)*string) - '0';
|
||||
} else if (base == 10) {
|
||||
|
||||
/* Digit is out of range; possible in to_integer case only */
|
||||
|
||||
term = 1;
|
||||
} else {
|
||||
this_digit = (u8)toupper((int)*string);
|
||||
if (isxdigit((int)this_digit)) {
|
||||
|
||||
/* Convert ASCII Hex char to value */
|
||||
|
||||
this_digit = this_digit - 'A' + 10;
|
||||
} else {
|
||||
term = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (term) {
|
||||
if (to_integer_op) {
|
||||
goto error_exit;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if ((valid_digits == 0) && (this_digit == 0)
|
||||
&& !sign_of0x) {
|
||||
|
||||
/* Skip zeros */
|
||||
string++;
|
||||
continue;
|
||||
}
|
||||
|
||||
valid_digits++;
|
||||
|
||||
if (sign_of0x
|
||||
&& ((valid_digits > 16)
|
||||
|| ((valid_digits > 8) && mode32))) {
|
||||
/*
|
||||
* This is to_integer operation case.
|
||||
* No any restrictions for string-to-integer conversion,
|
||||
* see ACPI spec.
|
||||
*/
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Divide the digit into the correct position */
|
||||
|
||||
(void)acpi_ut_short_divide((dividend - (u64)this_digit),
|
||||
base, "ient, NULL);
|
||||
|
||||
if (return_value > quotient) {
|
||||
if (to_integer_op) {
|
||||
goto error_exit;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return_value *= base;
|
||||
return_value += this_digit;
|
||||
string++;
|
||||
}
|
||||
|
||||
/* All done, normal exit */
|
||||
|
||||
all_done:
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
|
||||
ACPI_FORMAT_UINT64(return_value)));
|
||||
|
||||
*ret_integer = return_value;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
error_exit:
|
||||
/* Base was set/validated above */
|
||||
|
||||
if (base == 10) {
|
||||
return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
|
||||
} else {
|
||||
return_ACPI_STATUS(AE_BAD_HEX_CONSTANT);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat
|
||||
*
|
||||
* PARAMETERS: Adds a "DestSize" parameter to each of the standard string
|
||||
* functions. This is the size of the Destination buffer.
|
||||
*
|
||||
* RETURN: TRUE if the operation would overflow the destination buffer.
|
||||
*
|
||||
* DESCRIPTION: Safe versions of standard Clib string functions. Ensure that
|
||||
* the result of the operation will not overflow the output string
|
||||
* buffer.
|
||||
*
|
||||
* NOTE: These functions are typically only helpful for processing
|
||||
* user input and command lines. For most ACPICA code, the
|
||||
* required buffer length is precisely calculated before buffer
|
||||
* allocation, so the use of these functions is unnecessary.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source)
|
||||
{
|
||||
|
||||
if (strlen(source) >= dest_size) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
strcpy(dest, source);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source)
|
||||
{
|
||||
|
||||
if ((strlen(dest) + strlen(source)) >= dest_size) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
strcat(dest, source);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
u8
|
||||
acpi_ut_safe_strncat(char *dest,
|
||||
acpi_size dest_size,
|
||||
char *source, acpi_size max_transfer_length)
|
||||
{
|
||||
acpi_size actual_transfer_length;
|
||||
|
||||
actual_transfer_length = ACPI_MIN(max_transfer_length, strlen(source));
|
||||
|
||||
if ((strlen(dest) + actual_transfer_length) >= dest_size) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
strncat(dest, source, max_transfer_length);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif
|
@ -48,286 +48,6 @@
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utstring")
|
||||
|
||||
/*
|
||||
* Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit
|
||||
* version of strtoul.
|
||||
*/
|
||||
#ifdef ACPI_ASL_COMPILER
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_strlwr (strlwr)
|
||||
*
|
||||
* PARAMETERS: src_string - The source string to convert
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Convert string to lowercase
|
||||
*
|
||||
* NOTE: This is not a POSIX function, so it appears here, not in utclib.c
|
||||
*
|
||||
******************************************************************************/
|
||||
void acpi_ut_strlwr(char *src_string)
|
||||
{
|
||||
char *string;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
if (!src_string) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Walk entire string, lowercasing the letters */
|
||||
|
||||
for (string = src_string; *string; string++) {
|
||||
*string = (char)tolower((int)*string);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_stricmp (stricmp)
|
||||
*
|
||||
* PARAMETERS: string1 - first string to compare
|
||||
* string2 - second string to compare
|
||||
*
|
||||
* RETURN: int that signifies string relationship. Zero means strings
|
||||
* are equal.
|
||||
*
|
||||
* DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
|
||||
* strings with no case sensitivity)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int acpi_ut_stricmp(char *string1, char *string2)
|
||||
{
|
||||
int c1;
|
||||
int c2;
|
||||
|
||||
do {
|
||||
c1 = tolower((int)*string1);
|
||||
c2 = tolower((int)*string2);
|
||||
|
||||
string1++;
|
||||
string2++;
|
||||
}
|
||||
while ((c1 == c2) && (c1));
|
||||
|
||||
return (c1 - c2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_strupr (strupr)
|
||||
*
|
||||
* PARAMETERS: src_string - The source string to convert
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Convert string to uppercase
|
||||
*
|
||||
* NOTE: This is not a POSIX function, so it appears here, not in utclib.c
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ut_strupr(char *src_string)
|
||||
{
|
||||
char *string;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
if (!src_string) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Walk entire string, uppercasing the letters */
|
||||
|
||||
for (string = src_string; *string; string++) {
|
||||
*string = (char)toupper((int)*string);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_strtoul64
|
||||
*
|
||||
* PARAMETERS: string - Null terminated string
|
||||
* base - Radix of the string: 16 or ACPI_ANY_BASE;
|
||||
* ACPI_ANY_BASE means 'in behalf of to_integer'
|
||||
* ret_integer - Where the converted integer is returned
|
||||
*
|
||||
* RETURN: Status and Converted value
|
||||
*
|
||||
* DESCRIPTION: Convert a string into an unsigned value. Performs either a
|
||||
* 32-bit or 64-bit conversion, depending on the current mode
|
||||
* of the interpreter.
|
||||
* NOTE: Does not support Octal strings, not needed.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
|
||||
{
|
||||
u32 this_digit = 0;
|
||||
u64 return_value = 0;
|
||||
u64 quotient;
|
||||
u64 dividend;
|
||||
u32 to_integer_op = (base == ACPI_ANY_BASE);
|
||||
u32 mode32 = (acpi_gbl_integer_byte_width == 4);
|
||||
u8 valid_digits = 0;
|
||||
u8 sign_of0x = 0;
|
||||
u8 term = 0;
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR(ut_stroul64, string);
|
||||
|
||||
switch (base) {
|
||||
case ACPI_ANY_BASE:
|
||||
case 16:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Invalid Base */
|
||||
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
if (!string) {
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Skip over any white space in the buffer */
|
||||
|
||||
while ((*string) && (isspace((int)*string) || *string == '\t')) {
|
||||
string++;
|
||||
}
|
||||
|
||||
if (to_integer_op) {
|
||||
/*
|
||||
* Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
|
||||
* We need to determine if it is decimal or hexadecimal.
|
||||
*/
|
||||
if ((*string == '0') && (tolower((int)*(string + 1)) == 'x')) {
|
||||
sign_of0x = 1;
|
||||
base = 16;
|
||||
|
||||
/* Skip over the leading '0x' */
|
||||
string += 2;
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any string left? Check that '0x' is not followed by white space. */
|
||||
|
||||
if (!(*string) || isspace((int)*string) || *string == '\t') {
|
||||
if (to_integer_op) {
|
||||
goto error_exit;
|
||||
} else {
|
||||
goto all_done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a 32-bit or 64-bit conversion, depending upon the current
|
||||
* execution mode of the interpreter
|
||||
*/
|
||||
dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
|
||||
|
||||
/* Main loop: convert the string to a 32- or 64-bit integer */
|
||||
|
||||
while (*string) {
|
||||
if (isdigit((int)*string)) {
|
||||
|
||||
/* Convert ASCII 0-9 to Decimal value */
|
||||
|
||||
this_digit = ((u8)*string) - '0';
|
||||
} else if (base == 10) {
|
||||
|
||||
/* Digit is out of range; possible in to_integer case only */
|
||||
|
||||
term = 1;
|
||||
} else {
|
||||
this_digit = (u8)toupper((int)*string);
|
||||
if (isxdigit((int)this_digit)) {
|
||||
|
||||
/* Convert ASCII Hex char to value */
|
||||
|
||||
this_digit = this_digit - 'A' + 10;
|
||||
} else {
|
||||
term = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (term) {
|
||||
if (to_integer_op) {
|
||||
goto error_exit;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if ((valid_digits == 0) && (this_digit == 0)
|
||||
&& !sign_of0x) {
|
||||
|
||||
/* Skip zeros */
|
||||
string++;
|
||||
continue;
|
||||
}
|
||||
|
||||
valid_digits++;
|
||||
|
||||
if (sign_of0x
|
||||
&& ((valid_digits > 16)
|
||||
|| ((valid_digits > 8) && mode32))) {
|
||||
/*
|
||||
* This is to_integer operation case.
|
||||
* No any restrictions for string-to-integer conversion,
|
||||
* see ACPI spec.
|
||||
*/
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* Divide the digit into the correct position */
|
||||
|
||||
(void)acpi_ut_short_divide((dividend - (u64)this_digit),
|
||||
base, "ient, NULL);
|
||||
|
||||
if (return_value > quotient) {
|
||||
if (to_integer_op) {
|
||||
goto error_exit;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return_value *= base;
|
||||
return_value += this_digit;
|
||||
string++;
|
||||
}
|
||||
|
||||
/* All done, normal exit */
|
||||
|
||||
all_done:
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
|
||||
ACPI_FORMAT_UINT64(return_value)));
|
||||
|
||||
*ret_integer = return_value;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
error_exit:
|
||||
/* Base was set/validated above */
|
||||
|
||||
if (base == 10) {
|
||||
return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
|
||||
} else {
|
||||
return_ACPI_STATUS(AE_BAD_HEX_CONSTANT);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_print_string
|
||||
@ -342,7 +62,6 @@ error_exit:
|
||||
* sequences.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ut_print_string(char *string, u16 max_length)
|
||||
{
|
||||
u32 i;
|
||||
@ -584,64 +303,3 @@ void ut_convert_backslashes(char *pathname)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat
|
||||
*
|
||||
* PARAMETERS: Adds a "DestSize" parameter to each of the standard string
|
||||
* functions. This is the size of the Destination buffer.
|
||||
*
|
||||
* RETURN: TRUE if the operation would overflow the destination buffer.
|
||||
*
|
||||
* DESCRIPTION: Safe versions of standard Clib string functions. Ensure that
|
||||
* the result of the operation will not overflow the output string
|
||||
* buffer.
|
||||
*
|
||||
* NOTE: These functions are typically only helpful for processing
|
||||
* user input and command lines. For most ACPICA code, the
|
||||
* required buffer length is precisely calculated before buffer
|
||||
* allocation, so the use of these functions is unnecessary.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source)
|
||||
{
|
||||
|
||||
if (strlen(source) >= dest_size) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
strcpy(dest, source);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source)
|
||||
{
|
||||
|
||||
if ((strlen(dest) + strlen(source)) >= dest_size) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
strcat(dest, source);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
u8
|
||||
acpi_ut_safe_strncat(char *dest,
|
||||
acpi_size dest_size,
|
||||
char *source, acpi_size max_transfer_length)
|
||||
{
|
||||
acpi_size actual_transfer_length;
|
||||
|
||||
actual_transfer_length = ACPI_MIN(max_transfer_length, strlen(source));
|
||||
|
||||
if ((strlen(dest) + actual_transfer_length) >= dest_size) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
strncat(dest, source, max_transfer_length);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif
|
||||
|
@ -92,13 +92,6 @@ acpi_status __init acpi_terminate(void)
|
||||
|
||||
acpi_ut_mutex_terminate();
|
||||
|
||||
#ifdef ACPI_DEBUGGER
|
||||
|
||||
/* Shut down the debugger */
|
||||
|
||||
acpi_db_terminate();
|
||||
#endif
|
||||
|
||||
/* Now we can shutdown the OS-dependent layer */
|
||||
|
||||
status = acpi_os_terminate();
|
||||
@ -517,7 +510,8 @@ acpi_decode_pld_buffer(u8 *in_buffer,
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!in_buffer || !return_buffer || (length < 16)) {
|
||||
if (!in_buffer || !return_buffer
|
||||
|| (length < ACPI_PLD_REV1_BUFFER_SIZE)) {
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
@ -567,7 +561,7 @@ acpi_decode_pld_buffer(u8 *in_buffer,
|
||||
pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword);
|
||||
pld_info->order = ACPI_PLD_GET_ORDER(&dword);
|
||||
|
||||
if (length >= ACPI_PLD_BUFFER_SIZE) {
|
||||
if (length >= ACPI_PLD_REV2_BUFFER_SIZE) {
|
||||
|
||||
/* Fifth 32-bit DWord (Revision 2 of _PLD) */
|
||||
|
||||
|
@ -124,17 +124,6 @@ acpi_status __init acpi_initialize_subsystem(void)
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* If configured, initialize the AML debugger */
|
||||
|
||||
#ifdef ACPI_DEBUGGER
|
||||
status = acpi_db_initialize();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"During Debugger initialization"));
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
#endif
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -18,10 +18,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -17,10 +17,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -18,10 +18,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -23,10 +23,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -21,10 +21,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -18,10 +18,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -20,10 +20,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -15,10 +15,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@ -423,6 +419,406 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
|
||||
acpi_evaluate_ost(handle, type, ost_code, NULL);
|
||||
}
|
||||
|
||||
static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_device *device = data;
|
||||
|
||||
device->driver->ops.notify(device, event);
|
||||
}
|
||||
|
||||
static void acpi_device_notify_fixed(void *data)
|
||||
{
|
||||
struct acpi_device *device = data;
|
||||
|
||||
/* Fixed hardware devices have no handles */
|
||||
acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
|
||||
}
|
||||
|
||||
static u32 acpi_device_fixed_event(void *data)
|
||||
{
|
||||
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
|
||||
return ACPI_INTERRUPT_HANDLED;
|
||||
}
|
||||
|
||||
static int acpi_device_install_notify_handler(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_device_fixed_event,
|
||||
device);
|
||||
else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_device_fixed_event,
|
||||
device);
|
||||
else
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_device_notify,
|
||||
device);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_device_remove_notify_handler(struct acpi_device *device)
|
||||
{
|
||||
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_device_fixed_event);
|
||||
else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_device_fixed_event);
|
||||
else
|
||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_device_notify);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Device Matching
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
|
||||
const struct device *dev)
|
||||
{
|
||||
struct mutex *physical_node_lock = &adev->physical_node_lock;
|
||||
|
||||
mutex_lock(physical_node_lock);
|
||||
if (list_empty(&adev->physical_node_list)) {
|
||||
adev = NULL;
|
||||
} else {
|
||||
const struct acpi_device_physical_node *node;
|
||||
|
||||
node = list_first_entry(&adev->physical_node_list,
|
||||
struct acpi_device_physical_node, node);
|
||||
if (node->dev != dev)
|
||||
adev = NULL;
|
||||
}
|
||||
mutex_unlock(physical_node_lock);
|
||||
return adev;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_device_is_first_physical_node - Is given dev first physical node
|
||||
* @adev: ACPI companion device
|
||||
* @dev: Physical device to check
|
||||
*
|
||||
* Function checks if given @dev is the first physical devices attached to
|
||||
* the ACPI companion device. This distinction is needed in some cases
|
||||
* where the same companion device is shared between many physical devices.
|
||||
*
|
||||
* Note that the caller have to provide valid @adev pointer.
|
||||
*/
|
||||
bool acpi_device_is_first_physical_node(struct acpi_device *adev,
|
||||
const struct device *dev)
|
||||
{
|
||||
return !!acpi_primary_dev_companion(adev, dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* acpi_companion_match() - Can we match via ACPI companion device
|
||||
* @dev: Device in question
|
||||
*
|
||||
* Check if the given device has an ACPI companion and if that companion has
|
||||
* a valid list of PNP IDs, and if the device is the first (primary) physical
|
||||
* device associated with it. Return the companion pointer if that's the case
|
||||
* or NULL otherwise.
|
||||
*
|
||||
* If multiple physical devices are attached to a single ACPI companion, we need
|
||||
* to be careful. The usage scenario for this kind of relationship is that all
|
||||
* of the physical devices in question use resources provided by the ACPI
|
||||
* companion. A typical case is an MFD device where all the sub-devices share
|
||||
* the parent's ACPI companion. In such cases we can only allow the primary
|
||||
* (first) physical device to be matched with the help of the companion's PNP
|
||||
* IDs.
|
||||
*
|
||||
* Additional physical devices sharing the ACPI companion can still use
|
||||
* resources available from it but they will be matched normally using functions
|
||||
* provided by their bus types (and analogously for their modalias).
|
||||
*/
|
||||
struct acpi_device *acpi_companion_match(const struct device *dev)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev)
|
||||
return NULL;
|
||||
|
||||
if (list_empty(&adev->pnp.ids))
|
||||
return NULL;
|
||||
|
||||
return acpi_primary_dev_companion(adev, dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_of_match_device - Match device object using the "compatible" property.
|
||||
* @adev: ACPI device object to match.
|
||||
* @of_match_table: List of device IDs to match against.
|
||||
*
|
||||
* If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
|
||||
* identifiers and a _DSD object with the "compatible" property, use that
|
||||
* property to match against the given list of identifiers.
|
||||
*/
|
||||
static bool acpi_of_match_device(struct acpi_device *adev,
|
||||
const struct of_device_id *of_match_table)
|
||||
{
|
||||
const union acpi_object *of_compatible, *obj;
|
||||
int i, nval;
|
||||
|
||||
if (!adev)
|
||||
return false;
|
||||
|
||||
of_compatible = adev->data.of_compatible;
|
||||
if (!of_match_table || !of_compatible)
|
||||
return false;
|
||||
|
||||
if (of_compatible->type == ACPI_TYPE_PACKAGE) {
|
||||
nval = of_compatible->package.count;
|
||||
obj = of_compatible->package.elements;
|
||||
} else { /* Must be ACPI_TYPE_STRING. */
|
||||
nval = 1;
|
||||
obj = of_compatible;
|
||||
}
|
||||
/* Now we can look for the driver DT compatible strings */
|
||||
for (i = 0; i < nval; i++, obj++) {
|
||||
const struct of_device_id *id;
|
||||
|
||||
for (id = of_match_table; id->compatible[0]; id++)
|
||||
if (!strcasecmp(obj->string.pointer, id->compatible))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool __acpi_match_device_cls(const struct acpi_device_id *id,
|
||||
struct acpi_hardware_id *hwid)
|
||||
{
|
||||
int i, msk, byte_shift;
|
||||
char buf[3];
|
||||
|
||||
if (!id->cls)
|
||||
return false;
|
||||
|
||||
/* Apply class-code bitmask, before checking each class-code byte */
|
||||
for (i = 1; i <= 3; i++) {
|
||||
byte_shift = 8 * (3 - i);
|
||||
msk = (id->cls_msk >> byte_shift) & 0xFF;
|
||||
if (!msk)
|
||||
continue;
|
||||
|
||||
sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);
|
||||
if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id *__acpi_match_device(
|
||||
struct acpi_device *device,
|
||||
const struct acpi_device_id *ids,
|
||||
const struct of_device_id *of_ids)
|
||||
{
|
||||
const struct acpi_device_id *id;
|
||||
struct acpi_hardware_id *hwid;
|
||||
|
||||
/*
|
||||
* If the device is not present, it is unnecessary to load device
|
||||
* driver for it.
|
||||
*/
|
||||
if (!device || !device->status.present)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(hwid, &device->pnp.ids, list) {
|
||||
/* First, check the ACPI/PNP IDs provided by the caller. */
|
||||
for (id = ids; id->id[0] || id->cls; id++) {
|
||||
if (id->id[0] && !strcmp((char *) id->id, hwid->id))
|
||||
return id;
|
||||
else if (id->cls && __acpi_match_device_cls(id, hwid))
|
||||
return id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, check ACPI_DT_NAMESPACE_HID and try to match the
|
||||
* "compatible" property if found.
|
||||
*
|
||||
* The id returned by the below is not valid, but the only
|
||||
* caller passing non-NULL of_ids here is only interested in
|
||||
* whether or not the return value is NULL.
|
||||
*/
|
||||
if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
|
||||
&& acpi_of_match_device(device, of_ids))
|
||||
return id;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_match_device - Match a struct device against a given list of ACPI IDs
|
||||
* @ids: Array of struct acpi_device_id object to match against.
|
||||
* @dev: The device structure to match.
|
||||
*
|
||||
* Check if @dev has a valid ACPI handle and if there is a struct acpi_device
|
||||
* object for that handle and use that object to match against a given list of
|
||||
* device IDs.
|
||||
*
|
||||
* Return a pointer to the first matching ID on success or %NULL on failure.
|
||||
*/
|
||||
const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
|
||||
const struct device *dev)
|
||||
{
|
||||
return __acpi_match_device(acpi_companion_match(dev), ids, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_match_device);
|
||||
|
||||
int acpi_match_device_ids(struct acpi_device *device,
|
||||
const struct acpi_device_id *ids)
|
||||
{
|
||||
return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_match_device_ids);
|
||||
|
||||
bool acpi_driver_match_device(struct device *dev,
|
||||
const struct device_driver *drv)
|
||||
{
|
||||
if (!drv->acpi_match_table)
|
||||
return acpi_of_match_device(ACPI_COMPANION(dev),
|
||||
drv->of_match_table);
|
||||
|
||||
return !!__acpi_match_device(acpi_companion_match(dev),
|
||||
drv->acpi_match_table, drv->of_match_table);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_driver_match_device);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
ACPI Driver Management
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* acpi_bus_register_driver - register a driver with the ACPI bus
|
||||
* @driver: driver being registered
|
||||
*
|
||||
* Registers a driver with the ACPI bus. Searches the namespace for all
|
||||
* devices that match the driver's criteria and binds. Returns zero for
|
||||
* success or a negative error status for failure.
|
||||
*/
|
||||
int acpi_bus_register_driver(struct acpi_driver *driver)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
driver->drv.name = driver->name;
|
||||
driver->drv.bus = &acpi_bus_type;
|
||||
driver->drv.owner = driver->owner;
|
||||
|
||||
ret = driver_register(&driver->drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(acpi_bus_register_driver);
|
||||
|
||||
/**
|
||||
* acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
|
||||
* @driver: driver to unregister
|
||||
*
|
||||
* Unregisters a driver with the ACPI bus. Searches the namespace for all
|
||||
* devices that match the driver's criteria and unbinds.
|
||||
*/
|
||||
void acpi_bus_unregister_driver(struct acpi_driver *driver)
|
||||
{
|
||||
driver_unregister(&driver->drv);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(acpi_bus_unregister_driver);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
ACPI Bus operations
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static int acpi_bus_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
struct acpi_driver *acpi_drv = to_acpi_driver(drv);
|
||||
|
||||
return acpi_dev->flags.match_driver
|
||||
&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
|
||||
}
|
||||
|
||||
static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
return __acpi_device_uevent_modalias(to_acpi_device(dev), env);
|
||||
}
|
||||
|
||||
static int acpi_device_probe(struct device *dev)
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
|
||||
int ret;
|
||||
|
||||
if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!acpi_drv->ops.add)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = acpi_drv->ops.add(acpi_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
acpi_dev->driver = acpi_drv;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Driver [%s] successfully bound to device [%s]\n",
|
||||
acpi_drv->name, acpi_dev->pnp.bus_id));
|
||||
|
||||
if (acpi_drv->ops.notify) {
|
||||
ret = acpi_device_install_notify_handler(acpi_dev);
|
||||
if (ret) {
|
||||
if (acpi_drv->ops.remove)
|
||||
acpi_drv->ops.remove(acpi_dev);
|
||||
|
||||
acpi_dev->driver = NULL;
|
||||
acpi_dev->driver_data = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
|
||||
acpi_drv->name, acpi_dev->pnp.bus_id));
|
||||
get_device(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_device_remove(struct device * dev)
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
struct acpi_driver *acpi_drv = acpi_dev->driver;
|
||||
|
||||
if (acpi_drv) {
|
||||
if (acpi_drv->ops.notify)
|
||||
acpi_device_remove_notify_handler(acpi_dev);
|
||||
if (acpi_drv->ops.remove)
|
||||
acpi_drv->ops.remove(acpi_dev);
|
||||
}
|
||||
acpi_dev->driver = NULL;
|
||||
acpi_dev->driver_data = NULL;
|
||||
|
||||
put_device(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bus_type acpi_bus_type = {
|
||||
.name = "acpi",
|
||||
.match = acpi_bus_match,
|
||||
.probe = acpi_device_probe,
|
||||
.remove = acpi_device_remove,
|
||||
.uevent = acpi_device_uevent,
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Initialization/Cleanup
|
||||
-------------------------------------------------------------------------- */
|
||||
@ -661,7 +1057,9 @@ static int __init acpi_bus_init(void)
|
||||
*/
|
||||
acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
|
||||
|
||||
return 0;
|
||||
result = bus_register(&acpi_bus_type);
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
/* Mimic structured exception handling */
|
||||
error1:
|
||||
|
@ -16,10 +16,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -11,10 +11,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -20,10 +20,6 @@
|
||||
* 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 <linux/acpi.h>
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define _COMPONENT ACPI_SYSTEM_COMPONENT
|
||||
ACPI_MODULE_NAME("debugfs");
|
||||
|
||||
|
@ -15,10 +15,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@ -1123,6 +1119,14 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
|
||||
if (dev->pm_domain)
|
||||
return -EEXIST;
|
||||
|
||||
/*
|
||||
* Only attach the power domain to the first device if the
|
||||
* companion is shared by multiple. This is to prevent doing power
|
||||
* management twice.
|
||||
*/
|
||||
if (!acpi_device_is_first_physical_node(adev, dev))
|
||||
return -EBUSY;
|
||||
|
||||
acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
|
||||
dev->pm_domain = &acpi_general_pm_domain;
|
||||
if (power_on) {
|
||||
|
521
drivers/acpi/device_sysfs.c
Normal file
521
drivers/acpi/device_sysfs.c
Normal file
@ -0,0 +1,521 @@
|
||||
/*
|
||||
* drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.
|
||||
*
|
||||
* Copyright (C) 2015, Intel Corp.
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/nls.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
/**
|
||||
* create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
|
||||
* @acpi_dev: ACPI device object.
|
||||
* @modalias: Buffer to print into.
|
||||
* @size: Size of the buffer.
|
||||
*
|
||||
* Creates hid/cid(s) string needed for modalias and uevent
|
||||
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
|
||||
* char *modalias: "acpi:IBM0001:ACPI0001"
|
||||
* Return: 0: no _HID and no _CID
|
||||
* -EINVAL: output error
|
||||
* -ENOMEM: output is truncated
|
||||
*/
|
||||
static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
int size)
|
||||
{
|
||||
int len;
|
||||
int count;
|
||||
struct acpi_hardware_id *id;
|
||||
|
||||
/*
|
||||
* Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
|
||||
* be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
|
||||
* device's list.
|
||||
*/
|
||||
count = 0;
|
||||
list_for_each_entry(id, &acpi_dev->pnp.ids, list)
|
||||
if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
|
||||
count++;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
len = snprintf(modalias, size, "acpi:");
|
||||
if (len <= 0)
|
||||
return len;
|
||||
|
||||
size -= len;
|
||||
|
||||
list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
|
||||
if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
|
||||
continue;
|
||||
|
||||
count = snprintf(&modalias[len], size, "%s:", id->id);
|
||||
if (count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (count >= size)
|
||||
return -ENOMEM;
|
||||
|
||||
len += count;
|
||||
size -= count;
|
||||
}
|
||||
modalias[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* create_of_modalias - Creates DT compatible string for modalias and uevent
|
||||
* @acpi_dev: ACPI device object.
|
||||
* @modalias: Buffer to print into.
|
||||
* @size: Size of the buffer.
|
||||
*
|
||||
* Expose DT compatible modalias as of:NnameTCcompatible. This function should
|
||||
* only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
|
||||
* ACPI/PNP IDs.
|
||||
*/
|
||||
static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
int size)
|
||||
{
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
|
||||
const union acpi_object *of_compatible, *obj;
|
||||
int len, count;
|
||||
int i, nval;
|
||||
char *c;
|
||||
|
||||
acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
|
||||
/* DT strings are all in lower case */
|
||||
for (c = buf.pointer; *c != '\0'; c++)
|
||||
*c = tolower(*c);
|
||||
|
||||
len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
|
||||
ACPI_FREE(buf.pointer);
|
||||
|
||||
if (len <= 0)
|
||||
return len;
|
||||
|
||||
of_compatible = acpi_dev->data.of_compatible;
|
||||
if (of_compatible->type == ACPI_TYPE_PACKAGE) {
|
||||
nval = of_compatible->package.count;
|
||||
obj = of_compatible->package.elements;
|
||||
} else { /* Must be ACPI_TYPE_STRING. */
|
||||
nval = 1;
|
||||
obj = of_compatible;
|
||||
}
|
||||
for (i = 0; i < nval; i++, obj++) {
|
||||
count = snprintf(&modalias[len], size, "C%s",
|
||||
obj->string.pointer);
|
||||
if (count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (count >= size)
|
||||
return -ENOMEM;
|
||||
|
||||
len += count;
|
||||
size -= count;
|
||||
}
|
||||
modalias[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
int __acpi_device_uevent_modalias(struct acpi_device *adev,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
if (list_empty(&adev->pnp.ids))
|
||||
return 0;
|
||||
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
|
||||
len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
|
||||
sizeof(env->buf) - env->buflen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
env->buflen += len;
|
||||
if (!adev->data.of_compatible)
|
||||
return 0;
|
||||
|
||||
if (len > 0 && add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
|
||||
len = create_of_modalias(adev, &env->buf[env->buflen - 1],
|
||||
sizeof(env->buf) - env->buflen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
env->buflen += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.
|
||||
*
|
||||
* Create the uevent modalias field for ACPI-enumerated devices.
|
||||
*
|
||||
* Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
|
||||
* hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
|
||||
*/
|
||||
int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
|
||||
|
||||
static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
|
||||
{
|
||||
int len, count;
|
||||
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
if (list_empty(&adev->pnp.ids))
|
||||
return 0;
|
||||
|
||||
len = create_pnp_modalias(adev, buf, size - 1);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
} else if (len > 0) {
|
||||
buf[len++] = '\n';
|
||||
size -= len;
|
||||
}
|
||||
if (!adev->data.of_compatible)
|
||||
return len;
|
||||
|
||||
count = create_of_modalias(adev, buf + len, size - 1);
|
||||
if (count < 0) {
|
||||
return count;
|
||||
} else if (count > 0) {
|
||||
len += count;
|
||||
buf[len++] = '\n';
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.
|
||||
*
|
||||
* Create the modalias sysfs attribute for ACPI-enumerated devices.
|
||||
*
|
||||
* Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
|
||||
* hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
|
||||
*/
|
||||
int acpi_device_modalias(struct device *dev, char *buf, int size)
|
||||
{
|
||||
return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_device_modalias);
|
||||
|
||||
static ssize_t
|
||||
acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
||||
return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
|
||||
}
|
||||
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
|
||||
|
||||
static ssize_t real_power_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_device *adev = to_acpi_device(dev);
|
||||
int state;
|
||||
int ret;
|
||||
|
||||
ret = acpi_device_get_power(adev, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%s\n", acpi_power_state_string(state));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);
|
||||
|
||||
static ssize_t power_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_device *adev = to_acpi_device(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct acpi_device *acpi_device = to_acpi_device(d);
|
||||
acpi_object_type not_used;
|
||||
acpi_status status;
|
||||
|
||||
if (!count || buf[0] != '1')
|
||||
return -EINVAL;
|
||||
|
||||
if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
|
||||
&& !acpi_device->driver)
|
||||
return -ENODEV;
|
||||
|
||||
status = acpi_get_type(acpi_device->handle, ¬_used);
|
||||
if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
|
||||
return -ENODEV;
|
||||
|
||||
get_device(&acpi_device->dev);
|
||||
status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
|
||||
if (ACPI_SUCCESS(status))
|
||||
return count;
|
||||
|
||||
put_device(&acpi_device->dev);
|
||||
acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
|
||||
ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
|
||||
return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
|
||||
|
||||
static ssize_t
|
||||
acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
|
||||
}
|
||||
static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
|
||||
|
||||
static ssize_t acpi_device_uid_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
|
||||
}
|
||||
static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
|
||||
|
||||
static ssize_t acpi_device_adr_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
|
||||
return sprintf(buf, "0x%08x\n",
|
||||
(unsigned int)(acpi_dev->pnp.bus_address));
|
||||
}
|
||||
static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
int result;
|
||||
|
||||
result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
result = sprintf(buf, "%s\n", (char*)path.pointer);
|
||||
kfree(path.pointer);
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
|
||||
|
||||
/* sysfs file that shows description text from the ACPI _STR method */
|
||||
static ssize_t description_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf) {
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
int result;
|
||||
|
||||
if (acpi_dev->pnp.str_obj == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The _STR object contains a Unicode identifier for a device.
|
||||
* We need to convert to utf-8 so it can be displayed.
|
||||
*/
|
||||
result = utf16s_to_utf8s(
|
||||
(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
|
||||
acpi_dev->pnp.str_obj->buffer.length,
|
||||
UTF16_LITTLE_ENDIAN, buf,
|
||||
PAGE_SIZE);
|
||||
|
||||
buf[result++] = '\n';
|
||||
|
||||
return result;
|
||||
}
|
||||
static DEVICE_ATTR(description, 0444, description_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf) {
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
acpi_status status;
|
||||
unsigned long long sun;
|
||||
|
||||
status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
return sprintf(buf, "%llu\n", sun);
|
||||
}
|
||||
static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
|
||||
|
||||
static ssize_t status_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf) {
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
acpi_status status;
|
||||
unsigned long long sta;
|
||||
|
||||
status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
return sprintf(buf, "%llu\n", sta);
|
||||
}
|
||||
static DEVICE_ATTR_RO(status);
|
||||
|
||||
/**
|
||||
* acpi_device_setup_files - Create sysfs attributes of an ACPI device.
|
||||
* @dev: ACPI device object.
|
||||
*/
|
||||
int acpi_device_setup_files(struct acpi_device *dev)
|
||||
{
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_status status;
|
||||
int result = 0;
|
||||
|
||||
/*
|
||||
* Devices gotten from FADT don't have a "path" attribute
|
||||
*/
|
||||
if (dev->handle) {
|
||||
result = device_create_file(&dev->dev, &dev_attr_path);
|
||||
if (result)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!list_empty(&dev->pnp.ids)) {
|
||||
result = device_create_file(&dev->dev, &dev_attr_hid);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
result = device_create_file(&dev->dev, &dev_attr_modalias);
|
||||
if (result)
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* If device has _STR, 'description' file is created
|
||||
*/
|
||||
if (acpi_has_method(dev->handle, "_STR")) {
|
||||
status = acpi_evaluate_object(dev->handle, "_STR",
|
||||
NULL, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
buffer.pointer = NULL;
|
||||
dev->pnp.str_obj = buffer.pointer;
|
||||
result = device_create_file(&dev->dev, &dev_attr_description);
|
||||
if (result)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (dev->pnp.type.bus_address)
|
||||
result = device_create_file(&dev->dev, &dev_attr_adr);
|
||||
if (dev->pnp.unique_id)
|
||||
result = device_create_file(&dev->dev, &dev_attr_uid);
|
||||
|
||||
if (acpi_has_method(dev->handle, "_SUN")) {
|
||||
result = device_create_file(&dev->dev, &dev_attr_sun);
|
||||
if (result)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (acpi_has_method(dev->handle, "_STA")) {
|
||||
result = device_create_file(&dev->dev, &dev_attr_status);
|
||||
if (result)
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* If device has _EJ0, 'eject' file is created that is used to trigger
|
||||
* hot-removal function from userland.
|
||||
*/
|
||||
if (acpi_has_method(dev->handle, "_EJ0")) {
|
||||
result = device_create_file(&dev->dev, &dev_attr_eject);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (dev->flags.power_manageable) {
|
||||
result = device_create_file(&dev->dev, &dev_attr_power_state);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (dev->power.flags.power_resources)
|
||||
result = device_create_file(&dev->dev,
|
||||
&dev_attr_real_power_state);
|
||||
}
|
||||
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_device_remove_files - Remove sysfs attributes of an ACPI device.
|
||||
* @dev: ACPI device object.
|
||||
*/
|
||||
void acpi_device_remove_files(struct acpi_device *dev)
|
||||
{
|
||||
if (dev->flags.power_manageable) {
|
||||
device_remove_file(&dev->dev, &dev_attr_power_state);
|
||||
if (dev->power.flags.power_resources)
|
||||
device_remove_file(&dev->dev,
|
||||
&dev_attr_real_power_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* If device has _STR, remove 'description' file
|
||||
*/
|
||||
if (acpi_has_method(dev->handle, "_STR")) {
|
||||
kfree(dev->pnp.str_obj);
|
||||
device_remove_file(&dev->dev, &dev_attr_description);
|
||||
}
|
||||
/*
|
||||
* If device has _EJ0, remove 'eject' file.
|
||||
*/
|
||||
if (acpi_has_method(dev->handle, "_EJ0"))
|
||||
device_remove_file(&dev->dev, &dev_attr_eject);
|
||||
|
||||
if (acpi_has_method(dev->handle, "_SUN"))
|
||||
device_remove_file(&dev->dev, &dev_attr_sun);
|
||||
|
||||
if (dev->pnp.unique_id)
|
||||
device_remove_file(&dev->dev, &dev_attr_uid);
|
||||
if (dev->pnp.type.bus_address)
|
||||
device_remove_file(&dev->dev, &dev_attr_adr);
|
||||
device_remove_file(&dev->dev, &dev_attr_modalias);
|
||||
device_remove_file(&dev->dev, &dev_attr_hid);
|
||||
if (acpi_has_method(dev->handle, "_STA"))
|
||||
device_remove_file(&dev->dev, &dev_attr_status);
|
||||
if (dev->handle)
|
||||
device_remove_file(&dev->dev, &dev_attr_path);
|
||||
}
|
@ -17,10 +17,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -22,10 +22,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@ -165,8 +161,16 @@ struct transaction {
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
struct acpi_ec_query {
|
||||
struct transaction transaction;
|
||||
struct work_struct work;
|
||||
struct acpi_ec_query_handler *handler;
|
||||
};
|
||||
|
||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
|
||||
static void advance_transaction(struct acpi_ec *ec);
|
||||
static void acpi_ec_event_handler(struct work_struct *work);
|
||||
static void acpi_ec_event_processor(struct work_struct *work);
|
||||
|
||||
struct acpi_ec *boot_ec, *first_ec;
|
||||
EXPORT_SYMBOL(first_ec);
|
||||
@ -978,60 +982,90 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
||||
|
||||
static void acpi_ec_run(void *cxt)
|
||||
static struct acpi_ec_query *acpi_ec_create_query(u8 *pval)
|
||||
{
|
||||
struct acpi_ec_query_handler *handler = cxt;
|
||||
struct acpi_ec_query *q;
|
||||
struct transaction *t;
|
||||
|
||||
q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL);
|
||||
if (!q)
|
||||
return NULL;
|
||||
INIT_WORK(&q->work, acpi_ec_event_processor);
|
||||
t = &q->transaction;
|
||||
t->command = ACPI_EC_COMMAND_QUERY;
|
||||
t->rdata = pval;
|
||||
t->rlen = 1;
|
||||
return q;
|
||||
}
|
||||
|
||||
static void acpi_ec_delete_query(struct acpi_ec_query *q)
|
||||
{
|
||||
if (q) {
|
||||
if (q->handler)
|
||||
acpi_ec_put_query_handler(q->handler);
|
||||
kfree(q);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_ec_event_processor(struct work_struct *work)
|
||||
{
|
||||
struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work);
|
||||
struct acpi_ec_query_handler *handler = q->handler;
|
||||
|
||||
if (!handler)
|
||||
return;
|
||||
ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
|
||||
if (handler->func)
|
||||
handler->func(handler->data);
|
||||
else if (handler->handle)
|
||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
|
||||
acpi_ec_put_query_handler(handler);
|
||||
acpi_ec_delete_query(q);
|
||||
}
|
||||
|
||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
||||
{
|
||||
u8 value = 0;
|
||||
int result;
|
||||
acpi_status status;
|
||||
struct acpi_ec_query_handler *handler;
|
||||
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
||||
.wdata = NULL, .rdata = &value,
|
||||
.wlen = 0, .rlen = 1};
|
||||
struct acpi_ec_query *q;
|
||||
|
||||
q = acpi_ec_create_query(&value);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Query the EC to find out which _Qxx method we need to evaluate.
|
||||
* Note that successful completion of the query causes the ACPI_EC_SCI
|
||||
* bit to be cleared (and thus clearing the interrupt source).
|
||||
*/
|
||||
result = acpi_ec_transaction(ec, &t);
|
||||
if (result)
|
||||
return result;
|
||||
if (data)
|
||||
*data = value;
|
||||
result = acpi_ec_transaction(ec, &q->transaction);
|
||||
if (!value)
|
||||
return -ENODATA;
|
||||
result = -ENODATA;
|
||||
if (result)
|
||||
goto err_exit;
|
||||
|
||||
mutex_lock(&ec->mutex);
|
||||
list_for_each_entry(handler, &ec->list, node) {
|
||||
if (value == handler->query_bit) {
|
||||
/* have custom handler for this bit */
|
||||
handler = acpi_ec_get_query_handler(handler);
|
||||
q->handler = acpi_ec_get_query_handler(handler);
|
||||
ec_dbg_evt("Query(0x%02x) scheduled",
|
||||
handler->query_bit);
|
||||
status = acpi_os_execute((handler->func) ?
|
||||
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
|
||||
acpi_ec_run, handler);
|
||||
if (ACPI_FAILURE(status))
|
||||
q->handler->query_bit);
|
||||
/*
|
||||
* It is reported that _Qxx are evaluated in a
|
||||
* parallel way on Windows:
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=94411
|
||||
*/
|
||||
if (!schedule_work(&q->work))
|
||||
result = -EBUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ec->mutex);
|
||||
|
||||
err_exit:
|
||||
if (result && q)
|
||||
acpi_ec_delete_query(q);
|
||||
if (data)
|
||||
*data = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
@ -15,10 +15,6 @@
|
||||
* 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 <linux/kernel.h>
|
||||
|
@ -13,9 +13,6 @@
|
||||
* 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.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _ACPI_INTERNAL_H_
|
||||
@ -70,7 +67,7 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern struct dentry *acpi_debugfs_dir;
|
||||
int acpi_debugfs_init(void);
|
||||
void acpi_debugfs_init(void);
|
||||
#else
|
||||
static inline void acpi_debugfs_init(void) { return; }
|
||||
#endif
|
||||
@ -93,10 +90,21 @@ int acpi_device_add(struct acpi_device *device,
|
||||
void (*release)(struct device *));
|
||||
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
int type, unsigned long long sta);
|
||||
int acpi_device_setup_files(struct acpi_device *dev);
|
||||
void acpi_device_remove_files(struct acpi_device *dev);
|
||||
void acpi_device_add_finalize(struct acpi_device *device);
|
||||
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
|
||||
bool acpi_device_is_present(struct acpi_device *adev);
|
||||
bool acpi_device_is_battery(struct acpi_device *adev);
|
||||
bool acpi_device_is_first_physical_node(struct acpi_device *adev,
|
||||
const struct device *dev);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Device Matching and Notification
|
||||
-------------------------------------------------------------------------- */
|
||||
struct acpi_device *acpi_companion_match(const struct device *dev);
|
||||
int __acpi_device_uevent_modalias(struct acpi_device *adev,
|
||||
struct kobj_uevent_env *env);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Power Resource
|
||||
|
@ -15,10 +15,6 @@
|
||||
* 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
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
*/
|
||||
|
@ -19,10 +19,6 @@
|
||||
* 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
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
*/
|
||||
@ -47,6 +43,7 @@
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm-generic/io-64-nonatomic-lo-hi.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@ -83,6 +80,7 @@ static void *acpi_irq_context;
|
||||
static struct workqueue_struct *kacpid_wq;
|
||||
static struct workqueue_struct *kacpi_notify_wq;
|
||||
static struct workqueue_struct *kacpi_hotplug_wq;
|
||||
static bool acpi_os_initialized;
|
||||
|
||||
/*
|
||||
* This list of permanent mappings is for memory that may be accessed from
|
||||
@ -947,21 +945,6 @@ acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
|
||||
|
||||
EXPORT_SYMBOL(acpi_os_write_port);
|
||||
|
||||
#ifdef readq
|
||||
static inline u64 read64(const volatile void __iomem *addr)
|
||||
{
|
||||
return readq(addr);
|
||||
}
|
||||
#else
|
||||
static inline u64 read64(const volatile void __iomem *addr)
|
||||
{
|
||||
u64 l, h;
|
||||
l = readl(addr);
|
||||
h = readl(addr+4);
|
||||
return l | (h << 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
acpi_status
|
||||
acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
||||
{
|
||||
@ -994,7 +977,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
||||
*(u32 *) value = readl(virt_addr);
|
||||
break;
|
||||
case 64:
|
||||
*(u64 *) value = read64(virt_addr);
|
||||
*(u64 *) value = readq(virt_addr);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
@ -1008,19 +991,6 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
#ifdef writeq
|
||||
static inline void write64(u64 val, volatile void __iomem *addr)
|
||||
{
|
||||
writeq(val, addr);
|
||||
}
|
||||
#else
|
||||
static inline void write64(u64 val, volatile void __iomem *addr)
|
||||
{
|
||||
writel(val, addr);
|
||||
writel(val>>32, addr+4);
|
||||
}
|
||||
#endif
|
||||
|
||||
acpi_status
|
||||
acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
|
||||
{
|
||||
@ -1049,7 +1019,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
|
||||
writel(value, virt_addr);
|
||||
break;
|
||||
case 64:
|
||||
write64(value, virt_addr);
|
||||
writeq(value, virt_addr);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
@ -1316,6 +1286,9 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
|
||||
long jiffies;
|
||||
int ret = 0;
|
||||
|
||||
if (!acpi_os_initialized)
|
||||
return AE_OK;
|
||||
|
||||
if (!sem || (units < 1))
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
@ -1355,6 +1328,9 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
|
||||
{
|
||||
struct semaphore *sem = (struct semaphore *)handle;
|
||||
|
||||
if (!acpi_os_initialized)
|
||||
return AE_OK;
|
||||
|
||||
if (!sem || (units < 1))
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
@ -1863,6 +1839,7 @@ acpi_status __init acpi_os_initialize(void)
|
||||
rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register);
|
||||
pr_debug(PREFIX "%s: map reset_reg status %d\n", __func__, rv);
|
||||
}
|
||||
acpi_os_initialized = true;
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
@ -19,10 +19,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user