提交 ae982073 编写于 作者: L Linus Torvalds

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)
  ...
/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
The status of the tracing feature.
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.
"enabled" means this feature is enabled
and the AML method is traced every time it's executed.
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.
"1" means this feature is enabled and the AML method
will only be traced during the next execution.
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
"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".
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.
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.
......
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_PROCESSOR
tristate "Processor"
config ACPI_CPU_FREQ_PSS
bool
select THERMAL
config ACPI_PROCESSOR_IDLE
bool
select CPU_IDLE
config ACPI_PROCESSOR
tristate "Processor"
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;
}
......
/******************************************************************************
*
* 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 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
/* 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 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
*
******************************************************************************/
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 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
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,
}
}
/*******************************************************************************
*
* 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;
}
......
/*******************************************************************************
*
* 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, &quotient, 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, &quotient, 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 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
* 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) {
......
此差异已折叠。
......@@ -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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
......
此差异已折叠。
......@@ -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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册